summaryrefslogtreecommitdiff
path: root/src/liana
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2024-12-18 11:06:44 -0500
committerAndrew Opalach <andrew@akon.city> 2024-12-18 11:06:44 -0500
commit3d55d2722a3129449ab1418e73abd97caa7fd2ae (patch)
tree0cba3f876c9b339d20d8e4a38a7a5d786fa2102d /src/liana
parent692785bc9da6904cf17e986fb034730ed3d78231 (diff)
downloadcamu-3d55d2722a3129449ab1418e73abd97caa7fd2ae.tar.gz
camu-3d55d2722a3129449ab1418e73abd97caa7fd2ae.tar.bz2
camu-3d55d2722a3129449ab1418e73abd97caa7fd2ae.zip
Extend server resource loading, work on client
Also, cleanup in preparation for changing code style. Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/liana')
-rw-r--r--src/liana/client.c2
-rw-r--r--src/liana/list.c136
-rw-r--r--src/liana/list.h23
-rw-r--r--src/liana/vcr.c16
4 files changed, 120 insertions, 57 deletions
diff --git a/src/liana/client.c b/src/liana/client.c
index a841f7a..ad365b3 100644
--- a/src/liana/client.c
+++ b/src/liana/client.c
@@ -62,7 +62,7 @@ static void parse_info_packet(struct lia_client *client, struct aki_packet *pack
client->mask |= 1 << index;
break;
case CAMU_STREAM_ATTACHMENT:
- // Assume we have all the data we need in the AVStream object.
+ // Assume all the data we need is in the AVStream object.
break;
default:
continue;
diff --git a/src/liana/list.c b/src/liana/list.c
index 23eabc3..073cdf0 100644
--- a/src/liana/list.c
+++ b/src/liana/list.c
@@ -77,11 +77,26 @@ static bool assume_ended(struct lia_list_entry *entry, u64 at)
return false;
}
-static bool entry_load_and_get_duration(struct lia_list *list, struct lia_list_entry *entry)
+static bool entry_load_and_get_duration(struct lia_list *list, struct lia_list_entry *entry, s32 sequence, bool *error)
{
- bool loaded;
- list->callback(list->userdata, LIANA_LOAD_ENTRY, entry, &loaded);
- if (loaded) {
+ u8 status;
+ list->callback(list->userdata, LIANA_LOAD_ENTRY, entry, &status);
+ if (status == LIANA_ENTRY_ERRORED) {
+ if (sequence >= 0) {
+ al_array_remove_at(list->entries, (u32)sequence);
+ if (sequence == list->current && (u32)list->current == list->entries.size) {
+ // This maps to the behavior of only skipping ahead on errors.
+ list->current--;
+ list->idle = true;
+ }
+ }
+ *error = true;
+ u8 meta = LIANA_META_FAILED;
+ list->callback(list->userdata, LIANA_LIST_META, entry, &meta);
+ return false;
+ }
+ *error = false;
+ if (status == LIANA_ENTRY_LOADED) {
list->callback(list->userdata, LIANA_GET_DURATION, entry, &entry->duration);
return true;
}
@@ -90,12 +105,13 @@ static bool entry_load_and_get_duration(struct lia_list *list, struct lia_list_e
static bool handle_add_sink(struct lia_list *list, struct lia_list_sink *sink)
{
- if (list->current >= 0) {
- struct lia_list_entry *current = al_array_at(list->entries, list->current);
- if (!entry_load_and_get_duration(list, current)) {
+ struct lia_list_entry *current;
+ if (list->current >= 0 && !list->idle && !(current = al_array_at(list->entries, list->current))->ended) {
+ bool error;
+ if (!entry_load_and_get_duration(list, current, list->current, &error)) {
+ if (error) pump_queue(list);
return false;
}
- sink->set = list->current;
u64 now = aki_get_timestamp();
u8 pause;
u64 at = LIANA_TIMESTAMP_INVALID;
@@ -121,6 +137,7 @@ static bool handle_add_sink(struct lia_list *list, struct lia_list_sink *sink)
.pause = pause,
.ended = ended
};
+ sink->set = list->current;
sink->callback(sink->userdata, LIANA_SINK_SET, current, list->current, &time);
} else {
sink->set = -1;
@@ -145,8 +162,9 @@ static void handle_remove_sink(struct lia_list *list, void *userdata)
static bool handle_add(struct lia_list *list, struct lia_list_entry *entry)
{
if (list->idle) {
- if (!entry_load_and_get_duration(list, entry)) {
- return false;
+ bool error;
+ if (!entry_load_and_get_duration(list, entry, -1, &error)) {
+ return error;
}
list->current++;
list->idle = false;
@@ -163,7 +181,8 @@ static bool handle_add(struct lia_list *list, struct lia_list_entry *entry)
sink->set = list->current;
sink->callback(sink->userdata, LIANA_SINK_SET, entry, list->current, &time);
}
- al_log_info("list", "Now playing: %ls.", AL_WSTR_PRINTF(&entry->name));
+ u8 meta = LIANA_META_PLAYING;
+ list->callback(list->userdata, LIANA_LIST_META, entry, &meta);
} else {
/*
if (list->queued == -1) {
@@ -185,7 +204,8 @@ static bool handle_add(struct lia_list *list, struct lia_list_entry *entry)
*/
entry->start = LIANA_TIMESTAMP_INVALID;
//}
- // meta queued
+ u8 meta = LIANA_META_QUEUED;
+ list->callback(list->userdata, LIANA_LIST_META, entry, &meta);
}
al_array_push(list->entries, entry);
return true;
@@ -202,7 +222,7 @@ static void adjust_current(struct lia_list *list, struct lia_list_entry *previou
if (i == (u32)list->current) return;
cmd->op = SKIPTO;
cmd->sequence = i;
- cmd->i = list->current;
+ cmd->value.i = list->current;
list->current = i;
break;
}
@@ -241,6 +261,18 @@ static struct lia_list_entry *get_entry_from_sequence(struct lia_list *list, s32
return al_array_at(list->entries, sequence);
}
+static struct lia_list_entry *get_entry_from_id(struct lia_list *list, u32 id, s32 *sequence)
+{
+ struct lia_list_entry *entry;
+ al_array_foreach(list->entries, i, entry) {
+ if (entry->id == id) {
+ *sequence = (s32)i;
+ return entry;
+ }
+ }
+ return NULL;
+}
+
// TODO:
//if (current->start != LIANA_TIMESTAMP_INVALID && current->start > ts - LIANA_BASE_PING) {
@@ -260,7 +292,10 @@ static bool handle_skipto(struct lia_list *list, s32 sequence, s32 index)
al_assert(current && !current->held);
if (!target) return true;
al_assert(current != target);
- if (!entry_load_and_get_duration(list, target)) {
+ bool error;
+ if (!entry_load_and_get_duration(list, target, index, &error)) {
+ // index might point to a different entry after an error.
+ if (error) pump_queue(list);
return false;
}
@@ -281,7 +316,7 @@ static bool handle_skipto(struct lia_list *list, s32 sequence, s32 index)
// An ended entry may never have been paused, but a non-ended entry that wasn't set
// cannot be unpaused. Checking assume_ended(target) should be safe here as long
// as it can't go from true to false (consideration for seek?).
- al_assert(assume_ended(target, now) || target->paused_at != LIANA_TIMESTAMP_INVALID);
+ //al_assert(assume_ended(target, now) || target->paused_at != LIANA_TIMESTAMP_INVALID);
}
// These are not equivalent to current/target->ended.
@@ -342,7 +377,8 @@ static bool handle_skipto(struct lia_list *list, s32 sequence, s32 index)
sink->callback(sink->userdata, LIANA_SINK_SET, target, index, &time);
}
- al_log_info("list", "Now playing: %ls.", AL_WSTR_PRINTF(&target->name));
+ u8 meta = LIANA_META_PLAYING;
+ list->callback(list->userdata, LIANA_LIST_META, target, &meta);
return true;
}
@@ -353,8 +389,8 @@ static bool handle_skip(struct lia_list *list, s32 sequence, s32 n)
struct lia_list_cmd *cmd = list->cmd;
cmd->op = SKIPTO;
cmd->sequence = sequence;
- cmd->i = sequence + n;
- return handle_skipto(list, cmd->sequence, cmd->i);
+ cmd->value.i = sequence + n;
+ return handle_skipto(list, cmd->sequence, cmd->value.i);
}
static void handle_toggle_pause(struct lia_list *list, s32 sequence, f64 pts)
@@ -408,19 +444,19 @@ static void handle_toggle_pause(struct lia_list *list, s32 sequence, f64 pts)
}
}
-// TODO: Take entry id instead of sequence for seek() and end()?
-
-static void handle_seek(struct lia_list *list, s32 sequence, f64 percent)
+static void handle_seek(struct lia_list *list, s32 sequence, u32 id, f64 percent)
{
- if (sequence == LIANA_SEQUENCE_ANY) sequence = list->current;
- if (sequence < 0) return;
- if (sequence != list->current) {
- return;
+ struct lia_list_entry *entry;
+ if (sequence == LIANA_SEQUENCE_ANY) {
+ sequence = list->current;
+ if (sequence < 0) return;
+ entry = get_entry_from_sequence(list, sequence);
+ al_assert(entry);
+ } else {
+ entry = get_entry_from_id(list, id, &sequence);
+ if (!entry) return;
}
- struct lia_list_entry *entry = get_entry_from_sequence(list, sequence);
- al_assert(entry);
if (entry->duration == LIANA_TIMESTAMP_INVALID) {
- // Until any kind of live resource buffering.
return;
}
entry->ended = false;
@@ -428,8 +464,9 @@ static void handle_seek(struct lia_list *list, s32 sequence, f64 percent)
u64 now = aki_get_timestamp();
u64 pos = (u64)(entry->duration * percent);
u64 at = now + LIANA_BASE_DELAY;
+ u8 pause = entry->paused_at == LIANA_TIMESTAMP_INVALID ? LIANA_PAUSE_RESUME : LIANA_PAUSE_NONE;
entry->offset = pos;
- if (entry->paused_at == LIANA_TIMESTAMP_INVALID) {
+ if (pause == LIANA_PAUSE_RESUME) {
entry->start = at;
}
@@ -440,31 +477,34 @@ static void handle_seek(struct lia_list *list, s32 sequence, f64 percent)
struct lia_timing time = {
.at = at,
.seek_pos = pos,
- .pause = LIANA_PAUSE_NONE,
+ .pause = pause,
.ended = false
};
struct lia_list_sink *sink;
al_array_foreach(list->sinks, i, sink) {
+ if (sequence == list->current && sink->set != sequence) {
+ sink->set = sequence;
+ sink->callback(sink->userdata, LIANA_SINK_SET, entry, sequence, &time);
+ }
sink->callback(sink->userdata, LIANA_SINK_SEEK, entry, sequence, &time);
}
}
-static bool handle_end(struct lia_list *list, s32 sequence)
+static bool handle_end(struct lia_list *list, s32 id)
{
- al_assert(sequence != LIANA_SEQUENCE_ANY);
+ s32 sequence;
+ struct lia_list_entry *entry = get_entry_from_id(list, id, &sequence);
+ if (!entry) return true;
- s32 size = (s32)list->entries.size;
- struct lia_list_entry *entry = al_array_at(list->entries, sequence);
- al_assert(entry);
if (entry->ended) {
al_log_warn("list", "Got end() from an already ended resource, ignoring.");
return true;
}
entry->ended = true;
- // TODO: Calculate duration for live resources?
entry->offset = entry->duration;
+ s32 size = (s32)list->entries.size;
if (sequence == list->current) {
s32 next = sequence + 1;
if (list->queued >= 0) {
@@ -476,12 +516,13 @@ static bool handle_end(struct lia_list *list, s32 sequence)
sink->queued = -1;
}
struct lia_list_entry *current = al_array_at(list->entries, list->current);
- al_log_info("list", "Now playing: %ls.", AL_WSTR_PRINTF(&current->name));
+ u8 meta = LIANA_META_PLAYING;
+ list->callback(list->userdata, LIANA_LIST_META, current, &meta);
} else if (next < size) {
struct lia_list_cmd *cmd = list->cmd;
cmd->op = SKIPTO;
cmd->sequence = sequence;
- cmd->i = next;
+ cmd->value.i = next;
pump_queue(list);
return false;
} else {
@@ -567,13 +608,13 @@ void pump_queue(struct lia_list *list)
handle_unset(list);
break;
case SKIPTO:
- if (!handle_skipto(list, cmd->sequence, cmd->i)) {
+ if (!handle_skipto(list, cmd->sequence, cmd->value.i)) {
// Target entry not loaded.
return;
}
break;
case SKIP:
- if (!handle_skip(list, cmd->sequence, cmd->i)) {
+ if (!handle_skip(list, cmd->sequence, cmd->value.i)) {
// Converted to skipto and entry not loaded.
return;
}
@@ -582,10 +623,10 @@ void pump_queue(struct lia_list *list)
handle_toggle_pause(list, cmd->sequence, cmd->f);
break;
case SEEK:
- handle_seek(list, cmd->sequence, cmd->f);
+ handle_seek(list, cmd->sequence, cmd->value.u, cmd->f);
break;
case END:
- if (!handle_end(list, cmd->sequence)) {
+ if (!handle_end(list, cmd->value.u)) {
// End was converted to a skip.
return;
}
@@ -665,7 +706,7 @@ void lia_list_skipto(struct lia_list *list, s32 sequence, s32 index)
struct lia_list_cmd *cmd = al_alloc_object(struct lia_list_cmd);
cmd->op = SKIPTO;
cmd->sequence = sequence;
- cmd->i = index;
+ cmd->value.i = index;
al_array_push(list->queue, cmd);
pump_queue(list);
}
@@ -675,7 +716,7 @@ void lia_list_skip(struct lia_list *list, s32 sequence, s32 n)
struct lia_list_cmd *cmd = al_alloc_object(struct lia_list_cmd);
cmd->op = SKIP;
cmd->sequence = sequence;
- cmd->i = n;
+ cmd->value.i = n;
al_array_push(list->queue, cmd);
pump_queue(list);
}
@@ -690,21 +731,22 @@ void lia_list_toggle_pause(struct lia_list *list, s32 sequence, f64 pts)
pump_queue(list);
}
-void lia_list_seek(struct lia_list *list, s32 sequence, f64 percent)
+void lia_list_seek(struct lia_list *list, s32 sequence, u32 id, f64 percent)
{
struct lia_list_cmd *cmd = al_alloc_object(struct lia_list_cmd);
cmd->op = SEEK;
cmd->sequence = sequence;
+ cmd->value.u = id;
cmd->f = percent;
al_array_push(list->queue, cmd);
pump_queue(list);
}
-void lia_list_end(struct lia_list *list, s32 sequence)
+void lia_list_end(struct lia_list *list, u32 id)
{
struct lia_list_cmd *cmd = al_alloc_object(struct lia_list_cmd);
cmd->op = END;
- cmd->sequence = sequence;
+ cmd->value.u = id;
al_array_push(list->queue, cmd);
pump_queue(list);
}
diff --git a/src/liana/list.h b/src/liana/list.h
index 90f8c02..8d47b72 100644
--- a/src/liana/list.h
+++ b/src/liana/list.h
@@ -26,7 +26,22 @@ enum {
enum {
LIANA_LOAD_ENTRY = 0,
LIANA_GET_DURATION,
- LIANA_UNLOAD_ENTRY
+ LIANA_UNLOAD_ENTRY,
+ LIANA_LIST_META
+};
+
+enum {
+ LIANA_ENTRY_PREPARING = 0,
+ LIANA_ENTRY_PREPARED,
+ LIANA_ENTRY_LOADING,
+ LIANA_ENTRY_LOADED,
+ LIANA_ENTRY_ERRORED
+};
+
+enum {
+ LIANA_META_PLAYING = 0,
+ LIANA_META_QUEUED,
+ LIANA_META_FAILED
};
// NOTE: To handle an entry being queued right before a skip, keep a global
@@ -75,7 +90,7 @@ struct lia_list_cmd {
void *userdata;
struct lia_list_entry *entry;
s32 sequence;
- s32 i;
+ union { s32 i; u32 u; } value;
f64 f;
};
@@ -106,8 +121,8 @@ 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, f64 percent);
-void lia_list_end(struct lia_list *list, s32 sequence);
+void lia_list_seek(struct lia_list *list, s32 sequence, u32 id, f64 percent);
+void lia_list_end(struct lia_list *list, u32 id);
void lia_list_reverse(struct lia_list *list);
void lia_list_sort(struct lia_list *list);
diff --git a/src/liana/vcr.c b/src/liana/vcr.c
index 435fcba..c4bf583 100644
--- a/src/liana/vcr.c
+++ b/src/liana/vcr.c
@@ -24,8 +24,8 @@ static void signal_callback(void *userdata)
static void reset_metrics(struct lia_vcr *vcr)
{
- vcr->metric.current_frame = 0;
- vcr->metric.last_report_ts = 0;
+ vcr->metric.current_frame = 0Lu;
+ vcr->metric.last_report_ts = 0Lu;
}
void lia_vcr_init(struct lia_vcr *vcr, struct aki_event_loop *loop, struct aki_packet_stream *data)
@@ -162,10 +162,15 @@ static void update_metrics(struct lia_vcr *vcr, u32 size)
}
u64 diff;
if ((diff = now - vcr->metric.last_report_ts) > 1000000Lu) {
- f32 kbps = (vcr->metric.current_frame / 125.f) / (diff / 1000000.f);
- al_log_info("vcr", "Receiving packets at %.2fkbps.", kbps);
- vcr->metric.current_frame = 0;
vcr->metric.last_report_ts = now;
+ u64 frame = vcr->metric.current_frame;
+ vcr->metric.current_frame = 0Lu;
+ if (diff > 2500000Lu) {
+ al_log_debug("vcr", "Ignoring %lu bytes in metrics.", frame);
+ return;
+ }
+ f32 kbps = (frame / 125.f) / (diff / 1000000.f);
+ al_log_info("vcr", "Receiving packets at %.2fkbps.", kbps);
}
}
@@ -263,6 +268,7 @@ void lia_vcr_flush(struct lia_vcr *vcr)
}
aki_signal_stop(&vcr->signal);
al_atomic_store(u64)(&vcr->count, 0, AL_ATOMIC_RELAXED);
+ reset_metrics(vcr);
if (vcr->expand == VCR_EXPAND_COMPLETE) {
vcr->mark.low = 0;
vcr->expand = VCR_EXPAND_GROWN;