Source code for jdxi_editor.midi.message.areas.system_common

"""
SystemCommonMessage
===================

# Example usage:
# Set master tune to +50 cents
>>> from jdxi_editor.midi.data.parameter.system.common import SystemCommonParam
>>> msg = SystemCommonMessage(
...     lsb=SystemCommonParam.MASTER_TUNE.value,
...     value=1024 + (50 * 10),  # Convert +50.0 cents to 1524
... )

# Set master key shift to -12 semitones
>>> msg = SystemCommonMessage(
...     lsb=SystemCommonParam.MASTER_KEY_SHIFT.value, value=52  # Convert -12 to 52 (64-12)
... )

# Set program control channel to 1
>>> msg = SystemCommonMessage(
...     lsb=SystemCommonParam.PROGRAM_CTRL_CH.value, value=1  # Channel 1
... )

# Enable program change reception
>>> msg = SystemCommonMessage(lsb=SystemCommonParam.RX_PROGRAM_CHANGE.value, value=1)  # ON
"""

from dataclasses import dataclass

from jdxi_editor.midi.data.address.address import (
    CommandID,
    JDXiSysExAddressStartMSB,
    JDXiSysExOffsetProgramLMB,
)
from jdxi_editor.midi.message.roland import JDXiSysEx
from picomidi.constant import Midi
from picomidi.utils.conversion import split_16bit_value_to_nibbles


@dataclass
[docs] class SystemCommonMessage(JDXiSysEx): """System Common parameter message"""
[docs] command: int = CommandID.DT1
[docs] msb: int = JDXiSysExAddressStartMSB.SETUP # 0x02: System area (02 00 00 00)
[docs] umb: int = JDXiSysExOffsetProgramLMB.COMMON # 0x00: Common section
[docs] lmb: int = Midi.value.ZERO # Always 0x00
[docs] lsb: int = Midi.value.ZERO # Parameter number
[docs] value: int = Midi.value.ZERO # Parameter value
[docs] def __post_init__(self): # Master Tune (0x00) uses 4-byte encoding (nibbles) for values 24-2024 # Convert value to nibbles BEFORE calling super() to avoid validation errors # Extract the actual address byte from lsb (handle tuple, enum, or int) if isinstance(self.lsb, tuple) and len(self.lsb) > 0: lsb_addr = self.lsb[0] # AddressParameter tuple: (address, min, max) elif hasattr(self.lsb, "address"): lsb_addr = self.lsb.address else: lsb_addr = self.lsb if lsb_addr == 0x00 and isinstance(self.value, int): # MASTER_TUNE parameter # Convert 16-bit value to 4 nibbles (4-bit values, 0-15 each) self.data = split_16bit_value_to_nibbles(self.value) self.size = 4 # Call parent __post_init__ which will validate the message structure super().__post_init__() # Set address and data from RolandSysEx