aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2016-07-14 15:39:54 +0200
committerIsmaël Bouya <ismael.bouya@normalesup.org>2016-07-14 15:39:54 +0200
commit0deb82a57ae3abefd44509dc88c546f6e5a94d1b (patch)
treecf082f141a89425f9014eb5b203336e49f5c0252
parentecaf3148af1d9adff1819f9536f483ebf7c85a95 (diff)
downloadMusicSampler-0deb82a57ae3abefd44509dc88c546f6e5a94d1b.tar.gz
MusicSampler-0deb82a57ae3abefd44509dc88c546f6e5a94d1b.tar.zst
MusicSampler-0deb82a57ae3abefd44509dc88c546f6e5a94d1b.zip
Make 'wait' action interruptible
-rw-r--r--helpers/action.py38
-rw-r--r--helpers/key.py7
-rw-r--r--helpers/mapping.py3
-rw-r--r--helpers/music_file.py9
4 files changed, 43 insertions, 14 deletions
diff --git a/helpers/action.py b/helpers/action.py
index 69ae96f..9145629 100644
--- a/helpers/action.py
+++ b/helpers/action.py
@@ -1,4 +1,4 @@
1import pygame 1import threading
2import time 2import time
3 3
4class Action: 4class Action:
@@ -21,6 +21,7 @@ class Action:
21 21
22 self.key = key 22 self.key = key
23 self.arguments = kwargs 23 self.arguments = kwargs
24 self.sleep_event = None
24 25
25 def ready(self): 26 def ready(self):
26 if 'music' in self.arguments: 27 if 'music' in self.arguments:
@@ -35,7 +36,13 @@ class Action:
35 def description(self): 36 def description(self):
36 return getattr(self, self.action + "_print")(**self.arguments) 37 return getattr(self, self.action + "_print")(**self.arguments)
37 38
39 def interrupt(self):
40 if getattr(self, self.action + "_interrupt", None):
41 return getattr(self, self.action + "_interrupt")(**self.arguments)
42
43 # Actions
38 def command(self, command = "", **kwargs): 44 def command(self, command = "", **kwargs):
45 # FIXME: todo
39 pass 46 pass
40 47
41 def music_list(self, music): 48 def music_list(self, music):
@@ -81,14 +88,15 @@ class Action:
81 pass 88 pass
82 89
83 def wait(self, duration = 0, music = None, **kwargs): 90 def wait(self, duration = 0, music = None, **kwargs):
84 # FIXME: Make it stoppable 91 self.sleep_event = threading.Event()
85 # http://stackoverflow.com/questions/29082268/python-time-sleep-vs-event-wait 92
86 if music is None: 93 if music is not None:
87 time.sleep(duration)
88 else:
89 # TODO
90 music.wait_end() 94 music.wait_end()
91 95
96 threading.Timer(duration, self.sleep_event.set).start()
97 self.sleep_event.wait()
98
99 # Action messages
92 def command_print(self, command = "", **kwargs): 100 def command_print(self, command = "", **kwargs):
93 return "running command {}".format(command) 101 return "running command {}".format(command)
94 102
@@ -146,7 +154,19 @@ class Action:
146 else: 154 else:
147 return "setting volume to {}%".format(value) 155 return "setting volume to {}%".format(value)
148 156
149 def wait_print(self, duration, **kwargs): 157 def wait_print(self, duration = 0, music = None, **kwargs):
150 return "waiting {}s".format(duration) 158 if music is None:
159 return "waiting {}s".format(duration)
160 elif duration == 0:
161 return "waiting the end of « {} »".format(music.name)
162 else:
163 return "waiting the end of « {} » + {}s".format(music.name, duration)
151 164
152 165
166 # Interruptions
167 def wait_interrupt(self, duration = 0, music = None, **kwargs):
168 if self.sleep_event is not None:
169 self.sleep_event.set()
170 if music is not None:
171 music.wait_event.set()
172
diff --git a/helpers/key.py b/helpers/key.py
index ca73b87..5eaf481 100644
--- a/helpers/key.py
+++ b/helpers/key.py
@@ -79,6 +79,9 @@ class Key(ButtonBehavior, Widget):
79 def add_action(self, action_name, **arguments): 79 def add_action(self, action_name, **arguments):
80 self.actions.append(Action(action_name, self, **arguments)) 80 self.actions.append(Action(action_name, self, **arguments))
81 81
82 def interrupt_action(self):
83 self.current_action.interrupt()
84
82 def do_actions(self): 85 def do_actions(self):
83 if not self.enabled: 86 if not self.enabled:
84 return None 87 return None
@@ -88,10 +91,10 @@ class Key(ButtonBehavior, Widget):
88 start_time = time.time() 91 start_time = time.time()
89 self.parent.start_running(self, start_time) 92 self.parent.start_running(self, start_time)
90 action_number = 0 93 action_number = 0
91 for action in self.actions: 94 for self.current_action in self.actions:
92 if self.parent.keep_running(self, start_time): 95 if self.parent.keep_running(self, start_time):
93 self.list_actions(action_number = action_number + 0.5) 96 self.list_actions(action_number = action_number + 0.5)
94 action.run() 97 self.current_action.run()
95 action_number += 1 98 action_number += 1
96 self.list_actions(action_number = action_number) 99 self.list_actions(action_number = action_number)
97 100
diff --git a/helpers/mapping.py b/helpers/mapping.py
index 95c9d67..ea9d075 100644
--- a/helpers/mapping.py
+++ b/helpers/mapping.py
@@ -65,7 +65,10 @@ class Mapping(RelativeLayout):
65 return False 65 return False
66 66
67 def stop_all_running(self): 67 def stop_all_running(self):
68 running = self.running
68 self.running = [] 69 self.running = []
70 for (key, start_time) in running:
71 key.interrupt_action()
69 72
70 def start_running(self, key, start_time): 73 def start_running(self, key, start_time):
71 self.running.append((key, start_time)) 74 self.running.append((key, start_time))
diff --git a/helpers/music_file.py b/helpers/music_file.py
index b40de1a..e6a340d 100644
--- a/helpers/music_file.py
+++ b/helpers/music_file.py
@@ -40,8 +40,8 @@ class MusicFile(Machine):
40 self.audio_segment = None 40 self.audio_segment = None
41 self.gain = gain 41 self.gain = gain
42 self.music_lock = Lock("music__" + filename) 42 self.music_lock = Lock("music__" + filename)
43 self.wait_event = threading.Event()
43 44
44 self.flag_paused = False
45 threading.Thread(name = "MSMusicLoad", target = self.load).start() 45 threading.Thread(name = "MSMusicLoad", target = self.load).start()
46 46
47 def on_enter_loading(self): 47 def on_enter_loading(self):
@@ -109,6 +109,9 @@ class MusicFile(Machine):
109 if self.is_loaded_stopping(): 109 if self.is_loaded_stopping():
110 self.stopped() 110 self.stopped()
111 111
112 def on_enter_loaded_stopped(self):
113 self.wait_event.set()
114
112 def play_callback(self, out_data, frame_count, time_info, status_flags): 115 def play_callback(self, out_data, frame_count, time_info, status_flags):
113 with self.music_lock: 116 with self.music_lock:
114 audio_segment = self.current_audio_segment.get_sample_slice_data( 117 audio_segment = self.current_audio_segment.get_sample_slice_data(
@@ -147,8 +150,8 @@ class MusicFile(Machine):
147 return 20 * math.log10(max(volume, 0.0001) / 100) 150 return 20 * math.log10(max(volume, 0.0001) / 100)
148 151
149 def wait_end(self): 152 def wait_end(self):
150 # FIXME: todo 153 self.wait_event.clear()
151 pass 154 self.wait_event.wait()
152 155
153# Add some more functions to AudioSegments 156# Add some more functions to AudioSegments
154def get_sample_slice_data(self, start_sample=0, end_sample=float('inf')): 157def get_sample_slice_data(self, start_sample=0, end_sample=float('inf')):