From 89a7fd4b3f52ee375ecd3e44cefa48736e6c4996 Mon Sep 17 00:00:00 2001 From: wesley Date: Sat, 8 May 2021 00:58:15 -0300 Subject: [PATCH 1/2] Separe PlayCtrl in gui and functionality classes Previously playCtrl had part of gui handling, and functionality due to untoggle the play button when playback stops. Make play_once and play_many be just one function Before when many playbacks were needed, play_many was executed in its own thread and created a thread for play_once. But now just a "play_once" thread is created and it calls a playback how many times are needed --- atbswp/control.py | 100 ++++++++++++++++++++++++++++++++++++++++++++++ atbswp/gui.py | 2 +- 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/atbswp/control.py b/atbswp/control.py index 7282d8c..0959ece 100644 --- a/atbswp/control.py +++ b/atbswp/control.py @@ -348,6 +348,104 @@ def update_timer(self, event): self.timer = self.countdown_dialog.update_ui() +class PlayControl: + """Control class for playback functionality""" + + def __init__(self, count=1, infinite=False): + self.count = count + self.infinite = infinite + self._stop_locks = [True] + self._current_count = 0 + self._play_thread = None + + def _play(self, capture, append_function=None): + for line in capture: + if self.is_stoped(): break + exec(line) + self._current_count += 1 + if self._current_count < self.count or self.infinite \ + and not self.is_stoped(): + self._play(capture, append_function) + else: + self.stop() + if append_function: + append_function() + + def _start_thread(self, target, *args, daemon=False): + thread = Thread(target=target, args=(*args,)) + thread.daemon = daemon + thread.start() + return thread + + def set_config(self, count, infinite): + """Set the configuration to the next playback""" + self.count = count + self.infinite = infinite + + def get_current_count(self): + """Returns the current playback time""" + return self._current_count + + def is_stoped(self): + return self._stop_locks[0] + + def play(self, capture, append_function=None): + """Starts playback according with configs setted + + :param capture: list of commands to be executed + :param append_function: a function to be executed after + a playback + """ + self._stop_locks[0] = False + self._current_count = 0 + self._play_thread = self._start_thread(self._play, capture, + append_function) + + def stop(self): + self._stop_locks[0] = True + + +class PlayInterface: + def __init__(self): + self.play_ctrl = PlayControl() + self.capture = None + self._config_was_updated = False + self._toggle_button = None + + def _load_capture_file(self): + if TMP_PATH is None or not os.path.isfile(TMP_PATH): + wx.LogError("No capture loaded") + self._toggle_button.Value = False + return False + with open(TMP_PATH, 'r') as f: + self.capture = f.readlines() + return True + + def _set_config(self): + if self._config_was_updated: return + count = settings.CONFIG.getint('DEFAULT', 'Repeat Count') + infinite = settings.CONFIG.getboolean('DEFAULT', 'Infinite Playback') + self.play_ctrl.set_config(count, infinite) + self._config_was_updated = False + + def _stop(self): + self._toggle_button.Value = False + self.play_ctrl.stop() + self._config_was_updated = False + settings.save_config() + + def action(self, event): + self._toggle_button = event.GetEventObject() + self._toggle_button.Parent.panel.SetFocus() + if self._toggle_button.Value: + if self.play_ctrl.is_stoped(): + if not self._load_capture_file(): return + self._set_config() + self.play_ctrl.play(self.capture, self._stop) + else: + self._stop() + + class PlayCtrl: """Control class for the play button.""" @@ -527,3 +625,5 @@ def end(self): def ended(self): return self._end.isSet() + + diff --git a/atbswp/gui.py b/atbswp/gui.py index a2e19d8..fd2b1d6 100644 --- a/atbswp/gui.py +++ b/atbswp/gui.py @@ -203,7 +203,7 @@ def __add_bindings(self): self.Bind(wx.EVT_TOGGLEBUTTON, self.rbc.action, self.record_button) # play_button_ctrl - self.pbc = control.PlayCtrl() + self.pbc = control.PlayInterface() self.Bind(wx.EVT_TOGGLEBUTTON, self.pbc.action, self.play_button) # compile_button_ctrl From 6cd1dadfb3b8a6f5da91834cfc01d43ef0aebf68 Mon Sep 17 00:00:00 2001 From: wesley Date: Sat, 8 May 2021 14:17:57 -0300 Subject: [PATCH 2/2] Fix the playback hotkey not working to stop Due to the refactoring of PlayCtrl, the playback hotkey was not working because its event was still being handled according to the previous way. --- atbswp/control.py | 52 +---------------------------------------------- atbswp/gui.py | 13 +++++------- 2 files changed, 6 insertions(+), 59 deletions(-) diff --git a/atbswp/control.py b/atbswp/control.py index 0959ece..cc898f4 100644 --- a/atbswp/control.py +++ b/atbswp/control.py @@ -405,7 +405,7 @@ def stop(self): self._stop_locks[0] = True -class PlayInterface: +class PlayGui: def __init__(self): self.play_ctrl = PlayControl() self.capture = None @@ -446,56 +446,6 @@ def action(self, event): self._stop() -class PlayCtrl: - """Control class for the play button.""" - - global TMP_PATH - - def __init__(self): - self.count = settings.CONFIG.getint('DEFAULT', 'Repeat Count') - self.infinite = settings.CONFIG.getboolean('DEFAULT', 'Infinite Playback') - self.count_was_updated = False - - def play(self, capture, toggle_button): - """Play the loaded capture.""" - for line in capture: - if self.play_thread.ended(): - return - exec(line) - btn_event = wx.CommandEvent(wx.wxEVT_TOGGLEBUTTON) - btn_event.EventObject = toggle_button - if self.count <= 0 and not self.infinite: - toggle_button.Value = False - self.action(btn_event) - - def action(self, event): - """Replay a `count` number of time.""" - toggle_button = event.GetEventObject() - toggle_button.Parent.panel.SetFocus() - self.infinite = settings.CONFIG.getboolean('DEFAULT', 'Infinite Playback') - if toggle_button.Value: - if not self.count_was_updated: - self.count = settings.CONFIG.getint('DEFAULT', 'Repeat Count') - self.count_was_updated = True - if TMP_PATH is None or not os.path.isfile(TMP_PATH): - wx.LogError("No capture loaded") - toggle_button.Value = False - return - with open(TMP_PATH, 'r') as f: - capture = f.readlines() - if self.count > 0 or self.infinite: - self.count = self.count - 1 if not self.infinite else self.count - self.play_thread = PlayThread() - self.play_thread.daemon = True - self.play_thread = PlayThread(target=self.play, - args=(capture, toggle_button,)) - self.play_thread.start() - else: - self.play_thread.end() - self.count_was_updated = False - settings.save_config() - - class CompileCtrl: """Produce an executable Python bytecode file.""" diff --git a/atbswp/gui.py b/atbswp/gui.py index fd2b1d6..049d9e9 100644 --- a/atbswp/gui.py +++ b/atbswp/gui.py @@ -203,7 +203,7 @@ def __add_bindings(self): self.Bind(wx.EVT_TOGGLEBUTTON, self.rbc.action, self.record_button) # play_button_ctrl - self.pbc = control.PlayInterface() + self.pbc = control.PlayGui() self.Bind(wx.EVT_TOGGLEBUTTON, self.pbc.action, self.play_button) # compile_button_ctrl @@ -263,13 +263,10 @@ def on_key_press(self, event): self.rbc.action(btn_event) elif keycode == settings.CONFIG.getint('DEFAULT', 'Playback Hotkey'): - if not self.play_button.Value: - self.play_button.Value = True - btn_event = wx.CommandEvent(wx.wxEVT_TOGGLEBUTTON) - btn_event.EventObject = self.play_button - self.pbc.action(btn_event) - else: - self.play_button.Value = False + self.play_button.Value = not self.play_button.Value + btn_event = wx.CommandEvent(wx.wxEVT_TOGGLEBUTTON) + btn_event.EventObject = self.play_button + self.pbc.action(btn_event) elif keycode == ord("R") and event.CmdDown(): menu_event = wx.CommandEvent(wx.wxEVT_MENU)