def start_main() -> None: """Starts the TK and Trio loops. See https://github.com/richardsheridan/trio-guest/. """ def tk_func() -> None: """Called to execute the callback.""" queue.popleft()() def run_sync_soon_threadsafe(func: Callable[[], Any]) -> None: """Run the specified func in the next loop, from other threads.""" queue.append(func) TK_ROOT.call("after", "idle", tk_func_name) def run_sync_soon_not_threadsafe(func: Callable[[], Any]) -> None: """Run the specified func in the next loop.""" queue.append(func) # The zero here apparently avoids blocking the event loop if an endless stream of # callbacks is triggered. TK_ROOT.call("after", "idle", "after", 0, tk_func_name) queue: collections.deque[Callable[[], Any]] = collections.deque() tk_func_name = TK_ROOT.register(tk_func) LOGGER.debug('Starting Trio loop.') trio.lowlevel.start_guest_run( app_main, run_sync_soon_threadsafe=run_sync_soon_threadsafe, run_sync_soon_not_threadsafe=run_sync_soon_not_threadsafe, done_callback=done_callback, ) TK_ROOT.mainloop()
def ticker() -> None: """We need to constantly trigger pyglet.clock.tick(). Instead of re-registering this, cache off the command name. Additionally, load sounds gradually in the background. """ if _todo: name = _todo.pop() fname = SOUNDS[name] path = str(utils.install_path('sounds/{}.ogg'.format(fname))) LOGGER.info('Loading sound "{}" -> {}', name, path) SOUNDS[name] = pyglet.media.load(path, streaming=False) tick() TK_ROOT.tk.call(ticker_cmd) ticker_cmd = ('after', 150, TK_ROOT.register(ticker)) TK_ROOT.tk.call(ticker_cmd) class SamplePlayer: """Handles playing a single audio file, and allows toggling it on/off.""" def __init__( self, start_callback: Callable[[], None], stop_callback: Callable[[], None], system: FileSystemChain, ) -> None: """Initialise the sample-playing manager. """ self.sample: Optional[Source] = None self.start_time: float = 0 # If set, the time to start the track at. self.after: Optional[str] = None