#ifndef TRANSPORT_H #define TRANSPORT_H #include #include #include #include #include #define MIDI_CLOCKS_PER_BEAT 24 #define BEATS_PER_BAR 4 #define DEFAULT_BPM 120.0 typedef enum { TRANSPORT_STOPPED, TRANSPORT_PLAYING, TRANSPORT_PAUSED } TransportState; typedef enum { CLOCK_SOURCE_INTERNAL, // Master clock CLOCK_SOURCE_MIDI // Slave to external MIDI clock } ClockSource; typedef struct { // State TransportState state; ClockSource clock_source; // Position uint32_t clock_count; uint32_t beat_position; // 0-3 uint32_t bar_position; uint32_t sample_position; // derived from clock at current sample rate // Internal clock generation double bpm; double samples_per_beat; double sample_accumulator; // For precise BPM timing // Atomic mirrors for frontend reads atomic_int state_atomic; // TransportState atomic_uint clock_count_atomic; atomic_uint beat_position_atomic; atomic_uint bar_position_atomic; atomic_uint sample_position_atomic; atomic_int clock_source_atomic; // ClockSource double bpm_atomic; // Direct read for audio thread atomic_uint bpm_atomic_raw; // Fixed-point (BPM * 100) for frontend reads // JACK ports for MIDI clock output (when master) jack_port_t *midi_clock_out_port; // Reference to engine for sample rate jack_nframes_t sample_rate; } Transport; // Lifecycle void transport_init(Transport *transport, jack_nframes_t sample_rate); void transport_cleanup(Transport *transport); // Control void transport_play(Transport *transport); void transport_pause(Transport *transport); void transport_stop(Transport *transport); void transport_toggle_play(Transport *transport); // Clock source void transport_set_clock_source(Transport *transport, ClockSource source); ClockSource transport_get_clock_source(Transport *transport); // BPM (only relevant for internal clock) void transport_set_bpm(Transport *transport, double bpm); double transport_get_bpm(Transport *transport); // Process function called from audio thread // Returns number of MIDI clock ticks generated (for master mode) int transport_process(Transport *transport, jack_nframes_t nframes, void *midi_clock_in_buf, void *midi_clock_out_buf); // Reset position void transport_reset(Transport *transport); // Utility const char* transport_state_to_string(TransportState state); const char* clock_source_to_string(ClockSource source); #endif // TRANSPORT_H