Source code for midi.slider.nrpn

"""
NRPN Slider
sends NRPN, (N)RPN messages to the synth

def send_nrpn(self, channel, msb, lsb, value):
    self.send_control_change(99, msb, channel)  # NRPN MSB
    self.send_control_change(98, lsb, channel)  # NRPN LSB
    self.send_control_change(6, value, channel)  # Data Entry MSB
    # Optional: Reset NRPN selection
    self.send_control_change(99, 127, channel)
    self.send_control_change(98, 127, channel)

"""

import threading

from decologr import Decologr as log

from jdxi_editor.jdxi.style import JDXiStyle
from jdxi_editor.midi.io.delay import send_with_delay
from jdxi_editor.midi.sysex.request.midi_requests import MidiRequests
from jdxi_editor.ui.widgets.slider import Slider


[docs] class NRPNSlider(Slider): """ A base class for sliders that send NRPN messages to a specified partial. """ def __init__( self, midi_helper, label: str, nrpn_map: dict, partial: int = 1, nrpn_msb: int = 0, min_value: int = 0, max_value: int = 127, vertical: bool = True, param_type: str = "nrpn", is_bipolar: bool = False, ): super().__init__( label, min_value=min_value, max_value=max_value, midi_helper=midi_helper, vertical=vertical, show_value_label=False, draw_tick_marks=False, is_bipolar=is_bipolar, ) """Initialize the NRPNSlider. :param midi_helper: MidiIOHelper :param label: str :param nrpn_map: dict :param partial: int :param is_bipolar: bool """
[docs] self.label = label
[docs] self.midi_helper = midi_helper
[docs] self.partial = partial
[docs] self.nrpn_map = nrpn_map
[docs] self.nrpn_msb = nrpn_msb
[docs] self.min_value = min_value
[docs] self.max_value = max_value
[docs] self.current_value = min_value
[docs] self.vertical = vertical
self.setTickPosition(self.TickPosition.NoTicks) self.valueChanged.connect(self.on_valueChanged)
[docs] self.param_type = param_type # "nrpn" or "rpn"
self.update_style(self.current_value)
[docs] self.midi_requests = MidiRequests.PROGRAM_TONE_NAME_PARTIAL
[docs] def update_style(self, value: int) -> None: """Update the style of the slider. :param value: int """ if value == 0: self.setStyleSheet(JDXiStyle.ADSR_DISABLED) else: self.setStyleSheet(JDXiStyle.ADSR)
[docs] def data_request(self) -> None: """ Request the current value of the NRPN parameter from the device. """ threading.Thread( target=send_with_delay, args=( self.midi_helper, self.midi_requests, ), ).start()
[docs] def on_valueChanged(self, value: int): """ Set the current value of the slider and send NRPN or RPN messages :param value: int """ log.message(f"{self.label} value changed to {value}") if not self.min_value <= value <= self.max_value: raise ValueError("Value out of range.") self.current_value = value self.update_style(value) for partial in [1, 2, 3]: param_lsb = self.nrpn_map.get(partial) if param_lsb is None: raise ValueError(f"Invalid partial number: {partial}") parameter = (self.nrpn_msb << 7) | param_lsb for channel in [0, 1, 2]: if self.param_type == "nrpn": self.midi_helper.send_nrpn( parameter=parameter, value=value, channel=channel ) self.data_request() elif self.param_type == "rpn": self.midi_helper.send_rpn( parameter=parameter, value=value, channel=channel ) self.data_request() else: raise ValueError(f"Unsupported parameter type: {self.param_type}")