From 63ba5a8dc2aa4ec3e6f203b0ba4db249ecf0b00e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isma=C3=ABl=20Bouya?= Date: Wed, 27 Jul 2016 21:33:09 +0200 Subject: Rename helpers to music_sampler --- helpers/mapping.py | 399 ----------------------------------------------------- 1 file changed, 399 deletions(-) delete mode 100644 helpers/mapping.py (limited to 'helpers/mapping.py') diff --git a/helpers/mapping.py b/helpers/mapping.py deleted file mode 100644 index bb20e67..0000000 --- a/helpers/mapping.py +++ /dev/null @@ -1,399 +0,0 @@ -from kivy.uix.relativelayout import RelativeLayout -from kivy.properties import NumericProperty, ListProperty, StringProperty -from kivy.core.window import Window -from kivy.clock import Clock - -import threading -import yaml -import sys -from collections import defaultdict - -from transitions.extensions import HierarchicalMachine as Machine - -from .music_file import MusicFile -from .mixer import Mixer -from . import Config, gain, error_print, warn_print -from .action import Action - -class Mapping(RelativeLayout): - STATES = [ - 'initial', - 'configuring', - 'configured', - 'loading', - 'loaded', - 'failed' - ] - - TRANSITIONS = [ - { - 'trigger': 'configure', - 'source': 'initial', - 'dest': 'configuring' - }, - { - 'trigger': 'fail', - 'source': 'configuring', - 'dest': 'failed' - }, - { - 'trigger': 'success', - 'source': 'configuring', - 'dest': 'configured', - 'after': 'load' - }, - { - 'trigger': 'load', - 'source': 'configured', - 'dest': 'loading' - }, - { - 'trigger': 'fail', - 'source': 'loading', - 'dest': 'failed' - }, - { - 'trigger': 'success', - 'source': 'loading', - 'dest': 'loaded' - }, - { - 'trigger': 'reload', - 'source': 'loaded', - 'dest': 'configuring' - } - ] - - master_volume = NumericProperty(100) - ready_color = ListProperty([1, 165/255, 0, 1]) - state = StringProperty("") - - def __init__(self, **kwargs): - self.keys = [] - self.running = [] - self.wait_ids = {} - self.open_files = {} - - Machine(model=self, states=self.STATES, - transitions=self.TRANSITIONS, initial='initial', - ignore_invalid_triggers=True, queued=True) - super(Mapping, self).__init__(**kwargs) - self.keyboard = Window.request_keyboard(self.on_keyboard_closed, self) - self.keyboard.bind(on_key_down=self.on_keyboard_down) - - self.configure() - - def on_enter_configuring(self): - if Config.builtin_mixing: - self.mixer = Mixer() - else: - self.mixer = None - - try: - self.key_config, self.open_files = self.parse_config() - except Exception as e: - error_print("Error while loading configuration: {}".format(e), - with_trace=True) - sys.exit() - else: - self.success() - - def on_enter_loading(self): - for key in self.keys: - key.reload() - self.success() - - # Kivy events - def add_widget(self, widget, index=0): - if type(widget).__name__ == "Key" and widget not in self.keys: - self.keys.append(widget) - return super(Mapping, self).add_widget(widget, index) - - def remove_widget(self, widget, index=0): - if type(widget).__name__ == "Key" and widget in self.keys: - self.keys.remove(widget) - return super(Mapping, self).remove_widget(widget, index) - - def on_keyboard_closed(self): - self.keyboard.unbind(on_key_down=self.on_keyboard_down) - self.keyboard = None - - def on_keyboard_down(self, keyboard, keycode, text, modifiers): - key = self.find_by_key_code(keycode) - if self.allowed_modifiers(modifiers) and key is not None: - modifiers.sort() - threading.Thread(name="MSKeyAction", target=key.run, - args=['-'.join(modifiers)]).start() - elif 'ctrl' in modifiers and (keycode[0] == 113 or keycode[0] == '99'): - self.stop_all_running() - for thread in threading.enumerate(): - if thread.getName()[0:2] != "MS": - continue - thread.join() - - sys.exit() - elif 'ctrl' in modifiers and keycode[0] == 114: - threading.Thread(name="MSReload", target=self.reload).start() - return True - - # Helpers - def allowed_modifiers(self, modifiers): - allowed = [] - return len([a for a in modifiers if a not in allowed]) == 0 - - def find_by_key_code(self, key_code): - if "Key_" + str(key_code[0]) in self.ids: - return self.ids["Key_" + str(key_code[0])] - return None - - def all_keys_ready(self): - partial = False - for key in self.keys: - if not key.is_loaded_or_failed(): - return "not_ready" - partial = partial or key.is_failed() - - if partial: - return "partial" - else: - return "success" - - # Callbacks - def key_loaded_callback(self): - result = self.all_keys_ready() - if result == "success": - self.ready_color = [0, 1, 0, 1] - elif result == "partial": - self.ready_color = [1, 0, 0, 1] - else: - self.ready_color = [1, 165/255, 0, 1] - - ## Some global actions - def stop_all_running(self, except_key=None, key_start_time=0): - running = self.running - self.running = [r for r in running\ - if r[0] == except_key and r[1] == key_start_time] - for (key, start_time) in running: - if (key, start_time) != (except_key, key_start_time): - key.interrupt() - - # Master volume methods - @property - def master_gain(self): - return gain(self.master_volume) - - def set_master_volume(self, value, delta=False, fade=0): - [db_gain, self.master_volume] = gain( - value + int(delta) * self.master_volume, - self.master_volume) - - for music in self.open_files.values(): - music.set_gain_with_effect(db_gain, fade=fade) - - # Wait handler methods - def add_wait_id(self, wait_id, action_or_wait): - self.wait_ids[wait_id] = action_or_wait - - def interrupt_wait(self, wait_id): - if wait_id in self.wait_ids: - action_or_wait = self.wait_ids[wait_id] - del(self.wait_ids[wait_id]) - if isinstance(action_or_wait, Action): - action_or_wait.interrupt() - else: - action_or_wait.set() - - # Methods to control running keys - def start_running(self, key, start_time): - self.running.append((key, start_time)) - - def keep_running(self, key, start_time): - return (key, start_time) in self.running - - def finished_running(self, key, start_time): - if (key, start_time) in self.running: - self.running.remove((key, start_time)) - - # YML config parser - def parse_config(self): - def update_alias(prop_hash, aliases, key): - if isinstance(aliases[key], dict): - prop_hash.update(aliases[key], **prop_hash) - else: - warn_print("Alias {} is not a hash, ignored".format(key)) - - def include_aliases(prop_hash, aliases): - if 'include' not in prop_hash: - return - - included = prop_hash['include'] - del(prop_hash['include']) - if isinstance(included, str): - update_alias(prop_hash, aliases, included) - elif isinstance(included, list): - for included_ in included: - if isinstance(included_, str): - update_alias(prop_hash, aliases, included_) - else: - warn_print("Unkown alias include type, ignored: " - "{} in {}".format(included_, included)) - else: - warn_print("Unkown alias include type, ignored: {}" - .format(included)) - - def check_key_property(key_property, key): - if 'description' in key_property: - desc = key_property['description'] - if not isinstance(desc, list): - warn_print("description in key_property '{}' is not " - "a list, ignored".format(key)) - del(key_property['description']) - if 'color' in key_property: - color = key_property['color'] - if not isinstance(color, list)\ - or len(color) != 3\ - or not all(isinstance(item, int) for item in color)\ - or any(item < 0 or item > 255 for item in color): - warn_print("color in key_property '{}' is not " - "a list of 3 valid integers, ignored".format(key)) - del(key_property['color']) - - def check_key_properties(config): - if 'key_properties' in config: - if isinstance(config['key_properties'], dict): - return config['key_properties'] - else: - warn_print("key_properties config is not a hash, ignored") - return {} - else: - return {} - - def check_mapped_keys(config): - if 'keys' in config: - if isinstance(config['keys'], dict): - return config['keys'] - else: - warn_print("keys config is not a hash, ignored") - return {} - else: - return {} - - def check_mapped_key(mapped_keys, key): - if not isinstance(mapped_keys[key], list): - warn_print("key config '{}' is not an array, ignored" - .format(key)) - return [] - else: - return mapped_keys[key] - - def check_music_property(music_property, filename): - if not isinstance(music_property, dict): - warn_print("music_property config '{}' is not a hash, ignored" - .format(filename)) - return {} - if 'name' in music_property: - music_property['name'] = str(music_property['name']) - if 'gain' in music_property: - try: - music_property['gain'] = float(music_property['gain']) - except ValueError as e: - del(music_property['gain']) - warn_print("gain for music_property '{}' is not " - "a float, ignored".format(filename)) - return music_property - - stream = open(Config.yml_file, "r") - try: - config = yaml.safe_load(stream) - except Exception as e: - error_print("Error while loading config file: {}".format(e)) - sys.exit() - stream.close() - - if not isinstance(config, dict): - raise Exception("Top level config is supposed to be a hash") - - if 'aliases' in config and isinstance(config['aliases'], dict): - aliases = config['aliases'] - else: - aliases = defaultdict(dict) - if 'aliases' in config: - warn_print("aliases config is not a hash, ignored") - - music_properties = defaultdict(dict) - if 'music_properties' in config and\ - isinstance(config['music_properties'], dict): - music_properties.update(config['music_properties']) - elif 'music_properties' in config: - warn_print("music_properties config is not a hash, ignored") - - seen_files = {} - - key_properties = defaultdict(lambda: { - "actions": [], - "properties": {}, - "files": [] - }) - - for key in check_key_properties(config): - key_prop = config['key_properties'][key] - - if not isinstance(key_prop, dict): - warn_print("key_property '{}' is not a hash, ignored" - .format(key)) - continue - - include_aliases(key_prop, aliases) - check_key_property(key_prop, key) - - key_properties[key]["properties"] = key_prop - - for mapped_key in check_mapped_keys(config): - for index, action in enumerate(check_mapped_key( - config['keys'], mapped_key)): - if not isinstance(action, dict) or\ - not len(action) == 1 or\ - not isinstance(list(action.values())[0] or {}, dict): - warn_print("action number {} of key '{}' is invalid, " - "ignored".format(index + 1, mapped_key)) - continue - - action_name = list(action)[0] - action_args = {} - if action[action_name] is None: - action[action_name] = {} - - include_aliases(action[action_name], aliases) - - for argument in action[action_name]: - if argument == 'file': - filename = str(action[action_name]['file']) - if filename not in seen_files: - music_property = check_music_property( - music_properties[filename], - filename) - - if filename in self.open_files: - self.open_files[filename]\ - .reload_properties(**music_property) - - seen_files[filename] =\ - self.open_files[filename] - else: - seen_files[filename] = MusicFile( - filename, self, **music_property) - - if filename not in key_properties[mapped_key]['files']: - key_properties[mapped_key]['files'] \ - .append(seen_files[filename]) - - action_args['music'] = seen_files[filename] - else: - action_args[argument] = action[action_name][argument] - - key_properties[mapped_key]['actions'] \ - .append([action_name, action_args]) - - return (key_properties, seen_files) - - -- cgit v1.2.3