diff options
| author | Louis Burda <quent.burda@gmail.com> | 2021-12-16 17:11:12 +0100 |
|---|---|---|
| committer | Louis Burda <quent.burda@gmail.com> | 2021-12-20 15:31:31 +0100 |
| commit | 3eea7a245a7ed49127a222628543f9509a6ff2b6 (patch) | |
| tree | 345a923819b73bc88b551af5f708476239b6b7d9 | |
| parent | 15a8fe2cf2b16af8739a7ec2b64b5c5f184161b8 (diff) | |
| download | tmus-3eea7a245a7ed49127a222628543f9509a6ff2b6.tar.gz tmus-3eea7a245a7ed49127a222628543f9509a6ff2b6.zip | |
Switched most buffers to wide chars, added general ref class, now clear mpd errors, added track and command completion
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | history.c | 28 | ||||
| -rw-r--r-- | history.h | 5 | ||||
| -rw-r--r-- | list.c (renamed from link.c) | 8 | ||||
| -rw-r--r-- | list.h (renamed from link.h) | 7 | ||||
| -rw-r--r-- | main.c | 240 | ||||
| -rw-r--r-- | player.c | 73 | ||||
| -rw-r--r-- | player.h | 6 | ||||
| -rw-r--r-- | ref.c | 68 | ||||
| -rw-r--r-- | ref.h | 16 | ||||
| -rw-r--r-- | tag.c | 49 | ||||
| -rw-r--r-- | tag.h | 10 | ||||
| -rw-r--r-- | track.c | 9 | ||||
| -rw-r--r-- | track.h | 13 | ||||
| -rw-r--r-- | util.c | 3 |
15 files changed, 352 insertions, 185 deletions
@@ -11,7 +11,7 @@ clean: %.o: %.c %.h $(CC) -c -o $@ $< $(CFLAGS) $(LDLIBS) -tmus: main.c util.o history.o link.o player.o tag.o track.o listnav.o +tmus: main.c util.o history.o list.o player.o tag.o track.o listnav.o ref.o $(CC) -o $@ $^ $(CFLAGS) $(LDLIBS) install: @@ -1,5 +1,4 @@ #include "history.h" -#include "link.h" #include "util.h" #include <string.h> @@ -45,7 +44,6 @@ history_free(struct history *history) free(ln); } history->list = LIST_HEAD; - free(history->query); history->query = NULL; history->cmd = NULL; } @@ -170,6 +168,8 @@ inputln_addch(struct inputln *line, wchar_t c) line->len++; line->cur++; + + line->buf[line->len] = '\0'; } void @@ -189,3 +189,27 @@ inputln_del(struct inputln *line, int n) line->len -= n; line->cur -= n; } + +void +inputln_copy(struct inputln *dst, struct inputln *src) +{ + if (dst->buf) { + free(dst->buf); + dst->buf = NULL; + } + dst->len = src->len; + dst->buf = wcsdup(src->buf); + ASSERT(dst->buf != NULL); + dst->cap = src->len + 1; + dst->cur = dst->len; +} + +void +inputln_replace(struct inputln *line, const wchar_t *str) +{ + line->buf = wcsdup(str); + ASSERT(line->buf != NULL); + line->len = wcslen(str); + line->cap = line->len + 1; + line->cur = line->len; +} @@ -1,6 +1,6 @@ #pragma once -#include "link.h" +#include "list.h" #include "wchar.h" @@ -38,3 +38,6 @@ void inputln_right(struct inputln *line); void inputln_addch(struct inputln *line, wchar_t c); void inputln_del(struct inputln *line, int n); + +void inputln_copy(struct inputln *dst, struct inputln *src); +void inputln_replace(struct inputln *line, const wchar_t *str); @@ -1,4 +1,4 @@ -#include "link.h" +#include "list.h" #include "util.h" int @@ -66,7 +66,7 @@ link_append(struct link *cur, struct link *link) link->next->prev = link; } -void +struct link * link_pop(struct link *link) { ASSERT(link != NULL); @@ -75,6 +75,8 @@ link_pop(struct link *link) link->prev->next = link->next; if (link->next) link->next->prev = link->prev; + + return link; } struct link * @@ -91,7 +93,7 @@ link_iter(struct link *link, int n) } void -link_push_back(struct link *cur, struct link *link) +list_push_back(struct link *cur, struct link *link) { struct link *back; @@ -10,6 +10,8 @@ #define LIST_HEAD ((struct link) { .prev = NULL, .next = NULL }) #define LINK_EMPTY ((struct link) { 0 }) +#define LINK(p) (&(p)->link) + struct link { struct link *prev; struct link *next; @@ -23,8 +25,9 @@ int list_ffind(struct link *head, struct link *link); struct link *link_back(struct link *list); void link_prepend(struct link *list, struct link *link); void link_append(struct link *list, struct link *link); -void link_pop(struct link *link); +struct link *link_pop(struct link *link); struct link *link_iter(struct link *link, int n); -void link_push_back(struct link *list, struct link *link); +void list_push_back(struct link *list, struct link *link); + @@ -2,12 +2,13 @@ #define _DEFAULT_SOURCE #include "util.h" -#include "link.h" +#include "list.h" #include "history.h" #include "tag.h" #include "track.h" #include "player.h" #include "listnav.h" +#include "ref.h" #include "mpd/player.h" #include "curses.h" @@ -53,7 +54,7 @@ struct pane; typedef int (*pane_handler)(wint_t c); typedef void (*pane_updater)(struct pane *pane, int sel); -typedef char *(*completion_generator)(const char *text, int state); +typedef wchar_t *(*completion_generator)(const wchar_t *text, int state); typedef int (*cmd_handler)(const char *args); struct pane { @@ -67,7 +68,7 @@ struct pane { }; struct cmd { - const char *name; + const wchar_t *name; cmd_handler func; }; @@ -85,12 +86,21 @@ struct pane *const panes[] = { &pane_bot }; +struct inputln completion_query = { 0 }; +int completion_reset = 1; completion_generator completion; + struct pane *cmd_pane; struct history search_history, command_history; struct history *history; int cmd_show, cmd_mode; +const char player_state_chars[] = { + [PLAYER_STATE_PAUSED] = '|', + [PLAYER_STATE_PLAYING] = '>', + [PLAYER_STATE_STOPPED] = '#' +}; + struct pane *tag_pane; struct listnav tag_nav; struct link tags; @@ -121,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); -char *command_name_generator(const char *text, int state); -char *track_name_generator(const char *text, int state); +wchar_t *command_name_generator(const wchar_t *text, int state); +wchar_t *track_name_generator(const wchar_t *text, int state); int tag_input(wint_t c); void tag_vis(struct pane *pane, int sel); @@ -139,7 +149,7 @@ void main_vis(void); int usercmd_save(const char *args); const struct cmd cmds[] = { - { "save", usercmd_save }, + { L"save", usercmd_save }, }; void @@ -186,6 +196,7 @@ init(void) pane_sel = &pane_left; pane_top_sel = pane_sel; + playlist = LIST_HEAD; tags_sel = LIST_HEAD; listnav_init(&tag_nav); listnav_init(&track_nav); @@ -194,17 +205,17 @@ init(void) void cleanup(void) { + delwin(pane_left.win); + delwin(pane_right.win); + delwin(pane_bot.win); + endwin(); + data_save(); player_free(); history_free(&search_history); history_free(&command_history); - - delwin(pane_left.win); - delwin(pane_right.win); - delwin(pane_bot.win); - endwin(); } void @@ -235,7 +246,7 @@ data_load(void) tag->name = sanitized(tag->fname); ASSERT(tag->name != NULL); tag->link = LINK_EMPTY; - link_push_back(&tags, &tag->link); + list_push_back(&tags, LINK(tag)); tracks_load(tag); } @@ -247,7 +258,7 @@ tracks_load(struct tag *tag) { struct dirent *ent; struct track *track; - struct tag_ref *tagref; + struct ref *ref; DIR *dir; dir = opendir(tag->fpath); @@ -261,13 +272,9 @@ tracks_load(struct tag *tag) continue; track = track_init(tag->fpath, ent->d_name); - tagref = malloc(sizeof(struct tag_ref)); - ASSERT(tagref != NULL); - tagref->tag = tag; - tagref->link = LINK_EMPTY; - link_push_back(&track->tags, &tagref->link); - - link_push_back(&tracks, &track->link); + ref = ref_init(tag); + list_push_back(&track->tags, LINK(ref)); + list_push_back(&tracks, LINK(track)); } closedir(dir); } @@ -364,26 +371,28 @@ style_off(WINDOW *win, int style) ATTR_OFF(win, COLOR_PAIR(style) | style_attrs[style]); } -char * -command_name_generator(const char *text, int reset) +wchar_t * +command_name_generator(const wchar_t *text, int reset) { static int index, len; if (reset) { index = 0; - len = strlen(text); + len = wcslen(text); + } else { + index++; } for (; index < ARRLEN(cmds); index++) { - if (!strncmp(cmds[index].name, text, len)) - return strdup(cmds[index].name); + if (!wcsncmp(cmds[index].name, text, len)) + return wcsdup(cmds[index].name); } return NULL; } -char * -track_name_generator(const char *text, int reset) +wchar_t * +track_name_generator(const wchar_t *text, int reset) { static struct link *cur; struct track *track; @@ -391,13 +400,15 @@ track_name_generator(const char *text, int reset) if (reset) { cur = tracks.next; - len = strlen(text); + len = wcslen(text); + } else if (cur) { + cur = cur->next; } for (; cur; cur = cur->next) { track = UPCAST(cur, struct track); - if (!strncmp(track->name, text, len)) - return strdup(track->name); + if (!wcsncmp(track->name, text, len)) + return wcsdup(track->name); } return NULL; @@ -406,8 +417,10 @@ track_name_generator(const char *text, int reset) int tag_input(wint_t c) { - struct link *cur; + struct link *tag_link, *iter; + struct track *track; struct tag *tag; + struct ref *ref; switch (c) { case KEY_UP: @@ -417,13 +430,25 @@ tag_input(wint_t c) listnav_update_sel(&tag_nav, tag_nav.sel + 1); return 1; case KEY_SPACE: - cur = link_iter(tags.next, tag_nav.sel); - ASSERT(cur != NULL); - tag = UPCAST(cur, struct tag); - if (tagrefs_incl(&tags_sel, tag)) { - tagrefs_rm(&tags_sel, tag); + 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 { - tagrefs_add(&tags_sel, tag); + 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)); + } + } } return 1; case KEY_NPAGE: @@ -453,7 +478,7 @@ tag_vis(struct pane *pane, int sel) index = 0; for (iter = tags.next; iter; iter = iter->next) { tag = UPCAST(iter, struct tag); - tsel = tagrefs_incl(&tags_sel, tag); + tsel = refs_incl(&tags_sel, tag); if (sel && index == tag_nav.sel && tsel) style_on(pane->win, STYLE_ITEM_HOVER_SEL); @@ -495,10 +520,10 @@ track_input(wint_t c) player->track = track; player_play_track(track); return 1; - case KEY_NPAGE: + case KEY_PPAGE: listnav_update_sel(&track_nav, track_nav.sel - track_nav.wlen / 2); return 1; - case KEY_PPAGE: + case KEY_NPAGE: listnav_update_sel(&track_nav, track_nav.sel + track_nav.wlen / 2); return 1; } @@ -516,15 +541,15 @@ track_vis(struct pane *pane, int sel) werase(pane->win); pane_title(pane, "Tracks", sel); - listnav_update_bounds(&track_nav, 0, list_len(&tracks)); + listnav_update_bounds(&track_nav, 0, list_len(&playlist)); listnav_update_wlen(&track_nav, pane->h - 1); - wmove(pane->win, 0, 45); - wprintw(pane->win, "%i %i", list_len(&tracks), track_nav.sel); + wmove(pane->win, 0, 50); + wprintw(pane->win, "%i", list_len(&playlist)); index = 0; - for (iter = tracks.next; iter; iter = iter->next, index++) { - track = UPCAST(iter, struct track); + for (iter = playlist.next; iter; iter = iter->next, index++) { + track = UPCAST(iter, struct ref)->data; if (index < track_nav.wmin) continue; if (index >= track_nav.wmax) break; @@ -537,7 +562,7 @@ track_vis(struct pane *pane, int sel) style_on(pane->win, STYLE_ITEM_SEL); wmove(pane->win, 1 + index - track_nav.wmin, 0); - wprintw(pane->win, "%-*.*s", pane->w, pane->w, track->name); + wprintw(pane->win, "%-*.*ls", pane->w, pane->w, track->name); if (sel && index == track_nav.sel && track == player->track) style_off(pane->win, STYLE_ITEM_HOVER_SEL); @@ -551,10 +576,14 @@ track_vis(struct pane *pane, int sel) int cmd_input(wint_t c) { + struct track *track; + struct link *iter; + wchar_t *res; + if (cmd_mode == IMODE_EXECUTE) { history = &command_history; completion = command_name_generator; - } else { + } else if (cmd_mode == IMODE_SEARCH) { history = &search_history; completion = track_name_generator; } @@ -583,18 +612,51 @@ cmd_input(wint_t c) history_prev(history); break; case KEY_ENTER: - history_submit(history); - if (!*history->cmd->buf) + if (!*history->cmd->buf) { 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; + } + } + } + history_submit(history); + pane_sel = pane_top_sel; break; case KEY_TAB: + if (history->cmd != history->query) { + inputln_copy(history->query, history->cmd); + history->cmd = history->query; + } + + if (completion_reset) + inputln_copy(&completion_query, history->query); + + res = completion(completion_query.buf, completion_reset); + if (res) inputln_replace(history->query, res); + free(res); + + completion_reset = 0; break; case KEY_BACKSPACE: + if (history->cmd->cur == 0) { + pane_sel = pane_top_sel; + break; + } inputln_del(history->cmd, 1); + completion_reset = 1; break; default: if (!iswprint(c)) return 0; inputln_addch(history->cmd, c); + completion_reset = 1; break; } return 1; @@ -604,28 +666,26 @@ void cmd_vis(struct pane *pane, int sel) { struct inputln *cmd; - char state_char; + struct link *iter; + int index, offset; char *line; werase(pane->win); wmove(pane->win, 0, 0); style_on(pane->win, STYLE_TITLE); - wprintw(pane->win, " %-*.*s\n", pane->w - 1, pane->w - 1, - player->track ? player->track->name : ""); + wprintw(pane->win, " %-*.*ls\n", pane->w - 1, pane->w - 1, + player->track ? player->track->name : L""); style_off(pane->win, STYLE_TITLE); - if (player->time_pos) { - state_char = player->state == PLAYER_STATE_PLAYING ? '>' : '|'; - line = appendstrf(NULL, "%c ", state_char); + if (player->loaded) { + line = appendstrf(NULL, "%c ", player_state_chars[player->state]); line = appendstrf(line, "%s / ", timestr(player->time_pos)); line = appendstrf(line, "%s", timestr(player->time_end)); - if (player->volume >= 0) { - line = appendstrf(line, " - vol: %u%", player->volume); - } - if (player->msg) { + if (player->volume >= 0) + line = appendstrf(line, " - vol: %u%%", player->volume); + if (player->msg) line = appendstrf(line, " | [PLAYER] %s", player->msg); - } wmove(pane->win, 1, 0); ATTR_ON(pane->win, A_REVERSE); @@ -633,16 +693,34 @@ cmd_vis(struct pane *pane, int sel) ATTR_OFF(pane->win, A_REVERSE); free(line); + } else { + if (player->msg) { + wmove(pane->win, 1, 0); + line = aprintf("[PLAYER] %s", player->msg); + wprintw(pane->win, "%-*.*s\n", pane->w, pane->w, line); + free(line); + } } if (sel || cmd_show) { - wmove(pane->win, 2, 0); - waddch(pane->win, cmd_mode == IMODE_SEARCH ? '/' : ':'); cmd = history->cmd; - wprintw(pane->win, "%-*.*ls", pane->w - 1, pane->w - 1, cmd->buf); + if (cmd != history->query) { + index = 0; + 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 ? '/' : ':'); + } else { + line = appendstrf(NULL, "%c", cmd_mode == IMODE_SEARCH ? '/' : ':'); + } + offset = strlen(line); + line = appendstrf(line, "%ls", cmd->buf); + wprintw(pane->win, "%-*.*s", pane->w, pane->w, line); + free(line); if (sel) { /* cursor */ ATTR_ON(pane->win, A_REVERSE); - wmove(pane->win, 2, 1 + cmd->cur); + wmove(pane->win, 2, offset + cmd->cur); waddch(pane->win, cmd->cur < cmd->len ? cmd->buf[cmd->cur] : ' '); ATTR_OFF(pane->win, A_REVERSE); } @@ -675,35 +753,41 @@ main_input(wint_t c) player_next(); } break; - case 't': + case L't': + case L' ': player_toggle_pause(); break; - case 'n': - case '>': + case L'n': + case L'>': player_next(); break; - case 'p': - case '<': + case L'p': + case L'<': player_prev(); break; - case 'b': + case L'b': player_seek(0); break; - case ':': + case L's': + player_stop(); + break; + case L':': cmd_mode = IMODE_EXECUTE; pane_sel = &pane_bot; + completion_reset = 1; + break; + case L'/': + cmd_mode = IMODE_SEARCH; + pane_sel = &pane_bot; + completion_reset = 1; break; - case '+': + case L'+': player_set_volume(MIN(100, player->volume + 5)); break; - case '-': + case L'-': player_set_volume(MAX(0, player->volume - 5)); break; - case '/': - cmd_mode = IMODE_SEARCH; - pane_sel = &pane_bot; - break; - case 'q': + case L'q': quit = 1; break; } @@ -1,4 +1,5 @@ #include "player.h" +#include "ref.h" #include "portaudio.h" #include "sndfile.h" @@ -64,16 +65,30 @@ player_update(void) status = mpd_run_status(player->conn); ASSERT(status != NULL); - player->state = mpd_status_get_state(status) == MPD_STATE_PLAY - ? PLAYER_STATE_PLAYING : PLAYER_STATE_PAUSED; + switch (mpd_status_get_state(status)) { + case MPD_STATE_PAUSE: + player->state = PLAYER_STATE_PAUSED; + break; + case MPD_STATE_PLAY: + player->state = PLAYER_STATE_PLAYING; + break; + case MPD_STATE_STOP: + player->state = PLAYER_STATE_STOPPED; + break; + default: + ASSERT(0); + } player->volume = mpd_status_get_volume(status); song = mpd_run_current_song(player->conn); if (song) { + player->loaded = true; player->time_pos = mpd_status_get_elapsed_time(status); player->time_end = mpd_song_get_duration(song); mpd_song_free(song); } else { + player->track = NULL; + player->loaded = false; player->time_pos = 0; player->time_end = 0; } @@ -84,15 +99,12 @@ player_update(void) void player_queue_clear(void) { - struct link *iter, *next;; + struct ref *ref; - for (iter = &player->queue; iter; ) { - next = iter->next; - free(UPCAST(iter, struct track_ref)); - iter = next; + while (player->queue.next) { + ref = UPCAST(link_pop(player->queue.next), struct ref); + ref_free(ref); } - - player->queue = LIST_HEAD; } void @@ -104,19 +116,12 @@ player_queue_append(struct track *track) void player_queue_insert(struct track *track, size_t pos) { - struct track_ref *new; - struct link *iter; - int i; - - new = malloc(sizeof(struct track_ref)); - new->track = track; - new->link = LINK_EMPTY; + struct ref *ref; + struct link *link; - iter = &player->queue; - for (i = 0; i < pos && iter->next; i++) - iter = iter->next; - - link_append(iter, &new->link); + ref = ref_init(track); + link = link_iter(&player->queue, pos); + link_append(link, &ref->link); } int @@ -130,6 +135,7 @@ player_play_track(struct track *track) if (!mpd_run_add(player->conn, player->track->fpath) || !mpd_run_play(player->conn)) { PLAYER_STATUS(PLAYER_MSG_ERR, "Playback failed"); + mpd_run_clearerror(player->conn); return PLAYER_ERR; } @@ -141,6 +147,7 @@ player_toggle_pause(void) { if (!mpd_run_toggle_pause(player->conn)) { PLAYER_STATUS(PLAYER_MSG_ERR, "Pause toggle failed"); + mpd_run_clearerror(player->conn); return PLAYER_ERR; } @@ -152,6 +159,7 @@ player_pause(void) { if (!mpd_run_pause(player->conn, true)) { PLAYER_STATUS(PLAYER_MSG_ERR, "Pausing track failed"); + mpd_run_clearerror(player->conn); return PLAYER_ERR; } @@ -163,6 +171,7 @@ player_resume(void) { if (!mpd_run_pause(player->conn, false)) { PLAYER_STATUS(PLAYER_MSG_ERR, "Resuming track failed"); + mpd_run_clearerror(player->conn); return PLAYER_ERR; } @@ -174,6 +183,7 @@ player_next(void) { if (!mpd_run_next(player->conn)) { PLAYER_STATUS(PLAYER_MSG_ERR, "Playing next track failed"); + mpd_run_clearerror(player->conn); return PLAYER_ERR; } @@ -185,6 +195,19 @@ player_prev(void) { if (!mpd_run_previous(player->conn)) { PLAYER_STATUS(PLAYER_MSG_ERR, "Playing prev track failed"); + mpd_run_clearerror(player->conn); + return PLAYER_ERR; + } + + return PLAYER_OK; +} + +int +player_stop(void) +{ + if (!mpd_run_stop(player->conn)) { + PLAYER_STATUS(PLAYER_MSG_ERR, "Stopping track failed"); + mpd_run_clearerror(player->conn); return PLAYER_ERR; } @@ -194,8 +217,14 @@ player_prev(void) int player_seek(int sec) { + if (player->state == PLAYER_STATE_STOPPED) { + PLAYER_STATUS(PLAYER_MSG_ERR, "Cannot seek stopped track"); + return PLAYER_ERR; + } + if (!mpd_run_seek_current(player->conn, sec, false)) { PLAYER_STATUS(PLAYER_MSG_ERR, "Track seek failed"); + mpd_run_clearerror(player->conn); return PLAYER_ERR; } @@ -207,11 +236,13 @@ player_set_volume(unsigned int vol) { if (player->volume == -1) { PLAYER_STATUS(PLAYER_MSG_INFO, "Setting volume not supported"); + mpd_run_clearerror(player->conn); return PLAYER_ERR; } if (!mpd_run_set_volume(player->conn, vol)) { PLAYER_STATUS(PLAYER_MSG_ERR, "Setting volume failed"); + mpd_run_clearerror(player->conn); return PLAYER_ERR; } @@ -1,6 +1,7 @@ #pragma once #include "track.h" +#include "list.h" #include "util.h" #include "mpd/client.h" @@ -20,7 +21,8 @@ enum { enum { PLAYER_STATE_PAUSED, - PLAYER_STATE_PLAYING + PLAYER_STATE_PLAYING, + PLAYER_STATE_STOPPED }; struct player { @@ -30,6 +32,7 @@ struct player { struct track *track; int state; + int loaded; int volume; unsigned int time_pos, time_end; @@ -53,6 +56,7 @@ int player_resume(void); int player_prev(void); int player_next(void); int player_seek(int sec); +int player_stop(void); int player_set_volume(unsigned int vol); @@ -0,0 +1,68 @@ +#include "ref.h" +#include "util.h" + +struct ref * +ref_init(void *data) +{ + struct ref *ref; + + ref = malloc(sizeof(struct ref)); + ASSERT(ref != NULL); + ref->link = LINK_EMPTY; + ref->data = data; + return ref; +} + +void +ref_free(struct ref *ref) +{ + free(ref); +} + +void +refs_free(struct link *head) +{ + struct link *cur; + + while (head->next) { + cur = link_pop(head->next); + ref_free(UPCAST(cur, struct ref)); + } +} + +static struct link * +refs_ffind(struct link *head, void *data) +{ + struct link *iter; + + for (iter = head->next; iter; iter = iter->next) { + if (UPCAST(iter, struct ref)->data == data) + return iter; + } + + return NULL; +} + +int +refs_incl(struct link *head, void *data) +{ + struct link *ref; + + ref = refs_ffind(head, data); + return ref != NULL; +} + +void +refs_rm(struct link *head, void *data) +{ + struct link *ref; + struct ref *dataref; + + ref = refs_ffind(head, data); + if (!ref) return; + + dataref = UPCAST(ref, struct ref); + link_pop(ref); + free(dataref); +} + @@ -0,0 +1,16 @@ +#pragma once + +#include "link.h" + +struct ref { + void *data; + + struct link link; +}; + +struct ref *ref_init(void *data); +void ref_free(struct ref *ref); + +void refs_free(struct link *head); +int refs_incl(struct link *head, void *data); +void refs_rm(struct link *head, void *data); @@ -1,53 +1,4 @@ #include "tag.h" #include "link.h" -static struct link * -tagrefs_ffind(struct link *head, struct tag *tag) -{ - struct link *iter; - for (iter = head->next; iter; iter = iter->next) { - if (UPCAST(iter, struct tag_ref)->tag == tag) - return iter; - } - - return NULL; -} - -int -tagrefs_incl(struct link *head, struct tag *tag) -{ - struct link *ref; - - ref = tagrefs_ffind(head, tag); - return ref != NULL; -} - -void -tagrefs_add(struct link *head, struct tag *tag) -{ - struct tag_ref *ref; - - if (tagrefs_incl(head, tag)) - return; - - ref = malloc(sizeof(struct tag_ref)); - ASSERT(ref != NULL); - ref->link = LINK_EMPTY; - ref->tag = tag; - link_push_back(head, &ref->link); -} - -void -tagrefs_rm(struct link *head, struct tag *tag) -{ - struct link *ref; - struct tag_ref *tagref; - - ref = tagrefs_ffind(head, tag); - if (!ref) return; - - tagref = UPCAST(ref, struct tag_ref); - link_pop(ref); - free(tagref); -} @@ -10,13 +10,3 @@ struct tag { struct link link; }; -struct tag_ref { - struct tag *tag; - - struct link link; -}; - -int tagrefs_incl(struct link *head, struct tag *tag); -void tagrefs_add(struct link *head, struct tag *tag); -void tagrefs_rm(struct link *head, struct tag *tag); - @@ -1,5 +1,6 @@ #include "track.h" +#include <wchar.h> #include <string.h> @@ -15,14 +16,10 @@ track_init(const char *dir, const char *file) ASSERT(track->fname != NULL); track->fpath = aprintf("%s/%s", dir, file); ASSERT(track->fpath != NULL); - track->name = sanitized(track->fname); - ASSERT(track->name != NULL); + track->name = calloc(strlen(track->fname) + 1, sizeof(wchar_t)); + mbstowcs(track->name, track->fname, strlen(track->fname) + 1); - // TODO track_load_info(track) - track->artist = NULL; - track->duration = 0; track->link = LINK_EMPTY; - track->tags = LIST_HEAD; return track; @@ -1,25 +1,16 @@ #pragma once -#include "link.h" +#include "list.h" #include "util.h" struct track { - char *name; - char *artist; - float duration; + wchar_t *name; struct link tags; char *fname, *fpath; struct link link; }; -struct track_ref { - struct track *track; - - struct link link; -}; - - struct track *track_init(const char *dir, const char *file); void track_free(struct track *t); @@ -2,6 +2,8 @@ #include "util.h" +#include "ncurses.h" + #include <stdarg.h> #include <stdlib.h> #include <string.h> @@ -42,6 +44,7 @@ assert(int cond, const char *file, int line, const char *condstr) { if (cond) return; + endwin(); fprintf(stderr, "Assertion failed %s:%i (%s)\n", file, line, condstr); exit(1); } |
