def start(self, config_lock, notification_queue_in, notification_queue_out, effect_queue, audio_queue): self._config_lock = config_lock self._config = ConfigService.instance(self._config_lock).config self._notification_queue_in = notification_queue_in self._notification_queue_out = notification_queue_out self._effect_queue = effect_queue print("Effect queue id DeviceManager " + str(id(self._effect_queue))) self._audio_queue = audio_queue #Init FPS Limiter self._fps_limiter = FPSLimiter(200) self._skip_routine = False self._devices = {} self.init_devices() self.start_devices() self.start_time = time.time() self.ten_seconds_counter = time.time() while True: self.routine()
def start(self, config_lock, notification_queue_in, notification_queue_out, effect_queue, audio_queue): self.logger = logging.getLogger(__name__) self._config_lock = config_lock self._config = ConfigService.instance(self._config_lock).config self._notification_queue_in = QueueWrapper(notification_queue_in) self._notification_queue_out = QueueWrapper(notification_queue_out) self._effect_queue = QueueWrapper(effect_queue) self._audio_queue = QueueWrapper(audio_queue) # Init FPS Limiter. self._fps_limiter = FPSLimiter(120) self._skip_routine = False self._devices = {} self.init_devices() self.start_devices() self.start_time = time() self.ten_seconds_counter = time() while True: try: self.routine() except KeyboardInterrupt: break
def refresh(self): self.logger.debug("Refreshing effects...") self._initialized_effects = {} self._fps_limiter = FPSLimiter(self._device.device_config["FPS"]) # Notify the master component, that I'm finished. self._device.device_notification_queue_out.put( NotificationEnum.config_refresh_finished) self.logger.debug("Effects refreshed.")
def start(self, device): self.logger = logging.getLogger(__name__) self._device = device self._led_strip = self._device.device_config["led_strip"] self.logger.info( f'Starting Output service... Device: {self._device.device_config["device_name"]}' ) # Initial config load. self._config = self._device.config self._output_queue = self._device.output_queue self._device_notification_queue_in = self._device.device_notification_queue_in self._device_notification_queue_out = self._device.device_notification_queue_out self.ten_seconds_counter = time() self.sec_ten_seconds_counter = time() self.start_time = time() # Init FPS Limiter. self._fps_limiter = FPSLimiter(self._device.device_config["fps"]) self._skip_output = False self._cancel_token = False self._available_outputs = { OutputsEnum.output_dummy: OutputDummy, OutputsEnum.output_raspi: OutputRaspi, OutputsEnum.output_udp: OutputUDP } current_output_enum = OutputsEnum[ self._device.device_config["output_type"]] self.logger.debug(f"Found output: {current_output_enum}") self._current_output = self._available_outputs[current_output_enum]( self._device) self.logger.debug( f'Output component started. Device: {self._device.device_config["device_name"]}' ) while not self._cancel_token: try: self.output_routine() except KeyboardInterrupt: break
def start(self, device): self._device = device print("Starting Output service.. Device: " + self._device.device_config["DEVICE_NAME"]) # Initial config load. self._config = self._device.config self._output_queue = self._device.output_queue self._device_notification_queue_in = self._device.device_notification_queue_in self._device_notification_queue_out = self._device.device_notification_queue_out self.ten_seconds_counter = time.time() self.sec_ten_seconds_counter = time.time() self.start_time = time.time() #Init FPS Limiter self._fps_limiter = FPSLimiter(self._device.device_config["FPS"]) self._skip_output = False self._cancel_token = False self._available_outputs = { OutputsEnum.output_dummy: OutputDummy, OutputsEnum.output_raspi: OutputRaspi, OutputsEnum.output_udp: OutputUDP } current_output_enum = OutputsEnum[ self._device.device_config["OUTPUT_TYPE"]] print("Found output: " + str(current_output_enum)) self._current_output = self._available_outputs[current_output_enum]( self._device) print("Output component started. Device: " + self._device.device_config["DEVICE_NAME"]) while not self._cancel_token: self.output_routine()
class OutputService(): def start(self, device): self._device = device print(f'Starting Output service... Device: {self._device.device_config["DEVICE_NAME"]}') # Initial config load. self._config = self._device.config self._output_queue = self._device.output_queue self._device_notification_queue_in = self._device.device_notification_queue_in self._device_notification_queue_out = self._device.device_notification_queue_out self.ten_seconds_counter = time.time() self.sec_ten_seconds_counter = time.time() self.start_time = time.time() # Init FPS Limiter. self._fps_limiter = FPSLimiter(self._device.device_config["FPS"]) self._skip_output = False self._cancel_token = False self._available_outputs = { OutputsEnum.output_dummy: OutputDummy, OutputsEnum.output_raspi: OutputRaspi, OutputsEnum.output_udp: OutputUDP } current_output_enum = OutputsEnum[self._device.device_config["OUTPUT_TYPE"]] print(f"Found output: {current_output_enum}") self._current_output = self._available_outputs[current_output_enum](self._device) print(f'Output component started. Device: {self._device.device_config["DEVICE_NAME"]}') while not self._cancel_token: self.output_routine() def output_routine(self): # Limit the fps to decrease lags caused by 100 percent CPU. self._fps_limiter.fps_limiter() # Check the nofitication queue. if not self._device_notification_queue_in.empty(): self._current_notification_in = self._device_notification_queue_in.get() if hasattr(self, "_current_notification_in"): if self._current_notification_in is NotificationEnum.config_refresh: self.refresh() elif self._current_notification_in is NotificationEnum.process_continue: self._skip_output = False elif self._current_notification_in is NotificationEnum.process_pause: self._skip_output = True elif self._current_notification_in is NotificationEnum.process_stop: self.stop() # Reset the current in notification, to do it only one time. self._current_notification_in = None # Skip the output sequence, for example to "pause" the process. if self._skip_output: if not self._output_queue.empty(): skip_output_queue = self._output_queue.get() del skip_output_queue return # Check if the queue is empty and stop if its empty. if not self._output_queue.empty(): current_output_array = self._output_queue.get() self._current_output.show(current_output_array) self.end_time = time.time() if time.time() - self.ten_seconds_counter > 10: self.ten_seconds_counter = time.time() self.time_dif = self.end_time - self.start_time self.fps = 1 / self.time_dif print(f'Output Service | FPS: {self.fps} | Device: {self._device.device_config["DEVICE_NAME"]}') self.start_time = time.time() def stop(self): self._cancel_token = True self._current_output.clear() def refresh(self): print("Refreshing output...") # Refresh the config, self._config = self._device.config # Notify the master component, that I'm finished. self._device_notification_queue_out.put(NotificationEnum.config_refresh_finished) print("Output refreshed.")
def init_audio_service(self, show_output=False): try: # Initial config load. ConfigService.instance(self._config_lock).load_config() self._config = ConfigService.instance(self._config_lock).config # Init FPS Limiter. self._fps_limiter = FPSLimiter(120) # Init pyaudio. self._py_audio = pyaudio.PyAudio() self._skip_routine = False self._numdevices = self._py_audio.get_device_count() self._default_device_id = self._py_audio.get_default_input_device_info()['index'] self._devices = [] self.log_output(show_output, logging.INFO, "Found the following audio sources:") # Select the audio device you want to use. selected_device_list_index = self._config["general_settings"]["DEVICE_ID"] # Check if the index is inside the list. foundMicIndex = False # For each audio device, add to list of devices. for i in range(0, self._numdevices): try: device_info = self._py_audio.get_device_info_by_host_api_device_index(0, i) if device_info["maxInputChannels"] >= 1: self._devices.append(device_info) self.log_output(show_output, logging.INFO, f'{device_info["index"]} - {device_info["name"]} - {device_info["defaultSampleRate"]}') if device_info["index"] == selected_device_list_index: foundMicIndex = True except Exception as e: self.log_output(show_output, logging.ERROR, "Could not get device infos.") self.logger.exception(f"Unexpected error in AudioProcessService: {e}") # Could not find a mic with the selected mic id, so I will use the first device I found. if not foundMicIndex: self.log_output(show_output, logging.ERROR, "********************************************************") self.log_output(show_output, logging.ERROR, "* Error *") self.log_output(show_output, logging.ERROR, "********************************************************") self.log_output(show_output, logging.ERROR, f"Could not find the mic with the id: {selected_device_list_index}") self.log_output(show_output, logging.ERROR, "Using the first mic as fallback.") self.log_output(show_output, logging.ERROR, "Please change the id of the mic inside the config.") selected_device_list_index = self._devices[0]["index"] for device in self._devices: if device["index"] == selected_device_list_index: self.log_output(show_output, logging.INFO, f"Selected ID: {selected_device_list_index}") self.log_output(show_output, logging.INFO, f'Using {device["index"]} - {device["name"]} - {device["defaultSampleRate"]}') self._device_id = device["index"] self._device_name = device["name"] self._device_rate = self._config["general_settings"]["DEFAULT_SAMPLE_RATE"] self._frames_per_buffer = self._config["general_settings"]["FRAMES_PER_BUFFER"] self.n_fft_bins = self._config["general_settings"]["N_FFT_BINS"] self.start_time_1 = time() self.ten_seconds_counter_1 = time() self.start_time_2 = time() self.ten_seconds_counter_2 = time() self._dsp = DSP(self._config) self.audio = np.empty((self._frames_per_buffer), dtype="int16") # Reinit buffer queue self.audio_buffer_queue = Queue(2) # callback function to stream audio, another thread. def callback(in_data, frame_count, time_info, status): if self._skip_routine: return (self.audio, pyaudio.paContinue) try: self.audio_buffer_queue.put(in_data) except Exception as e: pass self.end_time_1 = time() if time() - self.ten_seconds_counter_1 > 10: self.ten_seconds_counter_1 = time() time_dif = self.end_time_1 - self.start_time_1 fps = 1 / time_dif self.logger.info(f"Callback | FPS: {fps:.2f}") self.start_time_1 = time() return (self.audio, pyaudio.paContinue) self.log_output(show_output, logging.DEBUG, "Starting Open Audio Stream...") self.stream = self._py_audio.open( format=pyaudio.paInt16, channels=1, rate=self._device_rate, input=True, input_device_index=self._device_id, frames_per_buffer=self._frames_per_buffer, stream_callback=callback ) except Exception as e: self.logger.error("Could not init AudioService.") self.logger.exception(f"Unexpected error in init_audio_service: {e}")
class DeviceManager(): def start(self, config_lock, notification_queue_in, notification_queue_out, effect_queue, audio_queue): self.logger = logging.getLogger(__name__) self._config_lock = config_lock self._config = ConfigService.instance(self._config_lock).config self._notification_queue_in = QueueWrapper(notification_queue_in) self._notification_queue_out = QueueWrapper(notification_queue_out) self._effect_queue = QueueWrapper(effect_queue) self._audio_queue = QueueWrapper(audio_queue) # Init FPS Limiter. self._fps_limiter = FPSLimiter(120) self._skip_routine = False self._devices = {} self.init_devices() self.start_devices() self.start_time = time() self.ten_seconds_counter = time() while True: try: self.routine() except KeyboardInterrupt: break def routine(self): # Check the effect queue. if not self._effect_queue.empty(): current_effect_item = self._effect_queue.get_blocking() self.logger.debug( f"Device Manager received new effect: {current_effect_item.effect_enum} {current_effect_item.device_id}" ) current_device = self._devices[current_effect_item.device_id] current_device.effect_queue.put_blocking(current_effect_item) if not self._notification_queue_in.empty(): current_notification_item = self._notification_queue_in.get_blocking( ) self.logger.debug( f"Device Manager received new notification: {current_notification_item.notification_enum} - {current_notification_item.device_id}" ) if current_notification_item.notification_enum is NotificationEnum.config_refresh: devices_count_before_reload = len( self._config["device_configs"].keys()) self.logger.debug( f"Device count before: {devices_count_before_reload}") self.reload_config() devices_count_after_reload = len( self._config["device_configs"].keys()) self.logger.debug( f"Device count after: {devices_count_after_reload}") if (devices_count_before_reload != devices_count_after_reload): self.reinit_devices() if (current_notification_item.device_id == "all_devices"): for key, value in self._devices.items(): self.restart_device(key) else: self.restart_device(current_notification_item.device_id) self._notification_queue_out.put_blocking( NotificationItem(NotificationEnum.config_refresh_finished, current_notification_item.device_id)) elif current_notification_item.notification_enum is NotificationEnum.process_continue: self._skip_routine = False elif current_notification_item.notification_enum is NotificationEnum.process_pause: self._skip_routine = True # Limit the fps to decrease lags caused by 100 percent CPU. self._fps_limiter.fps_limiter() if self._skip_routine: return audio_data = self.get_audio_data() self.refresh_audio_queues(audio_data) self.end_time = time() if time() - self.ten_seconds_counter > 10: self.ten_seconds_counter = time() self.time_dif = self.end_time - self.start_time self.fps = 1 / self.time_dif self.logger.info(f"FPS: {self.fps:.2f}") self.start_time = time() def get_audio_data(self): audio_data = None if not self._audio_queue.empty(): audio_data = self._audio_queue.get_blocking() return audio_data def refresh_audio_queues(self, audio_data): if audio_data is None: return for key, value in self._devices.items(): audio_copy = copy.deepcopy(audio_data) value.audio_queue.put_none_blocking(audio_data) def init_devices(self): self.logger.debug("Entering init_devices()") self._color_service_global = ColorServiceGlobal(self._config) for key in self._config["device_configs"].keys(): device_id = key self.logger.debug(f"Init device with device id: {device_id}") self._devices[device_id] = Device( self._config, self._config["device_configs"][device_id], self._color_service_global) self.logger.debug("Leaving init_devices()") def reinit_devices(self): self.logger.debug("Entering reinit_devices()") for key, value in self._devices.items(): self.stop_device(key) self._devices = {} self.init_devices() self.start_devices() self.logger.debug("Leaving reinit_devices()") def start_devices(self): for key, value in self._devices.items(): self.logger.debug(f"Starting device: {key}") value.start_device() def reload_config(self): self.logger.debug("Entering reload_config()") ConfigService.instance(self._config_lock).load_config() self._config = ConfigService.instance(self._config_lock).config self.logger.debug("Leaving reload_config()") def restart_device(self, device_id): self.logger.debug(f"Restarting {device_id}") self._devices[device_id].refresh_config( self._config, self._config["device_configs"][device_id]) self.logger.debug(f"Restarted {device_id}") def stop_device(self, device_id): self.logger.debug(f"Stopping {device_id}") self._devices[device_id].stop_device() self.logger.debug(f"Stopped {device_id}")
def start(self, device): """ Start the effect service process. You can change the effect by adding a new effect enum inside the enum_queue. """ self.logger = logging.getLogger(__name__) self._device = device self.logger.info( f'Starting Effect Service component from device: {self._device.device_config["DEVICE_NAME"]}' ) self.ten_seconds_counter = time() self.start_time = time() self._fps_limiter = FPSLimiter(self._device.device_config["FPS"]) self._available_effects = { EffectsEnum.effect_off: EffectOff, EffectsEnum.effect_single: EffectSingle, EffectsEnum.effect_gradient: EffectGradient, EffectsEnum.effect_fade: EffectFade, EffectsEnum.effect_sync_fade: EffectSyncFade, EffectsEnum.effect_slide: EffectSlide, EffectsEnum.effect_bubble: EffectBubble, EffectsEnum.effect_twinkle: EffectTwinkle, EffectsEnum.effect_pendulum: EffectPendulum, EffectsEnum.effect_rods: EffectRods, EffectsEnum.effect_advanced_scroll: EffectAdvancedScroll, EffectsEnum.effect_scroll: EffectScroll, EffectsEnum.effect_energy: EffectEnergy, EffectsEnum.effect_wavelength: EffectWavelength, EffectsEnum.effect_bars: EffectBars, EffectsEnum.effect_power: EffectPower, EffectsEnum.effect_beat: EffectBeat, EffectsEnum.effect_wave: EffectWave, EffectsEnum.effect_beat_slide: EffectBeatSlide, EffectsEnum.effect_spectrum_analyzer: EffectSpectrumAnalyzer, EffectsEnum.effect_vu_meter: EffectVuMeter, EffectsEnum.effect_wiggle: EffectWiggle, EffectsEnum.effect_direction_changer: EffectDirectionChanger, EffectsEnum.effect_beat_twinkle: EffectBeatTwinkle, EffectsEnum.effect_segment_color: EffectSegmentColor } self._initialized_effects = {} self._current_effect = {} try: # Get the last effect and set it. last_effect_string = self._device.device_config["effects"][ "last_effect"] self._current_effect = EffectsEnum[last_effect_string] except Exception: self.logger.exception( "Could not parse last effect. Set effect to off.") self._current_effect = EffectsEnum.effect_off # A token to cancel the while loop. self._cancel_token = False self._skip_effect = False self.logger.info( f'Effects component started. Device: {self._device.device_config["DEVICE_NAME"]}' ) while not self._cancel_token: try: self.effect_routine() except KeyboardInterrupt: break self.logger.info( f'Effects component stopped. Device: {self._device.device_config["DEVICE_NAME"]}' )
class EffectService(): def start(self, device): """ Start the effect service process. You can change the effect by adding a new effect enum inside the enum_queue. """ self.logger = logging.getLogger(__name__) self._device = device self.logger.info( f'Starting Effect Service component from device: {self._device.device_config["DEVICE_NAME"]}' ) self.ten_seconds_counter = time() self.start_time = time() self._fps_limiter = FPSLimiter(self._device.device_config["FPS"]) self._available_effects = { EffectsEnum.effect_off: EffectOff, EffectsEnum.effect_single: EffectSingle, EffectsEnum.effect_gradient: EffectGradient, EffectsEnum.effect_fade: EffectFade, EffectsEnum.effect_sync_fade: EffectSyncFade, EffectsEnum.effect_slide: EffectSlide, EffectsEnum.effect_bubble: EffectBubble, EffectsEnum.effect_twinkle: EffectTwinkle, EffectsEnum.effect_pendulum: EffectPendulum, EffectsEnum.effect_rods: EffectRods, EffectsEnum.effect_advanced_scroll: EffectAdvancedScroll, EffectsEnum.effect_scroll: EffectScroll, EffectsEnum.effect_energy: EffectEnergy, EffectsEnum.effect_wavelength: EffectWavelength, EffectsEnum.effect_bars: EffectBars, EffectsEnum.effect_power: EffectPower, EffectsEnum.effect_beat: EffectBeat, EffectsEnum.effect_wave: EffectWave, EffectsEnum.effect_beat_slide: EffectBeatSlide, EffectsEnum.effect_spectrum_analyzer: EffectSpectrumAnalyzer, EffectsEnum.effect_vu_meter: EffectVuMeter, EffectsEnum.effect_wiggle: EffectWiggle, EffectsEnum.effect_direction_changer: EffectDirectionChanger, EffectsEnum.effect_beat_twinkle: EffectBeatTwinkle, EffectsEnum.effect_segment_color: EffectSegmentColor } self._initialized_effects = {} self._current_effect = {} try: # Get the last effect and set it. last_effect_string = self._device.device_config["effects"][ "last_effect"] self._current_effect = EffectsEnum[last_effect_string] except Exception: self.logger.exception( "Could not parse last effect. Set effect to off.") self._current_effect = EffectsEnum.effect_off # A token to cancel the while loop. self._cancel_token = False self._skip_effect = False self.logger.info( f'Effects component started. Device: {self._device.device_config["DEVICE_NAME"]}' ) while not self._cancel_token: try: self.effect_routine() except KeyboardInterrupt: break self.logger.info( f'Effects component stopped. Device: {self._device.device_config["DEVICE_NAME"]}' ) def effect_routine(self): # Limit the fps to decrease lags caused by 100 percent CPU. self._fps_limiter.fps_limiter() # Check the notification queue. if not self._device.device_notification_queue_in.empty(): self._current_notification_in = self._device.device_notification_queue_in.get( ) self.logger.debug( f'Effects Service has a new notification in. Notification: {self._current_notification_in} | Device: {self._device.device_config["DEVICE_NAME"]}' ) if hasattr(self, "_current_notification_in"): if self._current_notification_in is NotificationEnum.config_refresh: self.refresh() elif self._current_notification_in is NotificationEnum.process_continue: self._skip_effect = False elif self._current_notification_in is NotificationEnum.process_pause: self._skip_effect = True elif self._current_notification_in is NotificationEnum.process_stop: self.stop() # Reset the current in notification, to do it only one time. self._current_notification_in = None # Skip the effect sequence, for example, to "pause" the process. if self._skip_effect: return # Check if the effect changed. if not self._device.effect_queue.empty(): new_effect_item = self._device.effect_queue.get() self._current_effect = new_effect_item.effect_enum self.logger.debug( f"New effect found: {new_effect_item.effect_enum}") # Something is wrong here, no effect set. So skip until we get new information. if self._current_effect is None: self.logger.error("Effect Service | Could not find effect.") return if (not (self._current_effect in self._initialized_effects.keys())): if self._current_effect in self._available_effects.keys(): self._initialized_effects[ self._current_effect] = self._available_effects[ self._current_effect](self._device) else: self.logger.error( f"Could not find effect: {self._current_effect}") self.end_time = time() if time() - self.ten_seconds_counter > 10: self.ten_seconds_counter = time() self.time_dif = self.end_time - self.start_time self.fps = 1 / self.time_dif self.logger.info( f'FPS: {self.fps:.2f} | Device: {self._device.device_config["DEVICE_NAME"]}' ) self.start_time = time() self._initialized_effects[self._current_effect].run() def stop(self): self.logger.info("Stopping effect component...") self.cancel_token = True def refresh(self): self.logger.debug("Refreshing effects...") self._initialized_effects = {} self._fps_limiter = FPSLimiter(self._device.device_config["FPS"]) # Notify the master component, that I'm finished. self._device.device_notification_queue_out.put( NotificationEnum.config_refresh_finished) self.logger.debug("Effects refreshed.")
def init_audio_service(self, show_output=False): try: # Initial config load. ConfigService.instance(self._config_lock).load_config() self._config = ConfigService.instance(self._config_lock).config # Init FPS Limiter. self._fps_limiter = FPSLimiter(120) self._skip_routine = False self._devices = AudioInfo.get_audio_devices(self._py_audio) self.log_output(show_output, logging.INFO, "Found the following audio sources:") # Select the audio device you want to use. selected_device_list_index = 0 try: mic_id = self._config["general_settings"]["device_id"] if mic_id != "no_mic": selected_device_list_index = int(mic_id) except Exception as e: self.logger.exception(f"Could not parse audio id: {e}") # Check if the index is inside the list. self.selected_device = None # For each audio device, add to list of devices. for current_audio_device in self._devices: if current_audio_device.id == selected_device_list_index: self.selected_device = current_audio_device self.logger.debug(f"Selected Device: {self.selected_device}") # Could not find a mic with the selected mic id, so I will use the first device I found. if self.selected_device is None: self.log_output( show_output, logging.ERROR, "********************************************************") self.log_output( show_output, logging.ERROR, "* Error *") self.log_output( show_output, logging.ERROR, "********************************************************") self.log_output( show_output, logging.ERROR, f"Could not find the mic with the id: {selected_device_list_index}" ) self.log_output(show_output, logging.ERROR, "Using the first mic as fallback.") self.log_output( show_output, logging.ERROR, "Please change the id of the mic inside the config.") self.selected_device = self._devices[0] self._device_rate = self._config["general_settings"][ "default_sample_rate"] self._frames_per_buffer = self._config["general_settings"][ "frames_per_buffer"] self.n_fft_bins = self._config["general_settings"]["n_fft_bins"] self.log_output( show_output, logging.INFO, f"Selected Device: {self.selected_device.to_string()}") # Init Timer self.start_time_1 = time() self.ten_seconds_counter_1 = time() self.start_time_2 = time() self.ten_seconds_counter_2 = time() self._dsp = DSP(self._config) self.audio = np.empty((self._frames_per_buffer), dtype="int16") # Reinit buffer queue self.audio_buffer_queue = QueueWrapper(Queue(2)) # callback function to stream audio, another thread. def callback(in_data, frame_count, time_info, status): if self._skip_routine: return (self.audio, pyaudio.paContinue) self.audio_buffer_queue.put_none_blocking(in_data) self.end_time_1 = time() if time() - self.ten_seconds_counter_1 > 10: self.ten_seconds_counter_1 = time() time_dif = self.end_time_1 - self.start_time_1 fps = 1 / time_dif self.logger.info(f"Callback | FPS: {fps:.2f}") self.start_time_1 = time() return (self.audio, pyaudio.paContinue) self.log_output(show_output, logging.DEBUG, "Starting Open Audio Stream...") self.stream = self._py_audio.open( format=pyaudio.paInt16, channels=1, rate=self._device_rate, input=True, input_device_index=self.selected_device.id, frames_per_buffer=self._frames_per_buffer, stream_callback=callback) except Exception as e: self.logger.error("Could not init AudioService.") self.logger.exception( f"Unexpected error in init_audio_service: {e}")
def start(self, device): """ Start the effect service process. You can change the effect by add a new effect enum inside the enum_queue. """ self._device = device print("Start Effect Service component from device: " + self._device.device_config["DEVICE_NAME"]) self.ten_seconds_counter = time.time() self.start_time = time.time() self._fps_limiter = FPSLimiter(self._device.device_config["FPS"]) self._available_effects = { EffectsEnum.effect_off: EffectOff, EffectsEnum.effect_single: EffectSingle, EffectsEnum.effect_gradient: EffectGradient, EffectsEnum.effect_fade: EffectFade, EffectsEnum.effect_sync_fade: EffectSyncFade, EffectsEnum.effect_slide: EffectSlide, EffectsEnum.effect_bubble: EffectBubble, EffectsEnum.effect_twinkle: EffectTwinkle, EffectsEnum.effect_pendulum: EffectPendulum, EffectsEnum.effect_rods: EffectRods, EffectsEnum.effect_advanced_scroll: EffectAdvancedScroll, EffectsEnum.effect_scroll: EffectScroll, EffectsEnum.effect_energy: EffectEnergy, EffectsEnum.effect_wavelength: EffectWavelength, EffectsEnum.effect_bars: EffectBars, EffectsEnum.effect_power: EffectPower, EffectsEnum.effect_beat: EffectBeat, EffectsEnum.effect_wave: EffectWave, EffectsEnum.effect_beat_slide: EffectBeatSlide, EffectsEnum.effect_spectrum_analyzer: EffectSpectrumAnalyzer, EffectsEnum.effect_vu_meter: EffectVuMeter, EffectsEnum.effect_wiggle: EffectWiggle, EffectsEnum.effect_direction_changer: EffectDirectionChanger, EffectsEnum.effect_beat_twinkle: EffectBeatTwinkle } self._initialized_effects = {} self._current_effect = {} try: # Get the last effect and set it. last_effect_string = self._device.device_config["effects"][ "last_effect"] self._current_effect = EffectsEnum[last_effect_string] except Exception: print("Could not parse last effect. Set effect to off.") self._current_effect = EffectsEnum.effect_off # A token to cancle the while loop self._cancel_token = False self._skip_effect = False print("Effects component started. Device: " + self._device.device_config["DEVICE_NAME"]) while not self._cancel_token: #try: self.effect_routine() #except Exception as e: # print("Error in Effect Service. Routine Restarted. Exception: " + str(e)) print("Effects component stopped. Device: " + self._device.device_config["DEVICE_NAME"])
class DeviceManager: def start(self, config_lock, notification_queue_in, notification_queue_out, effect_queue, audio_queue): self._config_lock = config_lock self._config = ConfigService.instance(self._config_lock).config self._notification_queue_in = notification_queue_in self._notification_queue_out = notification_queue_out self._effect_queue = effect_queue print("Effect queue id DeviceManager " + str(id(self._effect_queue))) self._audio_queue = audio_queue #Init FPS Limiter self._fps_limiter = FPSLimiter(200) self._skip_routine = False self._devices = {} self.init_devices() self.start_devices() self.start_time = time.time() self.ten_seconds_counter = time.time() while True: self.routine() def routine(self): # Check the effect queue if not self._effect_queue.empty(): current_effect_item = self._effect_queue.get() print("Device Manager received new effect: " + str(current_effect_item.effect_enum) + current_effect_item.device_id) current_device = self._devices[current_effect_item.device_id] current_device.effect_queue.put(current_effect_item) if not self._notification_queue_in.empty(): current_notification_item = self._notification_queue_in.get() print("Device Manager received new notification: " + str(current_notification_item.notification_enum) + " - " + str(current_notification_item.device_id)) if current_notification_item.notification_enum is NotificationEnum.config_refresh: devices_count_before_reload = len( self._config["device_configs"].keys()) print("Device count before: " + str(devices_count_before_reload)) self.reload_config() devices_count_after_reload = len( self._config["device_configs"].keys()) print("Device count after: " + str(devices_count_after_reload)) if (devices_count_before_reload != devices_count_after_reload): self.reinit_devices() if (current_notification_item.device_id == "all_devices"): for key, value in self._devices.items(): self.restart_device(key) else: self.restart_device(current_notification_item.device_id) self._notification_queue_out.put( NotificationItem(NotificationEnum.config_refresh_finished, current_notification_item.device_id)) elif current_notification_item.notification_enum is NotificationEnum.process_continue: self._skip_routine = False elif current_notification_item.notification_enum is NotificationEnum.process_pause: self._skip_routine = True # Limit the fps to decrease laggs caused by 100 percent cpu self._fps_limiter.fps_limiter() if self._skip_routine: return audio_data = self.get_audio_data() self.refresh_audio_queues(audio_data) self.end_time = time.time() if time.time() - self.ten_seconds_counter > 10: self.ten_seconds_counter = time.time() self.time_dif = self.end_time - self.start_time self.fps = 1 / self.time_dif print("Device Manager | FPS: " + str(self.fps)) self.start_time = time.time() def get_audio_data(self): audio_data = None if not self._audio_queue.empty(): audio_data = self._audio_queue.get() return audio_data def refresh_audio_queues(self, audio_data): if audio_data is None: return for key, value in self._devices.items(): if value.audio_queue.full(): try: pre_audio_data = value.audio_queue.get(False) del pre_audio_data except: #print("Empty audio queue of devices.") pass audio_copy = copy.deepcopy(audio_data) try: value.audio_queue.put(audio_copy, block=True, timeout=0.33) except: pass def init_devices(self): print("Enter init_devices()") self._color_service_global = ColorServiceGlobal(self._config) for key in self._config["device_configs"].keys(): device_id = key print("Init device with device id:" + device_id) self._devices[device_id] = Device( self._config, self._config["device_configs"][device_id], self._color_service_global) print("Leave init_devices()") def reinit_devices(self): print("Enter reinit_devices()") for key, value in self._devices.items(): self.stop_device(key) self._devices = {} self.init_devices() self.start_devices() print("Leave reinit_devices()") def start_devices(self): for key, value in self._devices.items(): print("Start device:" + key) value.start_device() def reload_config(self): print("Enter reload_config()") ConfigService.instance(self._config_lock).load_config() self._config = ConfigService.instance(self._config_lock).config print("Leave reload_config()") def restart_device(self, device_id): print("Restart " + device_id) self._devices[device_id].refresh_config( self._config, self._config["device_configs"][device_id]) print("Restarted " + device_id) def stop_device(self, device_id): print("Stop " + device_id) self._devices[device_id].stop_device() print("Stopped " + device_id)
def init_audio_service(self): # Initial config load. ConfigService.instance(self._config_lock).load_config() self._config = ConfigService.instance(self._config_lock).config #Init FPS Limiter self._fps_limiter = FPSLimiter(100) # Init pyaudio self._py_audio = pyaudio.PyAudio() self._skip_routine = False self._numdevices = self._py_audio.get_device_count() self._default_device_id = self._py_audio.get_default_input_device_info( )['index'] self._devices = [] print("Found the following audio sources:") # Select the audio device you want to use. selected_device_list_index = self._config["general_settings"][ "DEVICE_ID"] # check if the index is inside the list foundMicIndex = False #for each audio device, add to list of devices for i in range(0, self._numdevices): try: device_info = self._py_audio.get_device_info_by_host_api_device_index( 0, i) if device_info["maxInputChannels"] >= 1: self._devices.append(device_info) print( str(device_info["index"]) + " - " + str(device_info["name"]) + " - " + str(device_info["defaultSampleRate"])) if device_info["index"] == selected_device_list_index: foundMicIndex = True except Exception as e: print("Could not get device infos.") print("Unexpected error in AudioProcessService :" + str(e)) # Could not find a mic with the selected mic id, so i will use the first device I found. if not foundMicIndex: print("********************************************************") print("* Error *") print("********************************************************") print("Could not find the mic with the id: " + str(selected_device_list_index)) print("Use the first mic as fallback.") print("Please change the id of the mic inside the config.") selected_device_list_index = self._devices[0]["index"] for device in self._devices: if device["index"] == selected_device_list_index: print("Selected ID: " + str(selected_device_list_index)) print("Use " + str(device["index"]) + " - " + str(device["name"]) + " - " + str(device["defaultSampleRate"])) self._device_id = device["index"] self._device_name = device["name"] self._device_rate = self._config["general_settings"][ "DEFAULT_SAMPLE_RATE"] self._frames_per_buffer = self._config["general_settings"][ "FRAMES_PER_BUFFER"] self.start_time_1 = time.time() self.ten_seconds_counter_1 = time.time() self.start_time_2 = time.time() self.ten_seconds_counter_2 = time.time() self._dsp = DSP(self._config) self.audio = np.empty((self._frames_per_buffer), dtype="int16") self.audio_buffer_queue = Queue(2) # callback function to stream audio, another thread. def callback(in_data, frame_count, time_info, status): if self._skip_routine: return (self.audio, pyaudio.paContinue) try: self.audio_buffer_queue.put(in_data) except: pass # self.end_time_1 = time.time() if time.time() - self.ten_seconds_counter_1 > 10: self.ten_seconds_counter_1 = time.time() time_dif = self.end_time_1 - self.start_time_1 fps = 1 / time_dif print("Audio Service Callback | FPS: " + str(fps)) self.start_time_1 = time.time() return (self.audio, pyaudio.paContinue) print("Start open Audio stream") self.stream = self._py_audio.open( format=pyaudio.paInt16, channels=1, rate=self._device_rate, input=True, input_device_index=self._device_id, frames_per_buffer=self._frames_per_buffer, stream_callback=callback)
class OutputService(): def start(self, device): self.logger = logging.getLogger(__name__) self._device = device self._led_strip = self._device.device_config["led_strip"] self.logger.info( f'Starting Output service... Device: {self._device.device_config["device_name"]}' ) # Initial config load. self._config = self._device.config self._output_queue = self._device.output_queue self._device_notification_queue_in = self._device.device_notification_queue_in self._device_notification_queue_out = self._device.device_notification_queue_out self.ten_seconds_counter = time() self.sec_ten_seconds_counter = time() self.start_time = time() # Init FPS Limiter. self._fps_limiter = FPSLimiter(self._device.device_config["fps"]) self._skip_output = False self._cancel_token = False self._available_outputs = { OutputsEnum.output_dummy: OutputDummy, OutputsEnum.output_raspi: OutputRaspi, OutputsEnum.output_udp: OutputUDP } current_output_enum = OutputsEnum[ self._device.device_config["output_type"]] self.logger.debug(f"Found output: {current_output_enum}") self._current_output = self._available_outputs[current_output_enum]( self._device) self.logger.debug( f'Output component started. Device: {self._device.device_config["device_name"]}' ) while not self._cancel_token: try: self.output_routine() except KeyboardInterrupt: break def output_routine(self): # Limit the fps to decrease lags caused by 100 percent CPU. self._fps_limiter.fps_limiter() # Check the notification queue. if not self._device_notification_queue_in.empty(): self._current_notification_in = self._device_notification_queue_in.get_blocking( ) if hasattr(self, "_current_notification_in"): if self._current_notification_in is NotificationEnum.config_refresh: self.refresh() elif self._current_notification_in is NotificationEnum.process_continue: self._skip_output = False elif self._current_notification_in is NotificationEnum.process_pause: self._skip_output = True elif self._current_notification_in is NotificationEnum.process_stop: self.stop() # Reset the current in notification, to do it only one time. self._current_notification_in = None # Skip the output sequence, for example to "pause" the process. if self._skip_output: if not self._output_queue.empty(): skip_output_queue = self._output_queue.get_blocking() del skip_output_queue return # Check if the queue is empty and stop if its empty. if not self._output_queue.empty(): current_output_array = self._output_queue.get_blocking() # Add another Array of LEDS for White Channel if "SK6812" in self._led_strip and len(current_output_array) == 3: current_output_array = np.vstack( (current_output_array, np.zeros(self._device.device_config["led_count"]))) self._current_output.show(current_output_array) self.end_time = time() if time() - self.ten_seconds_counter > 10: self.ten_seconds_counter = time() self.time_dif = self.end_time - self.start_time self.fps = 1 / self.time_dif self.logger.info( f'FPS: {self.fps:.2f} | Device: {self._device.device_config["device_name"]}' ) self.start_time = time() def stop(self): self._cancel_token = True self._current_output.clear() def refresh(self): self.logger.debug("Refreshing output...") # Refresh the config, self._config = self._device.config # Notify the master component, that I'm finished. self._device_notification_queue_out.put_blocking( NotificationEnum.config_refresh_finished) self.logger.debug("Output refreshed.")