summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/fruits/cmc/cmc.c134
-rw-r--r--src/fruits/cmc/cmc.h8
-rw-r--r--src/fruits/cmc/ui/pane_list.c224
-rw-r--r--src/fruits/cmc/ui/pane_search.c30
-rw-r--r--src/fruits/cmc/ui/ui.c47
-rw-r--r--src/fruits/cmc/ui/ui.h19
-rw-r--r--src/fruits/cmc/ui/waveform.h104
-rw-r--r--src/fruits/cmv/cmv.c2
-rw-r--r--src/fruits/ctv/ctv.c2
-rw-r--r--src/liana/list.c20
-rw-r--r--src/liana/list.h10
-rw-r--r--src/libclient/client.c8
-rw-r--r--src/libclient/client.h6
-rw-r--r--src/portal/cpy/portal.pyx14
-rw-r--r--src/server/server.c90
-rw-r--r--src/sink/desktop.c2
-rw-r--r--src/sink/desktop.h2
17 files changed, 506 insertions, 216 deletions
diff --git a/src/fruits/cmc/cmc.c b/src/fruits/cmc/cmc.c
index 61ac25a..4278663 100644
--- a/src/fruits/cmc/cmc.c
+++ b/src/fruits/cmc/cmc.c
@@ -2,7 +2,6 @@
#include <nnwt/event_loop.h>
#include <nnwt/packet.h>
-#include "../../portal/src/packet_ext.h"
#include "../../server/common.h"
#include "../../liana/list.h"
@@ -29,7 +28,7 @@ static struct cmc_search *get_search_by_id(struct cmc *c, s32 id)
}
*/
-static void parse_list_entry(struct nn_packet *packet, struct cmc_list_entry *entry, u32 id)
+static void read_list_entry(struct nn_packet *packet, struct cmc_list_entry *entry, u32 id)
{
entry->id = id;
entry->duration = nn_packet_read_u64(packet);
@@ -38,7 +37,10 @@ static void parse_list_entry(struct nn_packet *packet, struct cmc_list_entry *en
entry->offset = nn_packet_read_u64(packet);
wstr w;
nn_packet_read_wstr(packet, &w);
- al_wstr_clone(&entry->name, &w);
+ if (!al_wstr_eq(&entry->name, &w)) {
+ al_wstr_free(&entry->name);
+ al_wstr_clone(&entry->name, &w);
+ }
}
static void parse_initial_user_state(struct cmc *c, struct nn_packet *packet)
@@ -66,25 +68,35 @@ static void parse_initial_user_state(struct cmc *c, struct nn_packet *packet)
u32 inner_count = nn_packet_read_s32(packet);
for (u32 j = 0; j < inner_count; j++) {
u32 id = nn_packet_read_u32(packet);
- struct cmc_list_entry entry;
- parse_list_entry(packet, &entry, id);
+ struct cmc_list_entry *entry = al_alloc_object(struct cmc_list_entry);
+ read_list_entry(packet, entry, id);
al_array_push(list->entries, entry);
}
al_array_push(c->lists, list);
}
}
+static struct cmc_list *get_list_by_name(struct cmc *c, str *name)
+{
+ struct cmc_list *list;
+ al_array_foreach(c->lists, i, list) {
+ if (al_str_eq(&list->name, name)) return list;
+ }
+ return NULL;
+}
+
static void client_callback(void *userdata, u8 op, void *opaque)
{
struct cmc *c = (struct cmc *)userdata;
switch (op) {
case CAMU_CLIENT_LOGGED_IN: {
struct nn_packet *packet = (struct nn_packet *)opaque;
- switch (c->command) {
+ switch (c->cli.command) {
case CLI_OPEN_UI:
parse_initial_user_state(c, packet);
if (!cmc_ui_init(&c->ui, &c->loop, c)) {
- nn_event_loop_break_one(&c->loop);
+ camu_client_disconnect(&c->client);
+ break;
}
struct cmc_list *list;
al_array_foreach(c->lists, i, list) {
@@ -96,11 +108,16 @@ static void client_callback(void *userdata, u8 op, void *opaque)
}
break;
case CLI_ADD: {
+ str *arg;
+ al_array_foreach_ptr(c->cli.args, i, arg) {
+ al_str_free(arg);
+ }
+ camu_client_disconnect(&c->client);
break;
}
case CLI_SEARCH: {
str *arg;
- al_array_foreach_ptr(c->args, i, arg) {
+ al_array_foreach_ptr(c->cli.args, i, arg) {
camu_client_create_search(&c->client, &al_str_c("youtube"), arg);
al_str_free(arg);
}
@@ -124,53 +141,50 @@ static void client_callback(void *userdata, u8 op, void *opaque)
case CAMU_CLIENT_GOT_META: {
struct nn_packet *packet = (struct nn_packet *)opaque;
u8 op = nn_packet_read_u8(packet);
+ str name;
+ nn_packet_read_str(packet, &name);
+ struct cmc_list *list = get_list_by_name(c, &name);
+ if (!list) break;
switch (op) {
- case LIANA_META_CURRENT_CHANGED: {
- str name;
- nn_packet_read_str(packet, &name);
- struct cmc_list *list;
- al_array_foreach(c->lists, i, list) {
- if (al_str_eq(&list->name, &name)) {
- list->current = nn_packet_read_s32(packet);
- u32 id = nn_packet_read_u32(packet);
- struct cmc_list_entry *entry = &al_array_at(list->entries, list->current);
- parse_list_entry(packet, entry, id);
- break;
- }
- }
+ case LIANA_META_ADDED_ENTRY: {
+ u32 id = nn_packet_read_u32(packet);
+ struct cmc_list_entry *entry = al_alloc_object(struct cmc_list_entry);
+ read_list_entry(packet, entry, id);
+ al_array_push(list->entries, entry);
cmc_ui_queue_render(&c->ui);
break;
}
- case LIANA_META_ADDED_ENTRY: {
- str name;
- nn_packet_read_str(packet, &name);
+ case LIANA_META_REMOVED_ENTRY: {
+ break;
+ }
+ case LIANA_META_CURRENT_CHANGED: {
+ list->current = nn_packet_read_s32(packet);
u32 id = nn_packet_read_u32(packet);
- struct cmc_list_entry entry;
- parse_list_entry(packet, &entry, id);
- struct cmc_list *list;
- al_array_foreach(c->lists, i, list) {
- if (al_str_eq(&list->name, &name)) {
- al_array_push(list->entries, entry);
- break;
+ struct cmc_list_entry *entry = al_array_at(list->entries, list->current);
+ read_list_entry(packet, entry, id);
+ cmc_ui_queue_render(&c->ui);
+ break;
+ }
+ case LIANA_META_ORDER_CHANGED: {
+ struct cmc_list_entry *entry;
+ u32 count = nn_packet_read_u32(packet);
+ for (u32 i = 0; i < count; i++) {
+ u32 id = nn_packet_read_u32(packet);
+ al_array_foreach(list->entries, j, entry) {
+ if (i != j && entry->id == id) {
+ SWAP(al_array_at(list->entries, i), al_array_at(list->entries, j));
+ }
}
}
- cmc_ui_queue_render(&c->ui);
break;
}
case LIANA_META_ENTRY_SEEKED: {
- str name;
- nn_packet_read_str(packet, &name);
- struct cmc_list *list;
- al_array_foreach(c->lists, i, list) {
- if (al_str_eq(&list->name, &name)) {
- u32 id = nn_packet_read_u32(packet);
- struct cmc_list_entry *entry;
- al_array_foreach_ptr(list->entries, j, entry) {
- if (entry->id == id) {
- parse_list_entry(packet, entry, id);
- break;
- }
- }
+ u32 id = nn_packet_read_u32(packet);
+ struct cmc_list_entry *entry;
+ al_array_foreach(list->entries, i, entry) {
+ if (entry->id == id) {
+ read_list_entry(packet, entry, id);
+ break;
}
}
break;
@@ -183,31 +197,27 @@ static void client_callback(void *userdata, u8 op, void *opaque)
static struct cmc c = { 0 };
-#ifdef NAUNET_ON_WINDOWS
-static bool parse_cmd(s32 argc, wchar_t **argv)
-#else
-static bool parse_cmd(s32 argc, char *argv[])
-#endif
+static bool parse_command_line(s32 argc, char *argv[])
{
if (argc < 2) {
- c.command = CLI_OPEN_UI;
+ c.cli.command = CLI_OPEN_UI;
return true;
}
if (al_str_eq(&al_str_cr(argv[1]), &al_str_c("add"))) {
if (argc < 3) return false;
- c.command = CLI_ADD;
+ c.cli.command = CLI_ADD;
char path[PATH_MAX];
str arg;
for (s32 i = 2; i < argc; i++) {
if (realpath(argv[i], path)) {
al_str_clone(&arg, &al_str_cs(path));
- al_array_push(c.args, arg);
+ al_array_push(c.cli.args, arg);
}
}
} else if (al_str_eq(&al_str_cr(argv[1]), &al_str_c("search"))) {
if (argc < 3) return false;
- c.command = CLI_SEARCH;
+ c.cli.command = CLI_SEARCH;
str query;
al_str_from(&query, "");
for (s32 i = 2; i < argc; i++) {
@@ -216,24 +226,22 @@ static bool parse_cmd(s32 argc, char *argv[])
al_str_cat(&query, &al_str_c(" "));
}
}
- al_array_push(c.args, query);
+ al_array_push(c.cli.args, query);
}
return true;
}
-#ifdef NAUNET_ON_WINDOWS
-s32 wmain(s32 argc, wchar_t **argv)
-#else
s32 main(s32 argc, char *argv[])
-#endif
{
if (!nn_common_init()) return EXIT_FAILURE;
- nn_event_loop_init(&c.loop);
+ al_array_init(c.cli.args);
+ if (!parse_command_line(argc, argv)) {
+ return EXIT_FAILURE;
+ }
- al_array_init(c.args);
- if (!parse_cmd(argc, argv)) return EXIT_FAILURE;
+ nn_event_loop_init(&c.loop);
al_array_init(c.lists);
camu_post_cache_init(&c.cache);
@@ -241,7 +249,7 @@ s32 main(s32 argc, char *argv[])
c.client.callback = client_callback;
c.client.userdata = &c;
- if (!camu_client_login(&c.client, &c.loop, CAMU_TEST_TYPE, &CAMU_TEST_ADDR, CAMU_PORT, &al_str_c("andrew"))) {
+ if (!camu_client_login(&c.client, &al_str_c("andrew"), &c.loop, CAMU_TEST_TYPE, &CAMU_TEST_ADDR, CAMU_PORT)) {
return EXIT_FAILURE;
}
diff --git a/src/fruits/cmc/cmc.h b/src/fruits/cmc/cmc.h
index 0a3cbca..e2cdde3 100644
--- a/src/fruits/cmc/cmc.h
+++ b/src/fruits/cmc/cmc.h
@@ -33,13 +33,15 @@ struct cmc_list_entry {
struct cmc_list {
str name;
s32 current;
- array(struct cmc_list_entry) entries;
+ array(struct cmc_list_entry *) entries;
};
struct cmc {
+ struct {
+ u8 command;
+ array(str) args;
+ } cli;
struct nn_event_loop loop;
- u8 command;
- array(str) args;
struct camu_client client;
array(struct cmc_list *) lists;
struct camu_post_cache cache;
diff --git a/src/fruits/cmc/ui/pane_list.c b/src/fruits/cmc/ui/pane_list.c
index 5fc9f81..557f5f3 100644
--- a/src/fruits/cmc/ui/pane_list.c
+++ b/src/fruits/cmc/ui/pane_list.c
@@ -26,58 +26,146 @@ void cmc_lp_add_list(struct cmc_ui *ui, struct cmc_list *list)
{
struct cmc_list_tab tab = {
.list = list,
- .selected = 0
+ .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;
- }
+ if (!ui->lp.tabs.count) return false;
struct cmc_list_tab *tab = &al_array_at(ui->lp.tabs, ui->lp.current);
- u32 count = tab->list->entries.count;
+ 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':
- if (!cmc_ui_consider_input(input, true) || tab->selected >= count - 1) {
- return false;
+ 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++;
+ }
}
- tab->selected++;
break;
case 'k':
- if (!cmc_ui_consider_input(input, true) || tab->selected == 0) {
- return false;
+ 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;
}
- tab->selected--;
break;
case NCKEY_RETURN:
- if (!cmc_ui_consider_input(input, false)) {
- return false;
+ CONSIDER_INPUT();
+ if (tab->move.active) {
+ tab->move.active = false;
+ } else {
+ camu_client_skipto(&ui->c->client, &tab->list->name, tab->selected);
}
- camu_client_skipto(&ui->c->client, &tab->list->name, tab->selected);
break;
- case NCKEY_BUTTON1: {
- if (!cmc_ui_consider_input(input, false)) {
+ 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;
}
- u32 height = ncplane_dim_y(ui->lp.n);
+ ui->last_mouse_ts = now;
u32 width = ncplane_dim_x(ui->lp.n);
- if (input->x > 0 && input->y > 0) {
- u32 x = (u32)input->x;
- u32 y = (u32)input->y;
- if (y > height - 3 && x >= 2 && x <= width) {
- struct cmc_list_entry *entry = &al_array_at(tab->list->entries, tab->list->current);
- f64 percent = (x - 2) / (f64)(width - 2);
- camu_client_seek(&ui->c->client, &tab->list->name, entry->id, percent);
- }
- ui->last_mouse_x = x;
- ui->last_mouse_y = y;
+ 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;
}
@@ -87,27 +175,57 @@ 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, u32 max_height)
+static void render_list_entries(struct cmc_ui *ui, struct cmc_list_tab *tab, s32 max_height)
{
struct cmc_list *list = tab->list;
- u32 count = list->entries.count;
- u32 index = tab->selected - (tab->selected % max_height);
- u32 end = MIN(index + max_height, count);
+ 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 (u32 i = index; i < end; i++) {
- entry = &al_array_at(list->entries, i);
- if (i == tab->selected) {
- ncplane_set_styles(ui->lp.n, NCSTYLE_BOLD);
- ncplane_set_fg_palindex(ui->lp.n, 6);
- } else {
- ncplane_set_styles(ui->lp.n, NCSTYLE_NONE);
- ncplane_set_fg_default(ui->lp.n);
+ 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);
}
- if (list->current >= 0 && i == (u32)list->current) {
- ncplane_putchar_yx(ui->lp.n, i - index, 1, '>');
- cmc_ui_putnwstr_yx(ui->lp.n, i - index, 3, entry->name.length, &entry->name);
+ 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(ui->lp.n, i - index, 0, entry->name.length, &entry->name);
+ cmc_ui_putnwstr_yx(n, y, 1, length, &entry->name);
+ }
+ if (styled) {
+ ncplane_set_styles(n, NCSTYLE_NONE);
+ ncplane_set_fg_default(n);
}
}
}
@@ -117,7 +235,7 @@ static void render_now_playing(struct cmc_ui *ui, struct cmc_list_tab *tab, u32
u32 width = ncplane_dim_x(ui->lp.n);
if (tab && tab->list->entries.count > 0) {
struct cmc_list *list = tab->list;
- struct cmc_list_entry *entry = &al_array_at(list->entries, list->current);
+ struct cmc_list_entry *entry = al_array_at(list->entries, list->current);
f32 percent = 1.0;
if (entry->duration > 0) {
u64 pos = entry->offset;
@@ -128,13 +246,19 @@ static void render_now_playing(struct cmc_ui *ui, struct cmc_list_tab *tab, u32
percent = MIN(pos / (f32)entry->duration, 1.f);
}
for (u32 i = 0; i < (width - 2) * percent; i++) {
- ncplane_putchar_yx(ui->lp.n, height - 2, i + 1, '-');
+ ncplane_putchar_yx(ui->lp.n, height - 6, i + 1, '-');
}
- cmc_ui_putnwstr_yx(ui->lp.n, height - 4, 1, entry->name.length, &entry->name);
+ cmc_ui_putnwstr_yx(ui->lp.n, height - 7, 2, entry->name.length, &entry->name);
}
+ ncplane_putchar_yx(ui->lp.n, height - 5, 2, 'A');
+ ncplane_putchar_yx(ui->lp.n, height - 4, 2, 'A');
+ ncplane_putchar_yx(ui->lp.n, height - 3, 2, 'A');
+ ncplane_putchar_yx(ui->lp.n, height - 2, 2, 'A');
+ /*
char buf[24];
al_snprintf(buf, sizeof(buf), "%u, %u | %u, %u", ui->last_mouse_x, ui->last_mouse_y, width, height);
ncplane_putstr_yx(ui->lp.n, height - 5, 1, buf);
+ */
u64 c = 0;
ncchannels_set_fg_default(&c);
ncplane_cursor_move_yx(ui->lp.n, y, 0);
@@ -150,9 +274,11 @@ void cmc_lp_render(struct cmc_ui *ui)
tab = &al_array_at(ui->lp.tabs, ui->lp.current);
}
+ tab->page_length = height - 8;
+
if (tab) {
- render_list_entries(ui, tab, height - 8);
+ render_list_entries(ui, tab, tab->page_length);
}
- render_now_playing(ui, tab, height - 8, height);
+ render_now_playing(ui, tab, tab->page_length, height);
}
diff --git a/src/fruits/cmc/ui/pane_search.c b/src/fruits/cmc/ui/pane_search.c
index 3b427ce..21c9b67 100644
--- a/src/fruits/cmc/ui/pane_search.c
+++ b/src/fruits/cmc/ui/pane_search.c
@@ -14,9 +14,22 @@ void cmc_sp_layout(struct cmc_ui *ui, struct ncplane *parent)
{
if (ui->sp.n) ncplane_destroy(ui->sp.n);
struct ncplane_options nopts = { 0 };
- nopts.rows = ncplane_dim_y(parent);
- nopts.cols = ncplane_dim_x(parent);
+ nopts.rows = ncplane_dim_y(parent) - 1;
+ nopts.cols = ncplane_dim_x(parent) - 1;
ui->sp.n = ncplane_create(parent, &nopts);
+ struct cmc_search_tab tab = {
+ .search = NULL,
+ };
+ nopts.x = 3;
+ nopts.y = 2;
+ nopts.rows = 10;
+ nopts.cols = ncplane_dim_x(ui->sp.n) - 3;
+ tab.input = ncplane_create(ui->sp.n, &nopts);
+ tab.cursor = 0;
+ tab.input_active = false;
+ tab.input_text = al_wstr_null();
+ tab.input_changed = false;
+ al_array_push(ui->sp.tabs, tab);
}
void cmc_sp_add_search(struct cmc_ui *ui, struct cmc_search *search)
@@ -60,10 +73,11 @@ static bool handle_text_input(struct cmc_search_tab *tab, struct ncinput *input)
}
break;
case NCKEY_RETURN:
- tab->input_active = false;
- // Erase text on next render.
- tab->input_changed = true;
entered = true;
+ // fallthrough
+ case NCKEY_ESC:
+ tab->input_active = false;
+ tab->input_changed = true; // Erase text on next render.
break;
default:
if (ncinput_ctrl_p(input)) {
@@ -138,19 +152,17 @@ bool cmc_sp_handle_input(struct cmc_ui *ui, struct ncinput *input)
if (tab->input_active) {
if (cmc_ui_consider_input(input, true)) {
if (handle_text_input(tab, input)) {
- notcurses_cursor_disable(ui->nc);
str query;
al_str_from_wstr(&query, &tab->input_text);
camu_client_create_search(&ui->c->client, &al_str_c("youtube"), &query);
al_str_free(&query);
}
+ if (!tab->input_active) notcurses_cursor_disable(ui->nc);
}
} else {
switch (input->id) {
case 'i':
- if (!cmc_ui_consider_input(input, false)) {
- return false;
- }
+ CONSIDER_INPUT();
tab->input_active = true;
tab->input_changed = true;
s32 absx = ncplane_abs_x(tab->input);
diff --git a/src/fruits/cmc/ui/ui.c b/src/fruits/cmc/ui/ui.c
index 9931620..bd76e56 100644
--- a/src/fruits/cmc/ui/ui.c
+++ b/src/fruits/cmc/ui/ui.c
@@ -33,21 +33,31 @@ static bool read_input(struct cmc_ui *ui, struct ncinput *input)
return !(ret == (u32)-1 || ret == 0);
}
-static void erase_previous_pane(struct cmc_ui *ui)
+static void erase_previous_pane(struct cmc_ui *ui, u8 previous, u8 upcoming)
{
- switch (ui->pane) {
+ struct ncplane *pn = NULL;
+ switch (previous) {
+ case CMC_PANE_LIST:
+ pn = ui->lp.n;
+ break;
+ case CMC_PANE_SEARCH:
+ pn = ui->sp.n;
+ break;
+ }
+ ncplane_erase(pn);
+ switch (upcoming) {
case CMC_PANE_LIST:
- ncplane_erase(ui->lp.n);
+ ncplane_move_family_below(pn, ui->lp.n);
break;
case CMC_PANE_SEARCH:
- ncplane_erase(ui->sp.n);
+ ncplane_move_family_below(pn, ui->sp.n);
break;
}
}
static void switch_to_pane(struct cmc_ui *ui, u8 pane)
{
- erase_previous_pane(ui);
+ erase_previous_pane(ui, ui->pane, pane);
ui->pane = pane;
}
@@ -68,8 +78,6 @@ void cmc_ui_queue_render(struct cmc_ui *ui)
ncplane_erase(ui->oln);
}
- //notcurses_render(ui->nc);
-
switch (ui->pane) {
case CMC_PANE_LIST:
cmc_lp_render(ui);
@@ -113,13 +121,8 @@ static void input_poll_callback(void *userdata, s32 revents)
(void)revents;
bool do_render;
struct ncinput input;
- for (;;) {
- if (!read_input(ui, &input)) {
- break;
- }
-
+ while (read_input(ui, &input)) {
do_render = false;
-
if (cmc_ui_consider_input(&input, false)) {
switch (input.id) {
case 'q':
@@ -140,7 +143,6 @@ static void input_poll_callback(void *userdata, s32 revents)
break;
}
}
-
switch (ui->pane) {
case CMC_PANE_LIST:
if (cmc_lp_handle_input(ui, &input)) {
@@ -153,7 +155,6 @@ static void input_poll_callback(void *userdata, s32 revents)
}
break;
}
-
if (do_render) {
cmc_ui_queue_render(ui);
notcurses_render(ui->nc);
@@ -173,14 +174,13 @@ static void render_timer_callback(void *userdata, struct nn_timer *timer)
static bool relayout(struct cmc_ui *ui)
{
struct ncplane *stdplane = notcurses_stdplane(ui->nc);
-
notcurses_stddim_yx(ui->nc, &ui->term_rows, &ui->term_cols);
if (ui->n) ncplane_destroy(ui->n);
struct ncplane_options nopts = { 0 };
- nopts.x = 2;
+ nopts.x = 1;
nopts.y = 1;
- nopts.margin_r = 4;
+ nopts.margin_r = 2;
nopts.margin_b = 1;
nopts.flags = NCPLANE_OPTION_MARGINALIZED;
ui->n = ncplane_create(stdplane, &nopts);
@@ -189,13 +189,12 @@ static bool relayout(struct cmc_ui *ui)
cmc_sp_layout(ui, ui->n);
if (ui->oln) ncplane_destroy(ui->oln);
- u32 width = ncplane_dim_x(ui->n);
- u32 height = ncplane_dim_y(ui->n);
- nopts.margin_r = MAX(6u, width / 2);
- nopts.margin_b = MAX(2u, height / 2);
+ nopts.margin_r = MAX((u32)6, ncplane_dim_x(ui->n) / 2);
+ nopts.margin_b = MAX((u32)2, ncplane_dim_y(ui->n) / 2);
nopts.x = nopts.margin_r / 2;
nopts.y = nopts.margin_b / 2;
ui->oln = ncplane_create(ui->n, &nopts);
+ ncplane_move_below(ui->oln, ui->n);
return true;
}
@@ -230,6 +229,10 @@ bool cmc_ui_init(struct cmc_ui *ui, struct nn_event_loop *loop, struct cmc *c)
ui->pane = CMC_PANE_SEARCH;
ui->overlay_shown = false;
+ ui->last_mouse_x = 0;
+ ui->last_mouse_y = 0;
+ ui->last_mouse_ts = (u64)-1;
+
relayout(ui);
struct ncplane *stdplane = notcurses_stdplane(ui->nc);
diff --git a/src/fruits/cmc/ui/ui.h b/src/fruits/cmc/ui/ui.h
index 2f73a81..b0ae730 100644
--- a/src/fruits/cmc/ui/ui.h
+++ b/src/fruits/cmc/ui/ui.h
@@ -14,7 +14,14 @@ enum {
struct cmc_list_tab {
struct cmc_list *list;
- u32 selected;
+ s32 page_length;
+ s32 selected;
+ bool leader_pressed;
+ struct {
+ bool active;
+ s32 selected;
+ s32 offset;
+ } move;
};
struct cmc_search_tab {
@@ -41,6 +48,7 @@ struct cmc_ui {
bool overlay_shown;
u32 last_mouse_x;
u32 last_mouse_y;
+ u64 last_mouse_ts;
struct {
struct ncplane *n;
array(struct cmc_list_tab) tabs;
@@ -56,6 +64,15 @@ struct cmc_ui {
struct cmc *c;
};
+#define CONSIDER_INPUT() \
+ if (!cmc_ui_consider_input(input, false)) return false
+
+#define CONSIDER_INPUT_REPEAT() \
+ if (!cmc_ui_consider_input(input, true)) return false
+
+#define CONSIDER_INPUT_MOD_CTRL() \
+ if (!input->ctrl) return false;
+
void cmc_ui_putnwstr_yx(struct ncplane *n, u32 y, u32 x, u32 width, wstr *w);
void cmc_ui_putnstr_yx(struct ncplane *n, u32 y, u32 x, u32 width, str *s);
bool cmc_ui_consider_input(struct ncinput *input, bool repeat);
diff --git a/src/fruits/cmc/ui/waveform.h b/src/fruits/cmc/ui/waveform.h
new file mode 100644
index 0000000..f3803dd
--- /dev/null
+++ b/src/fruits/cmc/ui/waveform.h
@@ -0,0 +1,104 @@
+/*
+
+notcurses.h:
+Halves
+
+▄ ▀
+
+Quadrants
+
+▗ ▐ ▖ ▀ ▟ ▌ ▙
+
+Sextants
+
+🬀 🬁 🬂 🬃 🬄 🬅 🬆 🬇 🬈 🬉 🬊 🬋 🬌 🬍 🬎 🬏 🬐 🬑 🬒 🬓 🬔 🬕 🬖 🬗 🬘 🬙 🬚 🬛 🬜 🬝 🬞
+
+https://wiki.ourworldoftext.com/wiki/Octant:
+Octants
+
+ 𜺨 𜺫 🮂 𜴀 ▘ 𜴁 𜴂 𜴃 𜴄 ▝ 𜴅 𜴆 𜴇 𜴈 ▀
+
+𜴉 𜴊 𜴋 𜴌 🯦 𜴍 𜴎 𜴏 𜴐 𜴑 𜴒 𜴓 𜴔 𜴕 𜴖 𜴗
+
+𜴘 𜴙 𜴚 𜴛 𜴜 𜴝 𜴞 𜴟 🯧 𜴠 𜴡 𜴢 𜴣 𜴤 𜴥 𜴦
+
+𜴧 𜴨 𜴩 𜴪 𜴫 𜴬 𜴭 𜴮 𜴯 𜴰 𜴱 𜴲 𜴳 𜴴 𜴵 🮅
+
+𜺣 𜴶 𜴷 𜴸 𜴹 𜴺 𜴻 𜴼 𜴽 𜴾 𜴿 𜵀 𜵁 𜵂 𜵃 𜵄
+
+▖ 𜵅 𜵆 𜵇 𜵈 ▌ 𜵉 𜵊 𜵋 𜵌 ▞ 𜵍 𜵎 𜵏 𜵐 ▛
+
+𜵑 𜵒 𜵓 𜵔 𜵕 𜵖 𜵗 𜵘 𜵙 𜵚 𜵛 𜵜 𜵝 𜵞 𜵟 𜵠
+
+𜵡 𜵢 𜵣 𜵤 𜵥 𜵦 𜵧 𜵨 𜵩 𜵪 𜵫 𜵬 𜵭 𜵮 𜵯 𜵰
+
+𜺠 𜵱 𜵲 𜵳 𜵴 𜵵 𜵶 𜵷 𜵸 𜵹 𜵺 𜵻 𜵼 𜵽 𜵾 𜵿
+
+𜶀 𜶁 𜶂 𜶃 𜶄 𜶅 𜶆 𜶇 𜶈 𜶉 𜶊 𜶋 𜶌 𜶍 𜶎 𜶏
+
+▗ 𜶐 𜶑 𜶒 𜶓 ▚ 𜶔 𜶕 𜶖 𜶗 ▐ 𜶘 𜶙 𜶚 𜶛 ▜
+
+𜶜 𜶝 𜶞 𜶟 𜶠 𜶡 𜶢 𜶣 𜶤 𜶥 𜶦 𜶧 𜶨 𜶩 𜶪 𜶫
+
+▂ 𜶬 𜶭 𜶮 𜶯 𜶰 𜶱 𜶲 𜶳 𜶴 𜶵 𜶶 𜶷 𜶸 𜶹 𜶺
+
+𜶻 𜶼 𜶽 𜶾 𜶿 𜷀 𜷁 𜷂 𜷃 𜷄 𜷅 𜷆 𜷇 𜷈 𜷉 𜷊
+
+𜷋 𜷌 𜷍 𜷎 𜷏 𜷐 𜷑 𜷒 𜷓 𜷔 𜷕 𜷖 𜷗 𜷘 𜷙 𜷚
+
+▄ 𜷛 𜷜 𜷝 𜷞 ▙ 𜷟 𜷠 𜷡 𜷢 ▟ 𜷣 ▆ 𜷤 𜷥 █
+
+AAAAAAAAAAAAAAAA
+
+▁ ▂ 𜶻 𜷋 ▃ ▄ 𜷞 𜷡 ▅ ▆ 𜷤 𜷥 ▇ █
+
+ ▐█
+ 𜷕█
+
+ ▌
+ ▌
+ ▌
+ 𜷀
+
+▂𜴧𜴐
+
+
+ ▁▂𜷋▃▄𜷡▅▆𜷥▇████▇𜷥▆▅𜷡▄▃𜷋▂▁
+▁▂𜷋▃▄𜷡▅▆𜷥▇████████████████████████████▇𜷥▆▅𜷡▄▃𜷋▂▁
+
+
+█▇𜷤▆▅𜷞▄▃𜶻▂▁
+
+▌𜵈▐𜷀
+▁▃▂▁▄
+
+0
+1 𜺨
+1 << 1 𜺫
+1 << 2 𜴀
+1 << 3 𜴃
+1 << 4 𜴉
+1 << 5 𜴘
+1 << 6 𜺣
+1 << 7 𜺠
+
+𜴢 0b00101011
+
+*/
+
+static char *bar_lut[] = {
+ [0] = " 𜺠▗𜶖▐" ,
+ [1] = "𜺣▂𜷋𜷓𜷕",
+ [2] = "▖𜶻▄𜷡𜷥",
+ [3] = "𜵈𜶿𜷞▆𜷥",
+ [4] = "▌𜷀▙𜷤█"
+};
+
+static char *bar_bottom_lut[] = {
+ [0] = " 𜺫▝𜴡▐" ,
+ [1] = "𜺨🮂𜴅𜴢𜶘",
+ [2] = "▘𜴂▀𜴦▜",
+ [3] = "𜴍𜴏𜴗🮅𜶫",
+ [4] = "▌𜵊▛𜵰█"
+};
+
diff --git a/src/fruits/cmv/cmv.c b/src/fruits/cmv/cmv.c
index 274319a..834e95a 100644
--- a/src/fruits/cmv/cmv.c
+++ b/src/fruits/cmv/cmv.c
@@ -176,7 +176,7 @@ s32 window_system_main(u32 argc, str *argv, void *extra)
c.desktop.userdata = &c;
}
#endif
- if (!camu_desktop_connect(&c.desktop, type, &c.loop, &addr, CAMU_PORT)) {
+ if (!camu_desktop_connect(&c.desktop, &c.loop, type, &addr, CAMU_PORT)) {
return EXIT_FAILURE;
}
diff --git a/src/fruits/ctv/ctv.c b/src/fruits/ctv/ctv.c
index d8094c3..55ab773 100644
--- a/src/fruits/ctv/ctv.c
+++ b/src/fruits/ctv/ctv.c
@@ -26,7 +26,7 @@ static nn_thread_result NNWT_THREADCALL event_loop_thread(void *userdata)
prefs->audio_lang = CAMU_LANG_ENGLISH;
prefs->subtitle_lang = CAMU_LANG_ENGLISH;
- if (!camu_desktop_connect(&c->desktop, NNWT_SOCKET_TCP, &c->loop, &CAMU_TEST_ADDR, CAMU_PORT)) {
+ if (!camu_desktop_connect(&c->desktop, &c->loop, NNWT_SOCKET_TCP, &CAMU_TEST_ADDR, CAMU_PORT)) {
return 0;
}
diff --git a/src/liana/list.c b/src/liana/list.c
index d5eef48..7d3d722 100644
--- a/src/liana/list.c
+++ b/src/liana/list.c
@@ -27,6 +27,7 @@ enum {
static inline u32 get_incremental_id(struct lia_list *list)
{
list->increment = al_u32_inc_wrap(list->increment);
+ al_assert(list->increment > 0); // Wrapping not currently handled.
return list->increment;
}
@@ -254,7 +255,7 @@ static bool handle_skipto(struct lia_list *list, s32 sequence, s32 index)
if (sequence == LIANA_SEQUENCE_ANY) sequence = list->current;
if (sequence < 0) return true; // list->current = -1
if (sequence != list->current) {
- warn("Discarding out of date skip().");
+ log_warn("Discarding out of date skip().");
return true;
}
@@ -319,7 +320,7 @@ static bool handle_skipto(struct lia_list *list, s32 sequence, s32 index)
current->held = true;
}
- trace("skipto(#%u-#%u): pause: %hhu, held: %s.", current->id, target->id, pause, BOOLSTR(current->held));
+ log_trace("skipto(#%u-#%u): pause: %hhu, held: %s.", current->id, target->id, pause, BOOLSTR(current->held));
struct lia_timing time = {
.at = at,
@@ -345,7 +346,7 @@ static void handle_toggle_pause(struct lia_list *list, s32 sequence, f64 pts)
if (sequence == LIANA_SEQUENCE_ANY) sequence = list->current;
if (sequence < 0) return; // list->current = -1
if (sequence != list->current) {
- warn("Discarding out of date toggle_pause().");
+ log_warn("Discarding out of date toggle_pause().");
return;
}
@@ -376,7 +377,7 @@ static void handle_toggle_pause(struct lia_list *list, s32 sequence, f64 pts)
break;
}
- trace("toggle_pause(#%u): pts: %f, pause: %hhu.", entry->id, pts, pause);
+ log_trace("toggle_pause(#%u): pts: %f, pause: %hhu.", entry->id, pts, pause);
struct lia_timing time = {
.at = at,
@@ -404,7 +405,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) {
- warn("Skipping seek on entry with no duration.");
+ log_warn("Skipping seek on entry with no duration.");
return;
}
@@ -422,7 +423,7 @@ static void handle_seek(struct lia_list *list, s32 sequence, u32 id, u64 pos)
list->idle = false;
- trace("seek(#%u): pos: %f, pause: %hhu.", entry->id, pos / 1000000.0, pause);
+ log_trace("seek(#%u): pos: %f, pause: %hhu.", entry->id, pos / 1000000.0, pause);
struct lia_timing time = {
.at = at,
@@ -449,16 +450,16 @@ static bool handle_end(struct lia_list *list, u32 id, u32 reset_id)
struct lia_list_entry *entry = get_entry_from_sequence(list, sequence);
if (reset_id != entry->reset_id) {
- warn("Got end() with out of order or incorrect reset id, ignoring.");
+ log_warn("Got end() with out of order or incorrect reset id, ignoring.");
return true;
}
if (entry->ended) {
- warn("Got end() from an already ended resource, ignoring.");
+ log_warn("Got end() from an already ended resource, ignoring.");
return true;
}
- trace("end(#%u).", entry->id);
+ log_trace("end(#%u).", entry->id);
entry->ended = true;
entry->offset = entry->duration;
@@ -518,6 +519,7 @@ static bool adjust_current(struct lia_list *list, struct lia_list_entry *previou
}
}
al_assert(entry && cmd->op == SKIPTO);
+ signal_meta(list, previous, LIANA_META_ORDER_CHANGED);
return handle_skipto(list, cmd->sequence, cmd->arg0.i);
}
diff --git a/src/liana/list.h b/src/liana/list.h
index 70873ff..86a9712 100644
--- a/src/liana/list.h
+++ b/src/liana/list.h
@@ -7,7 +7,7 @@
#define LIANA_SEQUENCE_ANY -1
#define LIANA_TIMESTAMP_INVALID ((u64)-1)
-#define LIANA_BASE_DELAY 500000u // 500ms
+#define LIANA_BASE_DELAY 600000u // 600ms
#define LIANA_BASE_PING 125000u // 125ms
#define LIANA_PAUSE_DELAY LIANA_BASE_PING
#define LIANA_DELAY_IGNORE 0u
@@ -49,13 +49,13 @@ enum {
};
enum {
- LIANA_META_CURRENT_CHANGED = 0,
- LIANA_META_ADDED_ENTRY,
+ LIANA_META_ADDED_ENTRY = 0,
LIANA_META_REMOVED_ENTRY,
+ LIANA_META_CURRENT_CHANGED,
+ LIANA_META_ORDER_CHANGED,
LIANA_META_ENTRY_PAUSED,
LIANA_META_ENTRY_SEEKED,
- LIANA_META_ENTRY_ERRORED,
- LIANA_META_ORDER_CHANGED
+ LIANA_META_ENTRY_ERRORED
};
enum {
diff --git a/src/libclient/client.c b/src/libclient/client.c
index 525b26e..7350df2 100644
--- a/src/libclient/client.c
+++ b/src/libclient/client.c
@@ -73,8 +73,8 @@ static void connection_closed_callback(void *userdata, struct nn_rpc_connection
client->conn = NULL;
}
-bool camu_client_login(struct camu_client *client, struct nn_event_loop *loop,
- u8 type, str *addr, u16 port, str *username)
+bool camu_client_login(struct camu_client *client, str *username,
+ struct nn_event_loop *loop, u8 type, str *addr, u16 port)
{
client->loop = loop;
al_str_clone(&client->username, username);
@@ -145,14 +145,14 @@ void camu_client_skipto(struct camu_client *client, str *list, s32 i)
nn_rpc_connection_command(client->conn, packet, NULL, NULL);
}
-void camu_client_seek(struct camu_client *client, str *list, u32 id, f64 percent)
+void camu_client_seek(struct camu_client *client, str *list, u32 id, u64 pos)
{
struct nn_packet *packet = nn_rpc_get_packet(&client->client, CAMU_SERVER_LIST_ACTION);
nn_packet_write_str(packet, list);
nn_packet_write_u8(packet, CAMU_LIST_SEEK);
nn_packet_write_s32(packet, LIANA_SEQUENCE_ANY);
nn_packet_write_u32(packet, id);
- nn_packet_write_f64(packet, percent);
+ nn_packet_write_u64(packet, pos);
nn_rpc_connection_command(client->conn, packet, NULL, NULL);
}
diff --git a/src/libclient/client.h b/src/libclient/client.h
index e6e80c8..892bf0d 100644
--- a/src/libclient/client.h
+++ b/src/libclient/client.h
@@ -18,8 +18,8 @@ struct camu_client {
void *userdata;
};
-bool camu_client_login(struct camu_client *client, struct nn_event_loop *loop,
- u8 type, str *addr, u16 port, str *username);
+bool camu_client_login(struct camu_client *client, str *username,
+ struct nn_event_loop *loop, u8 type, str *addr, u16 port);
void camu_client_create_list(struct camu_client *client, str *name,
void (*callback)(void *, struct nn_rpc_connection *conn, struct nn_packet *), void *userdata);
@@ -30,6 +30,6 @@ void camu_client_create_search(struct camu_client *client, str *module, str *que
void camu_client_get_page(struct camu_client *client, s32 id, u32 num);
void camu_client_skipto(struct camu_client *client, str *list, s32 i);
-void camu_client_seek(struct camu_client *client, str *list, u32 id, f64 percent);
+void camu_client_seek(struct camu_client *client, str *list, u32 id, u64 pos);
void camu_client_disconnect(struct camu_client *client);
diff --git a/src/portal/cpy/portal.pyx b/src/portal/cpy/portal.pyx
index d6909f3..22d2ef9 100644
--- a/src/portal/cpy/portal.pyx
+++ b/src/portal/cpy/portal.pyx
@@ -6,16 +6,16 @@ cimport bridge
import sys
sys.path.append('./py')
-cdef public int log_info(char *message) except -1:
+cdef int log_info(char *message) except -1:
return lib.al_log_info("portal", "%s", message)
-cdef public int log_warn(char *message) except -1:
+cdef int log_warn(char *message) except -1:
return lib.al_log_warn("portal", "%s", message)
-cdef public int log_error(char *message) except -1:
+cdef int log_error(char *message) except -1:
return lib.al_log_error("portal", "%s", message)
-cdef public int log_debug(char *message) except -1:
+cdef int log_debug(char *message) except -1:
return lib.al_log_debug("portal", "%s", message)
def encode_str(str):
@@ -121,15 +121,15 @@ cdef public int portal_bridge_search(str.str *module, str.str *query) except -1:
lib.al_free(c_str1)
return ret
-cdef public int py_str_to_str(str.str *s, char *py_c_str) except -1:
+cdef int py_str_to_str(str.str *s, char *py_c_str) except -1:
str.al_str_from(s, py_c_str)
return 0
-cdef public int py_str_to_wstr(str.wstr *w, char *py_c_str) except -1:
+cdef int py_str_to_wstr(str.wstr *w, char *py_c_str) except -1:
str.al_wstr_from_cstr(w, py_c_str)
return 0
-cdef public int add_post_internal(bridge.camu_search *search, int id, unsigned int num, char *py_unique_id) except -1:
+cdef int add_post_internal(bridge.camu_search *search, int id, unsigned int num, char *py_unique_id) except -1:
cdef post.camu_post cpost
cdef str.str key
cdef str.str url
diff --git a/src/server/server.c b/src/server/server.c
index d7ff702..467067a 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -23,23 +23,12 @@ static struct camu_user *get_user_by_username(struct camu_server *server, str *u
{
struct camu_user *user;
al_array_foreach(server->users, i, user) {
- if (al_str_eq(&user->name, username)) {
- return user;
- }
- }
- return NULL;
-}
-
-static struct camu_server_client *get_client_by_connection(struct camu_server *server, struct nn_rpc_connection *conn)
-{
- struct camu_server_client *client;
- al_array_foreach(server->clients, i, client) {
- if (client->conn == conn) return client;
+ if (al_str_eq(&user->name, username)) return user;
}
return NULL;
}
-static struct lia_list *get_list_from_name(struct camu_server *server, str *name)
+static struct lia_list *get_list_by_name(struct camu_server *server, str *name)
{
struct lia_list *list;
al_array_foreach(server->lists, i, list) {
@@ -48,7 +37,7 @@ static struct lia_list *get_list_from_name(struct camu_server *server, str *name
return NULL;
}
-static struct camu_server_sink *get_sink_from_name(struct camu_server *server, str *name)
+static struct camu_server_sink *get_sink_by_name(struct camu_server *server, str *name)
{
struct camu_server_sink *sink;
al_array_foreach(server->sinks, i, sink) {
@@ -57,6 +46,15 @@ static struct camu_server_sink *get_sink_from_name(struct camu_server *server, s
return NULL;
}
+static struct camu_server_client *get_client_by_connection(struct camu_server *server, struct nn_rpc_connection *conn)
+{
+ struct camu_server_client *client;
+ al_array_foreach(server->clients, i, client) {
+ if (client->conn == conn) return client;
+ }
+ return NULL;
+}
+
static void write_list_entry(struct lia_list_entry *entry, struct nn_packet *packet)
{
nn_packet_write_u32(packet, entry->id);
@@ -107,7 +105,7 @@ static bool identify_callback(void *userdata, struct nn_rpc_connection *conn,
struct camu_server_node *node = al_alloc_object(struct camu_server_node);
node->conn = conn;
al_array_push(server->nodes, node);
- info("New node.");
+ log_info("New node.");
break;
}
case CAMU_CLIENT: {
@@ -123,7 +121,7 @@ static bool identify_callback(void *userdata, struct nn_rpc_connection *conn,
}
client->user = user;
al_array_push(server->clients, client);
- info("User \"%.*s\" logged in.", al_str_x(&user->name));
+ log_info("User \"%.*s\" logged in.", al_str_x(&user->name));
write_initial_user_state(server, user, rpacket);
break;
}
@@ -136,7 +134,7 @@ static bool identify_callback(void *userdata, struct nn_rpc_connection *conn,
sink->server = server;
al_array_push(server->sinks, sink);
handle_toggle_sink(server, &al_str_c("default"), sink, true);
- info("New sink.");
+ log_info("New sink.");
break;
}
}
@@ -201,7 +199,7 @@ static void list_sink_callback(void *userdata, u8 op, struct lia_list_entry *ent
void handle_toggle_sink(struct camu_server *server, str *name, struct camu_server_sink *sink, bool enable)
{
- struct lia_list *list = get_list_from_name(server, name);
+ struct lia_list *list = get_list_by_name(server, name);
if (!list) return;
if (enable) lia_list_add_sink(list, list_sink_callback, sink);
else lia_list_remove_sink(list, sink);
@@ -236,6 +234,18 @@ static void node_callback(void *userdata, u8 op, u64 duration)
process_pending(resource);
}
+static void send_clients_added_entry(struct camu_server *server, struct lia_list *list, struct lia_list_entry *entry)
+{
+ 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_META);
+ nn_packet_write_u8(packet, LIANA_META_ADDED_ENTRY);
+ nn_packet_write_str(packet, &list->name);
+ write_list_entry(entry, packet);
+ nn_rpc_connection_command(client->conn, packet, NULL, NULL);
+ }
+}
+
static void send_clients_current_changed(struct camu_server *server, struct lia_list *list, struct lia_list_entry *entry)
{
struct camu_server_client *client;
@@ -249,14 +259,18 @@ static void send_clients_current_changed(struct camu_server *server, struct lia_
}
}
-static void send_clients_added_entry(struct camu_server *server, struct lia_list *list, struct lia_list_entry *entry)
+static void send_clients_order_changed(struct camu_server *server, struct lia_list *list)
{
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_META);
- nn_packet_write_u8(packet, LIANA_META_ADDED_ENTRY);
+ nn_packet_write_u8(packet, LIANA_META_ORDER_CHANGED);
nn_packet_write_str(packet, &list->name);
- write_list_entry(entry, packet);
+ nn_packet_write_u32(packet, list->entries.count);
+ struct lia_list_entry *entry;
+ al_array_foreach(list->entries, i, entry) {
+ nn_packet_write_u32(packet, entry->id);
+ }
nn_rpc_connection_command(client->conn, packet, NULL, NULL);
}
}
@@ -284,7 +298,7 @@ static struct cch_entry *entry_from_post(struct camu_server *server, struct camu
}
}
if (!entry) {
- error("Failed to load post media %.*s %u.", al_str_x(&post->unique_id), index);
+ log_error("Failed to load post media %.*s %u.", al_str_x(&post->unique_id), index);
return NULL;
}
entry->handler->maybe_spawn_worker(entry->handler, 0);
@@ -408,25 +422,27 @@ static void list_callback(void *userdata, u8 op, struct lia_list_entry *entry, v
if (server->meta_callback) {
server->meta_callback(server->userdata, *(u8 *)opaque, entry);
}
+ struct lia_list *list = entry->list;
switch (*(u8 *)opaque) {
- case LIANA_META_CURRENT_CHANGED:
- info("Now playing: %ls.", entry->name.data);
- send_clients_current_changed(server, entry->list, entry);
- break;
case LIANA_META_ADDED_ENTRY:
- send_clients_added_entry(server, entry->list, entry);
+ send_clients_added_entry(server, list, entry);
break;
case LIANA_META_REMOVED_ENTRY:
break;
+ case LIANA_META_CURRENT_CHANGED:
+ log_info("Now playing: %ls.", entry->name.data);
+ send_clients_current_changed(server, list, entry);
+ break;
+ case LIANA_META_ORDER_CHANGED:
+ send_clients_order_changed(server, list);
+ break;
case LIANA_META_ENTRY_PAUSED:
break;
case LIANA_META_ENTRY_SEEKED:
- send_clients_entry_seeked(server, entry->list, entry);
+ send_clients_entry_seeked(server, list, entry);
break;
case LIANA_META_ENTRY_ERRORED:
- error("Failed to load: %ls.", entry->name.data);
- break;
- case LIANA_META_ORDER_CHANGED:
+ log_error("Failed to load: %ls.", entry->name.data);
break;
}
break;
@@ -502,7 +518,7 @@ static bool client_command_callback(void *userdata, struct nn_rpc_connection *co
case CAMU_CLIENT_TOGGLE_SINK: {
str name;
nn_packet_read_str(packet, &name);
- struct camu_server_sink *sink = get_sink_from_name(server, &name);
+ struct camu_server_sink *sink = get_sink_by_name(server, &name);
if (!sink) goto out;
nn_packet_read_str(packet, &name); // list name.
bool enable = nn_packet_read_bool(packet);
@@ -557,7 +573,7 @@ static void simple_search_portal_callback(void *userdata0, void *userdata1, stru
return;
}
// No return is the error case.
- warn("Failed to process simple search request.");
+ log_warn("Failed to process simple search request.");
resource->load = LIANA_ENTRY_ERRORED;
}
#endif
@@ -656,7 +672,7 @@ static bool list_action_callback(void *userdata, struct nn_rpc_connection *conn,
str name;
nn_packet_read_str(packet, &name);
- struct lia_list *list = get_list_from_name(server, &name);
+ struct lia_list *list = get_list_by_name(server, &name);
if (!list) goto out;
u8 op = nn_packet_read_u8(packet);
@@ -748,7 +764,7 @@ static void connection_closed_callback(void *userdata, struct nn_rpc_connection
struct camu_server_node *node;
al_array_foreach(server->nodes, i, node) {
if (node->conn == conn) {
- info("Node removed.");
+ log_info("Node removed.");
cleanup_node(node);
al_array_remove_at(server->nodes, i);
break;
@@ -758,7 +774,7 @@ static void connection_closed_callback(void *userdata, struct nn_rpc_connection
struct camu_server_client *client;
al_array_foreach(server->clients, i, client) {
if (client->conn == conn) {
- info("User \"%.*s\" logged out.", al_str_x(&client->user->name));
+ log_info("User \"%.*s\" logged out.", al_str_x(&client->user->name));
cleanup_client(client);
al_array_remove_at(server->clients, i);
break;
@@ -768,7 +784,7 @@ static void connection_closed_callback(void *userdata, struct nn_rpc_connection
struct camu_server_sink *sink;
al_array_foreach(server->sinks, i, sink) {
if (sink->conn == conn) {
- info("Sink removed.");
+ log_info("Sink removed.");
struct lia_list *list;
al_array_foreach(server->lists, j, list) {
lia_list_remove_sink(list, sink);
diff --git a/src/sink/desktop.c b/src/sink/desktop.c
index 7803982..fa8d623 100644
--- a/src/sink/desktop.c
+++ b/src/sink/desktop.c
@@ -234,7 +234,7 @@ bool camu_desktop_init(struct camu_desktop *c, const char *name)
return true;
}
-bool camu_desktop_connect(struct camu_desktop *c, u8 type, struct nn_event_loop *loop, str *addr, u16 port)
+bool camu_desktop_connect(struct camu_desktop *c, struct nn_event_loop *loop, u8 type, str *addr, u16 port)
{
c->loop = loop;
camu_sink_init(&c->sink, c->loop, &c->mixer, c->renderer);
diff --git a/src/sink/desktop.h b/src/sink/desktop.h
index 2b3ec94..65fcfe0 100644
--- a/src/sink/desktop.h
+++ b/src/sink/desktop.h
@@ -20,7 +20,7 @@ struct camu_desktop {
};
bool camu_desktop_init(struct camu_desktop *c, const char *name);
-bool camu_desktop_connect(struct camu_desktop *c, u8 type, struct nn_event_loop *loop, str *addr, u16 port);
+bool camu_desktop_connect(struct camu_desktop *c, struct nn_event_loop *loop, u8 type, str *addr, u16 port);
bool camu_desktop_tick(struct camu_desktop *c);
void camu_desktop_stop(struct camu_desktop *c);
void camu_desktop_free(struct camu_desktop *c);