From 2bee71a7e032c0972418e324bb1d7e6b02330b18 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Wed, 19 Feb 2025 13:40:38 -0500 Subject: 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 --- src/server/resource.h | 2 + src/server/server.c | 206 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 133 insertions(+), 75 deletions(-) (limited to 'src/server') 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); -- cgit v1.2.3-101-g0448