Source code for jdxi_editor.midi.message.channel

"""
MIDI Channel Message Module
===========================

This module defines the `ChannelMessage` class, which represents a MIDI Channel Voice Message.
It extends the `Message` base class and provides a structured way to handle MIDI messages
that operate on specific channels, such as Note On, Note Off, and Control Change.

Classes:
    - ChannelMessage: Represents a MIDI channel message with status, data bytes, and channel information.

Features:
    - Validates MIDI channel range (0-15).
    - Constructs MIDI messages with status and data bytes.
    - Converts messages to byte lists for transmission.

Usage Example:
    >>> msg = ChannelMessage(status=0x90, data1=60, data2=127, channel=1)  # Note On for Middle C
    >>> msg.to_message_list()
    [145, 60, 127]  # (0x91 in hex: Note On for channel 1)
"""

from dataclasses import dataclass
from typing import List, Optional

from jdxi_editor.midi.message.midi import MidiMessage


@dataclass
[docs] class ChannelMessage(MidiMessage): """MIDI Channel Message"""
[docs] channel: int = 0 # Default value first
[docs] status: int = 0 # Must have a default since `channel` does
[docs] data1: Optional[int] = None
[docs] data2: Optional[int] = None
[docs] def to_message_list(self) -> List[int]: """Convert to list of bytes for sending""" if not (0 <= self.channel <= 15): raise ValueError( f"Channel {self.channel} is out of valid MIDI range (0-15)." ) # Build the MIDI message message = [ (self.status & self.MIDI_STATUS_MASK) | (self.channel & self.MIDI_CHANNEL_MASK) ] if self.data1 is not None: message.append(self.data1 & self.MIDI_MAX_VALUE) if self.data2 is not None: message.append(self.data2 & self.MIDI_MAX_VALUE) return message