X-Git-Url: https://git.immae.eu/?p=perso%2FImmae%2FProjets%2FPython%2FMusicSampler.git;a=blobdiff_plain;f=music_sampler%2Faction.py;h=bc62f33c7a24492757d8f801341351fb3b8b8770;hp=22a2bdc9feeb3231fa8a9c80f7b7d72f02c0d71a;hb=93a3e51e749afc0c3ba8488b900124fda6bb8774;hpb=6dc040edf2f31497d4492c159397c4634037be66 diff --git a/music_sampler/action.py b/music_sampler/action.py index 22a2bdc..bc62f33 100644 --- a/music_sampler/action.py +++ b/music_sampler/action.py @@ -9,8 +9,9 @@ class Action: 'failed', { 'name': 'loaded', - 'children': ['running'] - } + 'children': ['stopped', 'running'] + }, + 'destroyed' ] TRANSITIONS = [ @@ -21,36 +22,42 @@ class Action: }, { 'trigger': 'fail', - 'source': 'loading', + 'source': ['loading', 'loaded'], 'dest': 'failed', - 'after': 'poll_loaded' }, { 'trigger': 'success', 'source': 'loading', - 'dest': 'loaded', - 'after': 'poll_loaded' + 'dest': 'loaded_stopped', }, { - 'trigger': 'run', + 'trigger': 'reload', 'source': 'loaded', + 'dest': 'loading', + }, + { + 'trigger': 'run', + 'source': 'loaded_stopped', 'dest': 'loaded_running', 'after': 'finish_action', - # 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': 'finish_action', 'source': 'loaded_running', - 'dest': 'loaded' + 'dest': 'loaded_stopped' + }, + { + 'trigger': 'destroy', + 'source': '*', + 'dest': 'destroyed' } ] def __init__(self, action, key, **kwargs): Machine(model=self, states=self.STATES, transitions=self.TRANSITIONS, initial='initial', - ignore_invalid_triggers=True, queued=True) + ignore_invalid_triggers=True, queued=True, + after_state_change=self.notify_state_change) self.action = action self.key = key @@ -62,18 +69,31 @@ class Action: def is_loaded_or_failed(self): return self.is_loaded(allow_substates=True) or self.is_failed() - def callback_music_loaded(self, success): - if success: - self.success() - else: + def callback_music_state(self, new_state): + # If a music gets unloaded while the action is loaded_running and + # depending on the music, it won't be able to do the finish_action. + # Can that happen? + # a: play 'mp3'; + # z: wait 'mp3'; + # e: pause 'mp3'; + # r: stop 'mp3'; unload_music 'mp3' + if new_state == 'failed': self.fail() + elif self.is_loaded(allow_substates=True) and\ + new_state in ['initial', 'loading']: + self.reload(reloading=True) + elif self.is_loading() and new_state.startswith('loaded_'): + self.success() # Machine states / events - def on_enter_loading(self): + def on_enter_loading(self, reloading=False): + if reloading: + return if hasattr(actions, self.action): - if 'music' in self.arguments: - self.arguments['music'].subscribe_loaded( - self.callback_music_loaded) + if 'music' in self.arguments and\ + self.action not in ['unload_music', 'load_music']: + self.arguments['music'].subscribe_state_change( + self.callback_music_state) else: self.success() else: @@ -86,9 +106,13 @@ class Action: getattr(actions, self.action).run(self, key_start_time=key_start_time, **self.arguments) - def poll_loaded(self): - self.key.callback_action_ready(self, - self.is_loaded(allow_substates=True)) + def on_enter_destroyed(self): + if 'music' in self.arguments: + self.arguments['music'].unsubscribe_state_change( + self.callback_music_state) + + def notify_state_change(self, *args, **kwargs): + self.key.callback_action_state_changed() # This one cannot be in the Machine state since it would be queued to run # *after* the wait is ended...