jdxi_editor.ui.editors.base.oscillator.section

LFO section of the digital partial editor.

Classes

OscillatorComponent

Oscillator Components

BaseOscillatorSection

Abstract base class for Oscillator sections (Analog and Digital).

Module Contents

class jdxi_editor.ui.editors.base.oscillator.section.OscillatorComponent[source]

Bases: enum.Enum

Oscillator Components

WAVE_SELECTOR[source]
TUNING[source]
PWM[source]
PITCH_ENV[source]
PCM[source]
SUB_OSC[source]
ADSR[source]
class jdxi_editor.ui.editors.base.oscillator.section.BaseOscillatorSection(*, send_midi_parameter: Callable = None, midi_helper=None, address=None, icons_row_type: str = IconType.OSCILLATOR, analog: bool = False)[source]

Bases: jdxi_editor.ui.widgets.editor.section_base.SectionBaseWidget

Abstract base class for Oscillator sections (Analog and Digital).

SKIP_BASE_SETUP_UI = True[source]
controls_tab_label: str = 'Controls'[source]
adsr_tab_label: str = 'ADSR'[source]
spec: jdxi_editor.ui.editors.base.oscillator.layout_spec.OscillatorLayoutSpec | None = None[source]
SYNTH_SPEC[source]
ANALOG_WAVES = [('SAW', 'UPSAW', 'UPSAW'), ('TRI', 'SQUARE', 'SQUARE'), ('SQUARE', 'PWSQU', 'PWSQU')][source]
DIGITAL_WAVES = [('SAW', 'UPSAW', 'UPSAW'), ('SQUARE', 'SQUARE', 'SQUARE'), ('PW_SQUARE', 'PWSQU', 'PWSQU'),...[source]
widgets[source]
pitch_env_widgets = None[source]
_widgets: dict[picomidi.sysex.parameter.address.AddressParameter, jdxi_editor.ui.common.QWidget][source]
shape_icon_map: dict | None = None[source]
sub_oscillator_type_switch: PySide6.QtWidgets.QPushButton | None = None[source]
tuning_sliders: list | None = None[source]
wave_layout_widgets: list = [][source]
wave_shape_param: list | None = None[source]
switch_row_widgets: list | None = None[source]
rate_layout_widgets: list | None = None[source]
depths_layout_widgets: list | None = None[source]
_send_param: Callable | None = None[source]
wave_shape_buttons: dict[source]
wave_button_group: PySide6.QtWidgets.QButtonGroup | None = None[source]
analog: bool = False[source]
widget_for(key: Any) jdxi_editor.ui.common.QWidget | None[source]

Return the widget stored under key (e.g. OscillatorWidgetTypes.PITCH_ENV).

_create_tab_widget()[source]

Create tab widget only. Tabs are added once in setup_ui() via base _create_tabs(); do not add tabs here or they appear twice.

_get_button_specs()[source]

Oscillator creates waveform buttons in its own build_widgets() / _create_core_widgets(). Return [] so SectionBaseWidget.build_widgets() does not create a second set and overwrite button_widgets with param-only keys (which breaks _on_button_selected lookup by (param, label)).

_create_tabs()[source]
finalize()[source]

Unified flow: feature widgets (if any), then setup_ui (layout + tabs), then init state. build_widgets runs once from __init__.

abstract _define_spec()[source]

Subclass must populate self.spec

_build_wave_specs(spec_rows)[source]
_create_feature_widgets()[source]

Subclass optional extension point

_initialize_states()[source]
_get_param_specs() list[source]

Return param specs for section_base._build_widgets. Oscillator layout specs (Analog) use .env/.tuning, not .controls.

build_widgets()[source]

Unified flow: feature widgets (e.g. tuning_sliders for Analog), base widgets, tuning sliders, additional (Analog/Digital), then tab widget.

setup_ui() None[source]

Setup the UI (standardized method name matching Digital Oscillator) :return: None

_add_pitch_env_tab()[source]
_add_pwm_tab()[source]
_add_tuning_tab()[source]
_has(feature: jdxi_editor.ui.editors.base.layout.spec.OscillatorFeature) bool[source]
_register_widget(key: Any, widget: jdxi_editor.ui.common.QWidget, *, legacy_attr: str | None = None) None[source]

Store widget by key. During migration also set legacy named attr so existing code keeps working; later remove legacy_attr and delete the named params.

_create_waveform_buttons()[source]

Create waveform buttons. Analog uses ModeButtonGroup (same as Digital); other subclasses use manual QButtonGroup.

_create_waveform_buttons_mode_group()[source]

Analog path: use ModeButtonGroup for exclusive waveform row (harmonized with Digital oscillator).

_create_waveform_buttons_manual()[source]

Manual QPushButton + QButtonGroup path (used when not analog and subclass does not override).

_on_wave_shape_selected(lfo_shape: jdxi_editor.midi.data.digital.lfo.DigitalLFOShape | jdxi_editor.midi.data.analog.lfo.AnalogLFOShape)[source]

Handle Mod LFO shape button clicks

Parameters:

lfo_shape – DigitalLFOShape enum value

_create_switch_row_layout() PySide6.QtWidgets.QHBoxLayout[source]

Create Switch row

_create_switch_layout_widgets()[source]

Create switch layout widgets

_on_button_selected(spec_or_param)[source]

Override to handle waveform button selection with correct MIDI parameter.

spec_or_param: SliderSpec (with .param, .label) or a single param enum for backward compat.

_resolve_rule_widget(key)[source]

Resolve a BUTTON_ENABLE_RULES key to a widget. Prefer _widgets, then attribute.

_update_button_enabled_states(button_param)[source]

Override to enable/disable widgets based on selected waveform.

This is called after all widgets are created (in setup_ui), so widgets should exist. We still check for None as a safety measure.

_create_button_row_layout()[source]

Override to create waveform button row layout

_create_tuning_pitch_widget() jdxi_editor.ui.common.QWidget[source]

Create tuning and pitch widget combining Tuning and Pitch Envelope (standardized name matching Digital)

_create_wave_layout() PySide6.QtWidgets.QHBoxLayout[source]

Create the waveform buttons layout (ModeButtonGroup when analog, else manual button row).

_create_tuning_group() PySide6.QtWidgets.QGroupBox[source]

Create the tuning group (standardized private method matching Digital)

Returns:

QGroupBox

_create_pw_group() PySide6.QtWidgets.QGroupBox[source]

Create the pulse width group (standardized private method matching Digital)

Returns:

QGroupBox

_create_pitch_env_group() PySide6.QtWidgets.QGroupBox[source]

Create the pitch envelope group (standardized private method matching Digital)

Returns:

QGroupBox

_on_waveform_selected_local(waveform: jdxi_editor.midi.data.analog.oscillator.AnalogWaveOsc | jdxi_editor.midi.data.digital.DigitalWaveOsc)[source]

Handle waveform button selection locally (for section-level handling) This is separate from the editor’s callback to avoid conflicts.

Parameters:

waveform – AnalogOscWave value

Returns:

None

_create_pwm_widget() jdxi_editor.ui.widgets.pulse_width.pwm.PWMWidget[source]

Create PWM widget from PWM_SPEC or SYNTH_SPEC params.

_create_pitch_env_widget() jdxi_editor.ui.widgets.pitch.envelope.PitchEnvWidget[source]

Create Pitch Envelope widget from PITCH_ENV_SPEC or SYNTH_SPEC params.

abstract _build_additional_widgets()[source]
abstract _build_additional_digital_widgets()[source]
abstract _build_additional_analog_widgets()[source]
abstract _add_pcm_wave_gain_tab()[source]
_create_tuning_sliders()[source]

create tuning sliders