Source code for jdxi_editor.ui.editors.digital.partial.amp

"""
AMP section for the digital partial editor.
"""

from typing import Callable

import qtawesome as qta
from picomidi.sysex.parameter.address import AddressParameter
from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
    QGroupBox,
    QHBoxLayout,
    QLabel,
    QTabWidget,
    QVBoxLayout,
    QWidget,
)

from jdxi_editor.jdxi.style import JDXiStyle, JDXiThemeManager
from jdxi_editor.midi.data.address.address import RolandSysExAddress
from jdxi_editor.midi.data.parameter.digital.partial import (
    DigitalPartialParam,
)
from jdxi_editor.midi.io.helper import MidiIOHelper
from jdxi_editor.ui.image.utils import base64_to_pixmap
from jdxi_editor.ui.image.waveform import generate_waveform_icon
from jdxi_editor.ui.widgets.adsr.adsr import ADSR
from jdxi_editor.ui.windows.jdxi.dimensions import JDXiDimensions


[docs] class DigitalAmpSection(QWidget): """Digital Amp Section for the JDXI Editor""" def __init__( self, create_parameter_slider: Callable, partial_number: int, midi_helper: MidiIOHelper, controls: dict[AddressParameter, QWidget], address: RolandSysExAddress, ): super().__init__() """ Initialize the DigitalAmpSection :param create_parameter_slider: Callable :param partial_number: int :param midi_helper: MidiIOHelper :param controls: dict :param address: RolandSysExAddress """
[docs] self.partial_number = partial_number
[docs] self.midi_helper = midi_helper
[docs] self.address = address
[docs] self.controls = controls
[docs] self._create_parameter_slider = create_parameter_slider
self.setup_ui()
[docs] def setup_ui(self): """Setup the amplifier section UI.""" amp_section_layout = QVBoxLayout() self.setLayout(amp_section_layout) amp_section_layout.setContentsMargins(5, 15, 5, 5) amp_section_layout.setSpacing(5) from jdxi_editor.jdxi.style.theme_manager import JDXiThemeManager JDXiThemeManager.apply_adsr_style(self) self.setMinimumHeight(JDXiDimensions.EDITOR_MINIMUM_HEIGHT) # Icons layout icons_hlayout = self._create_icons_layout() amp_section_layout.addLayout(icons_hlayout) # Create tab widget self.digital_amp_tab_widget = QTabWidget() amp_section_layout.addWidget(self.digital_amp_tab_widget) # Add Controls tab amp_controls_layout = self._create_amp_controls_layout() amp_controls_widget = QWidget() amp_controls_widget.setLayout(amp_controls_layout) self.digital_amp_tab_widget.addTab(amp_controls_widget, "Controls") # Add ADSR tab amp_adsr_group = self._create_amp_adsr_group() self.digital_amp_tab_widget.addTab(amp_adsr_group, "ADSR") amp_section_layout.addSpacing(10) amp_section_layout.addStretch()
[docs] def _create_icons_layout(self) -> QHBoxLayout: """Create icons layout""" icons_hlayout = QHBoxLayout() for icon in [ "mdi.volume-variant-off", "mdi6.volume-minus", "mdi.amplifier", "mdi6.volume-plus", "mdi.waveform", ]: icon_label = QLabel() icon_pixmap = qta.icon(icon, color="#666666").pixmap(30, 30) icon_label.setPixmap(icon_pixmap) icon_label.setAlignment(Qt.AlignmentFlag.AlignHCenter) icons_hlayout.addWidget(icon_label) return icons_hlayout
[docs] def _create_amp_controls_layout(self) -> QVBoxLayout: """Create amp controls layout""" main_layout = QVBoxLayout() # Level and velocity controls row controls_row_layout = QHBoxLayout() controls_row_layout.addStretch() controls_row_layout.addWidget( self._create_parameter_slider( DigitalPartialParam.AMP_LEVEL, "Level", vertical=True ) ) controls_row_layout.addWidget( self._create_parameter_slider( DigitalPartialParam.AMP_VELOCITY, "Velocity", vertical=True ) ) controls_row_layout.addWidget( self._create_parameter_slider( DigitalPartialParam.AMP_LEVEL_KEYFOLLOW, "KeyFollow", vertical=True ) ) controls_row_layout.addWidget( self._create_parameter_slider( DigitalPartialParam.LEVEL_AFTERTOUCH, "After-touch Sensitivity", vertical=True, ) ) controls_row_layout.addWidget( self._create_parameter_slider( DigitalPartialParam.CUTOFF_AFTERTOUCH, "After-touch Cutoff", vertical=True, ) ) controls_row_layout.addStretch() main_layout.addLayout(controls_row_layout) # Pan slider in a separate row pan_row_layout = QHBoxLayout() pan_row_layout.addStretch() pan_slider = self._create_parameter_slider(DigitalPartialParam.AMP_PAN, "Pan") pan_slider.setValue(0) pan_row_layout.addWidget(pan_slider) pan_row_layout.addStretch() main_layout.addLayout(pan_row_layout) main_layout.addStretch() return main_layout
[docs] def _create_amp_adsr_group(self) -> QGroupBox: """Create amp ADSR group""" env_group = QGroupBox("Envelope") env_group.setProperty("adsr", True) amp_env_adsr_vlayout = QVBoxLayout() env_group.setLayout(amp_env_adsr_vlayout) # Generate the ADSR waveform icon icon_base64 = generate_waveform_icon("adsr", "#FFFFFF", 2.0) pixmap = base64_to_pixmap(icon_base64) icon_label = QLabel() icon_label.setPixmap(pixmap) icon_label.setAlignment(Qt.AlignmentFlag.AlignHCenter) icons_hlayout = QHBoxLayout() icons_hlayout.addWidget(icon_label) amp_env_adsr_vlayout.addLayout(icons_hlayout) # Create ADSRWidget ( group_address, _, ) = DigitalPartialParam.AMP_ENV_ATTACK_TIME.get_address_for_partial( self.partial_number ) self.amp_env_adsr_widget = ADSR( attack_param=DigitalPartialParam.AMP_ENV_ATTACK_TIME, decay_param=DigitalPartialParam.AMP_ENV_DECAY_TIME, sustain_param=DigitalPartialParam.AMP_ENV_SUSTAIN_LEVEL, release_param=DigitalPartialParam.AMP_ENV_RELEASE_TIME, midi_helper=self.midi_helper, create_parameter_slider=self._create_parameter_slider, controls=self.controls, address=self.address, ) JDXiThemeManager.apply_adsr_style(self.amp_env_adsr_widget) amp_env_adsr_vlayout.addWidget(self.amp_env_adsr_widget) return env_group