From 16847231fa5a85cbb0f792e6e461392879047c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isma=C3=ABl=20Bouya?= Date: Fri, 12 Aug 2016 12:22:01 +0200 Subject: Add config key to config.yml to store command line arguments --- config.yml | 32 ++++++- documentation_en.md | 28 ++++-- documentation_fr.md | 29 ++++-- music_sampler/app.py | 2 +- music_sampler/helpers.py | 243 +++++++++++++++++++++++++++++++---------------- 5 files changed, 233 insertions(+), 101 deletions(-) diff --git a/config.yml b/config.yml index e543b04..8802dcf 100644 --- a/config.yml +++ b/config.yml @@ -1,3 +1,31 @@ +################################# +##### General configuration ##### +## Keep in mind that in-line option override these + +#option listed here are the default options. +config: +# debug info + debug: false +# languages. Available: fr, en + language: fr +# path to the musics. + music_path: . +# The awful red message that shows up when you lose the focus + focus_warning: true +# built-in mixing + builtin_mixing: true +# Device used for playing musics. Default value depends on your system +# device: +# Advanced parameters: use at your own risk! (your computer probably won't explode, though) + latency: high + blocksize: 0 + frame_rate: 44100 + sample_width: 2 + channels: 2 + + + + ################### ##### Aliases ##### @@ -41,8 +69,8 @@ music_properties: name: Crocodile noise gain: 1.2 -#################################################### -##### Key properties: how do the key look like ##### +############################################################################### +##### Key properties: how do the key look like, and some other properties ##### key_properties: 'a': diff --git a/documentation_en.md b/documentation_en.md index 87b9bd7..1cf5cfd 100644 --- a/documentation_en.md +++ b/documentation_en.md @@ -39,7 +39,7 @@ must be available on your system, as well as the `portaudio` library: sudo apt-get install ttf-ancient-fonts ttf-ubuntu-font-family portaudio -Pour compiler kivy avec la librairie SDL2, il faut certains paquets installés: +To compile Kivy with the SDL2 library, you need some packages: sudo apt-get install libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev @@ -96,26 +96,29 @@ understand just by looking at it. ### Options available at launch All the options below are optional; usually, running the program in the correct -folder is enough +folder is enough. Most of the parameters can be defined also in the config file. +The command line parameters always take precedence. * `-h, --help`: shows a list of available options * `-c CONFIG, --config CONFIG`: gives the configuration file to load (by default, `config.yml` in the current folder). * `-p MUSIC_PATH, --music-path MUSIC_PATH`: gives the path to find the musics (by default, the current folder) - * `-d, --debug`: show debug informations in the terminal (disabled by default) + * `--no-debug, --debug`: show debug informations in the terminal (disabled by + default) * `-V, --version`: show current version and exit (only for the compiled version) * `-L, --language`: change application language. Current languages: fr, en (default 'fr') - * `--no-focus-warning`: don't show warning when focus gets lost. + * `--focus-warning, --no-focus-warning`: show / don't show warning when focus gets + lost (default is to show it) The following options are reserved for a more advanced use of Music Sampler, or in case of problem with the standard configuration: - * `-m, --builtin-mixing`: make the sound mixing locally. By default, Music - Sampler will let the system do it and open one channel per music loaded. Use - it only if the system cannot handle it. + * `--no-builtin-mixing, --builtin-mixing`: make the sound mixing locally. By + default, Music Sampler will let the system do it and open one channel per + music loaded. Use it only if the system cannot handle it. * `-l LATENCY, --latency LATENCY`: "low", "high" or a number of seconds (default "high") * `-b BLOCKSIZE, --blocksize BLOCKSIZE`: Number of frames for each mixing @@ -144,6 +147,9 @@ corresponding problems) or abort. The file contains several sections: :::yaml + config: + ... + aliases: ... @@ -156,6 +162,14 @@ The file contains several sections: keys: ... +### `config` + +The config section lets you store configuration parameters that you would +normally use in the command line parameters. The '-' in the long parameter name +should be replaced by '_' (e.g. '--music-path' -> 'music_path'). For toggles +(`debug`, `focus_warning`, `builtin_mixing`) use the version without 'no-' and +specify `true` or `false` as value. Note that command line arguments always take +precedence. ### `music_properties` diff --git a/documentation_fr.md b/documentation_fr.md index a55ae73..b739aa2 100644 --- a/documentation_fr.md +++ b/documentation_fr.md @@ -103,7 +103,9 @@ gardées d'une fois sur l'autre. ### Options disponibles au lancement Toutes les options au lancement sont facultatives ; la plupart du temps lancer -le programme dans le bon dossier suffit. +le programme dans le bon dossier suffit. La plupart d'entre elles peuvent être +définies également dans le fichier de config (à part `--config` bien sûr). Les +arguments en ligne de commande ont toujours la priorité. * `-h, --help` : affiche une liste des options disponibles. * `-c CONFIG, --config CONFIG` : précise le fichier de configuration à charger @@ -111,20 +113,21 @@ le programme dans le bon dossier suffit. music_sampler). * `-p MUSIC_PATH, --music-path MUSIC_PATH` : précise le chemin des musiques (par défaut, le dossier courant). - * `-d, --debug` : Affiche les informations de déboggage (désactivé par défaut) + * `--no-debug, --debug` : Affiche les informations de déboggage (désactivé par + défaut) * `-V, --version` : affiche la version courante et quitte (utilisable uniquement pour la version compilée). * `-L, --language` : change la langue de l'application. Actuellement: fr, en (par défaut 'fr') - * `--no-focus-warning`: Ne pas afficher d'avertissement lorsque l'application - perd le focus. + * `--focus-warning, --no-focus-warning`: Afficher / Ne pas afficher + d'avertissement lorsque l'application perd le focus (activé par défaut). Les options suivantes sont plutôt réservées à un usage avancé de music_sampler, ou en cas de problème avec la configuration standard : - * `-m, --builtin-mixing` Effectue en interne le mixage des sons. Par défaut, - music_sampler confie le mixage au système : n'activer cette option que si le - système n'y parvient pas. + * `--no-builtin-mixing, --builtin-mixing` Effectue en interne le mixage des + sons. Par défaut, music_sampler confie le mixage au système : n'activer + cette option que si le système n'y parvient pas. * `-l LATENCY, --latency LATENCY` : latence. Préciser "low", "high" ou un nombre de secondes (par défaut, "high") * `-b BLOCKSIZE, --blocksize BLOCKSIZE` : taille des blocs. Nombre de frames @@ -158,6 +161,9 @@ ne se lance pas du tout. Le fichier contient plusieurs sections : :::yaml + config: + ... + aliases: ... @@ -171,6 +177,15 @@ Le fichier contient plusieurs sections : ... +### `config` + +La section config permet d'enregistrer les paramètres habituellement donnés en +ligne de commande. Les '-' dans le nom du paramètre long doivent être remplacés +par des '_' (par exemple '--music-path' -> 'music_path'). Pour les switches +(`debug`, `focus_warning`, `builtin_mixing`), utilisez la version sans le 'no-' +et spécifiez `true` / `false` en valeur. Notez que les arguments donnés en ligne +de commande sont toujours prioritaires sur les valeurs du fichier. + ### `music_properties` : propriétés des musiques Cette section sert à définir des propriétés globales des musiques. diff --git a/music_sampler/app.py b/music_sampler/app.py index e7c90db..ce84235 100644 --- a/music_sampler/app.py +++ b/music_sampler/app.py @@ -50,7 +50,7 @@ class Screen(FloatLayout): Window.on_request_close = self.on_request_close def focus_changed(self, instance, focus): - if Config.no_focus_warning: + if not Config.focus_warning: return if not focus: self.add_widget(self.unfocused_widget) diff --git a/music_sampler/helpers.py b/music_sampler/helpers.py index 2199058..943e5a1 100644 --- a/music_sampler/helpers.py +++ b/music_sampler/helpers.py @@ -6,6 +6,7 @@ import math import sounddevice as sd import logging import gettext +import yaml gettext.install('music_sampler') Logger = logging.getLogger("kivy") @@ -52,6 +53,96 @@ def path(): else: return os.path.dirname(os.path.realpath(__file__)) + +Configs = { + 'music_path': { + 'abbr': '-p', + 'default': '.', + 'help': _("Folder in which to find the music files"), + 'type': None + }, + 'latency': { + 'abbr': '-l', + 'default': 'high', + 'help': _("Latency: low, high or number of seconds"), + 'type': None + }, + 'language': { + 'abbr': '-L', + 'default': "fr", + 'help': _("Select another language"), + 'type': None + }, + 'device': { + 'abbr': '-d', + 'default': None, + 'help': _("Select this sound device"), + 'type': None + }, + 'blocksize': { + 'abbr': '-b', + 'default': 0, + 'help': _("Blocksize: If not 0, the number of frames to take\ + at each step for the mixer"), + 'type': int + }, + 'frame_rate': { + 'abbr': '-f', + 'default': 44100, + 'help': _("Frame rate to play the musics"), + 'type': int + }, + 'channels': { + 'abbr': '-x', + 'default': 2, + 'help': _("Number of channels to use"), + 'type': int + }, + 'sample_width': { + 'abbr': '-s', + 'default': 2, + 'help': _("Sample width (number of bytes for each frame)"), + 'type': int + }, + 'builtin_mixing': { + 'default': False, + 'help_yes': _("Make the mixing of sounds manually\ + (do it if the system cannot handle it correctly)"), + 'help_no': _("Don't make the mixing of sounds manually (default)"), + 'type': 'boolean' + }, + 'debug': { + 'abbr': '-d', + 'default': False, + 'help_yes': _("Print messages in console"), + 'help_no': _("Don't print messages in console (default)"), + 'type': 'boolean' + }, + 'focus_warning': { + 'default': True, + 'help_yes': _("Show a warning when focus is lost (default)"), + 'help_no': _("Don't show warning when focus is lost"), + 'type': 'boolean' + }, + 'list_devices': { + 'help': _("List available sound devices"), + 'type': 'action' + }, +} +Configs_order = [ + 'debug', + 'music_path', + 'builtin_mixing', + 'latency', + 'blocksize', + 'frame_rate', + 'channels', + 'sample_width', + 'focus_warning', + 'language', + 'list_devices', + 'device', +] def parse_args(): argv = sys.argv[1 :] sys.argv = sys.argv[: 1] @@ -68,72 +159,34 @@ def parse_args(): sys.argv.extend(["-c", "kivy:log_name:/tmp/music_sampler_%_.txt"]) parser = argparse.ArgumentParser( - description=_("A Music Sampler application."), - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - parser.add_argument("-c", "--config", - default="config.yml", - required=False, - help=_("Config file to load")) - parser.add_argument("-p", "--music-path", - default=".", - required=False, - help=_("Folder in which to find the music files")) - parser.add_argument("-d", "--debug", - nargs=0, - action=DebugModeAction, - help=_("Print messages in console")) - parser.add_argument("-m", "--builtin-mixing", - action="store_true", - help=_("Make the mixing of sounds manually\ - (do it if the system cannot handle it correctly)")) - parser.add_argument("-l", "--latency", - default="high", - required=False, - help=_("Latency: low, high or number of seconds")) - parser.add_argument("-b", "--blocksize", - default=0, - type=int, - required=False, - help=_("Blocksize: If not 0, the number of frames to take\ - at each step for the mixer")) - parser.add_argument("-f", "--frame-rate", - default=44100, - type=int, - required=False, - help=_("Frame rate to play the musics")) - parser.add_argument("-x", "--channels", - default=2, - type=int, - required=False, - help=_("Number of channels to use")) - parser.add_argument("-s", "--sample-width", - default=2, - type=int, - required=False, - help=_("Sample width (number of bytes for each frame)")) + argument_default=argparse.SUPPRESS, + description=_("A Music Sampler application.")) parser.add_argument("-V", "--version", action="version", help=_("Displays the current version and exits. Only use\ in bundled package"), version=show_version()) - parser.add_argument("--device", - action=SelectDeviceAction, - help=_("Select this sound device") - ) - parser.add_argument("--list-devices", - nargs=0, - action=ListDevicesAction, - help=_("List available sound devices") - ) - parser.add_argument("--no-focus-warning", - action='store_true', - help=_("Don't show warning when focus is lost") - ) - parser.add_argument("-L", "--language", + parser.add_argument("-c", "--config", + default="config.yml", required=False, - default="fr", - help=_("Select another language") - ) + help=_("Config file to load (default: config.yml)")) + for argument in Configs_order: + arg = Configs[argument] + if arg['type'] != 'boolean' and arg['type'] != 'action': + parser.add_argument(arg['abbr'], '--' + argument.replace('_', '-'), + type=arg['type'], + help=arg['help']+_(" (default: {})").format(arg['default'])) + elif arg['type'] == 'boolean': + parser.add_argument('--' + argument.replace('_', '-'), + action='store_const', const=True, + help=arg['help_yes']) + parser.add_argument('--no-' + argument.replace('_', '-'), + action='store_const', const=True, + help=arg['help_no']) + else: + parser.add_argument('--' + argument.replace('_', '-'), + action='store_const', const=True, + help=arg['help']) parser.add_argument('--', dest="args", help=_("Kivy arguments. All arguments after this are interpreted\ @@ -142,36 +195,58 @@ def parse_args(): args = parser.parse_args(argv) Config.yml_file = args.config + build_config(args) - Config.latency = args.latency - Config.blocksize = args.blocksize - Config.frame_rate = args.frame_rate - Config.channels = args.channels - Config.sample_width = args.sample_width - Config.builtin_mixing = args.builtin_mixing - Config.no_focus_warning = args.no_focus_warning - if args.language != 'en': + if Config.device is not None: + sd.default.device = Config.device + + if Config.list_devices: + print(sd.query_devices()) + sys.exit() + + if Config.debug: + sys.argv.extend(["-c", "kivy:log_level:debug"]) + + if Config.language != 'en': gettext.translation("music_sampler", localedir=path() + '/locales', - languages=[args.language]).install() - if args.music_path.endswith("/"): - Config.music_path = args.music_path - else: - Config.music_path = args.music_path + "/" + languages=[Config.language]).install() + if not Config.music_path.endswith("/"): + Config.music_path = Config.music_path + "/" -class DebugModeAction(argparse.Action): - def __call__(self, parser, namespace, values, option_string=None): - sys.argv.extend(["-c", "kivy:log_level:debug"]) +def build_config(args): + 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)) + config = {} + stream.close() + if 'config' in config: + config = config['config'] + else: + config = {} -class SelectDeviceAction(argparse.Action): - def __call__(self, parser, namespace, values, option_string=None): - sd.default.device = values + for config_item in Configs_order: + if Configs[config_item]['type'] != 'boolean' and \ + Configs[config_item]['type'] != 'action': + t = Configs[config_item]['type'] or str + if hasattr(args, config_item): + setattr(Config, config_item, getattr(args, config_item)) + elif config_item in config: + setattr(Config, config_item, t(config[config_item])) + else: + setattr(Config, config_item, Configs[config_item]['default']) + elif Configs[config_item]['type'] == 'boolean': + if hasattr(args, 'no_' + config_item) or hasattr(args, config_item): + setattr(Config, config_item, hasattr(args, config_item)) + elif config_item in config: + setattr(Config, config_item, config[config_item]) + else: + setattr(Config, config_item, Configs[config_item]['default']) + else: + setattr(Config, config_item, hasattr(args, config_item)) -class ListDevicesAction(argparse.Action): - nargs = 0 - def __call__(self, parser, namespace, values, option_string=None): - print(sd.query_devices()) - sys.exit() def show_version(): if getattr(sys, 'frozen', False): -- cgit v1.2.3