def __init__(self): super().__init__() self._prewarp_list = WarpList('pre', self._get_base_wave, self._get_update_signal_type) self._base_func_selector = KqtComboBox() self._postwarp_list = WarpList('post', self._get_base_wave, self._get_update_signal_type) self._waveform = Waveform() pw_layout = QVBoxLayout() pw_layout.setSpacing(0) pw_layout.addWidget(self._prewarp_list) pw_layout.addWidget(self._base_func_selector) pw_layout.addWidget(self._postwarp_list) ed_layout = QHBoxLayout() ed_layout.setSpacing(0) ed_layout.addLayout(pw_layout) ed_layout.addWidget(self._waveform) v = QVBoxLayout() v.setContentsMargins(0, 0, 0, 0) v.setSpacing(2) v.addWidget(HeaderLine('Waveshaping')) v.addLayout(ed_layout) self.setLayout(v)
def __init__(self): super().__init__() self._sample_size = KqtComboBox() self._sample_count = QSpinBox() self._sample_count.setRange(1, 128) self._range_min = SamplePitchRangeMinEditor() self._range_max = SamplePitchRangeMaxEditor() self._centre_pitch = SampleCentrePitchEditor() self.add_to_updaters(self._range_min, self._range_max, self._centre_pitch) h = QHBoxLayout() h.setContentsMargins(0, 0, 0, 0) h.setSpacing(2) h.addWidget(QLabel('Sample size:')) h.addWidget(self._sample_size) h.addWidget(QLabel('Sample count:')) h.addWidget(self._sample_count) h.addWidget(QLabel('Pitch range:')) h.addWidget(self._range_min) h.addWidget(self._range_max) h.addWidget(QLabel('Centre pitch:')) h.addWidget(self._centre_pitch) self.setLayout(h)
def __init__(self): super().__init__() self._expr_names = KqtComboBox() h = QHBoxLayout() h.setContentsMargins(0, 0, 0, 0) h.setSpacing(4) h.addWidget(QLabel('Default note expression:')) h.addWidget(self._expr_names, 1) self.setLayout(h)
def __init__(self): super().__init__() self._au_id = None self._proc_id = None self._ui_model = None self._updater = None self._prewarp_list = WarpList( 'pre', self._get_base_wave, self._get_update_signal_type) self._base_func_selector = KqtComboBox() self._postwarp_list = WarpList( 'post', self._get_base_wave, self._get_update_signal_type) self._waveform = Waveform() pw_layout = QVBoxLayout() pw_layout.setSpacing(0) pw_layout.addWidget(self._prewarp_list) pw_layout.addWidget(self._base_func_selector) pw_layout.addWidget(self._postwarp_list) ed_layout = QHBoxLayout() ed_layout.setSpacing(0) ed_layout.addLayout(pw_layout) ed_layout.addWidget(self._waveform) v = QVBoxLayout() v.setContentsMargins(0, 0, 0, 0) v.setSpacing(2) v.addWidget(HeaderLine('Waveshaping')) v.addLayout(ed_layout) self.setLayout(v)
def __init__(self): super().__init__() self._au_id = None self._proc_id = None self._ui_model = None self._updater = None self._sample_size = KqtComboBox() self._sample_count = QSpinBox() self._sample_count.setRange(1, 128) self._range_min = SamplePitchRangeMinEditor() self._range_max = SamplePitchRangeMaxEditor() self._centre_pitch = SampleCentrePitchEditor() h = QHBoxLayout() h.setContentsMargins(0, 0, 0, 0) h.setSpacing(2) h.addWidget(QLabel('Sample size:')) h.addWidget(self._sample_size) h.addWidget(QLabel('Sample count:')) h.addWidget(self._sample_count) h.addWidget(QLabel('Pitch range:')) h.addWidget(self._range_min) h.addWidget(self._range_max) h.addWidget(QLabel('Centre pitch:')) h.addWidget(self._centre_pitch) self.setLayout(h)
def __init__(self, warp_type, index, get_base_wave, get_update_signal_type): super().__init__() self._warp_type = warp_type self._index = index self._get_base_wave = get_base_wave self._get_update_signal_type = get_update_signal_type self._down_button = ProcessorIconButton() self._up_button = ProcessorIconButton() self._func_selector = KqtComboBox() self._slider = QSlider(Qt.Horizontal) self._slider.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred) self._value_display = QLabel() self._remove_button = ProcessorIconButton() self.add_to_updaters(self._down_button, self._up_button, self._remove_button) self._slider.setRange(-self._ARG_SCALE, self._ARG_SCALE) self._up_button.setEnabled(self._index != 0) fm = QFontMetrics(QFont()) value_width = fm.boundingRect('{}'.format(-1.0 / self._ARG_SCALE)).width() value_width += 10 self._value_display.setFixedWidth(value_width) h = QHBoxLayout() h.setContentsMargins(0, 0, 0, 0) h.setSpacing(2) h.addWidget(self._down_button) h.addWidget(self._up_button) h.addWidget(self._func_selector) h.addWidget(self._slider) h.addWidget(self._value_display) h.addWidget(self._remove_button) self.setLayout(h)
def __init__(self): super().__init__() self._au_id = None self._ui_model = None self._updater = None self._expr_names = KqtComboBox() h = QHBoxLayout() h.setContentsMargins(0, 0, 0, 0) h.setSpacing(4) h.addWidget(QLabel('Default note expression:')) h.addWidget(self._expr_names, 1) self.setLayout(h)
def __init__(self): super().__init__() self._au_id = None self._proc_id = None self._ui_model = None self._updater = None self._signal_type = KqtComboBox() for info in self._SIGNAL_INFO: _, text = info self._signal_type.addItem(text) v = QHBoxLayout() v.setContentsMargins(4, 4, 4, 4) v.addWidget(HeaderFrame('Signal type', self._signal_type)) self.setLayout(v)
def __init__(self, warp_type, index, get_base_wave, get_update_signal_type): super().__init__() self._au_id = None self._proc_id = None self._ui_model = None self._updater = None self._warp_type = warp_type self._index = index self._get_base_wave = get_base_wave self._get_update_signal_type = get_update_signal_type self._down_button = SmallButton() self._up_button = SmallButton() self._func_selector = KqtComboBox() self._slider = QSlider(Qt.Horizontal) self._slider.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred) self._value_display = QLabel() self._remove_button = SmallButton() self._slider.setRange(-self._ARG_SCALE, self._ARG_SCALE) self._up_button.setEnabled(self._index != 0) fm = QFontMetrics(QFont()) value_width = fm.boundingRect('{}'.format(-1.0 / self._ARG_SCALE)).width() value_width += 10 self._value_display.setFixedWidth(value_width) h = QHBoxLayout() h.setContentsMargins(0, 0, 0, 0) h.setSpacing(2) h.addWidget(self._down_button) h.addWidget(self._up_button) h.addWidget(self._func_selector) h.addWidget(self._slider) h.addWidget(self._value_display) h.addWidget(self._remove_button) self.setLayout(h)
class SampleConfigEditor(QWidget, ProcessorUpdater): def __init__(self): super().__init__() self._sample_size = KqtComboBox() self._sample_count = QSpinBox() self._sample_count.setRange(1, 128) self._range_min = SamplePitchRangeMinEditor() self._range_max = SamplePitchRangeMaxEditor() self._centre_pitch = SampleCentrePitchEditor() self.add_to_updaters(self._range_min, self._range_max, self._centre_pitch) h = QHBoxLayout() h.setContentsMargins(0, 0, 0, 0) h.setSpacing(2) h.addWidget(QLabel('Sample size:')) h.addWidget(self._sample_size) h.addWidget(QLabel('Sample count:')) h.addWidget(self._sample_count) h.addWidget(QLabel('Pitch range:')) h.addWidget(self._range_min) h.addWidget(self._range_max) h.addWidget(QLabel('Centre pitch:')) h.addWidget(self._centre_pitch) self.setLayout(h) def _on_setup(self): self.register_action('signal_au', self._update_sample_params) self.register_action(self._get_update_signal_type(), self._update_sample_params) self.register_action('signal_style_changed', self._update_style) for sample_length in self._get_params().get_allowed_sample_lengths(): self._sample_size.addItem(str(sample_length), userData=sample_length) self._sample_size.currentIndexChanged.connect(self._change_sample_size) self._sample_count.valueChanged.connect(self._change_sample_count) self._update_style() self._update_sample_params() def _get_update_signal_type(self): return 'signal_padsynth_{}'.format(self._proc_id) def _get_params(self): return utils.get_proc_params(self._ui_model, self._au_id, self._proc_id) def _update_style(self): style_mgr = self._ui_model.get_style_manager() self.layout().setSpacing( style_mgr.get_scaled_size_param('small_padding')) def _update_sample_params(self): params = self._get_params() old_block = self._sample_size.blockSignals(True) new_sample_size = params.get_sample_length() if (self._sample_size.itemData(self._sample_size.currentIndex()) != new_sample_size): self._sample_size.setCurrentIndex( self._sample_size.findData(new_sample_size)) self._sample_size.blockSignals(old_block) old_block = self._sample_count.blockSignals(True) new_sample_count = params.get_sample_count() if self._sample_count.value() != new_sample_count: self._sample_count.setValue(new_sample_count) self._sample_count.blockSignals(old_block) def _change_sample_size(self, index): sample_size = self._sample_size.itemData(index) self._get_params().set_sample_length(sample_size) self._updater.signal_update(self._get_update_signal_type()) def _change_sample_count(self, count): params = self._get_params() params.set_sample_count(count) self._updater.signal_update(self._get_update_signal_type())
class DefaultNoteExpr(QWidget, AudioUnitUpdater): def __init__(self): super().__init__() self._expr_names = KqtComboBox() h = QHBoxLayout() h.setContentsMargins(0, 0, 0, 0) h.setSpacing(4) h.addWidget(QLabel('Default note expression:')) h.addWidget(self._expr_names, 1) self.setLayout(h) def _on_setup(self): self.register_action(self._get_list_update_signal_type(), self._update_contents) self.register_action(self._get_default_update_signal_type(), self._update_contents) self.register_action('signal_style_changed', self._update_style) self._expr_names.currentIndexChanged.connect(self._change_expression) self._update_style() self._update_contents() def _get_list_update_signal_type(self): return 'signal_expr_list_{}'.format(self._au_id) def _get_default_update_signal_type(self): return 'signal_expr_default_{}'.format(self._au_id) def _get_audio_unit(self): module = self._ui_model.get_module() au = module.get_audio_unit(self._au_id) return au def _update_style(self): style_mgr = self._ui_model.get_style_manager() self.layout().setSpacing( style_mgr.get_scaled_size_param('medium_padding')) def _update_contents(self): au = self._get_audio_unit() names = sorted(au.get_expression_names()) selection = au.get_default_note_expression() old_block = self._expr_names.blockSignals(True) self._expr_names.setEnabled(len(names) > 0) self._expr_names.set_items(chain(['(none)'], (name for name in names))) try: self._expr_names.setCurrentIndex(names.index(selection) + 1) except ValueError: self._expr_names.setCurrentIndex(0) self._expr_names.blockSignals(old_block) def _change_expression(self, item_index): au = self._get_audio_unit() if item_index == 0: au.set_default_note_expression('') else: expr_name = self._expr_names.itemText(item_index) au.set_default_note_expression(expr_name)
class WarpEditor(QWidget): _ARG_SCALE = 1000 def __init__(self, warp_type, index, get_base_wave, get_update_signal_type): super().__init__() self._au_id = None self._proc_id = None self._ui_model = None self._updater = None self._warp_type = warp_type self._index = index self._get_base_wave = get_base_wave self._get_update_signal_type = get_update_signal_type self._down_button = SmallButton() self._up_button = SmallButton() self._func_selector = KqtComboBox() self._slider = QSlider(Qt.Horizontal) self._slider.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred) self._value_display = QLabel() self._remove_button = SmallButton() self._slider.setRange(-self._ARG_SCALE, self._ARG_SCALE) self._up_button.setEnabled(self._index != 0) fm = QFontMetrics(QFont()) value_width = fm.boundingRect('{}'.format(-1.0 / self._ARG_SCALE)).width() value_width += 10 self._value_display.setFixedWidth(value_width) h = QHBoxLayout() h.setContentsMargins(0, 0, 0, 0) h.setSpacing(2) h.addWidget(self._down_button) h.addWidget(self._up_button) h.addWidget(self._func_selector) h.addWidget(self._slider) h.addWidget(self._value_display) h.addWidget(self._remove_button) self.setLayout(h) def set_au_id(self, au_id): self._au_id = au_id def set_proc_id(self, proc_id): self._proc_id = proc_id def set_ui_model(self, ui_model): self._ui_model = ui_model self._updater = ui_model.get_updater() self._updater.register_updater(self._perform_updates) icon_bank = self._ui_model.get_icon_bank() self._down_button.setIcon(QIcon(icon_bank.get_icon_path('arrow_down_small'))) self._up_button.setIcon(QIcon(icon_bank.get_icon_path('arrow_up_small'))) self._remove_button.setIcon(QIcon(icon_bank.get_icon_path('delete_small'))) base_wave = self._get_base_wave() func_names = base_wave.get_warp_func_names(self._warp_type) self._func_selector.set_items(name for name in func_names) self._update_all() QObject.connect(self._down_button, SIGNAL('clicked()'), self._moved_down) QObject.connect(self._up_button, SIGNAL('clicked()'), self._moved_up) QObject.connect( self._func_selector, SIGNAL('currentIndexChanged(int)'), self._func_selected) QObject.connect(self._slider, SIGNAL('valueChanged(int)'), self._slider_adjusted) QObject.connect(self._remove_button, SIGNAL('clicked()'), self._removed) def unregister_updaters(self): self._updater.unregister_updater(self._perform_updates) def _perform_updates(self, signals): update_signals = set(['signal_au', self._get_update_signal_type()]) if not signals.isdisjoint(update_signals): self._update_all() def _update_all(self): base_wave = self._get_base_wave() warp_func_count = base_wave.get_warp_func_count(self._warp_type) if self._index >= warp_func_count: # We have been removed return self._down_button.setEnabled(self._index < warp_func_count - 1) name, arg = base_wave.get_warp_func(self._warp_type, self._index) old_block = self._func_selector.blockSignals(True) for i in range(self._func_selector.count()): if self._func_selector.itemText(i) == name: self._func_selector.setCurrentIndex(i) break self._func_selector.blockSignals(old_block) old_block = self._slider.blockSignals(True) int_val = int(round(arg * self._ARG_SCALE)) self._slider.setValue(int_val) self._slider.blockSignals(old_block) self._value_display.setText(str(float(arg))) def _moved_down(self): base_wave = self._get_base_wave() base_wave.move_warp_func(self._warp_type, self._index, self._index + 1) self._updater.signal_update(set([self._get_update_signal_type()])) def _moved_up(self): base_wave = self._get_base_wave() base_wave.move_warp_func(self._warp_type, self._index, self._index - 1) self._updater.signal_update(set([self._get_update_signal_type()])) def _set_warp(self): base_wave = self._get_base_wave() name = str(self._func_selector.currentText()) arg = self._slider.value() / float(self._ARG_SCALE) base_wave.set_warp_func(self._warp_type, self._index, name, arg) self._updater.signal_update(set([self._get_update_signal_type()])) def _func_selected(self, index): self._set_warp() def _slider_adjusted(self, int_val): self._set_warp() def _removed(self): base_wave = self._get_base_wave() base_wave.remove_warp_func(self._warp_type, self._index) self._updater.signal_update(set([self._get_update_signal_type()]))
class WaveformEditor(QWidget, ProcessorUpdater): def __init__(self): super().__init__() self._prewarp_list = WarpList( 'pre', self._get_base_wave, self._get_update_signal_type) self._base_func_selector = KqtComboBox() self._postwarp_list = WarpList( 'post', self._get_base_wave, self._get_update_signal_type) self._waveform = Waveform() pw_layout = QVBoxLayout() pw_layout.setSpacing(0) pw_layout.addWidget(self._prewarp_list) pw_layout.addWidget(self._base_func_selector) pw_layout.addWidget(self._postwarp_list) ed_layout = QHBoxLayout() ed_layout.setSpacing(0) ed_layout.addLayout(pw_layout) ed_layout.addWidget(self._waveform) self._header = HeaderLine('Waveshaping') v = QVBoxLayout() v.setContentsMargins(0, 0, 0, 0) v.setSpacing(2) v.addWidget(self._header) v.addLayout(ed_layout) self.setLayout(v) def _on_setup(self): self.add_to_updaters(self._prewarp_list, self._postwarp_list) self.register_action('signal_au', self._update_all) self.register_action(self._get_update_signal_type(), self._update_all) self.register_action('signal_style_changed', self._update_style) self._update_style() self._update_all() self._base_func_selector.currentIndexChanged.connect(self._base_func_selected) def _update_style(self): style_mgr = self._ui_model.get_style_manager() self._header.update_style(style_mgr) self.layout().setSpacing(style_mgr.get_scaled_size_param('small_padding')) def get_colour(name): return QColor(style_mgr.get_style_param(name)) disabled_colour = QColor(get_colour('bg_colour')) disabled_colour.setAlpha(0x7f) config = { 'bg_colour': get_colour('waveform_bg_colour'), 'centre_line_colour': get_colour('waveform_centre_line_colour'), 'waveform_colour': get_colour('waveform_zoomed_out_colour'), 'disabled_colour': disabled_colour, 'line_thickness' : style_mgr.get_scaled_size(0.1), } self._waveform.set_config(config) def _update_all(self): base_wave = self._get_base_wave() selected_base_func = base_wave.get_waveform_func() enable_warps = (selected_base_func != None) self._prewarp_list.setEnabled(enable_warps) old_block = self._base_func_selector.blockSignals(True) func_names = list(base_wave.get_waveform_func_names()) if not selected_base_func: func_names.append('Custom') self._base_func_selector.set_items(func_names) self._base_func_selector.setCurrentIndex( self._base_func_selector.findText(selected_base_func or 'Custom')) self._base_func_selector.blockSignals(old_block) self._postwarp_list.setEnabled(enable_warps) self._waveform.set_waveform(base_wave.get_waveform()) def _base_func_selected(self, index): base_wave = self._get_base_wave() func_names = base_wave.get_waveform_func_names() base_wave.set_waveform_func(func_names[index]) self._updater.signal_update(self._get_update_signal_type()) # Protected interface def _get_base_wave(self): raise NotImplementedError def _get_update_signal_type(self): raise NotImplementedError
class WaveformEditor(QWidget): def __init__(self): super().__init__() self._au_id = None self._proc_id = None self._ui_model = None self._updater = None self._prewarp_list = WarpList( 'pre', self._get_base_wave, self._get_update_signal_type) self._base_func_selector = KqtComboBox() self._postwarp_list = WarpList( 'post', self._get_base_wave, self._get_update_signal_type) self._waveform = Waveform() pw_layout = QVBoxLayout() pw_layout.setSpacing(0) pw_layout.addWidget(self._prewarp_list) pw_layout.addWidget(self._base_func_selector) pw_layout.addWidget(self._postwarp_list) ed_layout = QHBoxLayout() ed_layout.setSpacing(0) ed_layout.addLayout(pw_layout) ed_layout.addWidget(self._waveform) v = QVBoxLayout() v.setContentsMargins(0, 0, 0, 0) v.setSpacing(2) v.addWidget(HeaderLine('Waveshaping')) v.addLayout(ed_layout) self.setLayout(v) def set_au_id(self, au_id): self._au_id = au_id self._prewarp_list.set_au_id(au_id) self._postwarp_list.set_au_id(au_id) def set_proc_id(self, proc_id): self._proc_id = proc_id self._prewarp_list.set_proc_id(proc_id) self._postwarp_list.set_proc_id(proc_id) def set_ui_model(self, ui_model): self._ui_model = ui_model self._prewarp_list.set_ui_model(ui_model) self._postwarp_list.set_ui_model(ui_model) self._updater = ui_model.get_updater() self._updater.register_updater(self._perform_updates) self._update_style() self._update_all() QObject.connect( self._base_func_selector, SIGNAL('currentIndexChanged(int)'), self._base_func_selected) def unregister_updaters(self): self._updater.unregister_updater(self._perform_updates) self._prewarp_list.unregister_updaters() self._postwarp_list.unregister_updaters() def _perform_updates(self, signals): update_signals = set(['signal_au', self._get_update_signal_type()]) if not signals.isdisjoint(update_signals): self._update_all() if 'signal_style_changed' in signals: self._update_style() def _update_style(self): style_manager = self._ui_model.get_style_manager() if not style_manager.is_custom_style_enabled(): self._waveform.set_config({}) return def get_colour(name): return QColor(style_manager.get_style_param(name)) disabled_colour = QColor(get_colour('bg_colour')) disabled_colour.setAlpha(0x7f) config = { 'bg_colour': get_colour('waveform_bg_colour'), 'centre_line_colour': get_colour('waveform_centre_line_colour'), 'waveform_colour': get_colour('waveform_zoomed_out_colour'), 'disabled_colour': disabled_colour, } self._waveform.set_config(config) def _update_all(self): base_wave = self._get_base_wave() selected_base_func = base_wave.get_waveform_func() enable_warps = (selected_base_func != None) self._prewarp_list.setEnabled(enable_warps) old_block = self._base_func_selector.blockSignals(True) func_names = list(base_wave.get_waveform_func_names()) if not selected_base_func: func_names.append('Custom') self._base_func_selector.set_items(func_names) self._base_func_selector.setCurrentIndex( self._base_func_selector.findText(selected_base_func or 'Custom')) self._base_func_selector.blockSignals(old_block) self._postwarp_list.setEnabled(enable_warps) self._waveform.set_waveform(base_wave.get_waveform()) def _base_func_selected(self, index): base_wave = self._get_base_wave() func_names = base_wave.get_waveform_func_names() base_wave.set_waveform_func(func_names[index]) self._updater.signal_update(set([self._get_update_signal_type()])) # Protected interface def _get_base_wave(self): raise NotImplementedError def _get_update_signal_type(self): raise NotImplementedError
class DefaultNoteExpr(QWidget): def __init__(self): super().__init__() self._au_id = None self._ui_model = None self._updater = None self._expr_names = KqtComboBox() h = QHBoxLayout() h.setContentsMargins(0, 0, 0, 0) h.setSpacing(4) h.addWidget(QLabel('Default note expression:')) h.addWidget(self._expr_names, 1) self.setLayout(h) def set_au_id(self, au_id): self._au_id = au_id def set_ui_model(self, ui_model): self._ui_model = ui_model self._updater = ui_model.get_updater() self._updater.register_updater(self._perform_updates) QObject.connect( self._expr_names, SIGNAL('currentIndexChanged(int)'), self._change_expression) self._update_contents() def unregister_updaters(self): self._updater.unregister_updater(self._perform_updates) def _get_list_update_signal_type(self): return 'signal_expr_list_{}'.format(self._au_id) def _get_default_update_signal_type(self): return 'signal_expr_default_{}'.format(self._au_id) def _perform_updates(self, signals): update_signals = set([ self._get_list_update_signal_type(), self._get_default_update_signal_type()]) if not signals.isdisjoint(update_signals): self._update_contents() def _get_audio_unit(self): module = self._ui_model.get_module() au = module.get_audio_unit(self._au_id) return au def _update_contents(self): au = self._get_audio_unit() names = sorted(au.get_expression_names()) selection = au.get_default_note_expression() old_block = self._expr_names.blockSignals(True) self._expr_names.setEnabled(len(names) > 0) self._expr_names.set_items(chain(['(none)'], (name for name in names))) try: self._expr_names.setCurrentIndex(names.index(selection) + 1) except ValueError: self._expr_names.setCurrentIndex(0) self._expr_names.blockSignals(old_block) def _change_expression(self, item_index): au = self._get_audio_unit() if item_index == 0: au.set_default_note_expression('') else: expr_name = self._expr_names.itemText(item_index) au.set_default_note_expression(expr_name)
class Signals(QWidget): _SIGNAL_INFO = [ ('voice', 'Voice signals'), ('mixed', 'Mixed signals'), ] def __init__(self): super().__init__() self._au_id = None self._proc_id = None self._ui_model = None self._updater = None self._signal_type = KqtComboBox() for info in self._SIGNAL_INFO: _, text = info self._signal_type.addItem(text) v = QHBoxLayout() v.setContentsMargins(4, 4, 4, 4) v.addWidget(HeaderFrame('Signal type', self._signal_type)) self.setLayout(v) def set_au_id(self, au_id): self._au_id = au_id def set_proc_id(self, proc_id): self._proc_id = proc_id def set_ui_model(self, ui_model): self._ui_model = ui_model self._updater = ui_model.get_updater() self._updater.register_updater(self._perform_updates) self._update_settings() QObject.connect( self._signal_type, SIGNAL('currentIndexChanged(int)'), self._signal_type_changed) def unregister_updaters(self): self._updater.unregister_updater(self._perform_updates) def _get_update_signal_type(self): return '_'.join(('signal_proc_signals', self._proc_id)) def _get_connections_signal_type(self): return '_'.join(('signal_connections', self._au_id)) def _perform_updates(self, signals): update_signals = set([ self._get_update_signal_type(), self._get_connections_signal_type()]) if not signals.isdisjoint(update_signals): self._update_settings() def _update_settings(self): module = self._ui_model.get_module() au = module.get_audio_unit(self._au_id) proc = au.get_processor(self._proc_id) # Don't try to update if we have been removed if not proc.get_existence(): return connections = au.get_connections() signal_type = proc.get_signal_type() # Update signal type selector old_block = self._signal_type.blockSignals(True) type_names = [info[0] for info in self._SIGNAL_INFO] index = type_names.index(signal_type) assert 0 <= index < len(self._SIGNAL_INFO) self._signal_type.setCurrentIndex(index) self._signal_type.blockSignals(old_block) def _signal_type_changed(self, index): module = self._ui_model.get_module() au = module.get_audio_unit(self._au_id) proc = au.get_processor(self._proc_id) new_signal_type = self._SIGNAL_INFO[index][0] update_signals = set([ self._get_update_signal_type(), self._get_connections_signal_type()]) proc.set_signal_type(new_signal_type) self._updater.signal_update(update_signals)
class WarpEditor(QWidget, ProcessorUpdater): _ARG_SCALE = 1000 def __init__(self, warp_type, index, get_base_wave, get_update_signal_type): super().__init__() self._warp_type = warp_type self._index = index self._get_base_wave = get_base_wave self._get_update_signal_type = get_update_signal_type self._down_button = ProcessorIconButton() self._up_button = ProcessorIconButton() self._func_selector = KqtComboBox() self._slider = QSlider(Qt.Horizontal) self._slider.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred) self._value_display = QLabel() self._remove_button = ProcessorIconButton() self.add_to_updaters(self._down_button, self._up_button, self._remove_button) self._slider.setRange(-self._ARG_SCALE, self._ARG_SCALE) self._up_button.setEnabled(self._index != 0) fm = QFontMetrics(QFont()) value_width = fm.boundingRect('{}'.format(-1.0 / self._ARG_SCALE)).width() value_width += 10 self._value_display.setFixedWidth(value_width) h = QHBoxLayout() h.setContentsMargins(0, 0, 0, 0) h.setSpacing(2) h.addWidget(self._down_button) h.addWidget(self._up_button) h.addWidget(self._func_selector) h.addWidget(self._slider) h.addWidget(self._value_display) h.addWidget(self._remove_button) self.setLayout(h) def _on_setup(self): self.register_action('signal_au', self._update_all) self.register_action(self._get_update_signal_type(), self._update_all) self.register_action('signal_style_changed', self._update_style) self._down_button.set_icon('arrow_down_small') self._up_button.set_icon('arrow_up_small') self._remove_button.set_icon('delete_small') style_mgr = self._ui_model.get_style_manager() for button in (self._down_button, self._up_button, self._remove_button): button.set_sizes( style_mgr.get_style_param('list_button_size'), style_mgr.get_style_param('list_button_padding')) base_wave = self._get_base_wave() func_names = base_wave.get_warp_func_names(self._warp_type) self._func_selector.set_items(name for name in func_names) self._update_style() self._update_all() self._down_button.clicked.connect(self._moved_down) self._up_button.clicked.connect(self._moved_up) self._func_selector.currentIndexChanged.connect(self._func_selected) self._slider.valueChanged.connect(self._slider_adjusted) self._remove_button.clicked.connect(self._removed) def _update_style(self): style_mgr = self._ui_model.get_style_manager() self.layout().setSpacing(style_mgr.get_scaled_size_param('small_padding')) def _update_all(self): base_wave = self._get_base_wave() warp_func_count = base_wave.get_warp_func_count(self._warp_type) if self._index >= warp_func_count: # We have been removed return self._down_button.setEnabled(self._index < warp_func_count - 1) name, arg = base_wave.get_warp_func(self._warp_type, self._index) old_block = self._func_selector.blockSignals(True) for i in range(self._func_selector.count()): if self._func_selector.itemText(i) == name: self._func_selector.setCurrentIndex(i) break self._func_selector.blockSignals(old_block) old_block = self._slider.blockSignals(True) int_val = int(round(arg * self._ARG_SCALE)) self._slider.setValue(int_val) self._slider.blockSignals(old_block) self._value_display.setText(str(float(arg))) def _moved_down(self): base_wave = self._get_base_wave() base_wave.move_warp_func(self._warp_type, self._index, self._index + 1) self._updater.signal_update(self._get_update_signal_type()) def _moved_up(self): base_wave = self._get_base_wave() base_wave.move_warp_func(self._warp_type, self._index, self._index - 1) self._updater.signal_update(self._get_update_signal_type()) def _set_warp(self): base_wave = self._get_base_wave() name = str(self._func_selector.currentText()) arg = self._slider.value() / float(self._ARG_SCALE) base_wave.set_warp_func(self._warp_type, self._index, name, arg) self._updater.signal_update(self._get_update_signal_type()) def _func_selected(self, index): self._set_warp() def _slider_adjusted(self, int_val): self._set_warp() def _removed(self): base_wave = self._get_base_wave() base_wave.remove_warp_func(self._warp_type, self._index) self._updater.signal_update(self._get_update_signal_type())
class WaveformEditor(QWidget, ProcessorUpdater): def __init__(self): super().__init__() self._prewarp_list = WarpList('pre', self._get_base_wave, self._get_update_signal_type) self._base_func_selector = KqtComboBox() self._postwarp_list = WarpList('post', self._get_base_wave, self._get_update_signal_type) self._waveform = Waveform() pw_layout = QVBoxLayout() pw_layout.setSpacing(0) pw_layout.addWidget(self._prewarp_list) pw_layout.addWidget(self._base_func_selector) pw_layout.addWidget(self._postwarp_list) ed_layout = QHBoxLayout() ed_layout.setSpacing(0) ed_layout.addLayout(pw_layout) ed_layout.addWidget(self._waveform) v = QVBoxLayout() v.setContentsMargins(0, 0, 0, 0) v.setSpacing(2) v.addWidget(HeaderLine('Waveshaping')) v.addLayout(ed_layout) self.setLayout(v) def _on_setup(self): self.add_to_updaters(self._prewarp_list, self._postwarp_list) self.register_action('signal_au', self._update_all) self.register_action(self._get_update_signal_type(), self._update_all) self.register_action('signal_style_changed', self._update_style) self._update_style() self._update_all() self._base_func_selector.currentIndexChanged.connect( self._base_func_selected) def _update_style(self): style_mgr = self._ui_model.get_style_manager() if not style_mgr.is_custom_style_enabled(): self._waveform.set_config({}) return def get_colour(name): return QColor(style_mgr.get_style_param(name)) disabled_colour = QColor(get_colour('bg_colour')) disabled_colour.setAlpha(0x7f) config = { 'bg_colour': get_colour('waveform_bg_colour'), 'centre_line_colour': get_colour('waveform_centre_line_colour'), 'waveform_colour': get_colour('waveform_zoomed_out_colour'), 'disabled_colour': disabled_colour, } self._waveform.set_config(config) def _update_all(self): base_wave = self._get_base_wave() selected_base_func = base_wave.get_waveform_func() enable_warps = (selected_base_func != None) self._prewarp_list.setEnabled(enable_warps) old_block = self._base_func_selector.blockSignals(True) func_names = list(base_wave.get_waveform_func_names()) if not selected_base_func: func_names.append('Custom') self._base_func_selector.set_items(func_names) self._base_func_selector.setCurrentIndex( self._base_func_selector.findText(selected_base_func or 'Custom')) self._base_func_selector.blockSignals(old_block) self._postwarp_list.setEnabled(enable_warps) self._waveform.set_waveform(base_wave.get_waveform()) def _base_func_selected(self, index): base_wave = self._get_base_wave() func_names = base_wave.get_waveform_func_names() base_wave.set_waveform_func(func_names[index]) self._updater.signal_update(self._get_update_signal_type()) # Protected interface def _get_base_wave(self): raise NotImplementedError def _get_update_signal_type(self): raise NotImplementedError
class WarpEditor(QWidget, ProcessorUpdater): _ARG_SCALE = 1000 def __init__(self, warp_type, index, get_base_wave, get_update_signal_type): super().__init__() self._warp_type = warp_type self._index = index self._get_base_wave = get_base_wave self._get_update_signal_type = get_update_signal_type self._down_button = SmallButton() self._up_button = SmallButton() self._func_selector = KqtComboBox() self._slider = QSlider(Qt.Horizontal) self._slider.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred) self._value_display = QLabel() self._remove_button = SmallButton() self._slider.setRange(-self._ARG_SCALE, self._ARG_SCALE) self._up_button.setEnabled(self._index != 0) fm = QFontMetrics(QFont()) value_width = fm.boundingRect('{}'.format(-1.0 / self._ARG_SCALE)).width() value_width += 10 self._value_display.setFixedWidth(value_width) h = QHBoxLayout() h.setContentsMargins(0, 0, 0, 0) h.setSpacing(2) h.addWidget(self._down_button) h.addWidget(self._up_button) h.addWidget(self._func_selector) h.addWidget(self._slider) h.addWidget(self._value_display) h.addWidget(self._remove_button) self.setLayout(h) def _on_setup(self): self.register_action('signal_au', self._update_all) self.register_action(self._get_update_signal_type(), self._update_all) icon_bank = self._ui_model.get_icon_bank() self._down_button.setIcon( QIcon(icon_bank.get_icon_path('arrow_down_small'))) self._up_button.setIcon( QIcon(icon_bank.get_icon_path('arrow_up_small'))) self._remove_button.setIcon( QIcon(icon_bank.get_icon_path('delete_small'))) base_wave = self._get_base_wave() func_names = base_wave.get_warp_func_names(self._warp_type) self._func_selector.set_items(name for name in func_names) self._update_all() self._down_button.clicked.connect(self._moved_down) self._up_button.clicked.connect(self._moved_up) self._func_selector.currentIndexChanged.connect(self._func_selected) self._slider.valueChanged.connect(self._slider_adjusted) self._remove_button.clicked.connect(self._removed) def _update_all(self): base_wave = self._get_base_wave() warp_func_count = base_wave.get_warp_func_count(self._warp_type) if self._index >= warp_func_count: # We have been removed return self._down_button.setEnabled(self._index < warp_func_count - 1) name, arg = base_wave.get_warp_func(self._warp_type, self._index) old_block = self._func_selector.blockSignals(True) for i in range(self._func_selector.count()): if self._func_selector.itemText(i) == name: self._func_selector.setCurrentIndex(i) break self._func_selector.blockSignals(old_block) old_block = self._slider.blockSignals(True) int_val = int(round(arg * self._ARG_SCALE)) self._slider.setValue(int_val) self._slider.blockSignals(old_block) self._value_display.setText(str(float(arg))) def _moved_down(self): base_wave = self._get_base_wave() base_wave.move_warp_func(self._warp_type, self._index, self._index + 1) self._updater.signal_update(self._get_update_signal_type()) def _moved_up(self): base_wave = self._get_base_wave() base_wave.move_warp_func(self._warp_type, self._index, self._index - 1) self._updater.signal_update(self._get_update_signal_type()) def _set_warp(self): base_wave = self._get_base_wave() name = str(self._func_selector.currentText()) arg = self._slider.value() / float(self._ARG_SCALE) base_wave.set_warp_func(self._warp_type, self._index, name, arg) self._updater.signal_update(self._get_update_signal_type()) def _func_selected(self, index): self._set_warp() def _slider_adjusted(self, int_val): self._set_warp() def _removed(self): base_wave = self._get_base_wave() base_wave.remove_warp_func(self._warp_type, self._index) self._updater.signal_update(self._get_update_signal_type())
class SampleConfigEditor(QWidget): def __init__(self): super().__init__() self._au_id = None self._proc_id = None self._ui_model = None self._updater = None self._sample_size = KqtComboBox() self._sample_count = QSpinBox() self._sample_count.setRange(1, 128) self._range_min = SamplePitchRangeMinEditor() self._range_max = SamplePitchRangeMaxEditor() self._centre_pitch = SampleCentrePitchEditor() h = QHBoxLayout() h.setContentsMargins(0, 0, 0, 0) h.setSpacing(2) h.addWidget(QLabel('Sample size:')) h.addWidget(self._sample_size) h.addWidget(QLabel('Sample count:')) h.addWidget(self._sample_count) h.addWidget(QLabel('Pitch range:')) h.addWidget(self._range_min) h.addWidget(self._range_max) h.addWidget(QLabel('Centre pitch:')) h.addWidget(self._centre_pitch) self.setLayout(h) def set_au_id(self, au_id): self._au_id = au_id self._range_min.set_au_id(au_id) self._range_max.set_au_id(au_id) self._centre_pitch.set_au_id(au_id) def set_proc_id(self, proc_id): self._proc_id = proc_id self._range_min.set_proc_id(proc_id) self._range_max.set_proc_id(proc_id) self._centre_pitch.set_proc_id(proc_id) def set_ui_model(self, ui_model): self._ui_model = ui_model self._updater = ui_model.get_updater() self._updater.register_updater(self._perform_updates) self._range_min.set_ui_model(ui_model) self._range_max.set_ui_model(ui_model) self._centre_pitch.set_ui_model(ui_model) for sample_length in self._get_params().get_allowed_sample_lengths(): self._sample_size.addItem(str(sample_length), userData=sample_length) QObject.connect( self._sample_size, SIGNAL('currentIndexChanged(int)'), self._change_sample_size) QObject.connect( self._sample_count, SIGNAL('valueChanged(int)'), self._change_sample_count) self._update_sample_params() def unregister_updaters(self): self._centre_pitch.unregister_updaters() self._range_max.unregister_updaters() self._range_min.unregister_updaters() self._updater.unregister_updater(self._perform_updates) def _get_update_signal_type(self): return 'signal_padsynth_{}'.format(self._proc_id) def _perform_updates(self, signals): update_signals = set(['signal_au', self._get_update_signal_type()]) if not signals.isdisjoint(update_signals): self._update_sample_params() def _get_params(self): return utils.get_proc_params(self._ui_model, self._au_id, self._proc_id) def _update_sample_params(self): params = self._get_params() old_block = self._sample_size.blockSignals(True) new_sample_size = params.get_sample_length() if (self._sample_size.itemData(self._sample_size.currentIndex()) != new_sample_size): self._sample_size.setCurrentIndex( self._sample_size.findData(new_sample_size)) self._sample_size.blockSignals(old_block) old_block = self._sample_count.blockSignals(True) new_sample_count = params.get_sample_count() if self._sample_count.value() != new_sample_count: self._sample_count.setValue(new_sample_count) self._sample_count.blockSignals(old_block) def _change_sample_size(self, index): sample_size = self._sample_size.itemData(index) self._get_params().set_sample_length(sample_size) self._updater.signal_update(set([self._get_update_signal_type()])) def _change_sample_count(self, count): params = self._get_params() params.set_sample_count(count) self._updater.signal_update(set([self._get_update_signal_type()]))