Source code for jdxi_editor.midi.sysex.parser.dynamic

"""
Dynamic Parameter Map resolver
"""

from typing import Dict

from decologr import Decologr as log

from jdxi_editor.jdxi.midi.constant import JDXiMidi
from jdxi_editor.jdxi.midi.message.sysex.offset import JDXiSysExMessageLayout
from jdxi_editor.midi.data.address.address import (
    AddressOffsetTemporaryToneUMB as TemporaryToneUMB,
)
from jdxi_editor.midi.data.parameter.drum.partial import DrumPartialParam
from jdxi_editor.midi.map.parameter_address import PARAMETER_ADDRESS_NAME_MAP
from jdxi_editor.midi.sysex.parser.tone_mapper import (
    get_drum_tone,
    get_synth_tone,
    get_temporary_area,
)
from jdxi_editor.midi.sysex.parser.utils import (
    _return_minimal_metadata,
    initialize_parameters,
    update_data_with_parsed_parameters,
    update_short_data_with_parsed_parameters,
)


[docs] def dynamic_map_resolver(data: bytes) -> Dict[str, str]: """ Dynamically resolve mappings for SysEx data. :param data: bytes SysEx message data :return: Dict[str, str] """ try: # Extract temporary area temporary_area = get_temporary_area(data) # Handle drum tones dynamically if temporary_area == TemporaryToneUMB.DRUM_KIT.name: address_lmb = data[JDXiSysExMessageLayout.ADDRESS.LMB] synth_tone, offset = get_drum_tone(address_lmb) else: synth_tone, offset = get_synth_tone( data[JDXiSysExMessageLayout.ADDRESS.LMB] ) # Resolve parameter class dynamically parameter_cls = PARAMETER_ADDRESS_NAME_MAP.get( (temporary_area, synth_tone), DrumPartialParam # Default fallback ) # Log the mappings for debugging log.parameter("temporary_area", temporary_area) log.parameter("synth_tone", synth_tone) log.parameter( "parameter_cls", parameter_cls.__name__ if parameter_cls else "None" ) return { "TEMPORARY_AREA": temporary_area, "SYNTH_TONE": synth_tone, "PARAMETER_CLASS": parameter_cls.__name__ if parameter_cls else "Unknown", } except Exception as ex: log.error(f"Error resolving mappings: {ex}") return { "TEMPORARY_AREA": "Error", "SYNTH_TONE": "Error", "PARAMETER_CLASS": "Error", }
[docs] def parse_sysex_with_dynamic_mapping(data: bytes) -> Dict[str, str]: """ Parse SysEx data using dynamic mapping. :param data: bytes SysEx message data :return: Dict[str, str] """ # Log the raw data log.parameter("data", data, silent=True) if len(data) < JDXiMidi.SYSEX.PARAMETER.LENGTH.ONE_BYTE: log.warning("Insufficient data length for parsing.") return _return_minimal_metadata(data) # Use dynamic map resolver resolved_mapping = dynamic_map_resolver(data) # Initialize parameters using resolved mappings parsed_data = initialize_parameters(data) # Get parameter type from resolved mapping parameter_cls_name = resolved_mapping.get("PARAMETER_CLASS", "Unknown") parameter_cls = globals().get(parameter_cls_name, None) # Update parsed data with parameters if parameter_cls: if len(data) < JDXiMidi.SYSEX.PARAMETER.LENGTH.FOUR_BYTE: update_short_data_with_parsed_parameters(data, parameter_cls, parsed_data) else: update_data_with_parsed_parameters(data, parameter_cls, parsed_data) # Log the parsed data log.json(parsed_data, silent=True) return parsed_data