"""Definitions and lookup tables for MIDI messages. TODO: * add lookup functions for messages definitions by type and status byte. """ from collections.abc import Sequence from typing import Literal, NotRequired, TypedDict, final, overload, type_check_only CHANNEL_MESSAGES: set[int] COMMON_MESSAGES: set[int] REALTIME_MESSAGES: set[int] SYSEX_START: int = 0xF0 SYSEX_END: int = 0xF7 # Pitchwheel is a 14 bit signed integer MIN_PITCHWHEEL: int = -8192 MAX_PITCHWHEEL: int = 8191 # Song pos is a 14 bit unsigned integer MIN_SONGPOS: int = 0 MAX_SONGPOS: int = 16383 @type_check_only class SpecsDict(TypedDict): status_byte: int type: str value_names: tuple[str, ...] attribute_names: set[str] length: int | float @type_check_only class MsgDictOverride(TypedDict): channel: NotRequired[int] control: NotRequired[int] data: NotRequired[Sequence[int]] frame_type: NotRequired[int] frame_value: NotRequired[int] note: NotRequired[int] pitch: NotRequired[int] pos: NotRequired[int] program: NotRequired[int] song: NotRequired[int] value: NotRequired[int] velocity: NotRequired[int] time: NotRequired[int | float] @type_check_only class MsgDictBase[T: str](TypedDict): type: T time: int | float @type_check_only class ChannelMsgDictBase[ T: Literal["note_off", "note_on", "polytouch", "control_change", "program_change", "aftertouch", "pitchwheel"] ](MsgDictBase[T]): channel: int @type_check_only @final class NoteMsgDict(ChannelMsgDictBase[Literal["note_off", "note_on"]]): note: int velocity: int @type_check_only @final class PolytouchMsgDict(ChannelMsgDictBase[Literal["polytouch"]]): note: int value: int @type_check_only @final class ControlChangeMsgDict(ChannelMsgDictBase[Literal["control_change"]]): control: int value: int @type_check_only @final class ProgramChangeMsgDict(ChannelMsgDictBase[Literal["program_change"]]): program: int @type_check_only @final class AftertouchMsgDict(ChannelMsgDictBase[Literal["aftertouch"]]): value: int @type_check_only @final class PitchwheelMsgDict(ChannelMsgDictBase[Literal["pitchwheel"]]): pitch: int @type_check_only @final class SysExMsgDict(MsgDictBase[Literal["sysex"]]): data: Sequence[int] @type_check_only @final class QuarterFrameMsgDict(MsgDictBase[Literal["quarter_frame"]]): frame_type: int frame_value: int @type_check_only @final class SongposMsgDict(MsgDictBase[Literal["songpos"]]): pos: int @type_check_only @final class SongSelectMsgDict(MsgDictBase[Literal["song_select"]]): song: int @type_check_only @final class RealTimeMsgDict( MsgDictBase[Literal["tune_request", "clock", "start", "continue", "stop", "active_sensing", "reset"]] ): ... type MsgDict = ( NoteMsgDict | PolytouchMsgDict | ControlChangeMsgDict | ProgramChangeMsgDict | AftertouchMsgDict | PitchwheelMsgDict | SysExMsgDict | QuarterFrameMsgDict | SongposMsgDict | SongSelectMsgDict | RealTimeMsgDict ) SPECS: list[SpecsDict] SPEC_LOOKUP: dict[str | int, SpecsDict] SPEC_BY_STATUS: dict[int, SpecsDict] SPEC_BY_TYPE: dict[str, SpecsDict] REALTIME_TYPES: set[str] DEFAULT_VALUES: MsgDict @overload def make_msgdict(type_: Literal["note_off", "note_on"], overrides: MsgDictOverride) -> NoteMsgDict: ... @overload def make_msgdict(type_: Literal["polytouch"], overrides: MsgDictOverride) -> PolytouchMsgDict: ... @overload def make_msgdict(type_: Literal["control_change"], overrides: MsgDictOverride) -> ControlChangeMsgDict: ... @overload def make_msgdict(type_: Literal["program_change"], overrides: MsgDictOverride) -> ProgramChangeMsgDict: ... @overload def make_msgdict(type_: Literal["aftertouch"], overrides: MsgDictOverride) -> AftertouchMsgDict: ... @overload def make_msgdict(type_: Literal["pitchwheel"], overrides: MsgDictOverride) -> PitchwheelMsgDict: ... @overload def make_msgdict(type_: Literal["sysex"], overrides: MsgDictOverride) -> SysExMsgDict: ... @overload def make_msgdict(type_: Literal["quarter_frame"], overrides: MsgDictOverride) -> QuarterFrameMsgDict: ... @overload def make_msgdict(type_: Literal["songpos"], overrides: MsgDictOverride) -> SongposMsgDict: ... @overload def make_msgdict(type_: Literal["song_select"], overrides: MsgDictOverride) -> SongSelectMsgDict: ... @overload def make_msgdict( type_: Literal["tune_request", "clock", "start", "continue", "stop", "active_sensing", "reset"], overrides: MsgDictOverride, ) -> RealTimeMsgDict: ... @overload def make_msgdict[T: str](type_: T, overrides: MsgDictOverride) -> MsgDictBase[T]: ... def make_msgdict[T: str](type_: T, overrides: MsgDictOverride) -> MsgDictBase[T]: """Return a new message. Returns a dictionary representing a message. Message values can be overriden. No type or value checking is done. The caller is responsible for calling `check_msgdict()`. """