]> git.immae.eu Git - perso/Immae/Projets/Python/MusicSampler.git/commitdiff
Modifications to mapping/keys
authorIsmaël Bouya <ismael.bouya@normalesup.org>
Fri, 17 Jun 2016 22:29:15 +0000 (00:29 +0200)
committerIsmaël Bouya <ismael.bouya@normalesup.org>
Fri, 17 Jun 2016 22:29:15 +0000 (00:29 +0200)
config.yml
helpers/__init__.py
music_sampler.py

index 1384c925d0d9f5d4dc951be94522f610a1c96010..11251b21bda8ccec380e62b5a754b0eef217147a 100644 (file)
@@ -1,16 +1,11 @@
 aliases:
   jongle:
-    file: "/home/sekhmet/bla/jongle.mp3"
+    file: "/home/immae/temp/Pirates/PIRATE_01-1-intro_jonglacro.mp3"
     volume: 110 # pouvoir dire que "par défaut" la musique a un volume à 110%
   acros:
-    file: "/home/sekhmet/chemin/ultra/chiant/acros.mp3"
+    file: "../../temp/Pirates/PIRATE_01-2-jonglacro_suite.mp3"
 
 keys:
-  'bla':
-    - unknown:
-        include: "bla"
-    - play:
-        include: "coucou"
   'a':
     - play:
         include: jongle
@@ -20,16 +15,17 @@ keys:
     - stop:
         include: jongle
     - wait:
-        time: 3
+        duration: 3
     - play:
         include: acros
     - wait:
-        time: 10
+        duration: 10
     - stop:
         include: acros
         fade_out: 10
   'ESC':
     - stop: ~
+    - stop_all_actions: ~
   '-':
     - volume:
         value: 90
index 7dbffdd1641c34f960d53512a624efec38251ffc..ec7da22f4397f44fe28d2333c29dac223b317e3d 100644 (file)
@@ -1,6 +1,11 @@
 # -*- coding: utf-8 -*-
 from pygame import *
+import pydub
 import sys
+import time
+import threading
+
+draw_lock = threading.RLock()
 
 class Action:
     action_types = [
@@ -8,6 +13,7 @@ class Action:
         'pause',
         'play',
         'stop',
+        'stop_all_actions',
         'volume',
         'wait',
     ]
@@ -20,49 +26,120 @@ class Action:
 
         self.arguments = kwargs
 
-    def run(self, callback):
-        getattr(self, self.action)(callback, **self.arguments)
+    def ready(self):
+        if 'music' in self.arguments:
+            return self.arguments['music'].loaded
+        else:
+            return True
 
-    def command(self, callback, command = "", **kwargs):
-        pass
+    def run(self):
+        print(getattr(self, self.action + "_print")(**self.arguments))
+        return getattr(self, self.action)(**self.arguments)
 
-    def pause(self, callback, music = None, **kwargs):
+    def command(self, command = "", **kwargs):
         pass
 
-    def play(self, callback,
-            music = None,
-            fade_in = 0,
-            restart_if_running = False,
-            volume = 100,
-            **kwargs):
-        pass
+    def pause(self, music = None, **kwargs):
+        if music is not None:
+            music.pause()
+        else:
+            mixer.pause()
 
-    def stop(self, callback, music = None, fade_out = 0, **kwargs):
-        print('stopping')
-        return callback()
+    def play(self, music = None, fade_in = 0, start_at = 0,
+            restart_if_running = False, volume = 100, **kwargs):
+        if music is not None:
+            music.play()
+        else:
+            mixer.unpause()
 
-    def volume(self, callback, music = None, value = 100, **kwargs):
-        pass
+    def stop(self, music = None, fade_out = 0, **kwargs):
+        if music is not None:
+            music.stop()
+        else:
+            mixer.stop()
+
+    def stop_all_actions(self, **kwargs):
+        Key.running = []
 
-    def wait(self, callback, time = 0, **kwargs):
+    def volume(self, music = None, value = 100, **kwargs):
         pass
 
+    def wait(self, duration = 0, **kwargs):
+        time.sleep(duration)
+
+    def command_print(self, command = "", **kwargs):
+        return "running command {}".format(command)
+
+    def pause_print(self, music = None, **kwargs):
+        if music is not None:
+            return "pausing {}".format(music.filename)
+        else:
+            return "pausing all musics"
+
+    def play_print(self, music = None, fade_in = 0, start_at = 0,
+            restart_if_running = False, volume = 100, **kwargs):
+        message = "starting "
+        if music is not None:
+            message += music.filename
+        else:
+            message += "music"
+
+        if start_at != 0:
+            message += " at {}s".format(start_at)
+
+        if fade_in != 0:
+            message += " with {}s fade_in".format(fade_in)
+
+        message += " at volume {}%".format(volume)
+
+        if restart_if_running:
+            message += " (restarting if already running)"
+
+        return message
+
+    def stop_print(self, music = None, fade_out = 0, **kwargs):
+        if music is not None:
+            if fade_out == 0:
+                return "stopping music {}".format(music.filename)
+            else:
+                return "stopping music {} with {}s fadeout".format(music.filename, fade_out)
+        else:
+            if fade_out == 0:
+                return "stopping all musics"
+            else:
+                return "stopping all musics with {}s fadeout".format(fade_out)
+
+    def stop_all_actions_print(self):
+        return "stopping all actions"
+
+    def volume_print(self, music = None, value = 100, *kwargs):
+        if music is not None:
+            return "setting volume of {} to {}%".format(music.filename, value)
+        else:
+            return "setting volume to {}%".format(value)
+
+    def wait_print(self, duration, **kwargs):
+        return "waiting {}s".format(duration)
+
 class Key:
     row_positions = {
-        'first':    5,
-        'second':  55,
-        'third':  105,
-        'fourth': 155,
-        'fifth':  205,
-        'sixth':  255,
+        'first':    0,
+        'second':  50,
+        'third':  100,
+        'fourth': 150,
+        'fifth':  200,
+        'sixth':  250,
     }
 
     default_outer_color = (120, 120, 120)
     lighter_outer_color = (200, 200, 200)
     default_inner_color = (255, 255, 255)
     mapped_inner_color  = (  0, 255,   0)
+    mapped_unready_inner_color = (255, 165, 0)
+    running = []
 
-    def __init__(self, key_name, key_sym, top, left, width = 48, height = 48, disabled = False):
+    def __init__(self, mapping, key_name, key_sym, top, left, width = 48, height = 48, disabled = False):
+        self.mapping = mapping
         self.key_name = key_name
         self.key_sym  = key_sym
 
@@ -91,9 +168,12 @@ class Key:
         self.inner_color = self.default_inner_color
         self.actions = []
 
-    def square(self):
-        if self.has_action():
-            self.inner_color = self.mapped_inner_color
+    def square(self, all_actions_ready):
+        if self.has_actions():
+            if all_actions_ready:
+                self.inner_color = self.mapped_inner_color
+            else:
+                self.inner_color = self.mapped_unready_inner_color
 
         return RoundedRect((0, 0, self.width, self.height),
             self.outer_color, self.inner_color, self.linewidth)
@@ -105,7 +185,10 @@ class Key:
                 )
 
     def draw(self, background_surface):
-        self.surface = self.square().surface()
+        draw_lock.acquire()
+        all_actions_ready = self.all_actions_ready()
+
+        self.surface = self.square(all_actions_ready).surface()
 
         if getattr(sys, 'frozen', False):
             police = font.Font(sys._MEIPASS + "/Ubuntu-Regular.ttf", 14)
@@ -115,154 +198,229 @@ class Key:
         text = police.render(self.key_sym, True, (0,0,0))
         self.surface.blit(text, (5,5))
         background_surface.blit(self.surface, self.position)
+        draw_lock.release()
+
+        return not all_actions_ready
 
-    def has_action(self):
+    def poll_redraw(self, background):
+        while True:
+            time.sleep(1)
+            if self.all_actions_ready():
+                self.draw(background)
+                self.mapping.blit()
+                break
+
+    def has_actions(self):
         return len(self.actions) > 0
 
+    def all_actions_ready(self):
+        return all(action.ready() for action in self.actions)
+
     def add_action(self, action_name, **arguments):
         self.actions.append(Action(action_name, **arguments))
 
-    def next_action(self):
-        print("running next action")
-
     def do_actions(self):
-        self.current_action = 0
         print("running actions for {}".format(self.key_sym))
-        if len(self.actions) > 0:
-            self.actions[0].run(self.next_action)
+        Key.running.append(self)
+        for action in self.actions:
+            #FIXME: si on stop_all_actions et qu'on relance, "self" est de
+            #nouveau dans Key.running
+            if self in Key.running:
+                action.run()
+
+        if self in Key.running:
+            Key.running.remove(self)
 
     def list_actions(self, surface):
+        # FIXME: Todo
         print("bouh", self.key_sym)
         surface.fill((255, 0, 0))
 
-    def find_by_key_num(key_num):
-        if key_num in Mapping.KEYS:
-            return Mapping.KEYS[key_num]
+
+class Mapping:
+    WIDTH  = 903
+    HEIGHT = 298
+    SIZE   = WIDTH, HEIGHT
+
+    KEYS = [
+        (K_ESCAPE, 'ESC', 'first',   0, {}),
+
+        (K_F1,     'F1',  'first', 100, {}),
+        (K_F2,     'F2',  'first', 150, {}),
+        (K_F3,     'F3',  'first', 200, {}),
+        (K_F4,     'F4',  'first', 250, {}),
+
+        (K_F5,     'F5',  'first', 325, {}),
+        (K_F6,     'F6',  'first', 375, {}),
+        (K_F7,     'F7',  'first', 425, {}),
+        (K_F8,     'F8',  'first', 475, {}),
+
+        (K_F9,     'F9',  'first', 550, {}),
+        (K_F10,    'F10', 'first', 600, {}),
+        (K_F11,    'F11', 'first', 650, {}),
+        (K_F12,    'F12', 'first', 700, {}),
+
+
+        (178,          '²', 'second',   0, {}),
+        (K_AMPERSAND,  '&', 'second',  50, {}),
+        (233,          'é', 'second', 100, {}),
+        (K_QUOTEDBL,   '"', 'second', 150, {}),
+        (K_QUOTE,      "'", 'second', 200, {}),
+        (K_LEFTPAREN,  '(', 'second', 250, {}),
+        (K_MINUS,      '-', 'second', 300, {}),
+        (232,          'è', 'second', 350, {}),
+        (K_UNDERSCORE, '_', 'second', 400, {}),
+        (231,          'ç', 'second', 450, {}),
+        (224,          'à', 'second', 500, {}),
+        (K_RIGHTPAREN, ')', 'second', 550, {}),
+        (K_EQUALS,     '=', 'second', 600, {}),
+
+        (K_BACKSPACE,  '<-', 'second', 650, { 'width': 98 }),
+
+
+        (K_TAB,        'tab', 'third',   0, { 'width' : 73 }),
+        (K_a,          'a',   'third',  75, {}),
+        (K_z,          'z',   'third', 125, {}),
+        (K_e,          'e',   'third', 175, {}),
+        (K_r,          'r',   'third', 225, {}),
+        (K_t,          't',   'third', 275, {}),
+        (K_y,          'y',   'third', 325, {}),
+        (K_u,          'u',   'third', 375, {}),
+        (K_i,          'i',   'third', 425, {}),
+        (K_o,          'o',   'third', 475, {}),
+        (K_p,          'p',   'third', 525, {}),
+        (K_CARET,      '^',   'third', 575, {}),
+        (K_DOLLAR,     '$',   'third', 625, {}),
+
+        (K_RETURN, 'Enter', 'third', 692, { 'width': 56, 'height': 98 }),
+
+        (K_CAPSLOCK,    'CAPS', 'fourth',  0, { 'width': 88, 'disabled': True }),
+
+        (K_q,        'q', 'fourth',  90, {}),
+        (K_s,        's', 'fourth', 140, {}),
+        (K_d,        'd', 'fourth', 190, {}),
+        (K_f,        'f', 'fourth', 240, {}),
+        (K_g,        'g', 'fourth', 290, {}),
+        (K_h,        'h', 'fourth', 340, {}),
+        (K_j,        'j', 'fourth', 390, {}),
+        (K_k,        'k', 'fourth', 440, {}),
+        (K_l,        'l', 'fourth', 490, {}),
+        (K_m,        'm', 'fourth', 540, {}),
+        (249,        'ù', 'fourth', 590, {}),
+        (K_ASTERISK, '*', 'fourth', 640, {}),
+
+
+        (K_LSHIFT, 'LShift', 'fifth', 0, { 'width': 63, 'disabled': True }),
+
+        (K_LESS,      '<', 'fifth',  65, {}),
+        (K_w,         'w', 'fifth', 115, {}),
+        (K_x,         'x', 'fifth', 165, {}),
+        (K_c,         'c', 'fifth', 215, {}),
+        (K_v,         'v', 'fifth', 265, {}),
+        (K_b,         'b', 'fifth', 315, {}),
+        (K_n,         'n', 'fifth', 365, {}),
+        (K_COMMA,     ',', 'fifth', 415, {}),
+        (K_SEMICOLON, ';', 'fifth', 465, {}),
+        (K_COLON,     ':', 'fifth', 515, {}),
+        (K_EXCLAIM,   '!', 'fifth', 565, {}),
+
+        (K_RSHIFT, 'RShift', 'fifth', 615, { 'width': 133, 'disabled': True }),
+
+        (K_LCTRL,    'LCtrl',   'sixth',   0, { 'width': 63, 'disabled': True }),
+        (K_LSUPER,   'LSuper',  'sixth', 115, { 'disabled': True }),
+        (K_LALT,     'LAlt',    'sixth', 165, { 'disabled': True }),
+        (K_SPACE,    'Espace',  'sixth', 215, { 'width': 248 }),
+        (K_MODE,     'AltGr',   'sixth', 465, { 'disabled': True }),
+        (314,        'Compose', 'sixth', 515, { 'disabled': True }),
+        (K_RCTRL,    'RCtrl',   'sixth', 565, { 'width': 63, 'disabled': True }),
+
+
+        (K_INSERT,   'ins',  'second', 755, {}),
+        (K_HOME,     'home', 'second', 805, {}),
+        (K_PAGEUP,   'pg_u', 'second', 855, {}),
+        (K_DELETE,   'del',  'third',  755, {}),
+        (K_END,      'end',  'third',  805, {}),
+        (K_PAGEDOWN, 'pg_d', 'third',  855, {}),
+
+
+        (K_UP,       'up',    'fifth',  805, {}),
+        (K_DOWN,     'down',  'sixth',  805, {}),
+        (K_LEFT,     'left',  'sixth',  755, {}),
+        (K_RIGHT,    'right', 'sixth',  855, {}),
+    ]
+
+    def __init__(self, screen):
+        self.screen = screen
+        self.background = Surface(self.SIZE).convert()
+        self.background.fill((250, 250, 250))
+        self.keys = {}
+        for key in self.KEYS:
+            self.keys[key[0]] = Key(self, *key[0:4], **key[4])
+
+    def draw(self):
+        for key_name in self.keys:
+            key = self.keys[key_name]
+            should_redraw_key = key.draw(self.background)
+
+            if should_redraw_key:
+                threading.Thread(target = key.poll_redraw, args = [self.background]).start()
+        self.blit()
+
+    def blit(self):
+        draw_lock.acquire()
+        self.screen.blit(self.background, (5, 5))
+        display.flip()
+        draw_lock.release()
+
+    def find_by_key_num(self, key_num):
+        if key_num in self.keys:
+            return self.keys[key_num]
         return None
 
-    def find_by_collidepoint(position):
-        for key in Mapping.KEYS:
-            if Mapping.KEYS[key].collidepoint(position):
-                return Mapping.KEYS[key]
+    def find_by_collidepoint(self, position):
+        for key in self.keys:
+            if self.keys[key].collidepoint(position):
+                return self.keys[key]
         return None
 
-    def find_by_unicode(key_sym):
-        for key in Mapping.KEYS:
-            if Mapping.KEYS[key].key_sym == key_sym:
-                return Mapping.KEYS[key]
+    def find_by_unicode(self, key_sym):
+        for key in self.keys:
+            if self.keys[key].key_sym == key_sym:
+                return self.keys[key]
         return None
 
-class Mapping:
-    KEYS = {
-        K_ESCAPE: Key(K_ESCAPE, 'ESC', 'first',   0),
-
-        K_F1:     Key(K_F1,     'F1',  'first', 100),
-        K_F2:     Key(K_F2,     'F2',  'first', 150),
-        K_F3:     Key(K_F3,     'F3',  'first', 200),
-        K_F4:     Key(K_F4,     'F4',  'first', 250),
-
-        K_F5:     Key(K_F5,     'F5',  'first', 325),
-        K_F6:     Key(K_F6,     'F6',  'first', 375),
-        K_F7:     Key(K_F7,     'F7',  'first', 425),
-        K_F8:     Key(K_F8,     'F8',  'first', 475),
-
-        K_F9:     Key(K_F9,     'F9',  'first', 550),
-        K_F10:    Key(K_F10,    'F10', 'first', 600),
-        K_F11:    Key(K_F11,    'F11', 'first', 650),
-        K_F12:    Key(K_F12,    'F12', 'first', 700),
-
-
-        178:          Key(178,          '²', 'second',   0),
-        K_AMPERSAND:  Key(K_AMPERSAND,  '&', 'second',  50),
-        233:          Key(233,          'é', 'second', 100),
-        K_QUOTEDBL:   Key(K_QUOTEDBL,   '"', 'second', 150),
-        K_QUOTE:      Key(K_QUOTE,      "'", 'second', 200),
-        K_LEFTPAREN:  Key(K_LEFTPAREN,  '(', 'second', 250),
-        K_MINUS:      Key(K_MINUS,      '-', 'second', 300),
-        232:          Key(232,          'è', 'second', 350),
-        K_UNDERSCORE: Key(K_UNDERSCORE, '_', 'second', 400),
-        231:          Key(231,          'ç', 'second', 450),
-        224:          Key(224,          'à', 'second', 500),
-        K_RIGHTPAREN: Key(K_RIGHTPAREN, ')', 'second', 550),
-        K_EQUALS:     Key(K_EQUALS,     '=', 'second', 600),
-
-        K_BACKSPACE:  Key(K_BACKSPACE,  '<-', 'second', 650, width = 98),
-
-
-        K_TAB:        Key(K_TAB,        'tab', 'third',   0, width = 73),
-        K_a:          Key(K_a,          'a',   'third',  75),
-        K_z:          Key(K_z,          'z',   'third', 125),
-        K_e:          Key(K_e,          'e',   'third', 175),
-        K_r:          Key(K_r,          'r',   'third', 225),
-        K_t:          Key(K_t,          't',   'third', 275),
-        K_y:          Key(K_y,          'y',   'third', 325),
-        K_u:          Key(K_u,          'u',   'third', 375),
-        K_i:          Key(K_i,          'i',   'third', 425),
-        K_o:          Key(K_o,          'o',   'third', 475),
-        K_p:          Key(K_p,          'p',   'third', 525),
-        K_CARET:      Key(K_CARET,      '^',   'third', 575),
-        K_DOLLAR:     Key(K_DOLLAR,     '$',   'third', 625),
-
-        K_RETURN: Key(K_RETURN, 'Enter', 'third', 692, width = 56, height = 98),
-
-        K_CAPSLOCK: Key(K_CAPSLOCK,    'CAPS', 'fourth',  0, width = 88, disabled = True),
-
-        K_q:        Key(K_q,        'q', 'fourth',  90),
-        K_s:        Key(K_s,        's', 'fourth', 140),
-        K_d:        Key(K_d,        'd', 'fourth', 190),
-        K_f:        Key(K_f,        'f', 'fourth', 240),
-        K_g:        Key(K_g,        'g', 'fourth', 290),
-        K_h:        Key(K_h,        'h', 'fourth', 340),
-        K_j:        Key(K_j,        'j', 'fourth', 390),
-        K_k:        Key(K_k,        'k', 'fourth', 440),
-        K_l:        Key(K_l,        'l', 'fourth', 490),
-        K_m:        Key(K_m,        'm', 'fourth', 540),
-        249:        Key(249,        'ù', 'fourth', 590),
-        K_ASTERISK: Key(K_ASTERISK, '*', 'fourth', 640),
-
-
-        K_LSHIFT: Key(K_LSHIFT, 'LShift', 'fifth', 0, width = 63, disabled = True),
-
-        K_LESS:      Key(K_LESS,      '<', 'fifth',  65),
-        K_w:         Key(K_w,         'w', 'fifth', 115),
-        K_x:         Key(K_x,         'x', 'fifth', 165),
-        K_c:         Key(K_c,         'c', 'fifth', 215),
-        K_v:         Key(K_v,         'v', 'fifth', 265),
-        K_b:         Key(K_b,         'b', 'fifth', 315),
-        K_n:         Key(K_n,         'n', 'fifth', 365),
-        K_COMMA:     Key(K_COMMA,     ',', 'fifth', 415),
-        K_SEMICOLON: Key(K_SEMICOLON, ';', 'fifth', 465),
-        K_COLON:     Key(K_COLON,     ':', 'fifth', 515),
-        K_EXCLAIM:   Key(K_EXCLAIM,   '!', 'fifth', 565),
-
-        K_RSHIFT: Key(K_RSHIFT, 'RShift', 'fifth', 615, width = 133, disabled = True),
-
-        K_LCTRL:   Key(K_LCTRL,    'LCtrl',   'sixth', 0, width = 63, disabled = True),
-        K_LSUPER:  Key(K_LSUPER,   'LSuper',  'sixth', 115, disabled = True),
-        K_LALT:    Key(K_LALT,     'LAlt',    'sixth', 165, disabled = True),
-        K_SPACE:   Key(K_SPACE,    'Espace',  'sixth', 215, width = 248),
-        K_MODE:    Key(K_MODE,     'AltGr',   'sixth', 465, disabled = True),
-        314:       Key(314,        'Compose', 'sixth', 515, disabled = True),
-        K_RCTRL:   Key(K_RCTRL,    'RCtrl',   'sixth', 565, width = 63, disabled = True),
-
-
-        K_INSERT:     Key(K_INSERT,   'ins',  'second', 755),
-        K_HOME:       Key(K_HOME,     'home', 'second', 805),
-        K_PAGEUP:     Key(K_PAGEUP,   'pg_u', 'second', 855),
-        K_DELETE:     Key(K_DELETE,   'del',  'third',  755),
-        K_END:        Key(K_END,      'end',  'third',  805),
-        K_PAGEDOWN:   Key(K_PAGEDOWN, 'pg_d', 'third',  855),
-
-
-        K_UP:         Key(K_UP,       'up',    'fifth',  805),
-        K_DOWN:       Key(K_DOWN,     'down',  'sixth',  805),
-        K_LEFT:       Key(K_LEFT,     'left',  'sixth',  755),
-        K_RIGHT:      Key(K_RIGHT,    'right', 'sixth',  855),
-    }
+
 
 class MusicFile:
-    def __init__(self, filename):
+    def __init__(self, filename, lock):
         self.filename = filename
+        self.channel = None
+        self.raw_data = None
+        self.sound = None
+
+        self.loaded = False
+        threading.Thread(target = self.load_sound, args = [lock]).start()
+
+    def load_sound(self, lock):
+        lock.acquire()
+        print("Loading {}".format(self.filename))
+        self.raw_data = pydub.AudioSegment.from_file(self.filename).raw_data
+        self.sound = mixer.Sound(self.raw_data)
+        print("Loaded {}".format(self.filename))
+        self.loaded = True
+        lock.release()
+
+    def play(self):
+        self.channel = self.sound.play()
+
+    def pause(self):
+        if self.channel is not None:
+            self.channel.pause()
+
+    def stop(self):
+        self.channel = None
+        self.sound.stop()
+
 
 class RoundedRect:
     def __init__(self, rect, outer_color, inner_color, linewidth = 2, radius = 0.4):
@@ -324,7 +482,7 @@ class RoundedRect:
         return rectangle
 
 
-def parse_config():
+def parse_config(mapping):
     import yaml
     stream = open("config.yml", "r")
     config = yaml.load(stream)
@@ -333,8 +491,10 @@ def parse_config():
     aliases = config['aliases']
     seen_files = {}
 
+    file_lock = threading.RLock()
+
     for mapped_key in config['keys']:
-        key = Key.find_by_unicode(mapped_key)
+        key = mapping.find_by_unicode(mapped_key)
         if key is None:
             continue
 
@@ -344,18 +504,21 @@ def parse_config():
             if action[action_name] is None:
                 action[action_name] = []
 
+            if 'include' in action[action_name]:
+                included = action[action_name]['include']
+                del(action[action_name]['include'])
+
+                if isinstance(included, str):
+                    action[action_name].update(aliases[included], **action[action_name])
+                else:
+                    for included_ in included:
+                        action[action_name].update(aliases[included_], **action[action_name])
+
             for argument in action[action_name]:
-                if argument == 'include':
-                    included = action[action_name]['include']
-                    if isinstance(included, str):
-                        action_args.update(aliases[included])
-                    else:
-                        for included_ in included:
-                            action_args.update(aliases[included_])
-                elif argument == 'file':
+                if argument == 'file':
                     filename = action[action_name]['file']
                     if filename not in seen_files:
-                        seen_files[filename] = MusicFile.new(filename)
+                        seen_files[filename] = MusicFile(filename, file_lock)
 
                     action_args['music'] = seen_files[filename]
 
index 7933d50acfb1f701bf00acbab5a9c0af4057b413..6cc49dff4884a7f0391f796ddd097321afe146b0 100644 (file)
@@ -1,30 +1,29 @@
 import sys
 import pygame
-import pydub
 import helpers
+import threading
 
 pygame.mixer.pre_init(frequency = 44100)
 pygame.init()
 
 size = width, height = 1024, 600
 
+helpers.draw_lock.acquire()
 screen = pygame.display.set_mode(size)
-background = pygame.Surface(screen.get_size())
-background = background.convert()
-background.fill((250, 250, 250))
+mapping = helpers.Mapping(screen)
 
 action_surface = pygame.Surface((600, 250)).convert()
 action_surface.fill((0,0,0))
-helpers.parse_config()
+helpers.parse_config(mapping)
+helpers.draw_lock.release()
 
-for key_name in helpers.Mapping.KEYS:
-    key = helpers.Mapping.KEYS[key_name]
-    key.draw(background)
+mapping.draw()
 
-screen.blit(background, (0, 0))
+helpers.draw_lock.acquire()
 screen.blit(action_surface, (10, 330))
 
 pygame.display.flip()
+helpers.draw_lock.release()
 
 contexts = [
     'normal'
@@ -34,6 +33,7 @@ context = 'normal'
 
 while 1:
     event = pygame.event.wait()
+
     if event.type == pygame.QUIT or (
             event.type == pygame.KEYDOWN and 
             event.mod  == 4160 and
@@ -43,11 +43,11 @@ while 1:
 
     if context == 'normal':
         if event.type == pygame.KEYDOWN:
-            key = helpers.Key.find_by_key_num(event.key)
+            key = mapping.find_by_key_num(event.key)
             if key is not None:
-                key.do_actions()
+                threading.Thread(target=key.do_actions).start()
         elif event.type == pygame.MOUSEBUTTONUP:
-            key = helpers.Key.find_by_collidepoint(pygame.mouse.get_pos())
+            key = mapping.find_by_collidepoint(pygame.mouse.get_pos())
             if key is not None:
                 key.list_actions(action_surface)