]>
git.immae.eu Git - perso/Immae/Projets/Python/MusicSampler.git/blob - music_sampler/helpers.py
1 # -*- coding: utf-8 -*-
6 import sounddevice
as sd
10 gettext
.install('music_sampler')
11 Logger
= logging
.getLogger("kivy")
18 def find_font(name
, style
=sysfont
.STYLE_NONE
):
19 if getattr(sys
, 'frozen', False):
20 font
= sys
._MEIPASS
+ "/fonts/{}_{}.ttf".format(name
, style
)
22 font
= sysfont
.get_font(name
, style
=style
)
28 from kivy
.core
.text
import LabelBase
30 ubuntu_regular
= find_font("Ubuntu", style
=sysfont
.STYLE_NORMAL
)
31 ubuntu_bold
= find_font("Ubuntu", style
=sysfont
.STYLE_BOLD
)
32 symbola
= find_font("Symbola")
34 if ubuntu_regular
is None:
35 error_print("Font Ubuntu regular could not be found, "
36 "please install it.", exit
=True)
38 error_print("Font Symbola could not be found, please install it.",
40 if ubuntu_bold
is None:
41 warn_print("Font Ubuntu Bold could not be found.")
43 LabelBase
.register(name
="Ubuntu",
44 fn_regular
=ubuntu_regular
,
46 LabelBase
.register(name
="Symbola",
51 if getattr(sys
, 'frozen', False):
52 return sys
._MEIPASS
+ "/"
54 return os
.path
.dirname(os
.path
.realpath(__file__
))
61 'help': _("Folder in which to find the music files"),
67 'help': _("Latency: low, high or number of seconds"),
73 'help': _("Select another language"),
79 'help': _("Select this sound device"),
85 'help': _("Blocksize: If not 0, the number of frames to take\
86 at each step for the mixer"),
92 'help': _("Frame rate to play the musics"),
98 'help': _("Number of channels to use"),
104 'help': _("Sample width (number of bytes for each frame)"),
109 'help_yes': _("Make the mixing of sounds manually\
110 (do it if the system cannot handle it correctly)"),
111 'help_no': _("Don't make the mixing of sounds manually (default)"),
117 'help_yes': _("Print messages in console"),
118 'help_no': _("Don't print messages in console (default)"),
123 'help_yes': _("Show a warning when focus is lost (default)"),
124 'help_no': _("Don't show warning when focus is lost"),
128 'help': _("List available sound devices"),
148 sys
.argv
= sys
.argv
[: 1]
150 index
= argv
.index("--")
151 kivy_args
= argv
[index
+1 :]
154 sys
.argv
.extend(kivy_args
)
156 os
.environ
["KIVY_NO_CONFIG"] = 'true'
157 sys
.argv
.extend(["-c", "kivy:log_level:warning"])
158 sys
.argv
.extend(["-c", "kivy:log_dir:/tmp"])
159 sys
.argv
.extend(["-c", "kivy:log_name:/tmp/music_sampler_%_.txt"])
161 parser
= argparse
.ArgumentParser(
162 argument_default
=argparse
.SUPPRESS
,
163 description
=_("A Music Sampler application."))
164 parser
.add_argument("-V", "--version",
166 help=_("Displays the current version and exits. Only use\
167 in bundled package"),
168 version
=show_version())
169 parser
.add_argument("-c", "--config",
170 default
="config.yml",
172 help=_("Config file to load (default: config.yml)"))
173 for argument
in Configs_order
:
174 arg
= Configs
[argument
]
175 if arg
['type'] != 'boolean' and arg
['type'] != 'action':
176 parser
.add_argument(arg
['abbr'], '--' + argument
.replace('_', '-'),
178 help=arg
['help']+_(" (default: {})").format(arg
['default']))
179 elif arg
['type'] == 'boolean':
180 parser
.add_argument('--' + argument
.replace('_', '-'),
181 action
='store_const', const
=True,
182 help=arg
['help_yes'])
183 parser
.add_argument('--no-' + argument
.replace('_', '-'),
184 action
='store_const', const
=True,
187 parser
.add_argument('--' + argument
.replace('_', '-'),
188 action
='store_const', const
=True,
190 parser
.add_argument('--',
192 help=_("Kivy arguments. All arguments after this are interpreted\
193 by Kivy. Pass \"-- --help\" to get Kivy's usage."))
195 args
= parser
.parse_args(argv
)
197 Config
.yml_file
= args
.config
200 if Config
.device
is not None:
201 sd
.default
.device
= Config
.device
203 if Config
.list_devices
:
204 print(sd
.query_devices())
208 sys
.argv
.extend(["-c", "kivy:log_level:debug"])
210 if Config
.language
!= 'en':
211 gettext
.translation("music_sampler",
212 localedir
=path() + '/locales',
213 languages
=[Config
.language
]).install()
214 if not Config
.music_path
.endswith("/"):
215 Config
.music_path
= Config
.music_path
+ "/"
218 max_size
= max(max(map(len, Configs_order
)), len('config'))
219 info_print("{:<{}} : {}".format(
220 "config", max_size
, Config
.yml_file
))
221 for item
in Config
.__dict
__:
222 if item
in Configs_order
:
223 info_print("{:<{}} : {}".format(
224 item
, max_size
, getattr(Config
, item
)))
226 def build_config(args
):
227 stream
= open(Config
.yml_file
, "r")
229 config
= yaml
.safe_load(stream
)
230 except Exception as e
:
231 error_print("Error while loading config file: {}".format(e
))
234 if 'config' in config
:
235 config
= config
['config']
239 for config_item
in Configs_order
:
240 if Configs
[config_item
]['type'] != 'boolean' and \
241 Configs
[config_item
]['type'] != 'action':
242 t
= Configs
[config_item
]['type'] or str
243 if hasattr(args
, config_item
):
244 setattr(Config
, config_item
, getattr(args
, config_item
))
245 elif config_item
in config
:
246 setattr(Config
, config_item
, t(config
[config_item
]))
248 setattr(Config
, config_item
, Configs
[config_item
]['default'])
249 elif Configs
[config_item
]['type'] == 'boolean':
250 if hasattr(args
, 'no_' + config_item
) or hasattr(args
, config_item
):
251 setattr(Config
, config_item
, hasattr(args
, config_item
))
252 elif config_item
in config
:
253 setattr(Config
, config_item
, config
[config_item
])
255 setattr(Config
, config_item
, Configs
[config_item
]['default'])
257 setattr(Config
, config_item
, hasattr(args
, config_item
))
261 if getattr(sys
, 'frozen', False):
262 with open(path() + ".pyinstaller_commit", "r") as f
:
265 return _("option '-V' can only be used in bundled package")
267 def duration_to_min_sec(duration
):
268 minutes
= int(duration
/ 60)
269 seconds
= int(duration
) % 60
271 return "{:2}:{:0>2}".format(minutes
, seconds
)
273 return "{}:{:0>2}".format(minutes
, seconds
)
275 def gain(volume
, old_volume
=None):
276 if old_volume
is None:
277 return 20 * math
.log10(max(volume
, 0.1) / 100)
280 20 * math
.log10(max(volume
, 0.1) / max(old_volume
, 0.1)),
283 def debug_print(message
, with_trace
=None):
284 if with_trace
is None:
285 with_trace
= (Logger
.getEffectiveLevel() < logging
.WARN
)
286 with_trace
&= (sys
.exc_info()[0] is not None)
288 Logger
.debug('MusicSampler: ' + message
, exc_info
=with_trace
)
290 def error_print(message
, exit
=False, with_trace
=None):
291 if with_trace
is None:
292 with_trace
= (Logger
.getEffectiveLevel() < logging
.WARN
)
293 with_trace
&= (sys
.exc_info()[0] is not None)
295 # FIXME: handle it correctly when in a thread
297 Logger
.critical('MusicSampler: ' + message
, exc_info
=with_trace
)
300 Logger
.error('MusicSampler: ' + message
, exc_info
=with_trace
)
302 def warn_print(message
, with_trace
=None):
303 if with_trace
is None:
304 with_trace
= (Logger
.getEffectiveLevel() < logging
.WARN
)
305 with_trace
&= (sys
.exc_info()[0] is not None)
307 Logger
.warn('MusicSampler: ' + message
, exc_info
=with_trace
)
309 def info_print(message
, with_trace
=None):
310 if with_trace
is None:
311 with_trace
= (Logger
.getEffectiveLevel() < logging
.WARN
)
312 with_trace
&= (sys
.exc_info()[0] is not None)
314 Logger
.info('MusicSampler: ' + message
, exc_info
=with_trace
)