summaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-02-19 13:40:38 -0500
committerAndrew Opalach <andrew@akon.city> 2025-02-19 13:40:38 -0500
commit2bee71a7e032c0972418e324bb1d7e6b02330b18 (patch)
treefa5819e9d9efe75cbc6f50d462dd0eb6bd19b6a2 /src/server
parentb36f022defd8d4ec5a8c29578bb583bea05dfbb6 (diff)
downloadcamu-2bee71a7e032c0972418e324bb1d7e6b02330b18.tar.gz
camu-2bee71a7e032c0972418e324bb1d7e6b02330b18.tar.bz2
camu-2bee71a7e032c0972418e324bb1d7e6b02330b18.zip
Server resource unload, many tweaks and fixes
- Initial liana client preferences. - Hook up libplacebo dx11 backend. - Make usage of FFmpeg hardware decoding api make some sense. Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/server')
-rw-r--r--src/server/resource.h2
-rw-r--r--src/server/server.c206
2 files changed, 133 insertions, 75 deletions
diff --git a/src/server/resource.h b/src/server/resource.h
index 1cd00fc..2999523 100644
--- a/src/server/resource.h
+++ b/src/server/resource.h
@@ -9,6 +9,7 @@ struct camu_resource {
struct cch_entry *entry;
struct lia_node *node;
u64 duration;
+ u32 ref;
array(struct lia_list_entry *) pending;
};
@@ -25,6 +26,7 @@ struct camu_resource_http {
struct camu_resource_portal {
struct camu_resource r;
struct camu_post *post;
+ u32 index;
};
struct camu_resource_cdio {
diff --git a/src/server/server.c b/src/server/server.c
index e22cf88..d85d82c 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -16,6 +16,8 @@
#include "common.h"
#include "db.h"
+#define RESOURCE_MAX_AGE 7
+
static struct camu_user *get_user_by_username(struct camu_server *server, str *username)
{
struct camu_user *user;
@@ -265,6 +267,91 @@ static void send_clients_entry_seeked(struct camu_server *server, struct lia_lis
}
}
+#ifdef CAMU_HAVE_PORTAL
+static struct cch_entry *entry_from_post(struct camu_server *server, struct camu_post *post, u32 index)
+{
+ struct cch_entry *entry = NULL;
+ if (index <= post->media.count) {
+ struct camu_post_media *media = &al_array_at(post->media, index);
+ if (!al_str_is_empty(&media->url)) {
+ entry = cch_handler_http_create(&media->url, server->loop);
+ }
+ }
+ if (!entry) {
+ al_log_warn("server", "Failed to load resource %.*s %u.", al_str_fmt(&post->unique_id), index);
+ return NULL;
+ }
+ entry->handler->maybe_spawn_worker(entry->handler, 0);
+ return entry;
+}
+#endif
+
+static bool prepare_server_resource(struct camu_server *server, struct camu_resource *resource)
+{
+ struct cch_entry *entry = NULL;
+ switch (resource->type) {
+ case CAMU_RESOURCE_FILE: {
+ struct camu_resource_file *file = (struct camu_resource_file *)resource;
+ entry = cch_handler_file_create(&file->path, &al_str_c("codec"));
+ if (!entry) {
+ resource->load = LIANA_ENTRY_ERRORED;
+ return false;
+ }
+ resource->load = LIANA_ENTRY_PREPARED;
+ break;
+ }
+#ifdef NAUNET_HAS_CURL
+ case CAMU_RESOURCE_HTTP: {
+ struct camu_resource_http *http = (struct camu_resource_http *)resource;
+ entry = cch_handler_http_create(&http->url, server->loop);
+ if (!entry) {
+ resource->load = LIANA_ENTRY_ERRORED;
+ return false;
+ }
+ entry->handler->maybe_spawn_worker(entry->handler, 0);
+ resource->load = LIANA_ENTRY_PREPARED;
+ break;
+ }
+#endif
+#ifdef CAMU_HAVE_PORTAL
+ case CAMU_RESOURCE_PORTAL: {
+ struct camu_resource_portal *portal = (struct camu_resource_portal *)resource;
+ entry = entry_from_post(server, portal->post, portal->index);
+ if (!entry) {
+ resource->load = LIANA_ENTRY_ERRORED;
+ return false;
+ }
+ resource->load = LIANA_ENTRY_PREPARED;
+ break;
+ }
+#endif
+#ifdef CACHE_HAVE_CDIO
+ case CAMU_RESOURCE_CDIO: {
+ struct camu_resource_cdio *cdio = (struct camu_resource_cdio *)resource;
+ entry = cch_handler_cdio_create();
+ if (!entry) {
+ resource->load = LIANA_ENTRY_ERRORED;
+ return false;
+ }
+ cdio->track = MIN(cdio->track, entry->chapters.count);
+ entry->chapter = &al_array_at(entry->chapters, cdio->track);
+ entry->handler->maybe_spawn_worker(entry->handler, entry->chapter->start);
+ resource->load = LIANA_ENTRY_PREPARED;
+ break;
+ }
+#endif
+ }
+
+ if (entry) {
+ resource->entry = entry;
+ resource->node = lia_server_create_node(&server->data.server, resource->entry);
+ resource->node->callback = node_callback;
+ resource->node->userdata = resource;
+ }
+
+ return true;
+}
+
static void list_callback(void *userdata, u8 op, struct lia_list_entry *entry, void *opaque)
{
struct camu_server *server = (struct camu_server *)userdata;
@@ -272,12 +359,18 @@ static void list_callback(void *userdata, u8 op, struct lia_list_entry *entry, v
switch (op) {
case LIANA_LOAD_ENTRY:
switch (resource->load) {
- case LIANA_ENTRY_PREPARED:
- resource->load = LIANA_ENTRY_LOADING;
- lia_node_get_duration(resource->node);
+ case LIANA_ENTRY_UNLOADED:
+ if (!prepare_server_resource(server, resource)) {
+ break;
+ }
// fallthrough
case LIANA_ENTRY_PREPARING:
+ case LIANA_ENTRY_PREPARED:
case LIANA_ENTRY_LOADING:
+ if (resource->load == LIANA_ENTRY_PREPARED) {
+ resource->load = LIANA_ENTRY_LOADING;
+ lia_node_get_duration(resource->node);
+ }
al_array_push(resource->pending, entry);
break;
case LIANA_ENTRY_LOADED:
@@ -286,12 +379,24 @@ static void list_callback(void *userdata, u8 op, struct lia_list_entry *entry, v
}
*(u8 *)opaque = resource->load;
break;
- case LIANA_GET_DURATION: {
+ case LIANA_GET_ENTRY_DURATION:
*(u64 *)opaque = resource->duration;
break;
- }
+ case LIANA_REF_ENTRY:
+ resource->ref = RESOURCE_MAX_AGE;
+ break;
+ case LIANA_UNREF_ENTRY:
+ if (!resource->ref || --resource->ref) {
+ break;
+ }
+ // fallthrough
case LIANA_UNLOAD_ENTRY:
- lia_node_close(resource->node);
+ if (resource->node) {
+ lia_node_close(resource->node);
+ resource->node = NULL;
+ resource->entry = NULL;
+ resource->load = LIANA_ENTRY_UNLOADED;
+ }
break;
case LIANA_LIST_META:
if (server->meta_callback) {
@@ -338,6 +443,7 @@ static void client_portal_callback(void *userdata0, void *userdata1, struct camu
struct camu_server *server = (struct camu_server *)userdata0;
struct nn_rpc_connection *conn = (struct nn_rpc_connection *)userdata1;
if (!client_still_connected(server, conn)) return;
+ // @TODO: result->id = -1 case.
struct nn_packet *packet = nn_rpc_get_packet(conn->rpc, CAMU_CLIENT_RESULTS);
nn_packet_write_u8(packet, result->op);
nn_packet_write_s32(packet, result->id);
@@ -421,52 +527,30 @@ out:
}
#ifdef CAMU_HAVE_PORTAL
-static struct cch_entry *entry_from_post(struct camu_server *server, struct camu_post *post, u32 index)
-{
- struct cch_entry *entry = NULL;
- if (index <= post->media.count) {
- struct camu_post_media *media = &al_array_at(post->media, index);
- if (!al_str_is_empty(&media->url)) {
- entry = cch_handler_http_create(&media->url, server->loop);
- }
- }
- if (!entry) {
- al_log_warn("server", "Failed to load resource %.*s %u.", al_str_fmt(&post->unique_id), index);
- return NULL;
- }
- entry->handler->maybe_spawn_worker(entry->handler, 0);
- return entry;
-}
-
static void simple_search_portal_callback(void *userdata0, void *userdata1, struct camu_portal_result *result)
{
struct camu_server *server = (struct camu_server *)userdata0;
struct camu_resource_portal *portal = (struct camu_resource_portal *)userdata1;
struct camu_resource *resource = (struct camu_resource *)portal;
switch (result->op) {
- case CAMU_CLIENT_CREATE_SEARCH: {
+ case CAMU_CLIENT_CREATE_SEARCH:
+ if (result->id == -1) {
+ break;
+ }
camu_portal_get_page(&server->bridge, result->id, 0, simple_search_portal_callback, portal);
return;
- }
- case CAMU_CLIENT_GET_PAGE: {
- if (!result->page || !result->page->list.count) break;
- struct camu_post *post = camu_post_cache_get(&server->cache, &al_array_at(result->page->list, 0));
- if (!post) break;
- struct cch_entry *entry = entry_from_post(server, post, 0);
- if (!entry) break;
- portal->post = post;
- resource->entry = entry;
- resource->node = lia_server_create_node(&server->data.server, resource->entry);
- resource->node->callback = node_callback;
- resource->node->userdata = resource;
+ case CAMU_CLIENT_GET_PAGE:
+ if (result->id == -1 || !result->page || !result->page->list.count) {
+ break;
+ }
+ portal->post = camu_post_cache_get(&server->cache, &al_array_at(result->page->list, 0));
resource->type = CAMU_RESOURCE_PORTAL;
- resource->load = LIANA_ENTRY_PREPARED;
+ prepare_server_resource(server, resource);
process_pending(resource);
return;
}
- }
// No return is the error case.
- al_log_warn("server", "Server resource failed to load.");
+ al_log_warn("server", "Failed to process simple search request.");
resource->load = LIANA_ENTRY_ERRORED;
}
#endif
@@ -474,79 +558,55 @@ static void simple_search_portal_callback(void *userdata0, void *userdata1, stru
static void handle_add_command(struct camu_server *server, struct lia_list *list, struct nn_packet *packet)
{
u8 op = nn_packet_read_u8(packet);
- struct cch_entry *entry = NULL;
struct camu_resource *resource = NULL;
wstr name;
switch (op) {
case CAMU_RESOURCE_FILE: {
str path;
nn_packet_read_str(packet, &path);
- entry = cch_handler_file_create(&path, &al_str_c("codec"));
- if (!entry) return;
struct camu_resource_file *file = al_alloc_object(struct camu_resource_file);
al_str_clone(&file->path, &path);
al_wstr_from_str(&name, &path);
resource = (struct camu_resource *)file;
resource->type = CAMU_RESOURCE_FILE;
- resource->load = LIANA_ENTRY_PREPARED;
+ resource->load = LIANA_ENTRY_UNLOADED;
break;
}
#ifdef NAUNET_HAS_CURL
case CAMU_RESOURCE_HTTP: {
str url;
nn_packet_read_str(packet, &url);
- entry = cch_handler_http_create(&url, server->loop);
- if (!entry) return;
- entry->handler->maybe_spawn_worker(entry->handler, 0);
struct camu_resource_http *http = al_alloc_object(struct camu_resource_http);
al_str_clone(&http->url, &url);
al_wstr_from_str(&name, &url);
resource = (struct camu_resource *)http;
resource->type = CAMU_RESOURCE_HTTP;
- resource->load = LIANA_ENTRY_PREPARED;
+ resource->load = LIANA_ENTRY_UNLOADED;
break;
}
#endif
#ifdef CACHE_HAVE_CDIO
case CAMU_RESOURCE_CDIO: {
- entry = cch_handler_cdio_create();
- if (!entry) return;
str url;
nn_packet_read_str(packet, &url);
u32 track = 0;
if (url.length > 7) {
bool error;
s64 index = al_str_to_long(&al_str_substr(&url, 7, url.length), 10, &error);
- if (!error && index <= entry->chapters.count)
+ if (!error && index > 0) {
track = (u32)index - 1;
+ }
}
- entry->chapter = &al_array_at(entry->chapters, track);
- entry->handler->maybe_spawn_worker(entry->handler, entry->chapter->start);
struct camu_resource_cdio *cdio = al_alloc_object(struct camu_resource_cdio);
cdio->track = track;
al_wstr_from_cstr(&name, "cdio");
resource = (struct camu_resource *)cdio;
resource->type = CAMU_RESOURCE_CDIO;
- resource->load = LIANA_ENTRY_PREPARED;
+ resource->load = LIANA_ENTRY_UNLOADED;
break;
}
#endif
#ifdef CAMU_HAVE_PORTAL
- case CAMU_RESOURCE_PORTAL: {
- str unique_id;
- nn_packet_read_str(packet, &unique_id);
- u32 index = nn_packet_read_u32(packet);
- struct camu_post *post = camu_post_cache_get(&server->cache, &unique_id);
- entry = entry_from_post(server, post, index);
- if (!entry) return;
- struct camu_resource_portal *portal = al_alloc_object(struct camu_resource_portal);
- portal->post = post;
- al_wstr_clone(&name, &post->title);
- resource = (struct camu_resource *)portal;
- resource->type = CAMU_RESOURCE_PORTAL;
- resource->load = LIANA_ENTRY_PREPARED;
- break;
- }
case CAMU_RESOURCE_SIMPLE_SEARCH: {
str search;
nn_packet_read_str(packet, &search);
@@ -563,7 +623,8 @@ static void handle_add_command(struct camu_server *server, struct lia_list *list
al_str_from(&query, "link:");
al_str_cat(&query, &search);
}
- camu_portal_create_search(&server->bridge, &al_str_c("youtube"), &query, simple_search_portal_callback, portal);
+ camu_portal_create_search(&server->bridge, &al_str_c("youtube"), &query,
+ simple_search_portal_callback, portal);
al_str_free(&query);
break;
}
@@ -571,12 +632,7 @@ static void handle_add_command(struct camu_server *server, struct lia_list *list
}
al_assert(resource);
al_array_push(server->data.resources, resource);
- if (entry) {
- resource->entry = entry;
- resource->node = lia_server_create_node(&server->data.server, resource->entry);
- resource->node->callback = node_callback;
- resource->node->userdata = resource;
- }
+ resource->node = NULL;
resource->duration = LIANA_TIMESTAMP_INVALID;
al_array_init(resource->pending);
lia_list_add(list, resource, resource->duration, &name);