From 8f9ddafb128eabe346b48adebdeb1f34da05b005 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Wed, 7 May 2025 16:52:14 -0400 Subject: Make server resource a fat entity Signed-off-by: Andrew Opalach --- flake.lock | 24 ++-- flake.nix | 2 +- src/cache/entry.h | 33 +++++ src/codec/ffmpeg/decoder.c | 6 +- src/codec/ffmpeg/demuxer.c | 1 + src/fruits/cmc/cmc.c | 10 +- src/fruits/cmc/cmc.h | 2 +- src/fruits/cmc/ui/panes/list.c | 244 +------------------------------- src/fruits/cmc/ui/widgets/now_playing.c | 4 +- src/fruits/cmsrv/cmsrv.c | 16 --- src/fruits/cmsrv/ui.c | 9 +- src/fruits/cmv/cmv.c | 16 --- src/liana/list.c | 13 +- src/liana/list.h | 4 +- src/liana/list_cmp.h | 27 ++-- src/liana/server.c | 11 -- src/liana/server.h | 1 - src/libsink/sink.c | 1 + src/server/common.h | 14 -- src/server/resource.h | 42 +++--- src/server/server.c | 146 +++++++------------ subprojects/libalabaster.wrap | 2 +- 22 files changed, 169 insertions(+), 459 deletions(-) diff --git a/flake.lock b/flake.lock index 89311ee..7c734e5 100644 --- a/flake.lock +++ b/flake.lock @@ -23,11 +23,11 @@ ] }, "locked": { - "lastModified": 1746177088, - "narHash": "sha256-hmHKl4meWr6ryzqQAwRD3+3Ihfb/Y/0CbK+WnE+oa6Q=", + "lastModified": 1746632058, + "narHash": "sha256-Mp5Bbvb+YlFEZ76C/0wFS6C1lRfH3D60u465wFNlnS0=", "owner": "nix-community", "repo": "home-manager", - "rev": "f045bd46b73c3b0ed4e46cdb6036b3d5823d7dee", + "rev": "708074ae6db9e0468e4f48477f856e8c2d059795", "type": "github" }, "original": { @@ -39,11 +39,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1745955289, - "narHash": "sha256-mmV2oPhQN+YF2wmnJzXX8tqgYmUYXUj3uUUBSTmYN5o=", + "lastModified": 1746621361, + "narHash": "sha256-T9vOxEqI1j1RYugV0b9dgy0AreiZ9yBDKZJYyclF0og=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "72081c9fbbef63765ae82bff9727ea79cc86bd5b", + "rev": "2ea3ad8a1f26a76f8a8e23fc4f7757c46ef30ee5", "type": "github" }, "original": { @@ -59,11 +59,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1744290088, - "narHash": "sha256-/X9XVEl0EiyisNbF5srrxXRSVoRqdwExuqyspYqqEjQ=", + "lastModified": 1746453552, + "narHash": "sha256-r66UGha+7KVHkI7ksrcMjnw/mm9Sg4l5bQlylxHwdGU=", "owner": "nix-community", "repo": "NixOS-WSL", - "rev": "60b4904a1390ac4c89e93d95f6ed928975e525ed", + "rev": "be618645aa0adf461f778500172b6896d5ab2d01", "type": "github" }, "original": { @@ -91,11 +91,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1746141548, - "narHash": "sha256-IgBWhX7A2oJmZFIrpRuMnw5RAufVnfvOgHWgIdds+hc=", + "lastModified": 1746461020, + "narHash": "sha256-7+pG1I9jvxNlmln4YgnlW4o+w0TZX24k688mibiFDUE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f02fddb8acef29a8b32f10a335d44828d7825b78", + "rev": "3730d8a308f94996a9ba7c7138ede69c1b9ac4ae", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 0c49aff..7f54f8a 100644 --- a/flake.nix +++ b/flake.nix @@ -161,7 +161,7 @@ export PATH=${pkgs.lib.makeBinPath shell.nativeBuildInputs}:$PATH export PKG_CONFIG_PATH=${pkgs.lib.makeSearchPathOutput "dev" "lib/pkgconfig" shell.buildInputs}:$PKG_CONFIG_PATH export PKG_CONFIG_PATH=${pkgs.lib.makeSearchPathOutput "dev" "share/pkgconfig" shell.buildInputs}:$PKG_CONFIG_PATH - ${pkgs.bashInteractive}/bin/bash --rcfile <(echo '${shell.shellHook}') $@ + ${shell.shellHook} ''; }); diff --git a/src/cache/entry.h b/src/cache/entry.h index c74870d..d6eb86a 100644 --- a/src/cache/entry.h +++ b/src/cache/entry.h @@ -18,6 +18,17 @@ - dvd/bluray (drive or iso) - live source (radio antenna) + Chapters: + - Potential resources with chapters: + - Single wav with cue. + - Multiple wav with cue. + - Single mp4 with chapters in metadata. + - DVD iso image. + - DVD/CD drive. + - Chapter as seek or node per chapter? + - Node per chapter definitely seems to make the most sense. Maybe we could + have a "ignore chapters" flag for single containers like mp4. + Other considerations: - Chapter priority (disc drive) - For now 1 user and 1 list owns the drive totally. @@ -28,10 +39,32 @@ - Networked backing? - Is a liana "node handler" necessary? + Flow of a resource: + - Entry: + - Holds the data but as of now doesn't read metadata. + - Server: + - Informs clients about entry metadata. + - Liana node: + - Only place currently setup to block for reading duration. + - Disc drive resources need to block to read chapters as well. + - File open could likely benefit from being non-blocking/threaded. + - Fit into server list_callback()? Could be as simple as replacing lia_node_get_duration(). + - Any catches to moving duration retrival to the cache entry? + - Cache objects? (Disc drive) + - Handles it's own state on demand. + - Re-evaluate list behavior without duration. + Cache/liana refactor: [x] get/set_size() no longer make sense. [x] // @TODO: Unknown size is unhandled in backings. - Handle keeps reading but will eventually have a wait cut short after a backing finalize. + [ ] Expanding list entry. + - How to handle unload? + - Disc drive can trigger unload. + - Make sure we can skip around in list while an entry load is pending. + - Also cancel load requests on unload. + - Consider pitfalls in the idea of having a "cd object" in the list that can be unloaded + and loaded with different cds. [ ] Separate cch_handler from cch_entry. - Move waits to entry? - Create cache entry with argument like file, cue, http, hls, etc. diff --git a/src/codec/ffmpeg/decoder.c b/src/codec/ffmpeg/decoder.c index 80b1d12..7401698 100644 --- a/src/codec/ffmpeg/decoder.c +++ b/src/codec/ffmpeg/decoder.c @@ -260,9 +260,9 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend } if (cpus > 0) { av->codec_context->thread_count = cpus; - // FF_THREAD_FRAME or FF_THREAD_SLICE. - // SLICE seems to work better based on videos that got completely choked - // in THREAD_FRAME mode (4k60 HEVC, FFmpeg 7.1.1, AMD 3900x). + // FF_THREAD_FRAME, FF_THREAD_SLICE or both. + // Slice seems to work better based on videos that get completely choked + // in frame-only or both (4k60 HEVC, FFmpeg 7.1.1, AMD 3900x). av->codec_context->thread_type = FF_THREAD_SLICE; log_info("Using %i threads for decoder.", cpus); } diff --git a/src/codec/ffmpeg/demuxer.c b/src/codec/ffmpeg/demuxer.c index c5ca20c..4cf52dd 100644 --- a/src/codec/ffmpeg/demuxer.c +++ b/src/codec/ffmpeg/demuxer.c @@ -41,6 +41,7 @@ static bool ff_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handl // AVIO_SEEKABLE_NORMAL should always be unset if we know we cannot seek. // However, it should also never be unset if we *do* want to seek because it // disables long seeks (Not tested in a long time). + // This will also make some resources (e.g. .opus) fail to determine a duration. av->io_context->seekable &= ~AVIO_SEEKABLE_NORMAL; } else { av->io_context->seekable |= AVIO_SEEKABLE_NORMAL; diff --git a/src/fruits/cmc/cmc.c b/src/fruits/cmc/cmc.c index 43f1144..39423c1 100644 --- a/src/fruits/cmc/cmc.c +++ b/src/fruits/cmc/cmc.c @@ -37,11 +37,11 @@ static void read_list_entry(struct nn_packet *packet, struct cmc_list_entry *ent entry->start = nn_packet_read_u64(packet); entry->paused_at = nn_packet_read_u64(packet); entry->offset = nn_packet_read_u64(packet); - wstr w; - nn_packet_read_wstr(packet, &w); - if (!al_wstr_eq(&entry->name, &w)) { - al_wstr_free(&entry->name); - al_wstr_clone(&entry->name, &w); + str brief; + nn_packet_read_str(packet, &brief); + if (!al_str_eq(&entry->brief, &brief)) { + al_str_free(&entry->brief); + al_str_clone(&entry->brief, &brief); } } diff --git a/src/fruits/cmc/cmc.h b/src/fruits/cmc/cmc.h index 817b8b0..b65b336 100644 --- a/src/fruits/cmc/cmc.h +++ b/src/fruits/cmc/cmc.h @@ -29,7 +29,7 @@ struct cmc_list_entry { u64 start; u64 paused_at; u64 offset; - wstr name; + str brief; struct { struct camu_audio_format fmt; u8 *data; diff --git a/src/fruits/cmc/ui/panes/list.c b/src/fruits/cmc/ui/panes/list.c index 34e18f9..15554b6 100644 --- a/src/fruits/cmc/ui/panes/list.c +++ b/src/fruits/cmc/ui/panes/list.c @@ -265,15 +265,16 @@ static void render_list_entries(struct cmc_list_pane *lp, struct cmc_list_tab *t ncplane_set_fg_palindex(n, 4); } s32 y = i - top; - u32 length = entry->name.length; + char *c_str = al_str_to_c_str(&entry->brief); if (tab->move.active && i == tracked) { - cmc_ui_putnwstr_yx(n, y, 0, length, &entry->name); + ncplane_putstr_yx(n, y, 0, c_str); } else if (on_current) { ncplane_putchar_yx(n, y, 1, '>'); - cmc_ui_putnwstr_yx(n, y, 3, length, &entry->name); + ncplane_putstr_yx(n, y, 3, c_str); } else { - cmc_ui_putnwstr_yx(n, y, 1, length, &entry->name); + ncplane_putstr_yx(n, y, 1, c_str); } + al_free(c_str); if (styled) { ncplane_set_styles(n, NCSTYLE_NONE); ncplane_set_fg_default(n); @@ -291,229 +292,6 @@ void cmc_list_pane_render(struct cmc_list_pane *lp) cmc_now_playing_render(&lp->np, tab_current_entry(tab)); } -//void cmc_lp_init(struct cmc_ui *ui) -//{ -// al_array_init(ui->lp.tabs); -// ui->lp.current = 0; -//} -// -//void cmc_lp_layout(struct cmc_ui *ui, struct ncplane *parent) -//{ -// if (ui->lp.n) ncplane_destroy(ui->lp.n); -// struct ncplane_options nopts = { 0 }; -// nopts.rows = ncplane_dim_y(parent); -// nopts.cols = ncplane_dim_x(parent); -// ui->lp.n = ncplane_create(parent, &nopts); -//} -// -//void cmc_lp_add_list(struct cmc_ui *ui, struct cmc_list *list) -//{ -// struct cmc_list_tab tab = { -// .list = list, -// .selected = list->current, -// .leader_pressed = false -// }; -// al_array_push(ui->lp.tabs, tab); -//} -// -//bool cmc_lp_handle_input(struct cmc_ui *ui, struct ncinput *input) -//{ -// if (!ui->lp.tabs.count) return false; -// -// struct cmc_list_tab *tab = &al_array_at(ui->lp.tabs, ui->lp.current); -// s32 count = (s32)tab->list->entries.count; -// bool leader = tab->leader_pressed; -// if (cmc_ui_consider_input(input, false)) { -// tab->leader_pressed = false; -// } -// -// switch (input->id) { -// case 'g': -// CONSIDER_INPUT(); -// if (leader) { -// if (tab->move.active) { -// tab->move.offset = -tab->move.selected; -// } else { -// tab->selected = 0; -// } -// } else { -// tab->leader_pressed = true; -// } -// break; -// case 'G': -// CONSIDER_INPUT(); -// if (tab->move.active) { -// tab->move.offset = count - 1 - tab->move.selected; -// } else { -// tab->selected = count - 1; -// } -// break; -// case 'f': -// //CONSIDER_INPUT_MOD_CTRL(); -// CONSIDER_INPUT_REPEAT(); -// if (tab->move.active) { -// if (tab->selected + tab->move.offset < count - tab->page_length) { -// tab->move.offset += tab->page_length; -// } else { -// tab->move.offset = count - 1 - tab->move.selected; -// } -// } else { -// if (tab->selected < count - tab->page_length) { -// tab->selected += tab->page_length; -// } else { -// tab->selected = count - 1; -// } -// } -// break; -// case 'b': -// //CONSIDER_INPUT_MOD_CTRL(); -// CONSIDER_INPUT_REPEAT(); -// if (tab->move.active) { -// if (tab->selected + tab->move.offset > tab->page_length) { -// tab->move.offset -= tab->page_length; -// } else { -// tab->move.offset = -tab->selected; -// } -// } else { -// if (tab->selected > tab->page_length) { -// tab->selected -= tab->page_length; -// } else { -// tab->selected = 0; -// } -// } -// break; -// case 'j': -// CONSIDER_INPUT_REPEAT(); -// if (tab->move.active) { -// if (tab->selected + tab->move.offset < count - 1) { -// tab->move.offset++; -// } -// } else { -// if (tab->selected < count - 1) { -// tab->selected++; -// } -// } -// break; -// case 'k': -// CONSIDER_INPUT_REPEAT(); -// if (tab->move.active) { -// if (tab->selected + tab->move.offset > 0) { -// tab->move.offset--; -// } -// } else { -// if (tab->selected > 0) { -// tab->selected--; -// } -// } -// break; -// case 'i': -// CONSIDER_INPUT(); -// if (!tab->move.active) { -// tab->move.active = true; -// tab->move.selected = tab->selected; -// tab->move.offset = 0; -// } -// break; -// case NCKEY_ESC: -// CONSIDER_INPUT(); -// if (tab->move.active) { -// tab->move.active = false; -// } -// break; -// case NCKEY_RETURN: -// CONSIDER_INPUT(); -// if (tab->move.active) { -// tab->move.active = false; -// } else if (tab->selected != tab->list->current) { -// camu_client_skipto(&ui->c->client, &tab->list->name, tab->selected); -// } -// break; -// case NCKEY_BUTTON1: -// CONSIDER_INPUT(); -// if (input->x < 0 || input->y < 0) return false; -// u32 x = (u32)input->x; -// u32 y = (u32)input->y; -// ui->last_mouse_x = x; -// ui->last_mouse_y = y; -// u64 now = nn_get_timestamp(); -// u64 last = ui->last_mouse_ts; -// if (last != (u64)-1 && now - last < 100000) { -// return false; -// } -// ui->last_mouse_ts = now; -// u32 width = ncplane_dim_x(ui->lp.n); -// u32 height = ncplane_dim_y(ui->lp.n); -// if (x >= 2 && x <= width && y > height - 3) { // @TODO: Make this defined, more to nowplaying. -// struct cmc_list_entry *entry = al_array_at(tab->list->entries, tab->list->current); -// u64 pos = ((x - 2) / (f64)(width - 2)) * entry->duration; -// camu_client_seek(&ui->c->client, &tab->list->name, entry->id, pos); -// } -// break; -// } -// -// return true; -//} -// -//void cmc_lp_erase(struct cmc_ui *ui) -//{ -// ncplane_erase(ui->lp.n); -//} -// -//static void render_list_entries(struct cmc_ui *ui, struct cmc_list_tab *tab, s32 max_height) -//{ -// struct cmc_list *list = tab->list; -// struct ncplane *n = ui->lp.n; -// s32 tracked = tab->move.active ? tab->move.selected + tab->move.offset : tab->selected; -// s32 count = (s32)list->entries.count; -// s32 midpoint = max_height / 2; -// s32 rounded = (max_height + 1) / 2; -// s32 top, end; -// if (tracked < midpoint) { -// top = 0; -// end = MIN(top + max_height, count); -// } else if (tracked + rounded >= count) { -// top = count - max_height; -// end = count; -// } else { -// top = tracked - midpoint; -// end = tracked + rounded; -// } -// s32 index; -// struct cmc_list_entry *entry; -// for (s32 i = top; i < end; i++) { -// index = i; -// if (tab->move.active) { -// if (index == tracked) { -// index = tab->move.selected; -// } else { -// if (index > tracked) index--; -// if (index >= tab->move.selected) index++; -// } -// } -// entry = al_array_at(list->entries, index); -// bool on_current = list->current >= 0 && index == list->current; -// bool styled = i == tracked; -// if (styled) { -// ncplane_set_styles(n, NCSTYLE_BOLD); -// ncplane_set_fg_palindex(n, 4); -// } -// s32 y = i - top; -// u32 length = entry->name.length; -// if (tab->move.active && i == tracked) { -// cmc_ui_putnwstr_yx(n, y, 0, length, &entry->name); -// } else if (on_current) { -// ncplane_putchar_yx(n, y, 1, '>'); -// cmc_ui_putnwstr_yx(n, y, 3, length, &entry->name); -// } else { -// cmc_ui_putnwstr_yx(n, y, 1, length, &entry->name); -// } -// if (styled) { -// ncplane_set_styles(n, NCSTYLE_NONE); -// ncplane_set_fg_default(n); -// } -// } -//} -// //static void render_now_playing(struct cmc_ui *ui, struct cmc_list_tab *tab, u32 y, u32 height) //{ // struct ncplane *n = ui->lp.n; @@ -676,15 +454,3 @@ void cmc_list_pane_render(struct cmc_list_pane *lp) // ncplane_cursor_move_yx(n, y, 0); // ncplane_light_box(n, NCSTYLE_NONE, c, height - 1, width - 1, 0); //} -// -//void cmc_lp_render(struct cmc_ui *ui) -//{ -// u32 height = ncplane_dim_y(ui->lp.n); -// -// if (ui->lp.tabs.count <= ui->lp.current) return; -// struct cmc_list_tab *tab = &al_array_at(ui->lp.tabs, ui->lp.current); -// -// tab->page_length = height - 9; -// render_list_entries(ui, tab, tab->page_length); -// render_now_playing(ui, tab, tab->page_length, height); -//} diff --git a/src/fruits/cmc/ui/widgets/now_playing.c b/src/fruits/cmc/ui/widgets/now_playing.c index ebb8361..a90c7e0 100644 --- a/src/fruits/cmc/ui/widgets/now_playing.c +++ b/src/fruits/cmc/ui/widgets/now_playing.c @@ -145,7 +145,9 @@ void cmc_now_playing_render(struct cmc_now_playing *np, struct cmc_list_entry *e ncplane_putstr_yx(np->n, 1, 4 + offset, "⎹"); if (entry) { - cmc_ui_putnwstr_yx(np->n, 1, 6 + offset, MIN(entry->name.length, (u32)60), &entry->name); + char *c_str = al_str_to_c_str(&entry->brief); + ncplane_putnstr_yx(np->n, 1, 6 + offset, MIN(al_strlen(c_str), (size_t)60), c_str); + al_free(c_str); } bool show_remaining = false; diff --git a/src/fruits/cmsrv/cmsrv.c b/src/fruits/cmsrv/cmsrv.c index e830831..ca65beb 100644 --- a/src/fruits/cmsrv/cmsrv.c +++ b/src/fruits/cmsrv/cmsrv.c @@ -57,22 +57,6 @@ static u8 server_line_callback(void *userdata, str *line) //lia_list_clear(list); } else { struct nn_packet *packet = nn_packet_create(); -#ifdef CAMU_HAVE_PORTAL - if (al_str_at(line, 0) == ';' || camu_is_url(line, 0)) { - nn_packet_write_u8(packet, CAMU_RESOURCE_SIMPLE_SEARCH); -#elif defined NAUNET_HAS_CURL - if (camu_is_url(line, 0)) { - nn_packet_write_u8(packet, CAMU_RESOURCE_HTTP); -#else - if (0) { -#endif -#if CACHE_HAVE_CDIO - } else if (al_str_cmp(line, &al_str_c("cdda://"), 0, 7) == 0) { - nn_packet_write_u8(packet, CAMU_RESOURCE_CDIO); -#endif - } else { - nn_packet_write_u8(packet, CAMU_RESOURCE_FILE); - } nn_packet_write_str(packet, line); camu_server_local_add(&s->server, packet); } diff --git a/src/fruits/cmsrv/ui.c b/src/fruits/cmsrv/ui.c index 0a41bfc..c8e9dcb 100644 --- a/src/fruits/cmsrv/ui.c +++ b/src/fruits/cmsrv/ui.c @@ -156,15 +156,16 @@ static void render_lists(struct cmsrv_ui *ui) ncplane_putchar_yx(n, y, 1, '>'); x += 2; } - wstr *name = &entry->name; #ifdef CAMU_HAVE_PORTAL struct camu_resource *resource = (struct camu_resource *)entry->opaque; if (resource->type == CAMU_RESOURCE_PORTAL) { - struct camu_resource_portal *portal = (struct camu_resource_portal *)resource; - name = &portal->post->title; + putnwstr_maxwidth_yx(n, y, x, max_width - x, &resource->post->title); + } else { + char *c_str = al_str_to_c_str(&entry->brief); + ncplane_putstr_yx(n, y, x, c_str); + al_free(c_str); } #endif - putnwstr_maxwidth_yx(n, y, x, max_width - x, name); if (++current_line >= max_height) break; } } diff --git a/src/fruits/cmv/cmv.c b/src/fruits/cmv/cmv.c index 2dda139..1b9c8c1 100644 --- a/src/fruits/cmv/cmv.c +++ b/src/fruits/cmv/cmv.c @@ -185,22 +185,6 @@ s32 window_system_main(u32 argc, str *argv, void *extra) if (local) { for (u32 i = 1; i < argc; i++) { struct nn_packet *packet = nn_packet_create(); -#if defined CAMU_HAVE_PORTAL - if (al_str_at(&argv[i], 0) == ';' || camu_is_url(&argv[i], 0)) { - nn_packet_write_u8(packet, CAMU_RESOURCE_SIMPLE_SEARCH); -#elif defined NAUNET_HAS_CURL - if (camu_is_url(&argv[i], 0)) { - nn_packet_write_u8(packet, CAMU_RESOURCE_HTTP); -#else - if (0) { -#endif -#if CACHE_HAVE_CDIO - } else if (al_str_cmp(&argv[i], &al_str_c("cdda://"), 0, 7) == 0) { - nn_packet_write_u8(packet, CAMU_RESOURCE_CDIO); -#endif - } else { - nn_packet_write_u8(packet, CAMU_RESOURCE_FILE); - } nn_packet_write_str(packet, &argv[i]); camu_server_local_add(&c.server, packet); nn_packet_free(packet); diff --git a/src/liana/list.c b/src/liana/list.c index 0ceb591..fd58ea1 100644 --- a/src/liana/list.c +++ b/src/liana/list.c @@ -407,7 +407,7 @@ static void handle_seek(struct lia_list *list, s32 sequence, u32 id, u64 pos) al_assert(entry); if (entry->duration == 0 || entry->duration == LIANA_TIMESTAMP_INVALID) { - log_warn("Skipping seek on entry with no duration."); + log_warn("Skipping seek on entry with unknown or 0 duration."); return; } @@ -451,6 +451,11 @@ static bool handle_end(struct lia_list *list, u32 id, u32 reset_id) if (sequence < 0) return true; struct lia_list_entry *entry = get_entry_from_sequence(list, sequence); + // Looping: + // - Main issue is rolling back an entry that skipped onto queued + // before it's looping state was synced. + // - Maybe we can track which sink END comes from. + if (reset_id != entry->reset_id) { log_warn("Got end() with out of order or incorrect reset id, ignoring."); return true; @@ -689,7 +694,7 @@ void lia_list_remove_sink(struct lia_list *list, void *userdata) handle_remove_sink(list, userdata); } -void lia_list_add(struct lia_list *list, void *opaque, u64 duration, wstr *name) +void lia_list_add(struct lia_list *list, void *opaque, u64 duration, str *brief) { struct lia_list_entry *entry = al_alloc_object(struct lia_list_entry); entry->opaque = opaque; @@ -701,7 +706,7 @@ void lia_list_add(struct lia_list *list, void *opaque, u64 duration, wstr *name) entry->ended = false; entry->reset_id = get_incremental_id(list); entry->duration = duration; - al_wstr_clone(&entry->name, name); + al_str_clone(&entry->brief, brief); entry->list = list; struct lia_list_cmd *cmd = al_alloc_object(struct lia_list_cmd); cmd->op = ADD; @@ -824,7 +829,7 @@ void lia_list_free(struct lia_list *list) if (list->cmd) al_free(list->cmd); struct lia_list_entry *entry; al_array_foreach(list->entries, i, entry) { - al_wstr_free(&entry->name); + al_str_free(&entry->brief); al_free(entry); } al_array_free(list->entries); diff --git a/src/liana/list.h b/src/liana/list.h index 86a9712..36d95a4 100644 --- a/src/liana/list.h +++ b/src/liana/list.h @@ -82,7 +82,7 @@ struct lia_list_entry { bool ended; u32 reset_id; u64 duration; - wstr name; + str brief; struct lia_list *list; }; @@ -136,7 +136,7 @@ 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, void *opaque, u64 duration, wstr *name); +void lia_list_add(struct lia_list *list, void *opaque, u64 duration, str *brief); 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); diff --git a/src/liana/list_cmp.h b/src/liana/list_cmp.h index 556f5dd..ee9b3f8 100644 --- a/src/liana/list_cmp.h +++ b/src/liana/list_cmp.h @@ -6,38 +6,38 @@ AL_IGNORE_WARNING("-Wunused-function") -static void camu_db_num_from_path(wstr *path, s64 *id, s64 *index) +static void camu_db_num_from_path(str *path, s64 *id, s64 *index) { - u32 last_slash = al_wstr_rfind(path, L'/'); + u32 last_slash = al_str_rfind(path, '/'); if (last_slash == AL_WSTR_NPOS) { return; } - wstr sub = al_wstr_substr(path, last_slash + 1, path->length); + str sub = al_str_substr(path, last_slash + 1, path->length); // Skip 2 '_' characters. - if (!(al_wstr_tok(&sub, L'_') && al_wstr_tok(&sub, L'_'))) { + if (!(al_str_tok(&sub, '_') && al_str_tok(&sub, '_'))) { return; } - u32 target = al_wstr_find(&sub, L'_'); + u32 target = al_str_find(&sub, '_'); if (target == AL_WSTR_NPOS) { return; } - sub = al_wstr_substr(&sub, 0, target); + sub = al_str_substr(&sub, 0, target); bool error; - s64 num = al_wstr_to_long(&sub, 10, &error); + s64 num = al_str_to_long(&sub, 10, &error); if (error) return; *id = num; - u32 ext_dot = al_wstr_rfind(path, L'.'); - u32 a_of_media = al_wstr_rfind(path, 'a'); + u32 ext_dot = al_str_rfind(path, '.'); + u32 a_of_media = al_str_rfind(path, 'a'); if (ext_dot == AL_WSTR_NPOS || a_of_media == AL_WSTR_NPOS) { return; } - sub = al_wstr_substr(path, a_of_media + 1, ext_dot); + sub = al_str_substr(path, a_of_media + 1, ext_dot); - num = al_wstr_to_long(&sub, 10, &error); + num = al_str_to_long(&sub, 10, &error); if (error) return; *index = num; } @@ -48,8 +48,9 @@ static s32 camu_db_compare(const void *a, const void *b) struct lia_list_entry *bb = *((struct lia_list_entry **)b); s64 a_id = -1, a_index = -1; s64 b_id = -1, b_index = -1; - camu_db_num_from_path(&aa->name, &a_id, &a_index); - camu_db_num_from_path(&bb->name, &b_id, &b_index); + // Assuming brief is the file path. + camu_db_num_from_path(&aa->brief, &a_id, &a_index); + camu_db_num_from_path(&bb->brief, &b_id, &b_index); if (a_id == b_id) { if (a_index > b_index) return 1; else if (a_index < b_index) return -1; diff --git a/src/liana/server.c b/src/liana/server.c index acb5f31..cc4ceed 100644 --- a/src/liana/server.c +++ b/src/liana/server.c @@ -1,7 +1,6 @@ #include "server.h" #include "handler.h" #include "handlers.h" -#include "process.h" #include "list.h" static inline u32 get_incremental_id(struct lia_server *server) @@ -443,13 +442,6 @@ static void duration_signal_callback(void *userdata) nn_signal_stop(&node->signal); nn_thread_join(&node->thread); node->handler->free(&node->handler); - bool got_visual_data = false; - struct lia_visual_data visual_data; -#if 0 // @TODO: This is obviously bad because it blocks the event loop. - // Evaluate this when getting around to http/hls stream fixes. - cch_handle_seek(&node->handle, 0, SEEK_SET); - got_visual_data = lia_prepare_visual_data(&node->handle, &visual_data); -#endif cch_entry_return_handle(node->entry, &node->handle); if (should_free_node(node)) { free_node(node); @@ -461,9 +453,6 @@ static void duration_signal_callback(void *userdata) node->callback(node->userdata, LIANA_NODE_DURATION, &node->duration); } } - if (got_visual_data) { - node->callback(node->userdata, LIANA_NODE_VISUAL_DATA, &visual_data); - } } void lia_node_get_duration(struct lia_node *node) diff --git a/src/liana/server.h b/src/liana/server.h index 55a581e..8035ee1 100644 --- a/src/liana/server.h +++ b/src/liana/server.h @@ -27,7 +27,6 @@ struct lia_node_connection { enum { LIANA_NODE_DURATION = 0, - LIANA_NODE_VISUAL_DATA, LIANA_NODE_ERRORED }; diff --git a/src/libsink/sink.c b/src/libsink/sink.c index c95096d..392f6b9 100644 --- a/src/libsink/sink.c +++ b/src/libsink/sink.c @@ -1530,6 +1530,7 @@ static void identify_callback(void *userdata, struct nn_rpc_connection *conn, st { struct camu_sink *sink = (struct camu_sink *)userdata; (void)sink; + // @TODO: Send sink id from list. nn_packet_stream_return_packet(conn->stream, packet); } diff --git a/src/server/common.h b/src/server/common.h index 9cb9501..5b27768 100644 --- a/src/server/common.h +++ b/src/server/common.h @@ -39,20 +39,6 @@ enum { CAMU_LIST_END }; -enum { - CAMU_RESOURCE_FILE = 0, -#ifdef NAUNET_HAS_CURL - CAMU_RESOURCE_HTTP, -#endif -#ifdef CACHE_HAVE_CDIO - CAMU_RESOURCE_CDIO, -#endif -#ifdef CAMU_HAVE_PORTAL - CAMU_RESOURCE_PORTAL, - CAMU_RESOURCE_SIMPLE_SEARCH -#endif -}; - static inline bool camu_is_url(str *s, u32 i) { return al_str_cmp(s, &al_str_c("https://"), i, 8) == 0 diff --git a/src/server/resource.h b/src/server/resource.h index 3158479..cdbb42e 100644 --- a/src/server/resource.h +++ b/src/server/resource.h @@ -1,7 +1,21 @@ #pragma once #include "../liana/server.h" -#include "../liana/process.h" +#include "../portal/src/post.h" + +enum { + CAMU_RESOURCE_FILE = 0, +#ifdef NAUNET_HAS_CURL + CAMU_RESOURCE_HTTP, +#endif +#ifdef CACHE_HAVE_CDIO + CAMU_RESOURCE_CDIO, +#endif +#ifdef CAMU_HAVE_PORTAL + CAMU_RESOURCE_PORTAL, + CAMU_RESOURCE_SIMPLE_SEARCH +#endif +}; struct camu_resource { u8 type; @@ -10,28 +24,8 @@ struct camu_resource { struct lia_node *node; u64 duration; u32 ref; - array(struct lia_list_entry *) pending; - struct lia_visual_data visual_data; - struct camu_server *server; -}; - -struct camu_resource_file { - struct camu_resource r; - str path; -}; - -struct camu_resource_http { - struct camu_resource r; - str url; -}; - -struct camu_resource_portal { - struct camu_resource r; - struct camu_post *post; + str uri; u32 index; -}; - -struct camu_resource_cdio { - struct camu_resource r; - u32 track; + struct camu_post *post; + array(struct lia_list_entry *) pending; }; diff --git a/src/server/server.c b/src/server/server.c index 0275147..6f8da78 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -12,7 +12,6 @@ #ifdef CAMU_HAVE_PORTAL #include "../portal/src/packet_ext.h" #endif -#include "../codec/packet_ext.h" #include "server.h" #include "common.h" @@ -79,7 +78,7 @@ static void write_list_entry(struct lia_list_entry *entry, struct nn_packet *pac nn_packet_write_u64(packet, entry->start); nn_packet_write_u64(packet, entry->paused_at); nn_packet_write_u64(packet, entry->offset); - nn_packet_write_wstr(packet, &entry->name); + nn_packet_write_str(packet, &entry->brief); } static void write_initial_user_state(struct camu_server *server, struct camu_user *user, struct nn_packet *packet) @@ -236,20 +235,6 @@ static void process_pending(struct camu_resource *resource) al_array_free(pending); } -static void send_clients_visual_data(struct camu_server *server, u32 node_id, struct lia_visual_data *visual_data) -{ - struct camu_server_client *client; - al_array_foreach(server->clients, i, client) { - struct nn_packet *packet = nn_rpc_get_packet(client->conn->rpc, CAMU_CLIENT_VISUAL_DATA); - nn_packet_write_u32(packet, node_id); - nn_packet_write_audio_format(packet, &visual_data->fmt); - nn_packet_write_u32(packet, visual_data->size); - NNWT_PACKET_WRITE_DATA(packet, visual_data->samples, visual_data->size); - nn_packet_write_u32(packet, visual_data->count); - nn_rpc_connection_command(client->conn, packet, NULL, NULL); - } -} - static void node_callback(void *userdata, u8 op, void *opaque) { struct camu_resource *resource = (struct camu_resource *)userdata; @@ -260,10 +245,6 @@ static void node_callback(void *userdata, u8 op, void *opaque) resource->duration = duration; break; } - case LIANA_NODE_VISUAL_DATA: { - resource->visual_data = *(struct lia_visual_data *)opaque; - break; - } case LIANA_NODE_ERRORED: resource->load = LIANA_ENTRY_ERRORED; break; @@ -359,20 +340,17 @@ static bool prepare_server_resource(struct camu_server *server, struct camu_reso { 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")); + case CAMU_RESOURCE_FILE: + entry = cch_handler_file_create(&resource->uri, &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); + case CAMU_RESOURCE_HTTP: + entry = cch_handler_http_create(&resource->uri, server->loop); if (!entry) { resource->load = LIANA_ENTRY_ERRORED; return false; @@ -380,34 +358,29 @@ static bool prepare_server_resource(struct camu_server *server, struct camu_reso 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); + case CAMU_RESOURCE_PORTAL: + entry = entry_from_post(server, resource->post, resource->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; + case CAMU_RESOURCE_CDIO: 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); + resource->index = MIN(resource->index, entry->chapters.count); + entry->chapter = &al_array_at(entry->chapters, resource->index); entry->handler->maybe_spawn_worker(entry->handler, entry->chapter->start); resource->load = LIANA_ENTRY_PREPARED; break; - } #endif } @@ -479,7 +452,7 @@ static void list_callback(void *userdata, u8 op, struct lia_list_entry *entry, v case LIANA_META_REMOVED_ENTRY: break; case LIANA_META_CURRENT_CHANGED: - log_info("Now playing: %ls.", entry->name.data); + log_info("Now playing: %.*s.", al_str_x(&entry->brief)); send_clients_current_changed(server, list, entry); break; case LIANA_META_ORDER_CHANGED: @@ -492,7 +465,7 @@ static void list_callback(void *userdata, u8 op, struct lia_list_entry *entry, v send_clients_entry_seeked(server, list, entry); break; case LIANA_META_ENTRY_ERRORED: - log_error("Failed to load: %ls.", entry->name.data); + log_error("Failed to load: %.*s.", al_str_x(&entry->brief)); break; } break; @@ -594,9 +567,7 @@ static bool client_command_callback(void *userdata, struct nn_rpc_connection *co case CAMU_CLIENT_REQUEST_VISUAL_DATA: { u32 node_id = nn_packet_read_u32(packet); struct camu_resource *resource = get_resource_by_node_id(server, node_id); - if (resource) { - send_clients_visual_data(resource->server, resource->node->id, &resource->visual_data); - } + (void)resource; break; } } @@ -611,20 +582,19 @@ out: 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; + struct camu_resource *resource = (struct camu_resource *)userdata1; switch (result->op) { case CAMU_CLIENT_CREATE_SEARCH: if (result->id == -1) { break; } - camu_portal_get_page(&server->bridge, result->id, 0, simple_search_portal_callback, portal); + camu_portal_get_page(&server->bridge, result->id, 0, simple_search_portal_callback, resource); return; 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->post = camu_post_cache_get(&server->cache, &al_array_at(result->page->list, 0)); resource->type = CAMU_RESOURCE_PORTAL; prepare_server_resource(server, resource); process_pending(resource); @@ -636,31 +606,41 @@ static void simple_search_portal_callback(void *userdata0, void *userdata1, stru } #endif +static u8 parse_resource_type(str *line) +{ +#if defined CAMU_HAVE_PORTAL + if (al_str_at(line, 0) == ';' || camu_is_url(line, 0)) { + return CAMU_RESOURCE_SIMPLE_SEARCH; +#elif defined NAUNET_HAS_CURL + if (camu_is_url(line, 0)) { + return CAMU_RESOURCE_HTTP; +#else + if (0) { +#endif +#if CACHE_HAVE_CDIO + } else if (al_str_cmp(line, &al_str_c("cdda://"), 0, 7) == 0) { + return CAMU_RESOURCE_CDIO; +#endif + } else { + return CAMU_RESOURCE_FILE; + } +} + 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 camu_resource *resource = NULL; - wstr name; - switch (op) { + struct camu_resource *resource = al_alloc_object(struct camu_resource); + str line; + nn_packet_read_str(packet, &line); + switch (parse_resource_type(&line)) { case CAMU_RESOURCE_FILE: { - str path; - nn_packet_read_str(packet, &path); - 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; + al_str_clone(&resource->uri, &line); resource->type = CAMU_RESOURCE_FILE; resource->load = LIANA_ENTRY_UNLOADED; break; } #ifdef NAUNET_HAS_CURL case CAMU_RESOURCE_HTTP: { - str url; - nn_packet_read_str(packet, &url); - 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; + al_str_clone(&resource->uri, &line); resource->type = CAMU_RESOURCE_HTTP; resource->load = LIANA_ENTRY_UNLOADED; break; @@ -668,20 +648,15 @@ static void handle_add_command(struct camu_server *server, struct lia_list *list #endif #ifdef CACHE_HAVE_CDIO case CAMU_RESOURCE_CDIO: { - str url; - nn_packet_read_str(packet, &url); u32 track = 0; - if (url.length > 7) { + if (line.length > 7) { bool error; - s64 index = al_str_to_long(&al_str_substr(&url, 7, url.length), 10, &error); + s64 index = al_str_to_long(&al_str_substr(&line, 7, line.length), 10, &error); if (!error && index > 0) { track = (u32)index - 1; } } - 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->index = track; resource->type = CAMU_RESOURCE_CDIO; resource->load = LIANA_ENTRY_UNLOADED; break; @@ -689,37 +664,30 @@ static void handle_add_command(struct camu_server *server, struct lia_list *list #endif #ifdef CAMU_HAVE_PORTAL case CAMU_RESOURCE_SIMPLE_SEARCH: { - str search; - nn_packet_read_str(packet, &search); - struct camu_resource_portal *portal = al_alloc_object(struct camu_resource_portal); - portal->post = NULL; - al_wstr_from_str(&name, &search); - resource = (struct camu_resource *)portal; + resource->post = NULL; resource->type = CAMU_RESOURCE_SIMPLE_SEARCH; resource->load = LIANA_ENTRY_PREPARING; str query; - if (al_str_at(&search, 0) == ';') { // search. - al_str_clone(&query, &al_str_substr(&search, 1, search.length)); + if (al_str_at(&line, 0) == ';') { // search. + al_str_clone(&query, &al_str_substr(&line, 1, line.length)); } else { al_str_from(&query, "link:"); - al_str_cat(&query, &search); + al_str_cat(&query, &line); } - 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, resource); al_str_free(&query); break; } #endif } al_assert(resource); - resource->server = server; al_array_push(server->data.resources, resource); resource->entry = NULL; resource->node = NULL; resource->duration = LIANA_TIMESTAMP_INVALID; al_array_init(resource->pending); - lia_list_add(list, resource, resource->duration, &name); - al_wstr_free(&name); + lia_list_add(list, resource, resource->duration, &line); } static bool list_action_callback(void *userdata, struct nn_rpc_connection *conn, @@ -953,13 +921,12 @@ void camu_server_free(struct camu_server *server) al_array_free(resource->pending); switch (resource->type) { case CAMU_RESOURCE_FILE: { - struct camu_resource_file *file = (struct camu_resource_file *)resource; - al_str_free(&file->path); - al_free(file); + al_str_free(&resource->uri); break; } #ifdef NAUNET_HAS_CURL case CAMU_RESOURCE_HTTP: + al_str_free(&resource->uri); break; #endif #ifdef CACHE_HAVE_CDIO @@ -968,17 +935,14 @@ void camu_server_free(struct camu_server *server) #endif #ifdef CAMU_HAVE_PORTAL case CAMU_RESOURCE_PORTAL: { - struct camu_resource_portal *portal = (struct camu_resource_portal *)resource; - al_free(portal); break; } case CAMU_RESOURCE_SIMPLE_SEARCH: { - struct camu_resource_portal *portal = (struct camu_resource_portal *)resource; - al_free(portal); break; } #endif } + al_free(resource); } al_array_free(server->data.resources); diff --git a/subprojects/libalabaster.wrap b/subprojects/libalabaster.wrap index fe96079..6ab8612 100644 --- a/subprojects/libalabaster.wrap +++ b/subprojects/libalabaster.wrap @@ -1,4 +1,4 @@ [wrap-git] url = https://git.akon.city/libalabaster -revision = a5516233d66eb1552cf7fdfe03779b2bf896c82d +revision = 34a5e136b6c79092eee73857bbad25892fe8047a depth = 1 -- cgit v1.2.3-101-g0448