diff options
-rw-r--r-- | config.yml | 14 | ||||
-rw-r--r-- | helpers/__init__.py | 495 | ||||
-rw-r--r-- | music_sampler.py | 24 |
3 files changed, 346 insertions, 187 deletions
@@ -1,16 +1,11 @@ | |||
1 | aliases: | 1 | aliases: |
2 | jongle: | 2 | jongle: |
3 | file: "/home/sekhmet/bla/jongle.mp3" | 3 | file: "/home/immae/temp/Pirates/PIRATE_01-1-intro_jonglacro.mp3" |
4 | volume: 110 # pouvoir dire que "par défaut" la musique a un volume à 110% | 4 | volume: 110 # pouvoir dire que "par défaut" la musique a un volume à 110% |
5 | acros: | 5 | acros: |
6 | file: "/home/sekhmet/chemin/ultra/chiant/acros.mp3" | 6 | file: "../../temp/Pirates/PIRATE_01-2-jonglacro_suite.mp3" |
7 | 7 | ||
8 | keys: | 8 | keys: |
9 | 'bla': | ||
10 | - unknown: | ||
11 | include: "bla" | ||
12 | - play: | ||
13 | include: "coucou" | ||
14 | 'a': | 9 | 'a': |
15 | - play: | 10 | - play: |
16 | include: jongle | 11 | include: jongle |
@@ -20,16 +15,17 @@ keys: | |||
20 | - stop: | 15 | - stop: |
21 | include: jongle | 16 | include: jongle |
22 | - wait: | 17 | - wait: |
23 | time: 3 | 18 | duration: 3 |
24 | - play: | 19 | - play: |
25 | include: acros | 20 | include: acros |
26 | - wait: | 21 | - wait: |
27 | time: 10 | 22 | duration: 10 |
28 | - stop: | 23 | - stop: |
29 | include: acros | 24 | include: acros |
30 | fade_out: 10 | 25 | fade_out: 10 |
31 | 'ESC': | 26 | 'ESC': |
32 | - stop: ~ | 27 | - stop: ~ |
28 | - stop_all_actions: ~ | ||
33 | '-': | 29 | '-': |
34 | - volume: | 30 | - volume: |
35 | value: 90 | 31 | value: 90 |
diff --git a/helpers/__init__.py b/helpers/__init__.py index 7dbffdd..ec7da22 100644 --- a/helpers/__init__.py +++ b/helpers/__init__.py | |||
@@ -1,6 +1,11 @@ | |||
1 | # -*- coding: utf-8 -*- | 1 | # -*- coding: utf-8 -*- |
2 | from pygame import * | 2 | from pygame import * |
3 | import pydub | ||
3 | import sys | 4 | import sys |
5 | import time | ||
6 | import threading | ||
7 | |||
8 | draw_lock = threading.RLock() | ||
4 | 9 | ||
5 | class Action: | 10 | class Action: |
6 | action_types = [ | 11 | action_types = [ |
@@ -8,6 +13,7 @@ class Action: | |||
8 | 'pause', | 13 | 'pause', |
9 | 'play', | 14 | 'play', |
10 | 'stop', | 15 | 'stop', |
16 | 'stop_all_actions', | ||
11 | 'volume', | 17 | 'volume', |
12 | 'wait', | 18 | 'wait', |
13 | ] | 19 | ] |
@@ -20,49 +26,120 @@ class Action: | |||
20 | 26 | ||
21 | self.arguments = kwargs | 27 | self.arguments = kwargs |
22 | 28 | ||
23 | def run(self, callback): | 29 | def ready(self): |
24 | getattr(self, self.action)(callback, **self.arguments) | 30 | if 'music' in self.arguments: |
31 | return self.arguments['music'].loaded | ||
32 | else: | ||
33 | return True | ||
25 | 34 | ||
26 | def command(self, callback, command = "", **kwargs): | 35 | def run(self): |
27 | pass | 36 | print(getattr(self, self.action + "_print")(**self.arguments)) |
37 | return getattr(self, self.action)(**self.arguments) | ||
28 | 38 | ||
29 | def pause(self, callback, music = None, **kwargs): | 39 | def command(self, command = "", **kwargs): |
30 | pass | 40 | pass |
31 | 41 | ||
32 | def play(self, callback, | 42 | def pause(self, music = None, **kwargs): |
33 | music = None, | 43 | if music is not None: |
34 | fade_in = 0, | 44 | music.pause() |
35 | restart_if_running = False, | 45 | else: |
36 | volume = 100, | 46 | mixer.pause() |
37 | **kwargs): | ||
38 | pass | ||
39 | 47 | ||
40 | def stop(self, callback, music = None, fade_out = 0, **kwargs): | 48 | def play(self, music = None, fade_in = 0, start_at = 0, |
41 | print('stopping') | 49 | restart_if_running = False, volume = 100, **kwargs): |
42 | return callback() | 50 | if music is not None: |
51 | music.play() | ||
52 | else: | ||
53 | mixer.unpause() | ||
43 | 54 | ||
44 | def volume(self, callback, music = None, value = 100, **kwargs): | 55 | def stop(self, music = None, fade_out = 0, **kwargs): |
45 | pass | 56 | if music is not None: |
57 | music.stop() | ||
58 | else: | ||
59 | mixer.stop() | ||
60 | |||
61 | def stop_all_actions(self, **kwargs): | ||
62 | Key.running = [] | ||
46 | 63 | ||
47 | def wait(self, callback, time = 0, **kwargs): | 64 | def volume(self, music = None, value = 100, **kwargs): |
48 | pass | 65 | pass |
49 | 66 | ||
67 | def wait(self, duration = 0, **kwargs): | ||
68 | time.sleep(duration) | ||
69 | |||
70 | def command_print(self, command = "", **kwargs): | ||
71 | return "running command {}".format(command) | ||
72 | |||
73 | def pause_print(self, music = None, **kwargs): | ||
74 | if music is not None: | ||
75 | return "pausing {}".format(music.filename) | ||
76 | else: | ||
77 | return "pausing all musics" | ||
78 | |||
79 | def play_print(self, music = None, fade_in = 0, start_at = 0, | ||
80 | restart_if_running = False, volume = 100, **kwargs): | ||
81 | message = "starting " | ||
82 | if music is not None: | ||
83 | message += music.filename | ||
84 | else: | ||
85 | message += "music" | ||
86 | |||
87 | if start_at != 0: | ||
88 | message += " at {}s".format(start_at) | ||
89 | |||
90 | if fade_in != 0: | ||
91 | message += " with {}s fade_in".format(fade_in) | ||
92 | |||
93 | message += " at volume {}%".format(volume) | ||
94 | |||
95 | if restart_if_running: | ||
96 | message += " (restarting if already running)" | ||
97 | |||
98 | return message | ||
99 | |||
100 | def stop_print(self, music = None, fade_out = 0, **kwargs): | ||
101 | if music is not None: | ||
102 | if fade_out == 0: | ||
103 | return "stopping music {}".format(music.filename) | ||
104 | else: | ||
105 | return "stopping music {} with {}s fadeout".format(music.filename, fade_out) | ||
106 | else: | ||
107 | if fade_out == 0: | ||
108 | return "stopping all musics" | ||
109 | else: | ||
110 | return "stopping all musics with {}s fadeout".format(fade_out) | ||
111 | |||
112 | def stop_all_actions_print(self): | ||
113 | return "stopping all actions" | ||
114 | |||
115 | def volume_print(self, music = None, value = 100, *kwargs): | ||
116 | if music is not None: | ||
117 | return "setting volume of {} to {}%".format(music.filename, value) | ||
118 | else: | ||
119 | return "setting volume to {}%".format(value) | ||
120 | |||
121 | def wait_print(self, duration, **kwargs): | ||
122 | return "waiting {}s".format(duration) | ||
123 | |||
50 | class Key: | 124 | class Key: |
51 | row_positions = { | 125 | row_positions = { |
52 | 'first': 5, | 126 | 'first': 0, |
53 | 'second': 55, | 127 | 'second': 50, |
54 | 'third': 105, | 128 | 'third': 100, |
55 | 'fourth': 155, | 129 | 'fourth': 150, |
56 | 'fifth': 205, | 130 | 'fifth': 200, |
57 | 'sixth': 255, | 131 | 'sixth': 250, |
58 | } | 132 | } |
59 | 133 | ||
60 | default_outer_color = (120, 120, 120) | 134 | default_outer_color = (120, 120, 120) |
61 | lighter_outer_color = (200, 200, 200) | 135 | lighter_outer_color = (200, 200, 200) |
62 | default_inner_color = (255, 255, 255) | 136 | default_inner_color = (255, 255, 255) |
63 | mapped_inner_color = ( 0, 255, 0) | 137 | mapped_inner_color = ( 0, 255, 0) |
138 | mapped_unready_inner_color = (255, 165, 0) | ||
139 | running = [] | ||
64 | 140 | ||
65 | def __init__(self, key_name, key_sym, top, left, width = 48, height = 48, disabled = False): | 141 | def __init__(self, mapping, key_name, key_sym, top, left, width = 48, height = 48, disabled = False): |
142 | self.mapping = mapping | ||
66 | self.key_name = key_name | 143 | self.key_name = key_name |
67 | self.key_sym = key_sym | 144 | self.key_sym = key_sym |
68 | 145 | ||
@@ -91,9 +168,12 @@ class Key: | |||
91 | self.inner_color = self.default_inner_color | 168 | self.inner_color = self.default_inner_color |
92 | self.actions = [] | 169 | self.actions = [] |
93 | 170 | ||
94 | def square(self): | 171 | def square(self, all_actions_ready): |
95 | if self.has_action(): | 172 | if self.has_actions(): |
96 | self.inner_color = self.mapped_inner_color | 173 | if all_actions_ready: |
174 | self.inner_color = self.mapped_inner_color | ||
175 | else: | ||
176 | self.inner_color = self.mapped_unready_inner_color | ||
97 | 177 | ||
98 | return RoundedRect((0, 0, self.width, self.height), | 178 | return RoundedRect((0, 0, self.width, self.height), |
99 | self.outer_color, self.inner_color, self.linewidth) | 179 | self.outer_color, self.inner_color, self.linewidth) |
@@ -105,7 +185,10 @@ class Key: | |||
105 | ) | 185 | ) |
106 | 186 | ||
107 | def draw(self, background_surface): | 187 | def draw(self, background_surface): |
108 | self.surface = self.square().surface() | 188 | draw_lock.acquire() |
189 | all_actions_ready = self.all_actions_ready() | ||
190 | |||
191 | self.surface = self.square(all_actions_ready).surface() | ||
109 | 192 | ||
110 | if getattr(sys, 'frozen', False): | 193 | if getattr(sys, 'frozen', False): |
111 | police = font.Font(sys._MEIPASS + "/Ubuntu-Regular.ttf", 14) | 194 | police = font.Font(sys._MEIPASS + "/Ubuntu-Regular.ttf", 14) |
@@ -115,154 +198,229 @@ class Key: | |||
115 | text = police.render(self.key_sym, True, (0,0,0)) | 198 | text = police.render(self.key_sym, True, (0,0,0)) |
116 | self.surface.blit(text, (5,5)) | 199 | self.surface.blit(text, (5,5)) |
117 | background_surface.blit(self.surface, self.position) | 200 | background_surface.blit(self.surface, self.position) |
201 | draw_lock.release() | ||
202 | |||
203 | return not all_actions_ready | ||
118 | 204 | ||
119 | def has_action(self): | 205 | def poll_redraw(self, background): |
206 | while True: | ||
207 | time.sleep(1) | ||
208 | if self.all_actions_ready(): | ||
209 | self.draw(background) | ||
210 | self.mapping.blit() | ||
211 | break | ||
212 | |||
213 | def has_actions(self): | ||
120 | return len(self.actions) > 0 | 214 | return len(self.actions) > 0 |
121 | 215 | ||
216 | def all_actions_ready(self): | ||
217 | return all(action.ready() for action in self.actions) | ||
218 | |||
122 | def add_action(self, action_name, **arguments): | 219 | def add_action(self, action_name, **arguments): |
123 | self.actions.append(Action(action_name, **arguments)) | 220 | self.actions.append(Action(action_name, **arguments)) |
124 | 221 | ||
125 | def next_action(self): | ||
126 | print("running next action") | ||
127 | |||
128 | def do_actions(self): | 222 | def do_actions(self): |
129 | self.current_action = 0 | ||
130 | print("running actions for {}".format(self.key_sym)) | 223 | print("running actions for {}".format(self.key_sym)) |
131 | if len(self.actions) > 0: | 224 | Key.running.append(self) |
132 | self.actions[0].run(self.next_action) | 225 | for action in self.actions: |
226 | #FIXME: si on stop_all_actions et qu'on relance, "self" est de | ||
227 | #nouveau dans Key.running | ||
228 | if self in Key.running: | ||
229 | action.run() | ||
230 | |||
231 | if self in Key.running: | ||
232 | Key.running.remove(self) | ||
133 | 233 | ||
134 | def list_actions(self, surface): | 234 | def list_actions(self, surface): |
235 | # FIXME: Todo | ||
135 | print("bouh", self.key_sym) | 236 | print("bouh", self.key_sym) |
136 | surface.fill((255, 0, 0)) | 237 | surface.fill((255, 0, 0)) |
137 | 238 | ||
138 | def find_by_key_num(key_num): | 239 | |
139 | if key_num in Mapping.KEYS: | 240 | class Mapping: |
140 | return Mapping.KEYS[key_num] | 241 | WIDTH = 903 |
242 | HEIGHT = 298 | ||
243 | SIZE = WIDTH, HEIGHT | ||
244 | |||
245 | KEYS = [ | ||
246 | (K_ESCAPE, 'ESC', 'first', 0, {}), | ||
247 | |||
248 | (K_F1, 'F1', 'first', 100, {}), | ||
249 | (K_F2, 'F2', 'first', 150, {}), | ||
250 | (K_F3, 'F3', 'first', 200, {}), | ||
251 | (K_F4, 'F4', 'first', 250, {}), | ||
252 | |||
253 | (K_F5, 'F5', 'first', 325, {}), | ||
254 | (K_F6, 'F6', 'first', 375, {}), | ||
255 | (K_F7, 'F7', 'first', 425, {}), | ||
256 | (K_F8, 'F8', 'first', 475, {}), | ||
257 | |||
258 | (K_F9, 'F9', 'first', 550, {}), | ||
259 | (K_F10, 'F10', 'first', 600, {}), | ||
260 | (K_F11, 'F11', 'first', 650, {}), | ||
261 | (K_F12, 'F12', 'first', 700, {}), | ||
262 | |||
263 | |||
264 | (178, '²', 'second', 0, {}), | ||
265 | (K_AMPERSAND, '&', 'second', 50, {}), | ||
266 | (233, 'é', 'second', 100, {}), | ||
267 | (K_QUOTEDBL, '"', 'second', 150, {}), | ||
268 | (K_QUOTE, "'", 'second', 200, {}), | ||
269 | (K_LEFTPAREN, '(', 'second', 250, {}), | ||
270 | (K_MINUS, '-', 'second', 300, {}), | ||
271 | (232, 'è', 'second', 350, {}), | ||
272 | (K_UNDERSCORE, '_', 'second', 400, {}), | ||
273 | (231, 'ç', 'second', 450, {}), | ||
274 | (224, 'à', 'second', 500, {}), | ||
275 | (K_RIGHTPAREN, ')', 'second', 550, {}), | ||
276 | (K_EQUALS, '=', 'second', 600, {}), | ||
277 | |||
278 | (K_BACKSPACE, '<-', 'second', 650, { 'width': 98 }), | ||
279 | |||
280 | |||
281 | (K_TAB, 'tab', 'third', 0, { 'width' : 73 }), | ||
282 | (K_a, 'a', 'third', 75, {}), | ||
283 | (K_z, 'z', 'third', 125, {}), | ||
284 | (K_e, 'e', 'third', 175, {}), | ||
285 | (K_r, 'r', 'third', 225, {}), | ||
286 | (K_t, 't', 'third', 275, {}), | ||
287 | (K_y, 'y', 'third', 325, {}), | ||
288 | (K_u, 'u', 'third', 375, {}), | ||
289 | (K_i, 'i', 'third', 425, {}), | ||
290 | (K_o, 'o', 'third', 475, {}), | ||
291 | (K_p, 'p', 'third', 525, {}), | ||
292 | (K_CARET, '^', 'third', 575, {}), | ||
293 | (K_DOLLAR, '$', 'third', 625, {}), | ||
294 | |||
295 | (K_RETURN, 'Enter', 'third', 692, { 'width': 56, 'height': 98 }), | ||
296 | |||
297 | (K_CAPSLOCK, 'CAPS', 'fourth', 0, { 'width': 88, 'disabled': True }), | ||
298 | |||
299 | (K_q, 'q', 'fourth', 90, {}), | ||
300 | (K_s, 's', 'fourth', 140, {}), | ||
301 | (K_d, 'd', 'fourth', 190, {}), | ||
302 | (K_f, 'f', 'fourth', 240, {}), | ||
303 | (K_g, 'g', 'fourth', 290, {}), | ||
304 | (K_h, 'h', 'fourth', 340, {}), | ||
305 | (K_j, 'j', 'fourth', 390, {}), | ||
306 | (K_k, 'k', 'fourth', 440, {}), | ||
307 | (K_l, 'l', 'fourth', 490, {}), | ||
308 | (K_m, 'm', 'fourth', 540, {}), | ||
309 | (249, 'ù', 'fourth', 590, {}), | ||
310 | (K_ASTERISK, '*', 'fourth', 640, {}), | ||
311 | |||
312 | |||
313 | (K_LSHIFT, 'LShift', 'fifth', 0, { 'width': 63, 'disabled': True }), | ||
314 | |||
315 | (K_LESS, '<', 'fifth', 65, {}), | ||
316 | (K_w, 'w', 'fifth', 115, {}), | ||
317 | (K_x, 'x', 'fifth', 165, {}), | ||
318 | (K_c, 'c', 'fifth', 215, {}), | ||
319 | (K_v, 'v', 'fifth', 265, {}), | ||
320 | (K_b, 'b', 'fifth', 315, {}), | ||
321 | (K_n, 'n', 'fifth', 365, {}), | ||
322 | (K_COMMA, ',', 'fifth', 415, {}), | ||
323 | (K_SEMICOLON, ';', 'fifth', 465, {}), | ||
324 | (K_COLON, ':', 'fifth', 515, {}), | ||
325 | (K_EXCLAIM, '!', 'fifth', 565, {}), | ||
326 | |||
327 | (K_RSHIFT, 'RShift', 'fifth', 615, { 'width': 133, 'disabled': True }), | ||
328 | |||
329 | (K_LCTRL, 'LCtrl', 'sixth', 0, { 'width': 63, 'disabled': True }), | ||
330 | (K_LSUPER, 'LSuper', 'sixth', 115, { 'disabled': True }), | ||
331 | (K_LALT, 'LAlt', 'sixth', 165, { 'disabled': True }), | ||
332 | (K_SPACE, 'Espace', 'sixth', 215, { 'width': 248 }), | ||
333 | (K_MODE, 'AltGr', 'sixth', 465, { 'disabled': True }), | ||
334 | (314, 'Compose', 'sixth', 515, { 'disabled': True }), | ||
335 | (K_RCTRL, 'RCtrl', 'sixth', 565, { 'width': 63, 'disabled': True }), | ||
336 | |||
337 | |||
338 | (K_INSERT, 'ins', 'second', 755, {}), | ||
339 | (K_HOME, 'home', 'second', 805, {}), | ||
340 | (K_PAGEUP, 'pg_u', 'second', 855, {}), | ||
341 | (K_DELETE, 'del', 'third', 755, {}), | ||
342 | (K_END, 'end', 'third', 805, {}), | ||
343 | (K_PAGEDOWN, 'pg_d', 'third', 855, {}), | ||
344 | |||
345 | |||
346 | (K_UP, 'up', 'fifth', 805, {}), | ||
347 | (K_DOWN, 'down', 'sixth', 805, {}), | ||
348 | (K_LEFT, 'left', 'sixth', 755, {}), | ||
349 | (K_RIGHT, 'right', 'sixth', 855, {}), | ||
350 | ] | ||
351 | |||
352 | def __init__(self, screen): | ||
353 | self.screen = screen | ||
354 | self.background = Surface(self.SIZE).convert() | ||
355 | self.background.fill((250, 250, 250)) | ||
356 | self.keys = {} | ||
357 | for key in self.KEYS: | ||
358 | self.keys[key[0]] = Key(self, *key[0:4], **key[4]) | ||
359 | |||
360 | def draw(self): | ||
361 | for key_name in self.keys: | ||
362 | key = self.keys[key_name] | ||
363 | should_redraw_key = key.draw(self.background) | ||
364 | |||
365 | if should_redraw_key: | ||
366 | threading.Thread(target = key.poll_redraw, args = [self.background]).start() | ||
367 | self.blit() | ||
368 | |||
369 | def blit(self): | ||
370 | draw_lock.acquire() | ||
371 | self.screen.blit(self.background, (5, 5)) | ||
372 | display.flip() | ||
373 | draw_lock.release() | ||
374 | |||
375 | def find_by_key_num(self, key_num): | ||
376 | if key_num in self.keys: | ||
377 | return self.keys[key_num] | ||
141 | return None | 378 | return None |
142 | 379 | ||
143 | def find_by_collidepoint(position): | 380 | def find_by_collidepoint(self, position): |
144 | for key in Mapping.KEYS: | 381 | for key in self.keys: |
145 | if Mapping.KEYS[key].collidepoint(position): | 382 | if self.keys[key].collidepoint(position): |
146 | return Mapping.KEYS[key] | 383 | return self.keys[key] |
147 | return None | 384 | return None |
148 | 385 | ||
149 | def find_by_unicode(key_sym): | 386 | def find_by_unicode(self, key_sym): |
150 | for key in Mapping.KEYS: | 387 | for key in self.keys: |
151 | if Mapping.KEYS[key].key_sym == key_sym: | 388 | if self.keys[key].key_sym == key_sym: |
152 | return Mapping.KEYS[key] | 389 | return self.keys[key] |
153 | return None | 390 | return None |
154 | 391 | ||
155 | class Mapping: | 392 | |
156 | KEYS = { | ||
157 | K_ESCAPE: Key(K_ESCAPE, 'ESC', 'first', 0), | ||
158 | |||
159 | K_F1: Key(K_F1, 'F1', 'first', 100), | ||
160 | K_F2: Key(K_F2, 'F2', 'first', 150), | ||
161 | K_F3: Key(K_F3, 'F3', 'first', 200), | ||
162 | K_F4: Key(K_F4, 'F4', 'first', 250), | ||
163 | |||
164 | K_F5: Key(K_F5, 'F5', 'first', 325), | ||
165 | K_F6: Key(K_F6, 'F6', 'first', 375), | ||
166 | K_F7: Key(K_F7, 'F7', 'first', 425), | ||
167 | K_F8: Key(K_F8, 'F8', 'first', 475), | ||
168 | |||
169 | K_F9: Key(K_F9, 'F9', 'first', 550), | ||
170 | K_F10: Key(K_F10, 'F10', 'first', 600), | ||
171 | K_F11: Key(K_F11, 'F11', 'first', 650), | ||
172 | K_F12: Key(K_F12, 'F12', 'first', 700), | ||
173 | |||
174 | |||
175 | 178: Key(178, '²', 'second', 0), | ||
176 | K_AMPERSAND: Key(K_AMPERSAND, '&', 'second', 50), | ||
177 | 233: Key(233, 'é', 'second', 100), | ||
178 | K_QUOTEDBL: Key(K_QUOTEDBL, '"', 'second', 150), | ||
179 | K_QUOTE: Key(K_QUOTE, "'", 'second', 200), | ||
180 | K_LEFTPAREN: Key(K_LEFTPAREN, '(', 'second', 250), | ||
181 | K_MINUS: Key(K_MINUS, '-', 'second', 300), | ||
182 | 232: Key(232, 'è', 'second', 350), | ||
183 | K_UNDERSCORE: Key(K_UNDERSCORE, '_', 'second', 400), | ||
184 | 231: Key(231, 'ç', 'second', 450), | ||
185 | 224: Key(224, 'à', 'second', 500), | ||
186 | K_RIGHTPAREN: Key(K_RIGHTPAREN, ')', 'second', 550), | ||
187 | K_EQUALS: Key(K_EQUALS, '=', 'second', 600), | ||
188 | |||
189 | K_BACKSPACE: Key(K_BACKSPACE, '<-', 'second', 650, width = 98), | ||
190 | |||
191 | |||
192 | K_TAB: Key(K_TAB, 'tab', 'third', 0, width = 73), | ||
193 | K_a: Key(K_a, 'a', 'third', 75), | ||
194 | K_z: Key(K_z, 'z', 'third', 125), | ||
195 | K_e: Key(K_e, 'e', 'third', 175), | ||
196 | K_r: Key(K_r, 'r', 'third', 225), | ||
197 | K_t: Key(K_t, 't', 'third', 275), | ||
198 | K_y: Key(K_y, 'y', 'third', 325), | ||
199 | K_u: Key(K_u, 'u', 'third', 375), | ||
200 | K_i: Key(K_i, 'i', 'third', 425), | ||
201 | K_o: Key(K_o, 'o', 'third', 475), | ||
202 | K_p: Key(K_p, 'p', 'third', 525), | ||
203 | K_CARET: Key(K_CARET, '^', 'third', 575), | ||
204 | K_DOLLAR: Key(K_DOLLAR, '$', 'third', 625), | ||
205 | |||
206 | K_RETURN: Key(K_RETURN, 'Enter', 'third', 692, width = 56, height = 98), | ||
207 | |||
208 | K_CAPSLOCK: Key(K_CAPSLOCK, 'CAPS', 'fourth', 0, width = 88, disabled = True), | ||
209 | |||
210 | K_q: Key(K_q, 'q', 'fourth', 90), | ||
211 | K_s: Key(K_s, 's', 'fourth', 140), | ||
212 | K_d: Key(K_d, 'd', 'fourth', 190), | ||
213 | K_f: Key(K_f, 'f', 'fourth', 240), | ||
214 | K_g: Key(K_g, 'g', 'fourth', 290), | ||
215 | K_h: Key(K_h, 'h', 'fourth', 340), | ||
216 | K_j: Key(K_j, 'j', 'fourth', 390), | ||
217 | K_k: Key(K_k, 'k', 'fourth', 440), | ||
218 | K_l: Key(K_l, 'l', 'fourth', 490), | ||
219 | K_m: Key(K_m, 'm', 'fourth', 540), | ||
220 | 249: Key(249, 'ù', 'fourth', 590), | ||
221 | K_ASTERISK: Key(K_ASTERISK, '*', 'fourth', 640), | ||
222 | |||
223 | |||
224 | K_LSHIFT: Key(K_LSHIFT, 'LShift', 'fifth', 0, width = 63, disabled = True), | ||
225 | |||
226 | K_LESS: Key(K_LESS, '<', 'fifth', 65), | ||
227 | K_w: Key(K_w, 'w', 'fifth', 115), | ||
228 | K_x: Key(K_x, 'x', 'fifth', 165), | ||
229 | K_c: Key(K_c, 'c', 'fifth', 215), | ||
230 | K_v: Key(K_v, 'v', 'fifth', 265), | ||
231 | K_b: Key(K_b, 'b', 'fifth', 315), | ||
232 | K_n: Key(K_n, 'n', 'fifth', 365), | ||
233 | K_COMMA: Key(K_COMMA, ',', 'fifth', 415), | ||
234 | K_SEMICOLON: Key(K_SEMICOLON, ';', 'fifth', 465), | ||
235 | K_COLON: Key(K_COLON, ':', 'fifth', 515), | ||
236 | K_EXCLAIM: Key(K_EXCLAIM, '!', 'fifth', 565), | ||
237 | |||
238 | K_RSHIFT: Key(K_RSHIFT, 'RShift', 'fifth', 615, width = 133, disabled = True), | ||
239 | |||
240 | K_LCTRL: Key(K_LCTRL, 'LCtrl', 'sixth', 0, width = 63, disabled = True), | ||
241 | K_LSUPER: Key(K_LSUPER, 'LSuper', 'sixth', 115, disabled = True), | ||
242 | K_LALT: Key(K_LALT, 'LAlt', 'sixth', 165, disabled = True), | ||
243 | K_SPACE: Key(K_SPACE, 'Espace', 'sixth', 215, width = 248), | ||
244 | K_MODE: Key(K_MODE, 'AltGr', 'sixth', 465, disabled = True), | ||
245 | 314: Key(314, 'Compose', 'sixth', 515, disabled = True), | ||
246 | K_RCTRL: Key(K_RCTRL, 'RCtrl', 'sixth', 565, width = 63, disabled = True), | ||
247 | |||
248 | |||
249 | K_INSERT: Key(K_INSERT, 'ins', 'second', 755), | ||
250 | K_HOME: Key(K_HOME, 'home', 'second', 805), | ||
251 | K_PAGEUP: Key(K_PAGEUP, 'pg_u', 'second', 855), | ||
252 | K_DELETE: Key(K_DELETE, 'del', 'third', 755), | ||
253 | K_END: Key(K_END, 'end', 'third', 805), | ||
254 | K_PAGEDOWN: Key(K_PAGEDOWN, 'pg_d', 'third', 855), | ||
255 | |||
256 | |||
257 | K_UP: Key(K_UP, 'up', 'fifth', 805), | ||
258 | K_DOWN: Key(K_DOWN, 'down', 'sixth', 805), | ||
259 | K_LEFT: Key(K_LEFT, 'left', 'sixth', 755), | ||
260 | K_RIGHT: Key(K_RIGHT, 'right', 'sixth', 855), | ||
261 | } | ||
262 | 393 | ||
263 | class MusicFile: | 394 | class MusicFile: |
264 | def __init__(self, filename): | 395 | def __init__(self, filename, lock): |
265 | self.filename = filename | 396 | self.filename = filename |
397 | self.channel = None | ||
398 | self.raw_data = None | ||
399 | self.sound = None | ||
400 | |||
401 | self.loaded = False | ||
402 | threading.Thread(target = self.load_sound, args = [lock]).start() | ||
403 | |||
404 | def load_sound(self, lock): | ||
405 | lock.acquire() | ||
406 | print("Loading {}".format(self.filename)) | ||
407 | self.raw_data = pydub.AudioSegment.from_file(self.filename).raw_data | ||
408 | self.sound = mixer.Sound(self.raw_data) | ||
409 | print("Loaded {}".format(self.filename)) | ||
410 | self.loaded = True | ||
411 | lock.release() | ||
412 | |||
413 | def play(self): | ||
414 | self.channel = self.sound.play() | ||
415 | |||
416 | def pause(self): | ||
417 | if self.channel is not None: | ||
418 | self.channel.pause() | ||
419 | |||
420 | def stop(self): | ||
421 | self.channel = None | ||
422 | self.sound.stop() | ||
423 | |||
266 | 424 | ||
267 | class RoundedRect: | 425 | class RoundedRect: |
268 | def __init__(self, rect, outer_color, inner_color, linewidth = 2, radius = 0.4): | 426 | def __init__(self, rect, outer_color, inner_color, linewidth = 2, radius = 0.4): |
@@ -324,7 +482,7 @@ class RoundedRect: | |||
324 | return rectangle | 482 | return rectangle |
325 | 483 | ||
326 | 484 | ||
327 | def parse_config(): | 485 | def parse_config(mapping): |
328 | import yaml | 486 | import yaml |
329 | stream = open("config.yml", "r") | 487 | stream = open("config.yml", "r") |
330 | config = yaml.load(stream) | 488 | config = yaml.load(stream) |
@@ -333,8 +491,10 @@ def parse_config(): | |||
333 | aliases = config['aliases'] | 491 | aliases = config['aliases'] |
334 | seen_files = {} | 492 | seen_files = {} |
335 | 493 | ||
494 | file_lock = threading.RLock() | ||
495 | |||
336 | for mapped_key in config['keys']: | 496 | for mapped_key in config['keys']: |
337 | key = Key.find_by_unicode(mapped_key) | 497 | key = mapping.find_by_unicode(mapped_key) |
338 | if key is None: | 498 | if key is None: |
339 | continue | 499 | continue |
340 | 500 | ||
@@ -344,18 +504,21 @@ def parse_config(): | |||
344 | if action[action_name] is None: | 504 | if action[action_name] is None: |
345 | action[action_name] = [] | 505 | action[action_name] = [] |
346 | 506 | ||
507 | if 'include' in action[action_name]: | ||
508 | included = action[action_name]['include'] | ||
509 | del(action[action_name]['include']) | ||
510 | |||
511 | if isinstance(included, str): | ||
512 | action[action_name].update(aliases[included], **action[action_name]) | ||
513 | else: | ||
514 | for included_ in included: | ||
515 | action[action_name].update(aliases[included_], **action[action_name]) | ||
516 | |||
347 | for argument in action[action_name]: | 517 | for argument in action[action_name]: |
348 | if argument == 'include': | 518 | if argument == 'file': |
349 | included = action[action_name]['include'] | ||
350 | if isinstance(included, str): | ||
351 | action_args.update(aliases[included]) | ||
352 | else: | ||
353 | for included_ in included: | ||
354 | action_args.update(aliases[included_]) | ||
355 | elif argument == 'file': | ||
356 | filename = action[action_name]['file'] | 519 | filename = action[action_name]['file'] |
357 | if filename not in seen_files: | 520 | if filename not in seen_files: |
358 | seen_files[filename] = MusicFile.new(filename) | 521 | seen_files[filename] = MusicFile(filename, file_lock) |
359 | 522 | ||
360 | action_args['music'] = seen_files[filename] | 523 | action_args['music'] = seen_files[filename] |
361 | 524 | ||
diff --git a/music_sampler.py b/music_sampler.py index 7933d50..6cc49df 100644 --- a/music_sampler.py +++ b/music_sampler.py | |||
@@ -1,30 +1,29 @@ | |||
1 | import sys | 1 | import sys |
2 | import pygame | 2 | import pygame |
3 | import pydub | ||
4 | import helpers | 3 | import helpers |
4 | import threading | ||
5 | 5 | ||
6 | pygame.mixer.pre_init(frequency = 44100) | 6 | pygame.mixer.pre_init(frequency = 44100) |
7 | pygame.init() | 7 | pygame.init() |
8 | 8 | ||
9 | size = width, height = 1024, 600 | 9 | size = width, height = 1024, 600 |
10 | 10 | ||
11 | helpers.draw_lock.acquire() | ||
11 | screen = pygame.display.set_mode(size) | 12 | screen = pygame.display.set_mode(size) |
12 | background = pygame.Surface(screen.get_size()) | 13 | mapping = helpers.Mapping(screen) |
13 | background = background.convert() | ||
14 | background.fill((250, 250, 250)) | ||
15 | 14 | ||
16 | action_surface = pygame.Surface((600, 250)).convert() | 15 | action_surface = pygame.Surface((600, 250)).convert() |
17 | action_surface.fill((0,0,0)) | 16 | action_surface.fill((0,0,0)) |
18 | helpers.parse_config() | 17 | helpers.parse_config(mapping) |
18 | helpers.draw_lock.release() | ||
19 | 19 | ||
20 | for key_name in helpers.Mapping.KEYS: | 20 | mapping.draw() |
21 | key = helpers.Mapping.KEYS[key_name] | ||
22 | key.draw(background) | ||
23 | 21 | ||
24 | screen.blit(background, (0, 0)) | 22 | helpers.draw_lock.acquire() |
25 | screen.blit(action_surface, (10, 330)) | 23 | screen.blit(action_surface, (10, 330)) |
26 | 24 | ||
27 | pygame.display.flip() | 25 | pygame.display.flip() |
26 | helpers.draw_lock.release() | ||
28 | 27 | ||
29 | contexts = [ | 28 | contexts = [ |
30 | 'normal' | 29 | 'normal' |
@@ -34,6 +33,7 @@ context = 'normal' | |||
34 | 33 | ||
35 | while 1: | 34 | while 1: |
36 | event = pygame.event.wait() | 35 | event = pygame.event.wait() |
36 | |||
37 | if event.type == pygame.QUIT or ( | 37 | if event.type == pygame.QUIT or ( |
38 | event.type == pygame.KEYDOWN and | 38 | event.type == pygame.KEYDOWN and |
39 | event.mod == 4160 and | 39 | event.mod == 4160 and |
@@ -43,11 +43,11 @@ while 1: | |||
43 | 43 | ||
44 | if context == 'normal': | 44 | if context == 'normal': |
45 | if event.type == pygame.KEYDOWN: | 45 | if event.type == pygame.KEYDOWN: |
46 | key = helpers.Key.find_by_key_num(event.key) | 46 | key = mapping.find_by_key_num(event.key) |
47 | if key is not None: | 47 | if key is not None: |
48 | key.do_actions() | 48 | threading.Thread(target=key.do_actions).start() |
49 | elif event.type == pygame.MOUSEBUTTONUP: | 49 | elif event.type == pygame.MOUSEBUTTONUP: |
50 | key = helpers.Key.find_by_collidepoint(pygame.mouse.get_pos()) | 50 | key = mapping.find_by_collidepoint(pygame.mouse.get_pos()) |
51 | if key is not None: | 51 | if key is not None: |
52 | key.list_actions(action_surface) | 52 | key.list_actions(action_surface) |
53 | 53 | ||