kitbash 1.5.2__tar.gz → 1.8.0__tar.gz

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.
Files changed (28) hide show
  1. kitbash-1.8.0/PKG-INFO +128 -0
  2. kitbash-1.8.0/README.md +111 -0
  3. {kitbash-1.5.2 → kitbash-1.8.0}/kitbash/__init__.py +10 -2
  4. {kitbash-1.5.2 → kitbash-1.8.0}/kitbash/__main__.py +4 -8
  5. {kitbash-1.5.2 → kitbash-1.8.0}/kitbash/gui/drumkit_widget.py +14 -5
  6. {kitbash-1.5.2 → kitbash-1.8.0}/kitbash/gui/kit_save_dialog.py +0 -1
  7. {kitbash-1.5.2 → kitbash-1.8.0}/kitbash/gui/main_window.py +54 -81
  8. {kitbash-1.5.2 → kitbash-1.8.0}/kitbash/gui/main_window.ui +13 -13
  9. kitbash-1.8.0/kitbash/install.py +42 -0
  10. kitbash-1.8.0/kitbash/jack_audio.py +78 -0
  11. kitbash-1.8.0/kitbash/res/kitbash-icon.png +0 -0
  12. kitbash-1.8.0/kitbash/res/kitbash-icon.svg +168 -0
  13. {kitbash-1.5.2 → kitbash-1.8.0}/kitbash/worker_threads.py +3 -3
  14. {kitbash-1.5.2 → kitbash-1.8.0}/pyproject.toml +7 -8
  15. kitbash-1.5.2/PKG-INFO +0 -22
  16. kitbash-1.5.2/README.md +0 -4
  17. kitbash-1.5.2/kitbash/jack_audio.py +0 -243
  18. kitbash-1.5.2/kitbash/res/kitbash-icon.png +0 -0
  19. {kitbash-1.5.2 → kitbash-1.8.0}/.gitignore +0 -0
  20. {kitbash-1.5.2 → kitbash-1.8.0}/LICENSE +0 -0
  21. {kitbash-1.5.2 → kitbash-1.8.0}/kitbash/gui/__init__.py +0 -0
  22. {kitbash-1.5.2 → kitbash-1.8.0}/kitbash/res/empty.sfz +0 -0
  23. {kitbash-1.5.2 → kitbash-1.8.0}/kitbash/res/group_expanded.svg +0 -0
  24. {kitbash-1.5.2 → kitbash-1.8.0}/kitbash/res/group_hidden.svg +0 -0
  25. {kitbash-1.5.2 → kitbash-1.8.0}/kitbash/scripts/bash_project.py +0 -0
  26. {kitbash-1.5.2 → kitbash-1.8.0}/kitbash/styles/light.css +0 -0
  27. {kitbash-1.5.2 → kitbash-1.8.0}/kitbash/styles/system.css +0 -0
  28. {kitbash-1.5.2 → kitbash-1.8.0}/tests/file_save_dialog.py +0 -0
kitbash-1.8.0/PKG-INFO ADDED
@@ -0,0 +1,128 @@
1
+ Metadata-Version: 2.1
2
+ Name: kitbash
3
+ Version: 1.8.0
4
+ Summary: Provides universal settings, styles, cached icons, and pixmaps, and the base
5
+ Author-email: Leon Dionne <ldionne@dridesign.sh.cn>
6
+ Description-Content-Type: text/markdown
7
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
8
+ Requires-Dist: log_soso >= 1.0.3
9
+ Requires-Dist: PyQt5
10
+ Requires-Dist: qt_liquid_pool >= 1.2.0
11
+ Requires-Dist: recent_items_list >= 1.1.2
12
+ Requires-Dist: sfzen >= 2.3.2
13
+ Requires-Dist: soso_qt_extras >= 1.7.0
14
+ Requires-Dist: xdg_soso >= 0.2.0
15
+ Project-URL: Home, https://github.com/Zen-Master-SoSo/kitbash
16
+
17
+ # KitBash
18
+
19
+ A GUI application which you can use to create a new SFZ drumkit from pieces of other drumkits.
20
+
21
+ ## Intro
22
+
23
+ Got a drumkit [SFZ](https://sfzformat.com/) that sounds pretty good, but
24
+ there's just one instrument that doesn't quite cut it? Want to replace that one
25
+ snare, or even that whole set of tom-toms?
26
+
27
+ That's what kitbash was written for!
28
+
29
+ Kitbash allows you to create projects in which you can import mutiple drumkits
30
+ from SFZ files, select the pieces of each kit you want, then export the
31
+ finished drumkit to a new SFZ.
32
+
33
+ ## Usage
34
+
35
+ Starting with an empty project, use the "Edit" -> "Load Drumkit" menu, or click
36
+ on the "plus" symbol in the toolbar. You'll see all the instruments defined in
37
+ the drumkit you just loaded, grouped into categories, such as "Snares", "Tom
38
+ toms", "Hi-hats", etc.
39
+
40
+ ### Audio preview
41
+
42
+ To listen to audio playback, you need to select an "Audio sink" from the dropdown
43
+ list at the top-right of the window. You audio out devices should be listed
44
+ there. Note that this is a JACK application, and your JACK audio connection kit
45
+ server must be running to play audio.
46
+
47
+ To preview the sound of each instrument, click on the instrument name.
48
+ Releasing the mouse stops the playback.
49
+
50
+ To preview the drumkit you are assembling, you need to send it MIDI note
51
+ events. Choose the MIDI source from the dropdown list at the top-right area of
52
+ the window, and send MIDI events. A MIDI source can be an external device, like
53
+ a MIDI keyboard, or the MIDI output of another program, such as
54
+ [qtractor](https://qtractor.org/), [MuseScore](https://musescore.com/), or
55
+ [JackMIDILooper](https://github.com/Zen-Master-SoSo/jack_midi_looper).
56
+
57
+ ### Instrument selection
58
+
59
+ The instruments selected to be included in your final drumkit are indicated by
60
+ the check boxes next to the instrument and category names.
61
+
62
+ Check the box next to a category to select all the instruments in that category
63
+ for inclusion in your new drumkit. Check the checkbox next to any individual
64
+ instrument (i.e. "Ride Bell"), to include only that instrument.
65
+
66
+ When you load the first drumkit, all categories and instruments are selected.
67
+ Load another drumkit in the same way as you did the first (using the menu or
68
+ the toolbar). Selecting an instrument from one drumkit de-selects that
69
+ instrument from all other loaded drumkits.
70
+
71
+ You can make changes while playing a loop from the incoming MIDI source, and
72
+ the changes are (almost) immediately made to the "bashed" drumkit you are
73
+ making.
74
+
75
+ ### Exporting SFZ
76
+
77
+ When you're satisfied with what you've selected, you can save the "bashed"
78
+ drumkit as an .sfz file in a new location. From the menu, select "File" ->
79
+ "Save Bashed Kit As..." and choose the location. Or, click the corresponding
80
+ icon in the toolbar.
81
+
82
+
83
+ ### Saving a project
84
+
85
+ A "project" is a list of the source SFZs and which groups and instruments from
86
+ each them are selected. You can save a project for later, make whatever changes
87
+ you desire, and then export the SFZ you created again. This way, you don't have
88
+ to start from scratch every time you wish to make that one small change.
89
+
90
+
91
+ ## Install
92
+
93
+ Install in the usual way:
94
+
95
+ ```bash
96
+ $ pip install kitbash
97
+ ```
98
+
99
+ ### Requirements
100
+
101
+ You'll need both [JACK audio connection kit](https://jackaudio.org/) and
102
+ [liquidsfz](https://github.com/swesterfeld/liquidsfz) in order to have live
103
+ previews. You can run the program without either, but you won't be able to
104
+ listen to your changes as you are making them.
105
+
106
+ To install JACK:
107
+
108
+ ```bash
109
+ $ sudo apt install jackd
110
+ ```
111
+
112
+ ...or...
113
+
114
+ ```bash
115
+ $ sudo dnf install jackd
116
+ ```
117
+
118
+ To install liquidsfz:
119
+
120
+ ```bash
121
+ $ git clone https://github.com/swesterfeld/liquidsfz.git
122
+ ```
123
+
124
+ ... and follow the instructions found in the liquidsfz README to install it.
125
+
126
+
127
+
128
+
@@ -0,0 +1,111 @@
1
+ # KitBash
2
+
3
+ A GUI application which you can use to create a new SFZ drumkit from pieces of other drumkits.
4
+
5
+ ## Intro
6
+
7
+ Got a drumkit [SFZ](https://sfzformat.com/) that sounds pretty good, but
8
+ there's just one instrument that doesn't quite cut it? Want to replace that one
9
+ snare, or even that whole set of tom-toms?
10
+
11
+ That's what kitbash was written for!
12
+
13
+ Kitbash allows you to create projects in which you can import mutiple drumkits
14
+ from SFZ files, select the pieces of each kit you want, then export the
15
+ finished drumkit to a new SFZ.
16
+
17
+ ## Usage
18
+
19
+ Starting with an empty project, use the "Edit" -> "Load Drumkit" menu, or click
20
+ on the "plus" symbol in the toolbar. You'll see all the instruments defined in
21
+ the drumkit you just loaded, grouped into categories, such as "Snares", "Tom
22
+ toms", "Hi-hats", etc.
23
+
24
+ ### Audio preview
25
+
26
+ To listen to audio playback, you need to select an "Audio sink" from the dropdown
27
+ list at the top-right of the window. You audio out devices should be listed
28
+ there. Note that this is a JACK application, and your JACK audio connection kit
29
+ server must be running to play audio.
30
+
31
+ To preview the sound of each instrument, click on the instrument name.
32
+ Releasing the mouse stops the playback.
33
+
34
+ To preview the drumkit you are assembling, you need to send it MIDI note
35
+ events. Choose the MIDI source from the dropdown list at the top-right area of
36
+ the window, and send MIDI events. A MIDI source can be an external device, like
37
+ a MIDI keyboard, or the MIDI output of another program, such as
38
+ [qtractor](https://qtractor.org/), [MuseScore](https://musescore.com/), or
39
+ [JackMIDILooper](https://github.com/Zen-Master-SoSo/jack_midi_looper).
40
+
41
+ ### Instrument selection
42
+
43
+ The instruments selected to be included in your final drumkit are indicated by
44
+ the check boxes next to the instrument and category names.
45
+
46
+ Check the box next to a category to select all the instruments in that category
47
+ for inclusion in your new drumkit. Check the checkbox next to any individual
48
+ instrument (i.e. "Ride Bell"), to include only that instrument.
49
+
50
+ When you load the first drumkit, all categories and instruments are selected.
51
+ Load another drumkit in the same way as you did the first (using the menu or
52
+ the toolbar). Selecting an instrument from one drumkit de-selects that
53
+ instrument from all other loaded drumkits.
54
+
55
+ You can make changes while playing a loop from the incoming MIDI source, and
56
+ the changes are (almost) immediately made to the "bashed" drumkit you are
57
+ making.
58
+
59
+ ### Exporting SFZ
60
+
61
+ When you're satisfied with what you've selected, you can save the "bashed"
62
+ drumkit as an .sfz file in a new location. From the menu, select "File" ->
63
+ "Save Bashed Kit As..." and choose the location. Or, click the corresponding
64
+ icon in the toolbar.
65
+
66
+
67
+ ### Saving a project
68
+
69
+ A "project" is a list of the source SFZs and which groups and instruments from
70
+ each them are selected. You can save a project for later, make whatever changes
71
+ you desire, and then export the SFZ you created again. This way, you don't have
72
+ to start from scratch every time you wish to make that one small change.
73
+
74
+
75
+ ## Install
76
+
77
+ Install in the usual way:
78
+
79
+ ```bash
80
+ $ pip install kitbash
81
+ ```
82
+
83
+ ### Requirements
84
+
85
+ You'll need both [JACK audio connection kit](https://jackaudio.org/) and
86
+ [liquidsfz](https://github.com/swesterfeld/liquidsfz) in order to have live
87
+ previews. You can run the program without either, but you won't be able to
88
+ listen to your changes as you are making them.
89
+
90
+ To install JACK:
91
+
92
+ ```bash
93
+ $ sudo apt install jackd
94
+ ```
95
+
96
+ ...or...
97
+
98
+ ```bash
99
+ $ sudo dnf install jackd
100
+ ```
101
+
102
+ To install liquidsfz:
103
+
104
+ ```bash
105
+ $ git clone https://github.com/swesterfeld/liquidsfz.git
106
+ ```
107
+
108
+ ... and follow the instructions found in the liquidsfz README to install it.
109
+
110
+
111
+
@@ -28,14 +28,14 @@ from functools import lru_cache
28
28
  from PyQt5.QtCore import QSettings
29
29
  from PyQt5.QtWidgets import QApplication, QSplitter
30
30
  from qt_extras import DevilBox
31
- from conn_jack import JackConnectError
32
31
 
33
- __version__ = "1.5.2"
32
+ __version__ = "1.8.0"
34
33
 
35
34
  APPLICATION_NAME = "kitbash"
36
35
  PACKAGE_DIR = dirname(__file__)
37
36
  DEFAULT_STYLE = 'system'
38
37
  AUDIO_ICON_SIZE = 16
38
+ KEY_PREVIEW_VELOCITY = 'PreviewVelocity'
39
39
  KEY_STYLE = 'Style'
40
40
  KEY_SAMPLES_MODE = 'KitSaveDialog/SamplesMode'
41
41
  KEY_RECENT_DRUMKIT_FOLDER = 'RecentDrumkitFolder'
@@ -44,8 +44,16 @@ KEY_RECENT_PROJECT_FOLDER = 'RecentProjectFolder'
44
44
  KEY_RECENT_PROJECTS = 'RecentProjects'
45
45
  KEY_SAMPLE_XPLORE_ROOT = 'SampleExplorer/Root'
46
46
  KEY_SAMPLE_XPLORE_CURR = 'SampleExplorer/Current'
47
+ KEY_MIDI_SOURCE = 'MIDISource'
48
+ KEY_AUDIO_SINK = 'AudioSink'
47
49
 
48
50
 
51
+ def audio():
52
+ if not hasattr(audio, 'instance'):
53
+ from kitbash.jack_audio import Audio
54
+ audio.instance = Audio()
55
+ return audio.instance
56
+
49
57
  @lru_cache
50
58
  def __settings():
51
59
  return QSettings('ZenSoSo', APPLICATION_NAME)
@@ -22,9 +22,8 @@ kitbash is a program you can use to combine parts of various SFZ files into a
22
22
  new SFZ with instruments "borrowed" from the originals.
23
23
  """
24
24
  import sys, os, argparse, logging
25
- from PyQt5.QtWidgets import QApplication
26
- from qt_extras import DevilBox
27
- from conn_jack import JackConnectError
25
+ from PyQt5.QtWidgets import QApplication, QErrorMessage
26
+ from qt_extras import exceptions_hook
28
27
  from kitbash.gui.main_window import MainWindow
29
28
 
30
29
 
@@ -61,11 +60,8 @@ def main():
61
60
  #-----------------------------------------------------------------------
62
61
 
63
62
  app = QApplication([])
64
- try:
65
- main_window = MainWindow(options)
66
- except JackConnectError:
67
- DevilBox('Could not connect to JACK server. Is it running?')
68
- sys.exit(1)
63
+ sys.excepthook = exceptions_hook
64
+ main_window = MainWindow(options)
69
65
  main_window.show()
70
66
  sys.exit(app.exec())
71
67
 
@@ -29,7 +29,7 @@ from PyQt5.QtWidgets import (QApplication, QVBoxLayout, QHBoxLayout, QLabel,
29
29
  QFrame, QSizePolicy, QPushButton, QCheckBox)
30
30
  from qt_extras import SigBlock
31
31
  from sfzen.drumkits import PercussionInstrument
32
- from kitbash import PACKAGE_DIR
32
+ from kitbash import PACKAGE_DIR, KEY_PREVIEW_VELOCITY, get_setting, audio
33
33
 
34
34
 
35
35
  @lru_cache
@@ -64,9 +64,9 @@ class DrumkitWidget(QFrame):
64
64
  self.sfz_filename = filename
65
65
  self.moniker = basename(self.sfz_filename)
66
66
  self.drumkit = None
67
- self.port_number = None
68
- self.initial_height = None
67
+ self.synth = None
69
68
 
69
+ self.initial_height = None
70
70
  self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred)
71
71
 
72
72
  main_layout = QVBoxLayout()
@@ -130,6 +130,7 @@ class DrumkitWidget(QFrame):
130
130
  Fills the groups and instruments of this the DrumkitWidget.
131
131
  """
132
132
  self.drumkit = drumkit
133
+ self.synth = audio().create_synth(self.sfz_filename)
133
134
  for group in self.drumkit.percussion_groups.values():
134
135
  if group.is_empty():
135
136
  continue
@@ -162,14 +163,21 @@ class DrumkitWidget(QFrame):
162
163
  """
163
164
  Triggered by InstrumentButton mouse press.
164
165
  """
165
- self.sig_note_on.emit(inst.pitch)
166
+ self.synth.noteon(
167
+ self.drumkit.midi_channel,
168
+ inst.pitch,
169
+ get_setting(KEY_PREVIEW_VELOCITY, 80, int)
170
+ )
166
171
 
167
172
  @pyqtSlot(PercussionInstrument)
168
173
  def slot_instrument_released(self, inst):
169
174
  """
170
175
  Triggered by InstrumentButton mouse relase.
171
176
  """
172
- self.sig_note_off.emit(inst.pitch)
177
+ self.synth.noteoff(
178
+ self.drumkit.midi_channel,
179
+ inst.pitch
180
+ )
173
181
 
174
182
  @pyqtSlot(QPushButton)
175
183
  def slot_instrument_toggled(self, button):
@@ -187,6 +195,7 @@ class DrumkitWidget(QFrame):
187
195
  """
188
196
  Triggered by the "remove" button click event.
189
197
  """
198
+ audio().delete_synth(self.synth)
190
199
  self.sig_remove_drumkit.emit(self)
191
200
 
192
201
  @pyqtSlot(bool)
@@ -20,7 +20,6 @@
20
20
  """
21
21
  Provides KitSaveDialog.
22
22
  """
23
- import logging
24
23
  from os.path import realpath, splitext
25
24
  from functools import partial
26
25
  from PyQt5.QtCore import Qt, pyqtSlot, QCoreApplication
@@ -31,20 +31,21 @@ from PyQt5.QtCore import Qt, QObject, pyqtSlot, QTimer, QThreadPool, QPoint, QCo
31
31
  from PyQt5.QtWidgets import (
32
32
  QApplication, QMainWindow, QMessageBox, QFileDialog, QAction, QActionGroup, QMenu)
33
33
  from PyQt5.QtGui import QIcon
34
- from qt_extras import ShutUpQT, SigBlock, DevilBox
34
+ from qt_extras import ShutUpQT, DevilBox
35
35
  from qt_extras.list_layout import VListLayout
36
36
  from recent_items_list import RecentItemsList
37
37
  from sfzen import SAMPLES_ABSPATH
38
38
  from sfzen.drumkits import Drumkit
39
39
  from kitbash import (
40
40
  APPLICATION_NAME, PACKAGE_DIR, DEFAULT_STYLE,
41
- styles, set_application_style, get_setting, set_setting, GeometrySaver,
42
- KEY_STYLE, KEY_SAMPLES_MODE, KEY_RECENT_DRUMKIT_FOLDER, KEY_RECENT_DRUMKITS,
41
+ styles, set_application_style, get_setting, set_setting, GeometrySaver, audio,
42
+ KEY_PREVIEW_VELOCITY, KEY_STYLE, KEY_SAMPLES_MODE,
43
+ KEY_RECENT_DRUMKIT_FOLDER, KEY_RECENT_DRUMKITS,
43
44
  KEY_RECENT_PROJECT_FOLDER, KEY_RECENT_PROJECTS)
44
45
  from kitbash.worker_threads import KitLoader, KitBasher
45
- from kitbash.jack_audio import Audio
46
46
  from kitbash.gui.drumkit_widget import DrumkitWidget
47
47
  from kitbash.gui.kit_save_dialog import KitSaveDialog
48
+ from kitbash.install import install
48
49
 
49
50
 
50
51
  UPDATES_DEBOUNCE = 680
@@ -94,7 +95,18 @@ class MainWindow(QMainWindow, GeometrySaver):
94
95
  # Setup background threadpool for KitLoader and KitBasher workers
95
96
  self.background_threadpool = QThreadPool()
96
97
  # Setup jack audio
97
- self.audio = Audio()
98
+ self.audio = audio()
99
+ # Setup source/sink combo boxes:
100
+ self.cmb_midi_sources = self.audio.midi_in_combo_box(self)
101
+ self.lo_source_combo.replaceWidget(self.cmb_midi_src_placeholder, self.cmb_midi_sources)
102
+ self.cmb_midi_src_placeholder.setVisible(False)
103
+ self.cmb_midi_src_placeholder.deleteLater()
104
+ del self.cmb_midi_src_placeholder
105
+ self.cmb_audio_sinks = self.audio.audio_out_combo_box(self)
106
+ self.lo_sink_combo.replaceWidget(self.cmb_audio_sink_placeholder, self.cmb_audio_sinks)
107
+ self.cmb_audio_sink_placeholder.setVisible(False)
108
+ self.cmb_audio_sink_placeholder.deleteLater()
109
+ del self.cmb_audio_sink_placeholder
98
110
  # Setup GUI elements
99
111
  self.fill_style_menu()
100
112
  self.setup_kits_area()
@@ -108,6 +120,7 @@ class MainWindow(QMainWindow, GeometrySaver):
108
120
  self.audio.connect()
109
121
  if self.options.Filename:
110
122
  self.load_project(self.options.Filename)
123
+ install()
111
124
 
112
125
  def setup_kits_area(self):
113
126
  self.drumkit_widgets = VListLayout(end_space = 10)
@@ -122,7 +135,7 @@ class MainWindow(QMainWindow, GeometrySaver):
122
135
  self.action_save_project.triggered.connect(self.slot_save_project)
123
136
  self.action_save_project_as.triggered.connect(self.slot_save_project_as)
124
137
  self.action_save_bashed_kit.triggered.connect(self.slot_save_kit)
125
- self.action_save_kit_as.triggered.connect(self.slot_save_kit_as)
138
+ self.action_save_bashed_kit_as.triggered.connect(self.slot_save_kit_as)
126
139
  self.action_add_drumkit.triggered.connect(self.slot_add_drumkit)
127
140
  self.action_remove_all_kits.triggered.connect(self.slot_remove_all_kits)
128
141
  self.action_reload_style.triggered.connect(self.slot_reload_style)
@@ -137,14 +150,8 @@ class MainWindow(QMainWindow, GeometrySaver):
137
150
  self.b_copy_path.clicked.connect(self.slot_copy_kit_path)
138
151
  self.b_add_drumkit.clicked.connect(self.slot_add_drumkit)
139
152
  self.b_xruns.clicked.connect(self.slot_xruns_clicked)
140
- self.cmb_midi_srcs.currentTextChanged.connect(
141
- self.audio.slot_midi_src_selected)
142
- self.cmb_audio_sinks.currentTextChanged.connect(
143
- self.audio.slot_audio_sink_selected)
144
- self.audio.sig_sources_changed.connect(
145
- self.slot_sources_changed)
146
- self.audio.sig_sinks_changed.connect(
147
- self.slot_sinks_changed)
153
+ self.spn_velocity.valueChanged.connect(self.slot_velocity_value_changed)
154
+ self.audio.sig_jack_ready.connect(self.slot_jack_ready)
148
155
 
149
156
  def update_ui(self):
150
157
  title = APPLICATION_NAME \
@@ -158,7 +165,11 @@ class MainWindow(QMainWindow, GeometrySaver):
158
165
  self.action_new_project.setEnabled(has_kits)
159
166
  self.action_save_project.setEnabled(has_kits and self.dirty)
160
167
  self.action_save_project_as.setEnabled(has_kits)
161
- self.action_save_bashed_kit.setEnabled(has_kits)
168
+ self.action_save_bashed_kit.setEnabled(has_kits and self.saved_sfz_filename is not None)
169
+ self.action_save_bashed_kit.setText(
170
+ 'Save bashed kit' if self.saved_sfz_filename is None
171
+ else f'Save "{self.saved_sfz_filename}"')
172
+ self.action_save_bashed_kit_as.setEnabled(has_kits)
162
173
  self.b_save_project.setEnabled(has_kits)
163
174
  self.b_save_kit.setEnabled(has_kits)
164
175
  self.b_copy_path.setVisible(bool(self.saved_sfz_filename))
@@ -218,7 +229,6 @@ class MainWindow(QMainWindow, GeometrySaver):
218
229
  Starts project load; saves recent file name.
219
230
  Permission to clear must already have been given.
220
231
  """
221
- logging.debug('load_project %s', filename)
222
232
  if exists(filename):
223
233
  try:
224
234
  with open(filename, 'r', encoding = 'utf-8') as fh:
@@ -251,18 +261,6 @@ class MainWindow(QMainWindow, GeometrySaver):
251
261
  self.set_dirty(False)
252
262
  self.statusbar.showMessage(f'Saved project at {self.project_filename}', MESSAGE_TIMEOUT)
253
263
 
254
- def save_kit(self):
255
- kit = self.bashed_kit.simplified()
256
- kit.default_path = dirname(self.saved_sfz_filename)
257
- try:
258
- kit.save_as(self.saved_sfz_filename, self.saved_sfz_samples_mode)
259
- logging.debug('Saved bashed SFZ at %s', self.saved_sfz_filename)
260
- self.statusbar.showMessage(f'Saved {self.saved_sfz_filename}', MESSAGE_TIMEOUT)
261
- except OSError as e:
262
- DevilBox('Hardlinks between devices are not allowed.\n' +\
263
- 'Choose a different path or sample mode.' if e.errno == 18 \
264
- else str(e))
265
-
266
264
  def register_recent_project(self):
267
265
  self.recent_projects.bump(self.project_filename)
268
266
  set_setting(KEY_RECENT_PROJECT_FOLDER, dirname(self.project_filename))
@@ -332,41 +330,10 @@ class MainWindow(QMainWindow, GeometrySaver):
332
330
  # -----------------------------------------------------------------
333
331
  # JACK audio / source / sink management
334
332
 
335
- @pyqtSlot(int)
336
- def slot_jack_ready(self, samplerate):
337
- self.lbl_jack_state.setText(f'JACK samplerate: {samplerate}')
338
-
339
- @pyqtSlot()
340
- def slot_jack_down(self):
341
- self.lbl_jack_state.setText('JACK is down')
342
-
343
- @pyqtSlot()
344
- def slot_sources_changed(self):
345
- with SigBlock(self.cmb_midi_srcs):
346
- self.cmb_midi_srcs.clear()
347
- self.cmb_midi_srcs.addItem('')
348
- for port in self.audio.conn_man.output_ports():
349
- if port.is_midi:
350
- self.cmb_midi_srcs.addItem(port.name)
351
- if self.audio.synth.connected_midi_src_port:
352
- self.cmb_midi_srcs.setCurrentText(self.audio.midi_src)
353
-
354
- @pyqtSlot()
355
- def slot_sinks_changed(self):
356
- with SigBlock(self.cmb_audio_sinks):
357
- self.cmb_audio_sinks.clear()
358
- self.cmb_audio_sinks.addItem('')
359
- valid_clients = set(
360
- port.client_name for port in self.audio.conn_man.input_ports()
361
- if port.is_audio )
362
- for client in valid_clients:
363
- self.cmb_audio_sinks.addItem(client)
364
- if self.audio.synth.connected_audio_sink_ports:
365
- self.cmb_audio_sinks.setCurrentText(self.audio.audio_sink)
366
-
367
- @pyqtSlot(str)
368
- def slot_midi_connected(self, port_name):
369
- self.statusbar.showMessage(f'Connected to "{port_name}"', MESSAGE_TIMEOUT)
333
+ @pyqtSlot(bool, int)
334
+ def slot_jack_ready(self, state, _):
335
+ if not state:
336
+ DevilBox('JACK is down')
370
337
 
371
338
  # -----------------------------------------------------------------
372
339
  # Drumkit load / delete / instrument selection
@@ -402,8 +369,6 @@ class MainWindow(QMainWindow, GeometrySaver):
402
369
  """
403
370
  drumkit_widget.set_drumkit(drumkit)
404
371
  drumkit_widget.sig_inst_toggle.connect(self.slot_inst_toggle)
405
- drumkit_widget.sig_note_on.connect(self.slot_note_on)
406
- drumkit_widget.sig_note_off.connect(self.slot_note_off)
407
372
  drumkit_widget.sig_remove_drumkit.connect(self.slot_remove_drumkit)
408
373
  if self.project_loading:
409
374
  drumkit_widget.apply_selections(
@@ -468,26 +433,23 @@ class MainWindow(QMainWindow, GeometrySaver):
468
433
  Triggered from KitBasher signal when bashing is finished.
469
434
  """
470
435
  self.bashed_kit = bashed_kit
471
- with open(self.tempfile, 'w') as fob:
472
- self.bashed_kit.write(fob)
473
- self.audio.synth.load(self.tempfile) # pylint: disable = no-member
436
+ self.audio.load_kit(self.bashed_kit)
474
437
  self.statusbar.showMessage('Drumkit updated', MESSAGE_TIMEOUT)
475
438
 
476
- @pyqtSlot(int)
477
- def slot_note_on(self, pitch):
478
- self.audio.synth.noteon(0, pitch, self.spn_velocity.value())
479
-
480
- @pyqtSlot(int)
481
- def slot_note_off(self, pitch):
482
- self.audio.synth.noteoff(0, pitch)
483
-
484
439
  # -----------------------------------------------------------------
485
440
  # UI handling slots:
486
441
 
442
+ @pyqtSlot(int)
443
+ def slot_velocity_value_changed(self, value):
444
+ """
445
+ Triggered by spn_velocity.valueChanged
446
+ """
447
+ set_setting(KEY_PREVIEW_VELOCITY, value)
448
+
487
449
  @pyqtSlot()
488
450
  def slot_xruns_clicked(self):
489
451
  """
490
- Triggered by b_xruns.click()
452
+ Triggered by b_xruns.click
491
453
  """
492
454
  self.base_xruns = self.current_xruns
493
455
  self.b_xruns.setText('0')
@@ -616,15 +578,26 @@ class MainWindow(QMainWindow, GeometrySaver):
616
578
  @pyqtSlot()
617
579
  def slot_save_kit(self):
618
580
  if self.saved_sfz_filename is None:
619
- self.slot_save_kit_as()
581
+ return self.slot_save_kit_as()
582
+ try:
583
+ self.bashed_kit.save_as(
584
+ self.saved_sfz_filename, samples_mode = self.saved_sfz_samples_mode)
585
+ except OSError as e:
586
+ if e.errno == 18:
587
+ DevilBox('Hardlinks between devices are not allowed.\n' +
588
+ 'Choose a different path or sample mode.')
589
+ elif e.errno == 2:
590
+ return self.slot_save_kit_as()
591
+ else:
592
+ DevilBox(str(e))
620
593
  else:
621
- self.save_kit()
594
+ self.statusbar.showMessage(f'Saved {self.saved_sfz_filename}', MESSAGE_TIMEOUT)
595
+ self.update_ui()
622
596
 
623
597
  @pyqtSlot()
624
598
  def slot_save_kit_as(self):
625
599
  """
626
600
  Triggered by "File -> Save bashed kit" menu
627
- See also: slot_drumkit_bashed
628
601
  """
629
602
  dlg = KitSaveDialog(self,
630
603
  int(get_setting(KEY_SAMPLES_MODE, SAMPLES_ABSPATH)) \
@@ -633,7 +606,7 @@ class MainWindow(QMainWindow, GeometrySaver):
633
606
  if dlg.exec_() and dlg.selected_file:
634
607
  self.saved_sfz_filename = dlg.selected_file
635
608
  self.saved_sfz_samples_mode = dlg.samples_mode
636
- self.save_kit()
609
+ self.slot_save_kit()
637
610
 
638
611
  @pyqtSlot()
639
612
  def slot_add_drumkit(self):