X-Git-Url: https://git.immae.eu/?p=perso%2FImmae%2FProjets%2FPython%2FMusicSampler.git;a=blobdiff_plain;f=helpers%2Fmusic_file.py;h=ba8614204e030423c2aa71baca8b3f084143e759;hp=ccf60ce5eb8874f5b68dc81d48a89b9e86fd8626;hb=ab47d2a1269c20d70f42942c4295c056544491f4;hpb=205861936ca55357beea6a8af7c0c9ed5a61f484 diff --git a/helpers/music_file.py b/helpers/music_file.py index ccf60ce..ba86142 100644 --- a/helpers/music_file.py +++ b/helpers/music_file.py @@ -32,7 +32,8 @@ class MusicFile: { 'trigger': 'load', 'source': 'initial', - 'dest': 'loading' + 'dest': 'loading', + 'after': 'poll_loaded' }, { 'trigger': 'fail', @@ -47,7 +48,10 @@ class MusicFile: { 'trigger': 'start_playing', 'source': 'loaded', - 'dest': 'loaded_playing' + 'dest': 'loaded_playing', + # if a child has no transitions, then it is bubbled to the parent, + # and we don't want that. Not useful in that machine precisely. + 'conditions': ['is_loaded'] }, { 'trigger': 'pause', @@ -68,7 +72,8 @@ class MusicFile: 'trigger': 'stopped', 'source': '*', 'dest': 'loaded', - 'before': 'trigger_stopped_events' + 'before': 'trigger_stopped_events', + 'conditions': ['is_in_use'] } ] @@ -77,6 +82,7 @@ class MusicFile: transitions=self.TRANSITIONS, initial='initial', ignore_invalid_triggers=True) + self.loaded_callbacks = [] self.mapping = mapping self.filename = filename self.name = name or filename @@ -86,6 +92,31 @@ class MusicFile: threading.Thread(name="MSMusicLoad", target=self.load).start() + def reload_properties(self, name=None, gain=1): + self.name = name or self.filename + if gain != self.initial_volume_factor: + self.initial_volume_factor = gain + self.reload_music_file() + + def reload_music_file(self): + with file_lock: + try: + debug_print("Reloading « {} »".format(self.name)) + initial_db_gain = gain(self.initial_volume_factor * 100) + self.audio_segment = pydub.AudioSegment \ + .from_file(self.filename) \ + .set_frame_rate(Config.frame_rate) \ + .set_channels(Config.channels) \ + .set_sample_width(Config.sample_width) \ + .apply_gain(initial_db_gain) + except Exception as e: + error_print("failed to reload « {} »: {}"\ + .format(self.name, e)) + self.loading_error = e + self.to_failed() + else: + debug_print("Reloaded « {} »".format(self.name)) + # Machine related events def on_enter_loading(self): with file_lock: @@ -109,6 +140,9 @@ class MusicFile: debug_print("Loaded « {} »".format(self.name)) def on_enter_loaded(self): + self.cleanup() + + def cleanup(self): self.gain_effects = [] self.set_gain(0, absolute=True) self.current_audio_segment = None @@ -130,6 +164,7 @@ class MusicFile: def trigger_stopped_events(self): self.mixer.remove_file(self) self.wait_event.set() + self.cleanup() # Actions and properties called externally @property @@ -230,6 +265,22 @@ class MusicFile: self.wait_event.clear() self.wait_event.wait() + # Let other subscribe for an event when they are ready + def subscribe_loaded(self, callback): + # FIXME: should lock to be sure we have no race, but it makes the + # initialization screen not showing until everything is loaded + if self.is_loaded(allow_substates=True): + callback(True) + elif self.is_failed(): + callback(False) + else: + self.loaded_callbacks.append(callback) + + def poll_loaded(self): + for callback in self.loaded_callbacks: + callback(self.is_loaded()) + self.loaded_callbacks = [] + # Callbacks def finished_callback(self): self.stopped()