@@ -103,11 +103,19 @@ def color565(r, g, b):
103103METER = color565 (80 , 220 , 140 )
104104METER_BG = color565 (38 , 42 , 54 )
105105
106- live = audiolive .LiveAudio (volume = audiolive .VOLUME )
107- # Synthesised before anything is on screen: `riff` is 115 200 Python loop
108- # iterations, and paying for it while a timer is already ticking is how an
109- # example ends up looking wedged on its first frame.
110- live .prepare ("riff" )
106+ # `available()` and `why()` exist for exactly this: a runtime without the pump
107+ # built in cannot play any of this, and an example that dies on its
108+ # constructor tells a reader nothing. The Pyodide half of the gallery is that
109+ # runtime, and so is a firmware built without the audiodsp usermod.
110+ _no_sound = None if audiolive .available () else audiolive .why ()
111+
112+ live = None
113+ if _no_sound is None :
114+ live = audiolive .LiveAudio (volume = audiolive .VOLUME )
115+ # Synthesised before anything is on screen: `riff` is 115 200 Python loop
116+ # iterations, and paying for it while a timer is already ticking is how an
117+ # example ends up looking wedged on its first frame.
118+ live .prepare ("riff" )
111119
112120# The pump's engine, through audiodev's accessor rather than a bare import:
113121# `module()` is the supported way to ask for it, and `threaded()` is the
@@ -119,25 +127,26 @@ def color565(r, g, b):
119127# pump fills a RAM ring and SOMEBODY has to drain it into a sink -- that is
120128# true on a desktop as much as in a browser. Whether that somebody also has to
121129# *run* the pump is the second question, and only WebAssembly answers yes.
122- _drains = not live .on_board
130+ _drains = live is not None and not live .on_board
123131_services = _drains and not pumpdev .threaded ()
124132
125133_sink = None
126134_sink_open = False
127- _sink_why = None
128135if _drains :
129136 from audiodev import auto as audioauto # noqa: E402
130137
131138 try :
132139 _sink = audioauto .pcm_out ()
133140 except Exception as exc : # a desktop with no audio backend installed
134- _sink_why = str (exc )
141+ _no_sound = str (exc )
135142 _drains = _services = False
136143
137144_WHERE = (
138- "on the board, straight into I2S"
139- if live .on_board
140- else ("in the browser, serviced by a timer" if _services else "into a ring you drain" )
145+ audiolive .why ()
146+ if _no_sound is not None
147+ else ("on the board, straight into I2S" if live .on_board
148+ else ("in the browser, serviced by a timer" if _services
149+ else "into a ring you drain" ))
141150)
142151
143152_buf = bytearray (DRAIN_BYTES )
@@ -167,8 +176,10 @@ def _sink_ready():
167176 there is no sink here at all -- the pump owns the I2S port itself.
168177 """
169178 global _sink_open
179+ if _no_sound is not None :
180+ return False
170181 if _sink is None :
171- return _sink_why is None
182+ return True
172183 if _sink_open :
173184 return True
174185 try :
@@ -299,10 +310,10 @@ def _draw_tick(_=None):
299310 y += 16 + 12
300311
301312 if not _started :
302- if _sink_why is not None :
303- pygraphics .text (display_drv , "NO AUDIO OUTPUT " , pad , y , ACCENT , scale = 2 )
313+ if _no_sound is not None :
314+ pygraphics .text (display_drv , "NO SOUND HERE " , pad , y , ACCENT , scale = 2 )
304315 y += 22
305- for line in _wrap (_sink_why , COLS ):
316+ for line in _wrap (_no_sound , COLS ):
306317 pygraphics .text (display_drv , line , pad , y , DIM , scale = 1 )
307318 y += ROW
308319 return
@@ -355,7 +366,8 @@ def _draw_tick(_=None):
355366
356367
357368def _on_quit (_e = None ):
358- live .stop ()
369+ if live is not None :
370+ live .stop ()
359371 if _sink is not None and _sink_open :
360372 _sink .close ()
361373 display_drv .quit ()
0 commit comments