From 0c65af91d9349db552495acd5ecca102d9e325d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Wed, 12 Oct 2016 23:42:57 +0200 Subject: First round of Library tab cleanups --- nncmpp.c | 171 ++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 88 insertions(+), 83 deletions(-) diff --git a/nncmpp.c b/nncmpp.c index 659323f..b9d8a4d 100644 --- a/nncmpp.c +++ b/nncmpp.c @@ -147,6 +147,13 @@ xstrtoul_map (const struct str_map *map, const char *key, unsigned long *out) return field && xstrtoul (out, field, 10); } +static const char * +xbasename (const char *path) +{ + const char *last_slash = strrchr (path, '/'); + return last_slash ? last_slash + 1 : path; +} + static char * latin1_to_utf8 (const char *latin1) { @@ -2010,6 +2017,14 @@ current_tab_init (void) // --- Library tab ------------------------------------------------------------- +static struct +{ + struct tab super; ///< Parent class + struct str path; ///< Current path + struct str_vector items; ///< Current items (type, name, path) +} +g_library_tab; + enum { // This list is also ordered by ASCII and important for sorting @@ -2020,13 +2035,31 @@ enum LIBRARY_FILE = 'f' ///< File }; -static struct +struct library_tab_item { - struct tab super; ///< Parent class - struct str path; ///< Current path - struct str_vector items; ///< Current items (type, name, path) + int type; ///< Type of the item + const char *name; ///< Visible name + const char *path; ///< MPD path +}; + +static void +library_tab_add (int type, const char *name, const char *path) +{ + str_vector_add_owned (&g_library_tab.items, + xstrdup_printf ("%c%s%c%s", type, name, 0, path)); +} + +static struct library_tab_item +library_tab_resolve (const char *raw) +{ + struct library_tab_item item; + item.type = *raw++; + item.name = raw; + item.path = strchr (raw, '\0') + 1; + return item; } -g_library_tab; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static void library_tab_on_item_draw (size_t item_index, struct row_buffer *buffer, @@ -2035,63 +2068,49 @@ library_tab_on_item_draw (size_t item_index, struct row_buffer *buffer, (void) width; hard_assert (item_index < g_library_tab.items.len); - const char *item = g_library_tab.items.vector[item_index]; - char type = *item++; - - switch (type) + struct library_tab_item x = + library_tab_resolve (g_library_tab.items.vector[item_index]); + switch (x.type) { case LIBRARY_ROOT: row_buffer_append (buffer, "/", 0); break; case LIBRARY_UP: row_buffer_append (buffer, "/..", 0); break; - case LIBRARY_DIR: row_buffer_addv (buffer, "/", 0, item, 0, NULL); break; - case LIBRARY_FILE: row_buffer_addv (buffer, " ", 0, item, 0, NULL); break; + case LIBRARY_DIR: row_buffer_addv (buffer, "/", 0, x.name, 0, NULL); break; + case LIBRARY_FILE: row_buffer_addv (buffer, " ", 0, x.name, 0, NULL); break; default: hard_assert (!"invalid item type"); } } -static void -library_tab_add (int type, const char *name, const char *path) -{ - str_vector_add_owned (&g_library_tab.items, - xstrdup_printf ("%c%s%c%s", type, name, 0, path)); -} - static void library_tab_chunk (struct str_map *map) { - if (!map->len) - return; - - const char *artist = str_map_find (map, "artist"); - const char *title = str_map_find (map, "title"); - char *name = (artist && title) - ? xstrdup_printf ("%s - %s", artist, title) - : NULL; - char *id, type; if ((id = str_map_find (map, "directory"))) type = LIBRARY_DIR; else if ((id = str_map_find (map, "file"))) type = LIBRARY_FILE; + else + return; - const char *last_slash = strrchr (id, '/'); - const char *base = last_slash ? last_slash + 1 : id; - library_tab_add (type, name ? name : base, id); + const char *artist = str_map_find (map, "artist"); + const char *title = str_map_find (map, "title"); + char *name = (artist && title) + ? xstrdup_printf ("%s - %s", artist, title) + : xstrdup (xbasename (id)); + library_tab_add (type, name, id); free (name); } static int library_tab_compare (char **a, char **b) { - char *item_a = *a; char type_a = *item_a++; - char *item_b = *b; char type_b = *item_b++; - char *path_a = strchr (item_a, '\0') + 1; - char *path_b = strchr (item_b, '\0') + 1; + struct library_tab_item xa = library_tab_resolve (*a); + struct library_tab_item xb = library_tab_resolve (*b); - if (type_a != type_b) - return type_a - type_b; + if (xa.type != xb.type) + return xa.type - xb.type; // TODO: this should be case insensitive - return u8_strcmp ((uint8_t *) path_a, (uint8_t *) path_b); + return u8_strcmp ((uint8_t *) xa.path, (uint8_t *) xb.path); } static void @@ -2103,10 +2122,21 @@ library_tab_on_data (const struct mpd_response *response, return; str_vector_reset (&g_library_tab.items); - if (g_library_tab.path.len) + + struct str *path = &g_library_tab.path; + if (path->len) { library_tab_add (LIBRARY_ROOT, "", ""); - library_tab_add (LIBRARY_UP, "", ""); + + char *last_slash; + if ((last_slash = strrchr (path->str, '/'))) + { + char *up = xstrndup (path->str, last_slash - path->str); + library_tab_add (LIBRARY_UP, "", up); + free (up); + } + else + library_tab_add (LIBRARY_UP, "", ""); } struct str_map map; @@ -2144,27 +2174,19 @@ library_tab_on_data (const struct mpd_response *response, app_invalidate (); } -static const char * -library_tab_path (void) -{ - struct str *path = &g_library_tab.path; - return path->len ? path->str : "/"; -} - static void library_tab_reload (const char *new_path) { // TODO: actually we should update the path _after_ we receive data + struct str *path = &g_library_tab.path; if (new_path) { - struct str *path = &g_library_tab.path; str_reset (path); str_append (path, new_path); } struct mpd_client *c = &g_ctx.client; - mpd_client_send_command (c, "lsinfo", library_tab_path (), NULL); - + mpd_client_send_command (c, "lsinfo", path->len ? path->str : "/", NULL); mpd_client_add_task (c, library_tab_on_data, NULL); mpd_client_idle (c, 0); } @@ -2180,51 +2202,34 @@ library_tab_on_action (enum action action) if (c->state != MPD_CONNECTED) return false; - char *item = g_library_tab.items.vector[self->item_selected]; - char type = *item++; - const char *item_path = strchr (item, '\0') + 1; - + struct library_tab_item x = + library_tab_resolve (g_library_tab.items.vector[self->item_selected]); switch (action) { case ACTION_CHOOSE: - switch (type) + switch (x.type) { - case LIBRARY_ROOT: library_tab_reload (""); break; + case LIBRARY_ROOT: case LIBRARY_UP: - { - struct str *path = &g_library_tab.path; - char *last_slash = strrchr (path->str, '/'); - if (last_slash) - { - char *new_path = xstrndup (path->str, last_slash - path->str); - library_tab_reload (new_path); - free (new_path); - } - else - library_tab_reload (""); - break; - } - case LIBRARY_DIR: library_tab_reload (item_path); break; - case LIBRARY_FILE: MPD_SIMPLE ("add", item_path) break; + case LIBRARY_DIR: library_tab_reload (x.path); break; + case LIBRARY_FILE: MPD_SIMPLE ("add", x.path) break; default: hard_assert (!"invalid item type"); } return true; case ACTION_MPD_REPLACE: // FIXME: we also need to play it if we've been playing things already - if (type == LIBRARY_DIR || type == LIBRARY_FILE) - { - MPD_SIMPLE ("clear"); - MPD_SIMPLE ("add", item_path) - return true; - } - return false; + if (x.type != LIBRARY_DIR && x.type != LIBRARY_FILE) + break; + + MPD_SIMPLE ("clear"); + MPD_SIMPLE ("add", x.path) + return true; case ACTION_MPD_ADD: - if (type == LIBRARY_DIR || type == LIBRARY_FILE) - { - MPD_SIMPLE ("add", item_path) - return true; - } - break; + if (x.type != LIBRARY_DIR && x.type != LIBRARY_FILE) + break; + + MPD_SIMPLE ("add", x.path) + return true; default: break; } -- cgit v1.2.3