commit 69e7a9341e811bf658f8d75bb43f6613d298c87d
parent 3eea7a245a7ed49127a222628543f9509a6ff2b6
Author: Louis Burda <quent.burda@gmail.com>
Date: Thu, 16 Dec 2021 18:32:50 +0100
Completion search into both directions, added delay to prevent pops when seeking, small refactor for readability
Diffstat:
M | history.c | | | 5 | +++-- |
M | main.c | | | 147 | ++++++++++++++++++++++++++++++++++++++++++++++++------------------------------- |
M | player.c | | | 32 | ++++++++++++++++++++++++++++++-- |
M | player.h | | | 3 | +++ |
4 files changed, 125 insertions(+), 62 deletions(-)
diff --git a/history.c b/history.c
@@ -157,9 +157,10 @@ inputln_addch(struct inputln *line, wchar_t c)
{
int i;
- if (line->len + 1 == line->cap) {
+ if (line->len + 1 >= line->cap) {
line->cap *= 2;
- line->buf = realloc(line->buf, line->cap);
+ line->buf = realloc(line->buf,
+ line->cap * sizeof(wchar_t));
}
for (i = line->len; i > line->cur; i--)
diff --git a/main.c b/main.c
@@ -54,7 +54,7 @@ struct pane;
typedef int (*pane_handler)(wint_t c);
typedef void (*pane_updater)(struct pane *pane, int sel);
-typedef wchar_t *(*completion_generator)(const wchar_t *text, int state);
+typedef wchar_t *(*completion_generator)(const wchar_t *text, int fwd, int state);
typedef int (*cmd_handler)(const char *args);
struct pane {
@@ -131,8 +131,8 @@ void style_init(int style, int fg, int bg, int attr);
void style_on(WINDOW *win, int style);
void style_off(WINDOW *win, int style);
-wchar_t *command_name_generator(const wchar_t *text, int state);
-wchar_t *track_name_generator(const wchar_t *text, int state);
+wchar_t *command_name_generator(const wchar_t *text, int fwd, int state);
+wchar_t *track_name_generator(const wchar_t *text, int fwd, int state);
int tag_input(wint_t c);
void tag_vis(struct pane *pane, int sel);
@@ -157,6 +157,7 @@ init(void)
{
quit = 0;
+ /* TODO handle as character intead of signal */
signal(SIGINT, exit);
atexit(cleanup);
@@ -198,6 +199,7 @@ init(void)
playlist = LIST_HEAD;
tags_sel = LIST_HEAD;
+
listnav_init(&tag_nav);
listnav_init(&track_nav);
}
@@ -372,56 +374,84 @@ style_off(WINDOW *win, int style)
}
wchar_t *
-command_name_generator(const wchar_t *text, int reset)
+command_name_generator(const wchar_t *text, int fwd, int reset)
{
static int index, len;
+ int dir;
+
+ dir = fwd ? 1 : -1;
if (reset) {
index = 0;
len = wcslen(text);
- } else {
- index++;
+ } else if (index >= -1 && index <= ARRLEN(cmds)) {
+ index += dir;
}
- for (; index < ARRLEN(cmds); index++) {
+ while (index >= 0 && index < ARRLEN(cmds)) {
if (!wcsncmp(cmds[index].name, text, len))
return wcsdup(cmds[index].name);
+ index += dir;
}
return NULL;
}
wchar_t *
-track_name_generator(const wchar_t *text, int reset)
+track_name_generator(const wchar_t *text, int fwd, int reset)
{
static struct link *cur;
struct track *track;
- static int len;
if (reset) {
cur = tracks.next;
- len = wcslen(text);
} else if (cur) {
- cur = cur->next;
+ cur = fwd ? cur->next : cur->prev;
}
- for (; cur; cur = cur->next) {
+ while (cur != &tracks && cur) {
track = UPCAST(cur, struct track);
- if (!wcsncmp(track->name, text, len))
+ if (wcsstr(track->name, text))
return wcsdup(track->name);
+ cur = fwd ? cur->next : cur->prev;
}
return NULL;
}
-int
-tag_input(wint_t c)
+void
+select_current_tag(void)
{
- struct link *tag_link, *iter;
+ struct link *link, *iter;
struct track *track;
struct tag *tag;
struct ref *ref;
+ link = link_iter(tags.next, tag_nav.sel);
+ ASSERT(link != NULL);
+ tag = UPCAST(link, struct tag);
+ if (refs_incl(&tags_sel, tag)) {
+ refs_rm(&tags_sel, tag);
+ } else {
+ ref = ref_init(tag);
+ list_push_back(&tags_sel, LINK(ref));
+ }
+ refs_free(&playlist);
+ for (link = tags_sel.next; link; link = link->next) {
+ tag = UPCAST(link, struct ref)->data;
+ for (iter = tracks.next; iter; iter = iter->next) {
+ track = UPCAST(iter, struct track);
+ if (refs_incl(&track->tags, tag) && !refs_incl(&playlist, track)) {
+ ref = ref_init(track);
+ list_push_back(&playlist, LINK(ref));
+ }
+ }
+ }
+}
+
+int
+tag_input(wint_t c)
+{
switch (c) {
case KEY_UP:
listnav_update_sel(&tag_nav, tag_nav.sel - 1);
@@ -430,26 +460,7 @@ tag_input(wint_t c)
listnav_update_sel(&tag_nav, tag_nav.sel + 1);
return 1;
case KEY_SPACE:
- tag_link = link_iter(tags.next, tag_nav.sel);
- ASSERT(tag_link != NULL);
- tag = UPCAST(tag_link, struct tag);
- if (refs_incl(&tags_sel, tag)) {
- refs_rm(&tags_sel, tag);
- } else {
- ref = ref_init(tag);
- list_push_back(&tags_sel, LINK(ref));
- }
- refs_free(&playlist);
- for (tag_link = tags_sel.next; tag_link; tag_link = tag_link->next) {
- tag = UPCAST(tag_link, struct ref)->data;
- for (iter = tracks.next; iter; iter = iter->next) {
- track = UPCAST(iter, struct track);
- if (refs_incl(&track->tags, tag) && !refs_incl(&playlist, track)) {
- ref = ref_init(track);
- list_push_back(&playlist, LINK(ref));
- }
- }
- }
+ select_current_tag();
return 1;
case KEY_NPAGE:
listnav_update_sel(&track_nav, track_nav.sel - track_nav.wlen / 2);
@@ -521,10 +532,10 @@ track_input(wint_t c)
player_play_track(track);
return 1;
case KEY_PPAGE:
- listnav_update_sel(&track_nav, track_nav.sel - track_nav.wlen / 2);
+ listnav_update_sel(&track_nav, track_nav.sel + track_nav.wlen / 2);
return 1;
case KEY_NPAGE:
- listnav_update_sel(&track_nav, track_nav.sel + track_nav.wlen / 2);
+ listnav_update_sel(&track_nav, track_nav.sel - track_nav.wlen / 2);
return 1;
}
@@ -573,11 +584,30 @@ track_vis(struct pane *pane, int sel)
}
}
-int
-cmd_input(wint_t c)
+void
+run_cmd(const wchar_t *query)
+{
+
+}
+
+void
+play_track(const wchar_t *query)
{
struct track *track;
struct link *iter;
+
+ for (iter = tracks.next; iter; iter = iter->next) {
+ track = UPCAST(iter, struct track);
+ if (wcsstr(track->name, history->cmd->buf)) {
+ player_play_track(track);
+ break;
+ }
+ }
+}
+
+int
+cmd_input(wint_t c)
+{
wchar_t *res;
if (cmd_mode == IMODE_EXECUTE) {
@@ -616,30 +646,28 @@ cmd_input(wint_t c)
pane_sel = pane_top_sel;
break;
}
+
if (cmd_mode == IMODE_EXECUTE) {
-
- } else {
- for (iter = tracks.next; iter; iter = iter->next) {
- track = UPCAST(iter, struct track);
- if (!wcscmp(track->name, history->cmd->buf)) {
- player_play_track(track);
- break;
- }
- }
+ run_cmd(history->cmd->buf);
+ } else if (cmd_mode == IMODE_SEARCH) {
+ play_track(history->cmd->buf);
}
+
history_submit(history);
pane_sel = pane_top_sel;
break;
case KEY_TAB:
+ case KEY_BTAB:
if (history->cmd != history->query) {
inputln_copy(history->query, history->cmd);
history->cmd = history->query;
}
- if (completion_reset)
+ if (completion_reset) {
inputln_copy(&completion_query, history->query);
+ }
- res = completion(completion_query.buf, completion_reset);
+ res = completion(completion_query.buf, c == KEY_TAB, completion_reset);
if (res) inputln_replace(history->query, res);
free(res);
@@ -709,8 +737,7 @@ cmd_vis(struct pane *pane, int sel)
for (iter = history->list.next; iter; iter = iter->next, index++)
if (UPCAST(iter, struct inputln) == cmd)
break;
- line = appendstrf(NULL, "[%i]%c ", iter ? index : -1,
- cmd_mode == IMODE_SEARCH ? '/' : ':');
+ line = appendstrf(NULL, "[%i] ", iter ? index : -1);
} else {
line = appendstrf(NULL, "%c", cmd_mode == IMODE_SEARCH ? '/' : ':');
}
@@ -747,14 +774,14 @@ main_input(wint_t c)
break;
case KEY_RIGHT:
if (player->track) {
- if (player->time_end > player->time_pos + 10)
+ if (player->time_end > player->time_pos + 10) {
player_seek(player->time_pos + 10);
- else
+ } else {
player_next();
+ }
}
break;
- case L't':
- case L' ':
+ case L'c':
player_toggle_pause();
break;
case L'n':
@@ -769,7 +796,11 @@ main_input(wint_t c)
player_seek(0);
break;
case L's':
- player_stop();
+ if (player->state == PLAYER_STATE_PLAYING) {
+ player_stop();
+ } else {
+ player_play();
+ }
break;
case L':':
cmd_mode = IMODE_EXECUTE;
diff --git a/player.c b/player.c
@@ -35,6 +35,8 @@ player_init(void)
player->track = NULL;
player->state = PLAYER_STATE_PAUSED;
+ player->seek_delay = 0;
+
player->volume = 0;
player->time_pos = 0;
player->time_end = 0;
@@ -80,6 +82,12 @@ player_update(void)
}
player->volume = mpd_status_get_volume(status);
+ if (player->seek_delay) {
+ player->seek_delay -= 1;
+ if (!player->seek_delay)
+ player_play();
+ }
+
song = mpd_run_current_song(player->conn);
if (song) {
player->loaded = true;
@@ -181,6 +189,8 @@ player_resume(void)
int
player_next(void)
{
+ if (!player->loaded) return PLAYER_ERR;
+
if (!mpd_run_next(player->conn)) {
PLAYER_STATUS(PLAYER_MSG_ERR, "Playing next track failed");
mpd_run_clearerror(player->conn);
@@ -193,6 +203,9 @@ player_next(void)
int
player_prev(void)
{
+ /* TODO prevent mpd from dying on error, how to use properly */
+ if (!player->loaded) return PLAYER_ERR;
+
if (!mpd_run_previous(player->conn)) {
PLAYER_STATUS(PLAYER_MSG_ERR, "Playing prev track failed");
mpd_run_clearerror(player->conn);
@@ -203,6 +216,18 @@ player_prev(void)
}
int
+player_play(void)
+{
+ if (!mpd_run_play(player->conn)) {
+ PLAYER_STATUS(PLAYER_MSG_ERR, "Playing track failed");
+ mpd_run_clearerror(player->conn);
+ return PLAYER_ERR;
+ }
+
+ return PLAYER_OK;
+}
+
+int
player_stop(void)
{
if (!mpd_run_stop(player->conn)) {
@@ -217,8 +242,8 @@ player_stop(void)
int
player_seek(int sec)
{
- if (player->state == PLAYER_STATE_STOPPED) {
- PLAYER_STATUS(PLAYER_MSG_ERR, "Cannot seek stopped track");
+ if (!player->loaded || player->state == PLAYER_STATE_STOPPED) {
+ PLAYER_STATUS(PLAYER_MSG_ERR, "No track loaded");
return PLAYER_ERR;
}
@@ -228,6 +253,9 @@ player_seek(int sec)
return PLAYER_ERR;
}
+ player->seek_delay = 8;
+ player_pause();
+
return PLAYER_OK;
}
diff --git a/player.h b/player.h
@@ -32,6 +32,8 @@ struct player {
struct track *track;
int state;
+ int seek_delay;
+
int loaded;
int volume;
unsigned int time_pos, time_end;
@@ -56,6 +58,7 @@ int player_resume(void);
int player_prev(void);
int player_next(void);
int player_seek(int sec);
+int player_play(void);
int player_stop(void);
int player_set_volume(unsigned int vol);