"""MIDI playback state management."""
from collections import defaultdict
from dataclasses import dataclass, field
from typing import Optional
from mido import MidiFile
from picomidi.constant import Midi
from PySide6.QtCore import QThread, QTimer
from jdxi_editor.midi.channel.channel import MidiChannel
@dataclass
[docs]
class MidiPlaybackState:
"""State container for MIDI file playback."""
[docs]
active_notes: dict = field(default_factory=lambda: defaultdict(set))
[docs]
buffered_msgs: list = field(default_factory=list)
[docs]
buffer_end_time: float = 0.0
[docs]
channel_selected: MidiChannel = MidiChannel.DIGITAL_SYNTH_1
[docs]
events: list = field(default_factory=list)
[docs]
event_index_current: int = 0
[docs]
event_index: Optional[int] = None
[docs]
event_buffer: list = field(default_factory=list)
[docs]
file: Optional[MidiFile] = None
[docs]
file_duration_seconds: float = 0.0
# New attributes for playback state
[docs]
suppress_control_changes: bool = field(default=True)
[docs]
suppress_program_changes: bool = field(default=True)
[docs]
custom_tempo_force: bool = field(default=False)
[docs]
custom_tempo: int = field(
default=Midi.TEMPO.BPM_162_USEC
) # Default custom tempo in microseconds
[docs]
tempo_initial: int = field(default=Midi.TEMPO.BPM_120_USEC)
[docs]
tempo_at_position: int = field(default=Midi.TEMPO.BPM_120_USEC)
[docs]
timer: Optional[QTimer] = field(default=None)
# end of new attributes
[docs]
muted_tracks: set[int] = field(default_factory=set)
[docs]
muted_channels: set[int] = field(default_factory=set)
[docs]
playback_thread: Optional[QThread] = None
[docs]
playback_paused_time: Optional[float] = None
[docs]
playback_start_time: Optional[float] = None
[docs]
playback_paused: bool = False
[docs]
def __post_init__(self) -> None:
if self.custom_tempo_force:
self.tempo_at_position = self.custom_tempo # Use custom tempo if forced
else:
self.tempo_at_position = Midi.TEMPO.BPM_120_USEC # Default of 120 bpm