]> git.immae.eu Git - perso/Immae/Projets/Python/MusicSampler.git/blame - music_sampler/helpers.py
Make music_sampler multilingual
[perso/Immae/Projets/Python/MusicSampler.git] / music_sampler / helpers.py
CommitLineData
6ebe6247
IB
1# -*- coding: utf-8 -*-
2import argparse
3import sys
4import os
5import math
6import sounddevice as sd
7import logging
6a327173
IB
8import gettext
9gettext.install('music_sampler')
023d9381 10Logger = logging.getLogger("kivy")
6ebe6247
IB
11
12from . import sysfont
13
14class Config:
15 pass
16
17def find_font(name, style=sysfont.STYLE_NONE):
18 if getattr(sys, 'frozen', False):
19 font = sys._MEIPASS + "/fonts/{}_{}.ttf".format(name, style)
20 else:
21 font = sysfont.get_font(name, style=style)
22 if font is not None:
23 font = font[4]
24 return font
25
26def register_fonts():
27 from kivy.core.text import LabelBase
28
29 ubuntu_regular = find_font("Ubuntu", style=sysfont.STYLE_NORMAL)
30 ubuntu_bold = find_font("Ubuntu", style=sysfont.STYLE_BOLD)
31 symbola = find_font("Symbola")
32
33 if ubuntu_regular is None:
2010311b
IB
34 error_print("Font Ubuntu regular could not be found, "
35 "please install it.", exit=True)
6ebe6247 36 if symbola is None:
2010311b
IB
37 error_print("Font Symbola could not be found, please install it.",
38 exit=True)
6ebe6247
IB
39 if ubuntu_bold is None:
40 warn_print("Font Ubuntu Bold could not be found.")
41
42 LabelBase.register(name="Ubuntu",
43 fn_regular=ubuntu_regular,
44 fn_bold=ubuntu_bold)
45 LabelBase.register(name="Symbola",
46 fn_regular=symbola)
47
48
49def path():
50 if getattr(sys, 'frozen', False):
51 return sys._MEIPASS + "/"
52 else:
53 return os.path.dirname(os.path.realpath(__file__))
54
55def parse_args():
56 argv = sys.argv[1 :]
57 sys.argv = sys.argv[: 1]
58 if "--" in argv:
59 index = argv.index("--")
60 kivy_args = argv[index+1 :]
61 argv = argv[: index]
62
63 sys.argv.extend(kivy_args)
64
023d9381
IB
65 os.environ["KIVY_NO_CONFIG"] = 'true'
66 sys.argv.extend(["-c", "kivy:log_level:warning"])
67 sys.argv.extend(["-c", "kivy:log_dir:/tmp"])
68 sys.argv.extend(["-c", "kivy:log_name:/tmp/music_sampler_%_.txt"])
69
6ebe6247 70 parser = argparse.ArgumentParser(
6a327173 71 description=_("A Music Sampler application."),
6ebe6247
IB
72 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
73 parser.add_argument("-c", "--config",
74 default="config.yml",
75 required=False,
6a327173 76 help=_("Config file to load"))
6ebe6247
IB
77 parser.add_argument("-p", "--music-path",
78 default=".",
79 required=False,
6a327173 80 help=_("Folder in which to find the music files"))
6ebe6247
IB
81 parser.add_argument("-d", "--debug",
82 nargs=0,
83 action=DebugModeAction,
6a327173 84 help=_("Print messages in console"))
6ebe6247
IB
85 parser.add_argument("-m", "--builtin-mixing",
86 action="store_true",
6a327173
IB
87 help=_("Make the mixing of sounds manually\
88 (do it if the system cannot handle it correctly)"))
6ebe6247
IB
89 parser.add_argument("-l", "--latency",
90 default="high",
91 required=False,
6a327173 92 help=_("Latency: low, high or number of seconds"))
6ebe6247
IB
93 parser.add_argument("-b", "--blocksize",
94 default=0,
95 type=int,
96 required=False,
6a327173
IB
97 help=_("Blocksize: If not 0, the number of frames to take\
98 at each step for the mixer"))
6ebe6247
IB
99 parser.add_argument("-f", "--frame-rate",
100 default=44100,
101 type=int,
102 required=False,
6a327173 103 help=_("Frame rate to play the musics"))
6ebe6247
IB
104 parser.add_argument("-x", "--channels",
105 default=2,
106 type=int,
107 required=False,
6a327173 108 help=_("Number of channels to use"))
6ebe6247
IB
109 parser.add_argument("-s", "--sample-width",
110 default=2,
111 type=int,
112 required=False,
6a327173 113 help=_("Sample width (number of bytes for each frame)"))
6ebe6247
IB
114 parser.add_argument("-V", "--version",
115 action="version",
6a327173
IB
116 help=_("Displays the current version and exits. Only use\
117 in bundled package"),
6ebe6247
IB
118 version=show_version())
119 parser.add_argument("--device",
120 action=SelectDeviceAction,
6a327173 121 help=_("Select this sound device")
6ebe6247
IB
122 )
123 parser.add_argument("--list-devices",
124 nargs=0,
125 action=ListDevicesAction,
6a327173 126 help=_("List available sound devices")
6ebe6247 127 )
7d6df771
IB
128 parser.add_argument("--no-focus-warning",
129 action='store_true',
6a327173
IB
130 help=_("Don't show warning when focus is lost")
131 )
132 parser.add_argument("-L", "--language",
133 required=False,
134 default="fr",
135 help=_("Select another language")
7d6df771 136 )
6ebe6247
IB
137 parser.add_argument('--',
138 dest="args",
6a327173
IB
139 help=_("Kivy arguments. All arguments after this are interpreted\
140 by Kivy. Pass \"-- --help\" to get Kivy's usage."))
6ebe6247 141
6ebe6247
IB
142 args = parser.parse_args(argv)
143
144 Config.yml_file = args.config
145
146 Config.latency = args.latency
147 Config.blocksize = args.blocksize
148 Config.frame_rate = args.frame_rate
149 Config.channels = args.channels
150 Config.sample_width = args.sample_width
151 Config.builtin_mixing = args.builtin_mixing
7d6df771 152 Config.no_focus_warning = args.no_focus_warning
6a327173
IB
153 if args.language != 'en':
154 gettext.translation("music_sampler",
155 localedir=path() + '/locales',
156 languages=[args.language]).install()
6ebe6247
IB
157 if args.music_path.endswith("/"):
158 Config.music_path = args.music_path
159 else:
160 Config.music_path = args.music_path + "/"
161
162class DebugModeAction(argparse.Action):
163 def __call__(self, parser, namespace, values, option_string=None):
023d9381 164 sys.argv.extend(["-c", "kivy:log_level:debug"])
6ebe6247
IB
165
166class SelectDeviceAction(argparse.Action):
167 def __call__(self, parser, namespace, values, option_string=None):
168 sd.default.device = values
169
170class ListDevicesAction(argparse.Action):
171 nargs = 0
172 def __call__(self, parser, namespace, values, option_string=None):
173 print(sd.query_devices())
174 sys.exit()
175
176def show_version():
177 if getattr(sys, 'frozen', False):
178 with open(path() + ".pyinstaller_commit", "r") as f:
179 return f.read()
180 else:
6a327173 181 return _("option '-V' can only be used in bundled package")
6ebe6247
IB
182
183def duration_to_min_sec(duration):
184 minutes = int(duration / 60)
185 seconds = int(duration) % 60
186 if minutes < 100:
187 return "{:2}:{:0>2}".format(minutes, seconds)
188 else:
189 return "{}:{:0>2}".format(minutes, seconds)
190
191def gain(volume, old_volume=None):
192 if old_volume is None:
193 return 20 * math.log10(max(volume, 0.1) / 100)
194 else:
195 return [
196 20 * math.log10(max(volume, 0.1) / max(old_volume, 0.1)),
197 max(volume, 0)]
198
2010311b
IB
199def debug_print(message, with_trace=None):
200 if with_trace is None:
201 with_trace = (Logger.getEffectiveLevel() < logging.WARN)
202 with_trace &= (sys.exc_info()[0] is not None)
203
6ebe6247
IB
204 Logger.debug('MusicSampler: ' + message, exc_info=with_trace)
205
2010311b
IB
206def error_print(message, exit=False, with_trace=None):
207 if with_trace is None:
208 with_trace = (Logger.getEffectiveLevel() < logging.WARN)
209 with_trace &= (sys.exc_info()[0] is not None)
210
211 # FIXME: handle it correctly when in a thread
212 if exit:
213 Logger.critical('MusicSampler: ' + message, exc_info=with_trace)
214 sys.exit(1)
215 else:
216 Logger.error('MusicSampler: ' + message, exc_info=with_trace)
217
218def warn_print(message, with_trace=None):
219 if with_trace is None:
220 with_trace = (Logger.getEffectiveLevel() < logging.WARN)
221 with_trace &= (sys.exc_info()[0] is not None)
6ebe6247 222
6ebe6247
IB
223 Logger.warn('MusicSampler: ' + message, exc_info=with_trace)
224