1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
#pragma once
#include <al/types.h>
#include <al/wstr.h>
#include <al/array.h>
#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);
|