From: Ismaël Bouya Date: Wed, 27 Jul 2016 20:15:25 +0000 (+0200) Subject: Use pip setup file X-Git-Tag: 1.0.0 X-Git-Url: https://git.immae.eu/?a=commitdiff_plain;h=6ebe62478a49df22c55ef6a2b1200473500a7f80;p=perso%2FImmae%2FProjets%2FPython%2FMusicSampler.git Use pip setup file --- diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..5dab67a --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include music_sampler/music_sampler.kv diff --git a/README b/README new file mode 100644 index 0000000..6017dcd --- /dev/null +++ b/README @@ -0,0 +1,14 @@ +Music Sampler is a music player which associates each key on the keyboard to a +set of actions to run. + +See full documentation in french in documentation_fr.md + +Git repository: +https://git.immae.eu/?p=perso/Immae/Projets/Python/MusicSampler.git + +Bug Tracker: +https://git.immae.eu/mantisbt/view_all_bug_page.php?project_id=1 + +Contributors: +Ismaël Bouya +Denise Maurice diff --git a/music_sampler.spec b/music_sampler.spec index 3794397..791cd68 100644 --- a/music_sampler.spec +++ b/music_sampler.spec @@ -28,11 +28,11 @@ pyinstaller_file.write(commit_message) pyinstaller_file.close() data = [ - ('music_sampler.kv', '.'), + ('music_sampler/music_sampler.kv', '.'), ('.pyinstaller_commit', '.') ] -a = Analysis(['music_sampler.py'], +a = Analysis(['run.py'], binaries=None, datas=data, hookspath=hookspath(), diff --git a/music_sampler/__init__.py b/music_sampler/__init__.py index 4827e6c..aa551fb 100644 --- a/music_sampler/__init__.py +++ b/music_sampler/__init__.py @@ -1,192 +1 @@ -# -*- coding: utf-8 -*- -import argparse -import sys -import os -import math -import sounddevice as sd -import logging - -from . import sysfont - -class Config: - pass - -def find_font(name, style=sysfont.STYLE_NONE): - if getattr(sys, 'frozen', False): - font = sys._MEIPASS + "/fonts/{}_{}.ttf".format(name, style) - else: - font = sysfont.get_font(name, style=style) - if font is not None: - font = font[4] - return font - -def register_fonts(): - from kivy.core.text import LabelBase - - ubuntu_regular = find_font("Ubuntu", style=sysfont.STYLE_NORMAL) - ubuntu_bold = find_font("Ubuntu", style=sysfont.STYLE_BOLD) - symbola = find_font("Symbola") - - if ubuntu_regular is None: - error_print("Font Ubuntu regular could not be found, please install it.") - sys.exit() - if symbola is None: - error_print("Font Symbola could not be found, please install it.") - sys.exit() - if ubuntu_bold is None: - warn_print("Font Ubuntu Bold could not be found.") - - LabelBase.register(name="Ubuntu", - fn_regular=ubuntu_regular, - fn_bold=ubuntu_bold) - LabelBase.register(name="Symbola", - fn_regular=symbola) - - -def path(): - if getattr(sys, 'frozen', False): - return sys._MEIPASS + "/" - else: - path = os.path.dirname(os.path.realpath(__file__)) - return path + "/../" - -def parse_args(): - argv = sys.argv[1 :] - sys.argv = sys.argv[: 1] - if "--" in argv: - index = argv.index("--") - kivy_args = argv[index+1 :] - argv = argv[: index] - - sys.argv.extend(kivy_args) - - 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)") - 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('--', - dest="args", - help="Kivy arguments. All arguments after this are interpreted\ - by Kivy. Pass \"-- --help\" to get Kivy's usage.") - - from kivy.logger import Logger - Logger.setLevel(logging.WARN) - - args = parser.parse_args(argv) - - Config.yml_file = args.config - - 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 - if args.music_path.endswith("/"): - Config.music_path = args.music_path - else: - Config.music_path = args.music_path + "/" - -class DebugModeAction(argparse.Action): - def __call__(self, parser, namespace, values, option_string=None): - from kivy.logger import Logger - Logger.setLevel(logging.DEBUG) - -class SelectDeviceAction(argparse.Action): - def __call__(self, parser, namespace, values, option_string=None): - sd.default.device = values - -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): - with open(path() + ".pyinstaller_commit", "r") as f: - return f.read() - else: - return "option '-v' can only be used in bundled package" - -def duration_to_min_sec(duration): - minutes = int(duration / 60) - seconds = int(duration) % 60 - if minutes < 100: - return "{:2}:{:0>2}".format(minutes, seconds) - else: - return "{}:{:0>2}".format(minutes, seconds) - -def gain(volume, old_volume=None): - if old_volume is None: - return 20 * math.log10(max(volume, 0.1) / 100) - else: - return [ - 20 * math.log10(max(volume, 0.1) / max(old_volume, 0.1)), - max(volume, 0)] - -def debug_print(message, with_trace=False): - from kivy.logger import Logger - Logger.debug('MusicSampler: ' + message, exc_info=with_trace) - -def error_print(message, with_trace=False): - from kivy.logger import Logger - Logger.error('MusicSampler: ' + message, exc_info=with_trace) - -def warn_print(message, with_trace=False): - from kivy.logger import Logger - Logger.warn('MusicSampler: ' + message, exc_info=with_trace) +from . import app diff --git a/music_sampler/action.py b/music_sampler/action.py index 4b5a71d..ef56b7c 100644 --- a/music_sampler/action.py +++ b/music_sampler/action.py @@ -1,5 +1,5 @@ from transitions.extensions import HierarchicalMachine as Machine -from . import debug_print, error_print +from .helpers import debug_print, error_print from . import actions class Action: diff --git a/music_sampler.py b/music_sampler/app.py similarity index 85% rename from music_sampler.py rename to music_sampler/app.py index 714598a..81c47a7 100644 --- a/music_sampler.py +++ b/music_sampler/app.py @@ -1,6 +1,6 @@ -import music_sampler +from .helpers import parse_args, register_fonts, duration_to_min_sec, path -music_sampler.parse_args() +parse_args() import kivy kivy.require("1.9.1") @@ -11,10 +11,10 @@ from kivy.properties import ListProperty, StringProperty from kivy.clock import Clock from kivy.core.window import Window from kivy.lang import Builder -from music_sampler.key import Key -from music_sampler.mapping import Mapping +from .key import Key +from .mapping import Mapping -music_sampler.register_fonts() +register_fonts() class KeyList(RelativeLayout): keylist = ListProperty([]) @@ -51,8 +51,8 @@ class PlayList(RelativeLayout): continue text = "{}/{}".format( - music_sampler.duration_to_min_sec(music_file.sound_position), - music_sampler.duration_to_min_sec(music_file.sound_duration)) + duration_to_min_sec(music_file.sound_position), + duration_to_min_sec(music_file.sound_duration)) if music_file.is_loaded_paused(): self.playlist.append(["⏸", music_file.name, text, False]) @@ -86,6 +86,6 @@ class MusicSamplerApp(App): return Screen() -if __name__ == '__main__': - Builder.load_file(music_sampler.path() + "/music_sampler.kv") +def main(): + Builder.load_file(path() + "/music_sampler.kv") MusicSamplerApp().run() diff --git a/music_sampler/helpers.py b/music_sampler/helpers.py new file mode 100644 index 0000000..1788084 --- /dev/null +++ b/music_sampler/helpers.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +import argparse +import sys +import os +import math +import sounddevice as sd +import logging + +from . import sysfont + +class Config: + pass + +def find_font(name, style=sysfont.STYLE_NONE): + if getattr(sys, 'frozen', False): + font = sys._MEIPASS + "/fonts/{}_{}.ttf".format(name, style) + else: + font = sysfont.get_font(name, style=style) + if font is not None: + font = font[4] + return font + +def register_fonts(): + from kivy.core.text import LabelBase + + ubuntu_regular = find_font("Ubuntu", style=sysfont.STYLE_NORMAL) + ubuntu_bold = find_font("Ubuntu", style=sysfont.STYLE_BOLD) + symbola = find_font("Symbola") + + if ubuntu_regular is None: + error_print("Font Ubuntu regular could not be found, please install it.") + sys.exit() + if symbola is None: + error_print("Font Symbola could not be found, please install it.") + sys.exit() + if ubuntu_bold is None: + warn_print("Font Ubuntu Bold could not be found.") + + LabelBase.register(name="Ubuntu", + fn_regular=ubuntu_regular, + fn_bold=ubuntu_bold) + LabelBase.register(name="Symbola", + fn_regular=symbola) + + +def path(): + if getattr(sys, 'frozen', False): + return sys._MEIPASS + "/" + else: + return os.path.dirname(os.path.realpath(__file__)) + +def parse_args(): + argv = sys.argv[1 :] + sys.argv = sys.argv[: 1] + if "--" in argv: + index = argv.index("--") + kivy_args = argv[index+1 :] + argv = argv[: index] + + sys.argv.extend(kivy_args) + + 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)") + 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('--', + dest="args", + help="Kivy arguments. All arguments after this are interpreted\ + by Kivy. Pass \"-- --help\" to get Kivy's usage.") + + from kivy.logger import Logger + Logger.setLevel(logging.WARN) + + args = parser.parse_args(argv) + + Config.yml_file = args.config + + 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 + if args.music_path.endswith("/"): + Config.music_path = args.music_path + else: + Config.music_path = args.music_path + "/" + +class DebugModeAction(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + from kivy.logger import Logger + Logger.setLevel(logging.DEBUG) + +class SelectDeviceAction(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + sd.default.device = values + +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): + with open(path() + ".pyinstaller_commit", "r") as f: + return f.read() + else: + return "option '-v' can only be used in bundled package" + +def duration_to_min_sec(duration): + minutes = int(duration / 60) + seconds = int(duration) % 60 + if minutes < 100: + return "{:2}:{:0>2}".format(minutes, seconds) + else: + return "{}:{:0>2}".format(minutes, seconds) + +def gain(volume, old_volume=None): + if old_volume is None: + return 20 * math.log10(max(volume, 0.1) / 100) + else: + return [ + 20 * math.log10(max(volume, 0.1) / max(old_volume, 0.1)), + max(volume, 0)] + +def debug_print(message, with_trace=False): + from kivy.logger import Logger + Logger.debug('MusicSampler: ' + message, exc_info=with_trace) + +def error_print(message, with_trace=False): + from kivy.logger import Logger + Logger.error('MusicSampler: ' + message, exc_info=with_trace) + +def warn_print(message, with_trace=False): + from kivy.logger import Logger + Logger.warn('MusicSampler: ' + message, exc_info=with_trace) + diff --git a/music_sampler/key.py b/music_sampler/key.py index 66e792d..b05de4c 100644 --- a/music_sampler/key.py +++ b/music_sampler/key.py @@ -4,7 +4,7 @@ from kivy.properties import AliasProperty, BooleanProperty, \ from kivy.uix.behaviors import ButtonBehavior from .action import Action -from . import debug_print +from .helpers import debug_print import time import threading from transitions.extensions import HierarchicalMachine as Machine diff --git a/music_sampler/lock.py b/music_sampler/lock.py index 9beafcd..5befe33 100644 --- a/music_sampler/lock.py +++ b/music_sampler/lock.py @@ -1,6 +1,6 @@ import threading -from . import debug_print +from .helpers import debug_print class Lock: def __init__(self, lock_type): diff --git a/music_sampler/mapping.py b/music_sampler/mapping.py index bb20e67..ca471ef 100644 --- a/music_sampler/mapping.py +++ b/music_sampler/mapping.py @@ -12,7 +12,7 @@ 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 .helpers import Config, gain, error_print, warn_print from .action import Action class Mapping(RelativeLayout): diff --git a/music_sampler/mixer.py b/music_sampler/mixer.py index 9242b61..c8ec907 100644 --- a/music_sampler/mixer.py +++ b/music_sampler/mixer.py @@ -2,7 +2,7 @@ import sounddevice as sd import audioop import time -from . import Config +from .helpers import Config sample_width = Config.sample_width diff --git a/music_sampler/music_file.py b/music_sampler/music_file.py index 2d3ba72..fa6293d 100644 --- a/music_sampler/music_file.py +++ b/music_sampler/music_file.py @@ -8,7 +8,7 @@ import os.path import audioop from .lock import Lock -from . import Config, gain, debug_print, error_print +from .helpers import Config, gain, debug_print, error_print from .mixer import Mixer from .music_effect import GainEffect diff --git a/music_sampler.kv b/music_sampler/music_sampler.kv similarity index 100% rename from music_sampler.kv rename to music_sampler/music_sampler.kv diff --git a/run.py b/run.py new file mode 100644 index 0000000..b486c50 --- /dev/null +++ b/run.py @@ -0,0 +1,3 @@ +import music_sampler + +music_sampler.app.main() diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..a4cdb3c --- /dev/null +++ b/setup.py @@ -0,0 +1,40 @@ +from setuptools import setup + +def readme(): + with open('README') as f: + return f.read() + +setup(name='music_sampler', + setup_requires=['setuptools_scm'], + use_scm_version=True, + description='A music player which associates each key on the keyboard ' + 'to a set of actions to run', + long_description=readme(), + classifiers= [ + 'Development Status :: 4 - Beta', + 'Intended Audience :: End Users/Desktop', + 'License :: OSI Approved :: MIT License', + 'Operating System :: POSIX :: Linux', + 'Programming Language :: Python :: 3.5', + 'Topic :: Multimedia :: Sound/Audio :: Players' + ], + keywords='music sampler keyboard', + url='https://git.immae.eu/?p=perso/Immae/Projets/Python/MusicSampler.git', + author='Ismaël Bouya', + author_email='ismael.bouya@normalesup.org', + license='MIT', + packages=['music_sampler', 'music_sampler.actions'], + install_requires=[ + 'Kivy>=1.9.1', + 'pydub>=0.16.4', + 'Pygame>=1.9.2.dev1', + 'sounddevice>=0.3.3', + 'TRANSITIONS>=0.4.1', + 'PyYAML>=3.11' + ], + entry_points={ + 'console_scripts': ['music_sampler=music_sampler.app:main'], + }, + include_package_data=True, + zip_safe=False) +