kitbash 1.0.1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kitbash/__init__.py +113 -0
- kitbash/gui/__init__.py +92 -0
- kitbash/gui/main_window.py +1263 -0
- kitbash/gui/main_window.ui +433 -0
- kitbash/gui/samples_explorer.py +200 -0
- kitbash/gui/samples_explorer.ui +126 -0
- kitbash/res/group_expanded.svg +2 -0
- kitbash/res/group_hidden.svg +2 -0
- kitbash/res/kitbash-icon.png +0 -0
- kitbash/scripts/bash_project.py +97 -0
- kitbash/styles/light.css +135 -0
- kitbash/styles/system.css +65 -0
- kitbash-1.0.1.dist-info/METADATA +25 -0
- kitbash-1.0.1.dist-info/RECORD +17 -0
- kitbash-1.0.1.dist-info/WHEEL +5 -0
- kitbash-1.0.1.dist-info/entry_points.txt +4 -0
- kitbash-1.0.1.dist-info/licenses/LICENSE +619 -0
kitbash/__init__.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# kitbash/__init__.py
|
|
2
|
+
#
|
|
3
|
+
# Copyright 2024 liyang <liyang@veronica>
|
|
4
|
+
#
|
|
5
|
+
# This program is free software; you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with this program; if not, write to the Free Software
|
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
18
|
+
# MA 02110-1301, USA.
|
|
19
|
+
#
|
|
20
|
+
"""
|
|
21
|
+
kitbash is a program you can use to combine parts of various SFZ files into a
|
|
22
|
+
new SFZ with instruments "borrowed" from the originals.
|
|
23
|
+
"""
|
|
24
|
+
import sys, os, argparse, logging, json, glob
|
|
25
|
+
try:
|
|
26
|
+
from functools import cache
|
|
27
|
+
except ImportError:
|
|
28
|
+
from functools import lru_cache as cache
|
|
29
|
+
from PyQt5.QtCore import QSettings
|
|
30
|
+
from PyQt5.QtWidgets import QApplication
|
|
31
|
+
from qt_extras import DevilBox
|
|
32
|
+
from conn_jack import JackConnectError
|
|
33
|
+
|
|
34
|
+
__version__ = "1.0.1"
|
|
35
|
+
|
|
36
|
+
APPLICATION_NAME = "kitbash"
|
|
37
|
+
PACKAGE_DIR = os.path.dirname(__file__)
|
|
38
|
+
DEFAULT_STYLE = 'system'
|
|
39
|
+
KEY_STYLE = 'Style'
|
|
40
|
+
KEY_SAMPLES_MODE = 'KitSaveDialog/SamplesMode'
|
|
41
|
+
KEY_RECENT_DRUMKIT_FOLDER = 'RecentDrumkitFolder'
|
|
42
|
+
KEY_RECENT_DRUMKITS = 'RecentDrumkits'
|
|
43
|
+
KEY_RECENT_PROJECT_FOLDER = 'RecentProjectFolder'
|
|
44
|
+
KEY_RECENT_PROJECTS = 'RecentProjects'
|
|
45
|
+
KEY_SAMPLE_XPLORE_ROOT = 'SampleExplorer/Root'
|
|
46
|
+
KEY_SAMPLE_XPLORE_CURR = 'SampleExplorer/Current'
|
|
47
|
+
|
|
48
|
+
@cache
|
|
49
|
+
def settings():
|
|
50
|
+
return QSettings('ZenSoSo', 'kitbash')
|
|
51
|
+
|
|
52
|
+
@cache
|
|
53
|
+
def styles():
|
|
54
|
+
return {
|
|
55
|
+
os.path.splitext(os.path.basename(path))[0] : path \
|
|
56
|
+
for path in glob.glob(os.path.join(PACKAGE_DIR, 'styles', '*.css'))
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
def set_application_style():
|
|
60
|
+
style = settings().value(KEY_STYLE, DEFAULT_STYLE)
|
|
61
|
+
with open(styles()[style], 'r', encoding = 'utf-8') as cssfile:
|
|
62
|
+
QApplication.instance().setStyleSheet(cssfile.read())
|
|
63
|
+
|
|
64
|
+
def main():
|
|
65
|
+
from kitbash.gui.main_window import MainWindow
|
|
66
|
+
|
|
67
|
+
p = argparse.ArgumentParser()
|
|
68
|
+
p.epilog = """
|
|
69
|
+
Write your help text!
|
|
70
|
+
"""
|
|
71
|
+
p.add_argument('Filename', type=str, nargs='?', help='SFZ file[s] to include at startup')
|
|
72
|
+
p.add_argument("--log-file", "-l", type=str, help="Log to this file")
|
|
73
|
+
p.add_argument("--verbose", "-v", action="store_true", help="Show more detailed debug information")
|
|
74
|
+
options = p.parse_args()
|
|
75
|
+
|
|
76
|
+
log_level = logging.DEBUG if options.verbose else logging.ERROR
|
|
77
|
+
log_format = "[%(filename)24s:%(lineno)4d] %(levelname)-8s %(message)s"
|
|
78
|
+
if options.log_file:
|
|
79
|
+
logging.basicConfig(
|
|
80
|
+
filename = options.log_file,
|
|
81
|
+
filemode = 'w',
|
|
82
|
+
level = log_level,
|
|
83
|
+
format = log_format
|
|
84
|
+
)
|
|
85
|
+
else:
|
|
86
|
+
logging.basicConfig(
|
|
87
|
+
level = log_level,
|
|
88
|
+
format = log_format
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
#-----------------------------------------------------------------------
|
|
92
|
+
# Annoyance fix per:
|
|
93
|
+
# https://stackoverflow.com/questions/986964/qt-session-management-error
|
|
94
|
+
try:
|
|
95
|
+
del os.environ['SESSION_MANAGER']
|
|
96
|
+
except KeyError:
|
|
97
|
+
pass
|
|
98
|
+
#-----------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
app = QApplication([])
|
|
101
|
+
try:
|
|
102
|
+
main_window = MainWindow(options)
|
|
103
|
+
except JackConnectError:
|
|
104
|
+
DevilBox('Could not connect to JACK server. Is it running?')
|
|
105
|
+
sys.exit(1)
|
|
106
|
+
main_window.show()
|
|
107
|
+
sys.exit(app.exec())
|
|
108
|
+
|
|
109
|
+
if __name__ == "__main__":
|
|
110
|
+
sys.exit(main())
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# end kitbash/__init__.py
|
kitbash/gui/__init__.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# kitbash/gui/__init__.py
|
|
2
|
+
#
|
|
3
|
+
# Copyright 2025 liyang <liyang@veronica>
|
|
4
|
+
#
|
|
5
|
+
# This program is free software; you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with this program; if not, write to the Free Software
|
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
18
|
+
# MA 02110-1301, USA.
|
|
19
|
+
#
|
|
20
|
+
import sys, os, argparse, logging, json, glob
|
|
21
|
+
from functools import lru_cache
|
|
22
|
+
from PyQt5.QtGui import QIcon
|
|
23
|
+
from PyQt5.QtWidgets import QApplication, QWidget, QSplitter
|
|
24
|
+
from qt_extras import DevilBox
|
|
25
|
+
from kitbash import PACKAGE_DIR, settings
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
AUDIO_ICON_SIZE = 16
|
|
29
|
+
|
|
30
|
+
@lru_cache
|
|
31
|
+
def group_expanded_icon():
|
|
32
|
+
"""
|
|
33
|
+
Defers loading of QPixmaps until a QGuiApplication is instantiated.
|
|
34
|
+
This is a Qt5 requirement.
|
|
35
|
+
"""
|
|
36
|
+
return QIcon(os.path.join(PACKAGE_DIR, 'res', 'group_expanded.svg'))
|
|
37
|
+
|
|
38
|
+
@lru_cache
|
|
39
|
+
def group_hidden_icon():
|
|
40
|
+
return QIcon(os.path.join(PACKAGE_DIR, 'res', 'group_hidden.svg'))
|
|
41
|
+
|
|
42
|
+
@lru_cache
|
|
43
|
+
def remove_icon():
|
|
44
|
+
return QIcon.fromTheme('edit-delete')
|
|
45
|
+
|
|
46
|
+
@lru_cache
|
|
47
|
+
def audio_off_pixmap():
|
|
48
|
+
return QIcon.fromTheme('audio-volume-muted').pixmap(AUDIO_ICON_SIZE)
|
|
49
|
+
|
|
50
|
+
@lru_cache
|
|
51
|
+
def audio_on_pixmap():
|
|
52
|
+
return QIcon.fromTheme('audio-volume-high').pixmap(AUDIO_ICON_SIZE)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class GeometrySaver:
|
|
56
|
+
"""
|
|
57
|
+
Provides classes declared in this project which inherit from QDialog methods to
|
|
58
|
+
easily save/restore window / splitter geometry.
|
|
59
|
+
|
|
60
|
+
Geometry is saved in this project's QSettings accessed as "settings()"
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
def restore_geometry(self):
|
|
64
|
+
if not hasattr(self, 'restoreGeometry'):
|
|
65
|
+
logging.error('Object of type %s has no "restoreGeometry" function',
|
|
66
|
+
type(self).__name__)
|
|
67
|
+
return
|
|
68
|
+
geometry = settings().value(self.__geometry_key())
|
|
69
|
+
if geometry is not None:
|
|
70
|
+
self.restoreGeometry(geometry)
|
|
71
|
+
for splitter in self.findChildren(QSplitter):
|
|
72
|
+
geometry = settings().value(self.__splitter_geometry_key(splitter))
|
|
73
|
+
if geometry is not None:
|
|
74
|
+
splitter.restoreState(geometry)
|
|
75
|
+
|
|
76
|
+
def save_geometry(self):
|
|
77
|
+
if not hasattr(self, 'saveGeometry'):
|
|
78
|
+
logging.error('Object of type %s has no "saveGeometry" function',
|
|
79
|
+
type(self).__name__)
|
|
80
|
+
return
|
|
81
|
+
settings().setValue(self.__geometry_key(), self.saveGeometry())
|
|
82
|
+
for splitter in self.findChildren(QSplitter):
|
|
83
|
+
settings().setValue(self.__splitter_geometry_key(splitter), splitter.saveState())
|
|
84
|
+
|
|
85
|
+
def __geometry_key(self):
|
|
86
|
+
return '{}/geometry'.format(type(self).__name__)
|
|
87
|
+
|
|
88
|
+
def __splitter_geometry_key(self, splitter):
|
|
89
|
+
return '{}/{}/geometry'.format(type(self).__name__, splitter.objectName())
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# end kitbash/gui/__init__.py
|