]>
git.immae.eu Git - perso/Immae/Projets/Python/MusicSampler.git/blob - music_sampler/helpers.py
943e5a197465143dc2f47e193bfbcc0f3bdf94e2
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
+ "/"
217 def build_config(args
):
218 stream
= open(Config
.yml_file
, "r")
220 config
= yaml
.safe_load(stream
)
221 except Exception as e
:
222 error_print("Error while loading config file: {}".format(e
))
225 if 'config' in config
:
226 config
= config
['config']
230 for config_item
in Configs_order
:
231 if Configs
[config_item
]['type'] != 'boolean' and \
232 Configs
[config_item
]['type'] != 'action':
233 t
= Configs
[config_item
]['type'] or str
234 if hasattr(args
, config_item
):
235 setattr(Config
, config_item
, getattr(args
, config_item
))
236 elif config_item
in config
:
237 setattr(Config
, config_item
, t(config
[config_item
]))
239 setattr(Config
, config_item
, Configs
[config_item
]['default'])
240 elif Configs
[config_item
]['type'] == 'boolean':
241 if hasattr(args
, 'no_' + config_item
) or hasattr(args
, config_item
):
242 setattr(Config
, config_item
, hasattr(args
, config_item
))
243 elif config_item
in config
:
244 setattr(Config
, config_item
, config
[config_item
])
246 setattr(Config
, config_item
, Configs
[config_item
]['default'])
248 setattr(Config
, config_item
, hasattr(args
, config_item
))
252 if getattr(sys
, 'frozen', False):
253 with open(path() + ".pyinstaller_commit", "r") as f
:
256 return _("option '-V' can only be used in bundled package")
258 def duration_to_min_sec(duration
):
259 minutes
= int(duration
/ 60)
260 seconds
= int(duration
) % 60
262 return "{:2}:{:0>2}".format(minutes
, seconds
)
264 return "{}:{:0>2}".format(minutes
, seconds
)
266 def gain(volume
, old_volume
=None):
267 if old_volume
is None:
268 return 20 * math
.log10(max(volume
, 0.1) / 100)
271 20 * math
.log10(max(volume
, 0.1) / max(old_volume
, 0.1)),
274 def debug_print(message
, with_trace
=None):
275 if with_trace
is None:
276 with_trace
= (Logger
.getEffectiveLevel() < logging
.WARN
)
277 with_trace
&= (sys
.exc_info()[0] is not None)
279 Logger
.debug('MusicSampler: ' + message
, exc_info
=with_trace
)
281 def error_print(message
, exit
=False, with_trace
=None):
282 if with_trace
is None:
283 with_trace
= (Logger
.getEffectiveLevel() < logging
.WARN
)
284 with_trace
&= (sys
.exc_info()[0] is not None)
286 # FIXME: handle it correctly when in a thread
288 Logger
.critical('MusicSampler: ' + message
, exc_info
=with_trace
)
291 Logger
.error('MusicSampler: ' + message
, exc_info
=with_trace
)
293 def warn_print(message
, with_trace
=None):
294 if with_trace
is None:
295 with_trace
= (Logger
.getEffectiveLevel() < logging
.WARN
)
296 with_trace
&= (sys
.exc_info()[0] is not None)
298 Logger
.warn('MusicSampler: ' + message
, exc_info
=with_trace
)