commit bb0f1e2ea23bb278f02c2a4ff19e5c6fa6946b92
parent a1e28b9eb1c89a37d24ad50feb203f99504274b2
Author: Louis Burda <quent.burda@gmail.com>
Date: Mon, 21 Feb 2022 17:17:08 +0100
Bug fixes, added select track shortcut and reindex command
Diffstat:
9 files changed, 181 insertions(+), 89 deletions(-)
diff --git a/src/cmd.c b/src/cmd.c
@@ -4,6 +4,7 @@
#include "list.h"
#include "player.h"
#include "ref.h"
+#include "tag.h"
#include "track.h"
#include "tui.h"
#include "util.h"
@@ -11,24 +12,25 @@
#include <stdbool.h>
#define CMD_ERROR(...) do { \
- free(cmd_status); \
- cmd_status = awprintf(__VA_ARGS__); \
+ CMD_SET_STATUS(__VA_ARGS__); \
return false; \
} while (0)
static bool cmd_save(const wchar_t *args);
static bool cmd_move(const wchar_t *args);
static bool cmd_add(const wchar_t *args);
+static bool cmd_reindex(const wchar_t *args);
const struct cmd commands[] = {
{ L"save", cmd_save },
{ L"move", cmd_move },
{ L"add", cmd_add },
+ { L"reindex", cmd_reindex },
};
const size_t command_count = ARRLEN(commands);
-wchar_t *cmd_status;
+char *cmd_status;
void
cmd_init(void)
@@ -36,6 +38,12 @@ cmd_init(void)
cmd_status = NULL;
}
+void
+cmd_deinit(void)
+{
+ free(cmd_status);
+}
+
bool
cmd_save(const wchar_t *args)
{
@@ -52,10 +60,10 @@ cmd_move(const wchar_t *name)
char *newpath;
tag = tag_find(name);
- if (!tag) CMD_ERROR(L"Tag not found");
+ if (!tag) CMD_ERROR("Tag not found");
link = list_at(tracks_vis, track_nav.sel);
- if (!link) CMD_ERROR(L"No track selected");
+ if (!link) CMD_ERROR("No track selected");
track = UPCAST(link, struct ref)->data;
newpath = aprintf("%s/%s", tag->fpath, track->fname);
@@ -99,3 +107,44 @@ cmd_add(const wchar_t *name)
return 1;
}
+
+bool
+cmd_reindex(const wchar_t *name)
+{
+ struct link *link;
+ struct tag *tag;
+ struct list matches;
+
+ list_init(&matches);
+
+ if (!*name) {
+ link = list_at(&tags, tag_nav.sel);
+ tag = UPCAST(link, struct tag);
+ if (tag == NULL) return false;
+ list_push_back(&matches, LINK(ref_init(tag)));
+ } else if (!wcscmp(name, L"*")) {
+ for (LIST_ITER(&tags, link)) {
+ tag = UPCAST(link, struct tag);
+ list_push_back(&matches, LINK(ref_init(tag)));
+ }
+ } else {
+ for (LIST_ITER(&tags, link)) {
+ tag = UPCAST(link, struct tag);
+ if (!wcscmp(tag->name, name)) {
+ list_push_back(&matches, LINK(ref_init(tag)));
+ break;
+ }
+ }
+ }
+
+ if (list_empty(&matches)) return false;
+
+ for (LIST_ITER(&matches, link)) {
+ tag = UPCAST(link, struct ref)->data;
+ index_update(tag);
+ }
+
+ refs_free(&matches);
+
+ return true;
+}
diff --git a/src/cmd.h b/src/cmd.h
@@ -4,6 +4,11 @@
#include <stdbool.h>
+#define CMD_SET_STATUS(...) do { \
+ free(cmd_status); \
+ cmd_status = aprintf(__VA_ARGS__); \
+ } while (0)
+
typedef bool (*cmd_func)(const wchar_t *args);
struct cmd {
@@ -12,7 +17,8 @@ struct cmd {
};
void cmd_init(void);
+void cmd_deinit(void);
extern const struct cmd commands[];
extern const size_t command_count;
-extern wchar_t *cmd_status;
+extern char *cmd_status;
diff --git a/src/player.c b/src/player.c
@@ -145,11 +145,9 @@ player_update(void)
const char *tmp;
status = mpd_run_status(player->conn);
- if (status == NULL) {
- fprintf(stderr, "MPD Fatal Error: %s\n",
+ if (status == NULL)
+ PANIC("MPD Fatal Error: %s",
mpd_connection_get_error_message(player->conn));
- exit(1);
- }
song = mpd_run_current_song(player->conn);
if (!song) {
@@ -204,11 +202,9 @@ player_update(void)
/* TODO move prev / next handling to own functions */
status = mpd_run_status(player->conn);
- if (status == NULL) {
- fprintf(stderr, "MPD Fatal Error: %s\n",
+ if (status == NULL)
+ PANIC("MPD Fatal Error: %s",
mpd_connection_get_error_message(player->conn));
- exit(1);
- }
song = mpd_run_current_song(player->conn);
if (song) {
diff --git a/src/ref.c b/src/ref.c
@@ -41,6 +41,24 @@ refs_ffind(struct list *list, void *data)
}
int
+refs_index(struct list *list, void *data)
+{
+ struct link *iter;
+ struct ref *ref;
+ int index;
+
+ index = 0;
+ for (LIST_ITER(list, iter)) {
+ ref = UPCAST(iter, struct ref);
+ if (ref->data == data)
+ return index;
+ index++;
+ }
+
+ return -1;
+}
+
+int
refs_incl(struct list *list, void *data)
{
struct link *ref;
diff --git a/src/ref.h b/src/ref.h
@@ -12,6 +12,7 @@ struct ref *ref_init(void *data);
void ref_free(void *ref);
void refs_free(struct list *list);
+int refs_index(struct list *list, void *data);
int refs_incl(struct list *list, void *data);
void refs_rm(struct list *list, void *data);
diff --git a/src/tui.c b/src/tui.c
@@ -29,8 +29,9 @@
enum {
IMODE_EXECUTE,
- IMODE_TRACK_SEARCH,
- IMODE_TAG_SEARCH,
+ IMODE_TRACK_PLAY,
+ IMODE_TRACK_SELECT,
+ IMODE_TAG_SELECT,
IMODE_COUNT
};
@@ -49,8 +50,10 @@ static void tag_pane_vis(struct pane *pane, int sel);
static int track_pane_input(wint_t c);
static void track_pane_vis(struct pane *pane, int sel);
-static int play_track(const wchar_t *name);
-static int select_tag(const wchar_t *name);
+static bool run_cmd(const wchar_t *name);
+static bool play_track(const wchar_t *name);
+static bool select_track(const wchar_t *name);
+static bool select_tag(const wchar_t *name);
static int cmd_pane_input(wint_t c);
static void cmd_pane_vis(struct pane *pane, int sel);
@@ -74,8 +77,9 @@ static struct pane *const panes[] = {
};
static struct history command_history;
-static struct history track_search_history;
-static struct history tag_search_history;
+static struct history track_play_history;
+static struct history track_select_history;
+static struct history tag_select_history;
static struct history *history;
static int cmd_input_mode;
@@ -86,7 +90,7 @@ static int completion_reset;
static completion_gen completion;
struct pane *cmd_pane, *tag_pane, *track_pane;
-struct pane *pane_sel, *pane_top_sel;
+struct pane *pane_sel, *pane_after_cmd;
struct list *tracks_vis;
int track_show_playlist;
@@ -95,8 +99,9 @@ struct listnav track_nav;
const char imode_prefix[IMODE_COUNT] = {
[IMODE_EXECUTE] = ':',
- [IMODE_TRACK_SEARCH] = '/',
- [IMODE_TAG_SEARCH] = '?',
+ [IMODE_TRACK_PLAY] = '!',
+ [IMODE_TRACK_SELECT] = '/',
+ [IMODE_TAG_SELECT] = '?',
};
static const char player_state_chars[] = {
@@ -392,7 +397,7 @@ track_pane_vis(struct pane *pane, int sel)
}
}
-int
+bool
run_cmd(const wchar_t *query)
{
const wchar_t *sep;
@@ -403,20 +408,17 @@ run_cmd(const wchar_t *query)
cmdlen = sep ? sep - query : wcslen(query);
for (i = 0; i < command_count; i++) {
if (!wcsncmp(commands[i].name, query, cmdlen)) {
- success = commands[i].func(sep ? sep + 1 : NULL);
- if (!success && !cmd_status) {
- free(cmd_status);
- cmd_status = wcsdup(L"Command Failed!\n");
- ASSERT(cmd_status != NULL);
- }
- return 1;
+ success = commands[i].func(sep ? sep + 1 : L"");
+ if (!success && !cmd_status)
+ CMD_SET_STATUS("Command Failed!");
+ return true;
}
}
- return 0;
+ return false;
}
-int
+bool
play_track(const wchar_t *query)
{
struct track *track;
@@ -426,14 +428,35 @@ play_track(const wchar_t *query)
track = UPCAST(iter, struct ref)->data;
if (!wcscmp(track->name, query)) {
player_play_track(track);
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
-int
+bool
+select_track(const wchar_t *query)
+{
+ struct track *track;
+ struct link *link;
+ int index;
+
+ index = 0;
+ for (LIST_ITER(tracks_vis, link)) {
+ track = UPCAST(link, struct ref)->data;
+ if (!wcscmp(track->name, query)) {
+ listnav_update_sel(&track_nav, index);
+ pane_after_cmd = track_pane;
+ return true;
+ }
+ index += 1;
+ }
+
+ return false;
+}
+
+bool
select_tag(const wchar_t *query)
{
struct tag *tag;
@@ -444,13 +467,14 @@ select_tag(const wchar_t *query)
for (LIST_ITER(&tags, iter)) {
index += 1;
tag = UPCAST(iter, struct tag);
- if (wcscasestr(tag->name, query)) {
+ if (!wcscmp(tag->name, query)) {
listnav_update_sel(&tag_nav, index);
- return 1;
+ pane_after_cmd = tag_pane;
+ return true;
}
}
- return 0;
+ return false;
}
int
@@ -462,12 +486,14 @@ cmd_pane_input(wint_t c)
switch (c) {
case KEY_ESC:
match = wcscmp(completion_query.buf, history->input->buf);
- if (!completion_reset && match)
+ if (!completion_reset && match) {
inputln_copy(history->input, &completion_query);
- else if (history->sel == history->input)
- pane_sel = pane_top_sel;
- else
+ } else if (history->sel == history->input) {
+ inputln_replace(history->input, L"");
+ pane_sel = pane_after_cmd;
+ } else {
history->sel = history->input;
+ }
break;
case KEY_LEFT:
inputln_left(history->sel);
@@ -486,20 +512,26 @@ cmd_pane_input(wint_t c)
break;
case KEY_ENTER:
if (!*history->sel->buf) {
- pane_sel = pane_top_sel;
+ pane_sel = pane_after_cmd;
break;
}
if (cmd_input_mode == IMODE_EXECUTE) {
- run_cmd(history->sel->buf);
- } else if (cmd_input_mode == IMODE_TRACK_SEARCH) {
- play_track(history->sel->buf);
- } else if (cmd_input_mode == IMODE_TAG_SEARCH) {
- select_tag(history->sel->buf);
+ if (!run_cmd(history->sel->buf))
+ CMD_SET_STATUS("No such command");
+ } else if (cmd_input_mode == IMODE_TRACK_PLAY) {
+ if (!play_track(history->sel->buf))
+ CMD_SET_STATUS("Failed to find track");
+ } else if (cmd_input_mode == IMODE_TRACK_SELECT) {
+ if (!select_track(history->sel->buf))
+ CMD_SET_STATUS("Failed to find track");
+ } else if (cmd_input_mode == IMODE_TAG_SELECT) {
+ if (!select_tag(history->sel->buf))
+ CMD_SET_STATUS("Failed to find tag");
}
history_submit(history);
- pane_sel = pane_top_sel;
+ pane_sel = pane_after_cmd;
break;
case KEY_TAB:
case KEY_BTAB:
@@ -520,7 +552,7 @@ cmd_pane_input(wint_t c)
break;
case KEY_BACKSPACE:
if (history->sel->cur == 0) {
- pane_sel = pane_top_sel;
+ pane_sel = pane_after_cmd;
break;
}
inputln_del(history->sel, 1);
@@ -651,7 +683,7 @@ cmd_pane_vis(struct pane *pane, int sel)
} else if (cmd_status) {
pane_clearln(pane, 2);
style_on(pane->win, STYLE_ERROR);
- mvwaddwstr(pane->win, 2, 1, cmd_status);
+ mvwprintw(pane->win, 2, 0, ">%.*s", pane->w - 1, cmd_status);
style_off(pane->win, STYLE_ERROR);
}
}
@@ -692,10 +724,10 @@ main_input(wint_t c)
case KEY_TAB:
pane_sel = pane_sel == &pane_left
? &pane_right : &pane_left;
- pane_top_sel = pane_sel;
break;
case KEY_ESC:
- pane_sel = pane_top_sel;
+ if (pane_sel == cmd_pane)
+ pane_sel = pane_after_cmd;
break;
case KEY_LEFT:
if (!player->loaded) break;
@@ -749,23 +781,34 @@ main_input(wint_t c)
break;
case L':':
cmd_input_mode = IMODE_EXECUTE;
+ pane_after_cmd = pane_sel;
pane_sel = &pane_bot;
completion_reset = 1;
history = &command_history;
completion = command_name_gen;
break;
case L'/':
- cmd_input_mode = IMODE_TRACK_SEARCH;
+ cmd_input_mode = IMODE_TRACK_SELECT;
+ pane_after_cmd = pane_sel;
pane_sel = &pane_bot;
completion_reset = 1;
- history = &track_search_history;
+ history = &track_select_history;
+ completion = track_name_gen;
+ break;
+ case L'!':
+ cmd_input_mode = IMODE_TRACK_PLAY;
+ pane_after_cmd = pane_sel;
+ pane_sel = &pane_bot;
+ completion_reset = 1;
+ history = &track_play_history;
completion = track_name_gen;
break;
case L'?':
- cmd_input_mode = IMODE_TAG_SEARCH;
+ cmd_input_mode = IMODE_TAG_SELECT;
+ pane_after_cmd = pane_sel;
pane_sel = &pane_bot;
completion_reset = 1;
- history = &tag_search_history;
+ history = &tag_select_history;
completion = tag_name_gen;
break;
case L'+':
@@ -855,17 +898,19 @@ tui_resize(void)
pane_resize(&pane_right, pane_left.ex + 1, 0, scrw, scrh - 3);
pane_resize(&pane_bot, 0, scrh - 3, scrw, scrh);
}
+
void
tui_init(void)
{
quit = 0;
- cmd_input_mode = IMODE_TRACK_SEARCH;
+ cmd_input_mode = IMODE_TRACK_SELECT;
inputln_init(&completion_query);
completion_reset = 1;
- history_init(&track_search_history);
- history_init(&tag_search_history);
+ history_init(&track_play_history);
+ history_init(&track_select_history);
+ history_init(&tag_select_history);
history_init(&command_history);
history = &command_history;
@@ -878,7 +923,7 @@ tui_init(void)
pane_init((cmd_pane = &pane_bot), cmd_pane_input, cmd_pane_vis);
pane_sel = &pane_left;
- pane_top_sel = pane_sel;
+ pane_after_cmd = pane_sel;
listnav_init(&tag_nav);
listnav_init(&track_nav);
@@ -896,8 +941,9 @@ tui_deinit(void)
pane_free(&pane_right);
pane_free(&pane_bot);
- history_free(&track_search_history);
- history_free(&tag_search_history);
+ history_free(&track_play_history);
+ history_free(&track_select_history);
+ history_free(&tag_select_history);
history_free(&command_history);
if (!isendwin()) endwin();
diff --git a/src/tui.h b/src/tui.h
@@ -14,7 +14,7 @@ bool tui_update(void);
void tui_restore(void);
extern struct pane *cmd_pane, *tag_pane, *track_pane;
-extern struct pane *pane_sel, *pane_top_sel;
+extern struct pane *pane_sel, *pane_after_cmd;
extern struct list *tracks_vis;
extern int track_show_playlist;
diff --git a/src/util.c b/src/util.c
@@ -98,29 +98,6 @@ error(const char *fmtstr, ...)
exit(1);
}
-wchar_t *
-awprintf(const wchar_t *fmtstr, ...)
-{
- va_list ap, cpy;
- size_t size;
- wchar_t *str;
-
- va_copy(cpy, ap);
-
- va_start(ap, fmtstr);
- size = swprintf(NULL, 0, fmtstr, ap);
- va_end(ap);
-
- str = malloc((size + 1) * sizeof(wchar_t));
- if (!str) return NULL;
-
- va_start(cpy, fmtstr);
- swprintf(str, size + 1, fmtstr, cpy);
- va_end(cpy);
-
- return str;
-}
-
char *
aprintf(const char *fmtstr, ...)
{
diff --git a/src/util.h b/src/util.h
@@ -24,7 +24,6 @@ void assert(int cond, const char *file, int line, const char *condstr);
void error(const char *fmtstr, ...);
char *aprintf(const char *fmtstr, ...);
-wchar_t *awprintf(const wchar_t *fmtstr, ...);
char *appendstrf(char *alloc, const char *fmtstr, ...);
char *sanitized(const char *instr);