#pragma once #include #include // Synced: // () = other clients only // Pause: // - User input -> start fade and request pause from server // - Get response -> (start fade) arm pause or reseek if late // Resume: // - User input -> request resume from server // - Get response -> arm resume, apply offset to queued // Next/Prev: // - User input -> start fade request next from server // - Get response -> (start fade) arm pause, arm resume on next, then swap on pause // // Local: // Pause: // - User input -> start fade and pause immediately // Reumse: // - User input -> resume and fade in // Next/Prev: // - User input -> swap // Values that PTS can never normally be. #define CAMU_PTS_PAUSED 0x1.fffffffffffffp+1023 #define CAMU_PTS_SIGNAL_PAUSE 0x1.fffffffffffffp+1022 #define CAMU_PTS_UNSET 0x1.fffffffffffffp+1021 #define CAMU_PTS_CONSIDER_PAUSED(pts) (pts == CAMU_PTS_PAUSED || pts == CAMU_PTS_SIGNAL_PAUSE || pts == CAMU_PTS_UNSET) enum { CAMU_CLOCK_PAUSED = 0 }; enum { CAMU_CLOCK_PAUSE_FOR_SWAP = 1, CAMU_CLOCK_EXTERNAL_PAUSE = 1 << 1, CAMU_CLOCK_NO_SIGNAL_PAUSE = 1 << 7 }; struct camu_clock { f64 base; f64 offset; atomic(f64) tick; atomic(f64) pause; f64 paused_at; atomic(bool) pause_for_swap; atomic(bool) external_pause; atomic(f64) last_pts; void (*callback)(void *, u8); void *userdata; }; void camu_clock_init(struct camu_clock *clock, void (*callback)(void *, u8), void *userdata); void camu_clock_set(struct camu_clock *clock, f64 base); void camu_clock_offset(struct camu_clock *clock, f64 offset); void camu_clock_seek(struct camu_clock *clock, f64 base, u64 target); bool camu_clock_pause(struct camu_clock *clock, u64 target); void camu_clock_set_pause_for_swap(struct camu_clock *clock); void camu_clock_set_external_pause(struct camu_clock *clock); void camu_clock_resume(struct camu_clock *clock, u64 target); f64 camu_clock_get_base_pts(struct camu_clock *clock); f64 camu_clock_get_pts(struct camu_clock *clock, f64 latency, bool allow_set, u8 *status); f64 camu_clock_get_last_pts(struct camu_clock *clock);