#pragma once #include #include #include #include "common.h" #define LIANA_SEQUENCE_ANY -1 #define LIANA_BASE_DELAY ((u64)2000000) // 2000ms #define LIANA_BASE_PING ((u64)500000) // 500ms #define LIANA_PAUSE_DELAY LIANA_BASE_PING #define LIANA_DELAY_IGNORE ((u64)0) #define LIANA_BUFFER_AHEAD 2 //#define LIANA_LIST_SCUFFED_LOOP // @TODO: // To handle an entry being queued right before a skip, keep a global // "max time until all sinks buffered" and used that instead of LIANA_PAUSE_DELAY (if greater). // Factor in LIANA_BASE_PING. enum { LIANA_SINK_SET = 0, LIANA_SINK_UNSET, LIANA_SINK_BUFFER, LIANA_SINK_BUFFER_AND_QUEUE, LIANA_SINK_PAUSE, LIANA_SINK_SEEK }; enum { LIANA_LOAD_ENTRY = 0, LIANA_GET_ENTRY_DURATION, LIANA_REF_ENTRY, LIANA_UNREF_ENTRY, LIANA_UNLOAD_ENTRY, LIANA_LIST_META }; enum { LIANA_ENTRY_UNLOADED = 0, LIANA_ENTRY_PREPARING, LIANA_ENTRY_PREPARED, LIANA_ENTRY_LOADING, LIANA_ENTRY_LOADED, LIANA_ENTRY_ERRORED }; enum { LIANA_META_ADDED_ENTRY = 0, LIANA_META_REMOVED_ENTRY, LIANA_META_CURRENT_CHANGED, LIANA_META_ORDER_PROBABLY_CHANGED, LIANA_META_ENTRY_PAUSED, LIANA_META_ENTRY_SEEKED, LIANA_META_ENTRY_ERRORED }; enum { LIANA_PAUSE_NONE = 0, LIANA_PAUSE_RESUME, LIANA_PAUSE_PAUSE, LIANA_PAUSE_BOTH }; struct lia_timing { u64 at; u64 pos; u8 pause; }; struct lia_list_entry { void *opaque; str brief; u32 id; u64 start; u64 paused_at; u64 offset; u64 delay; u64 duration; u8 load; bool held; bool ended; u32 reset_token; struct lia_list *list; }; struct lia_list_sink { s32 set; void (*callback)(void *, u8, struct lia_list_entry *, s32, struct lia_timing *); void *userdata; }; struct lia_list_cmd { u8 op; struct lia_list_sink *sink; void *userdata; struct lia_list_entry *entry; s32 sequence; union { s32 i; u32 u; } arg0; union { u64 l; u32 u; f64 f; } arg1; }; struct lia_list { str name; s32 current; bool idle; bool closed; u32 increment; array(struct lia_list_entry *) entries; array(struct lia_list_sink *) sinks; array(struct lia_list_cmd *) command_queue; struct lia_list_cmd *cmd; void (*callback)(void *, u8, struct lia_list_entry *, void *); void *userdata; }; static inline const char *lia_pause_op_name(u8 pause) { switch (pause) { case LIANA_PAUSE_NONE: return "PAUSE_NONE"; case LIANA_PAUSE_RESUME: return "PAUSE_RESUME"; case LIANA_PAUSE_PAUSE: return "PAUSE_PAUSE"; case LIANA_PAUSE_BOTH: return "PAUSE_BOTH"; default: al_assert_and_return(""); } } void lia_list_init(struct lia_list *list, str *name); void lia_list_pump(struct lia_list *list); void lia_list_add_sink(struct lia_list *list, void (*callback)(void *, u8, struct lia_list_entry *, s32, struct lia_timing *), void *userdata); void lia_list_remove_sink(struct lia_list *list, void *userdata); void lia_list_add(struct lia_list *list, str *brief, void *opaque, u64 duration, u8 load); void lia_list_unset(struct lia_list *list); void lia_list_skipto(struct lia_list *list, s32 sequence, s32 i); void lia_list_skip(struct lia_list *list, s32 sequence, s32 n); void lia_list_toggle_pause(struct lia_list *list, s32 sequence, f64 pts); void lia_list_seek(struct lia_list *list, s32 sequence, u32 id, u64 pos); void lia_list_end(struct lia_list *list, u32 id, u32 reset_token); void lia_list_reverse(struct lia_list *list); void lia_list_sort(struct lia_list *list); void lia_list_shuffle(struct lia_list *list); void lia_list_clear(struct lia_list *list); void lia_list_close(struct lia_list *list); void lia_list_free(struct lia_list *list);