commit 7902429e5d69bb6aa57c6f1411b163d3e037e0e1
parent fb0a1cabe8d61d3305d9d14acc4754a1b6151b8c
Author: Louis Burda <quent.burda@gmail.com>
Date: Wed, 29 Dec 2021 01:46:08 +0100
More refactoring, moved track manipulation into player
Planning on creating a modular player_backend component
Diffstat:
12 files changed, 259 insertions(+), 150 deletions(-)
diff --git a/src/main.c b/src/main.c
@@ -5,7 +5,6 @@
#include "list.h"
#include "history.h"
#include "tag.h"
-#include "track.h"
#include "pane.h"
#include "player.h"
#include "listnav.h"
@@ -17,6 +16,7 @@
#include <dirent.h>
#include <locale.h>
#include <signal.h>
+#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -44,6 +44,7 @@ enum {
STYLE_ITEM_SEL,
STYLE_ITEM_HOVER,
STYLE_ITEM_HOVER_SEL,
+ STYLE_PREV,
STYLE_COUNT
};
@@ -80,6 +81,11 @@ static struct pane *const panes[] = {
&pane_bot
};
+/* 'tracks' holds all *unique* tracks */
+static struct link tracks;
+static struct link tags;
+static struct link tags_sel;
+
/* bottom 'cmd' pane for search / exec */
static struct pane *cmd_pane;
static struct history search_history, command_history;
@@ -92,16 +98,10 @@ static completion_gen completion;
/* left pane for tags */
static struct pane *tag_pane;
static struct listnav tag_nav;
-static struct link tags;
-static struct link tags_sel;
/* right pane for tracks */
static struct pane *track_pane;
static struct listnav track_nav;
-static struct link playlist;
-static struct link tracks;
-static int autoplay;
-static int shuffle;
static void init(void);
static void cleanup(int code, void *arg);
@@ -114,6 +114,7 @@ static void ncurses_init(void);
static void data_load(void);
static void data_save(void);
+static void data_free(void);
static void tracks_load(struct tag *tag);
static void tracks_save(struct tag *tag);
@@ -134,8 +135,8 @@ 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 cmd_input(wint_t c);
-static void cmd_vis(struct pane *pane, int sel);
+static int cmd_pane_input(wint_t c);
+static void cmd_pane_vis(struct pane *pane, int sel);
static void queue_hover(void);
static void main_input(wint_t c);
@@ -143,8 +144,6 @@ static void main_vis(void);
static int usercmd_save(const wchar_t *args);
-static void update_player(void);
-
const struct cmd cmds[] = {
{ L"save", usercmd_save },
};
@@ -198,10 +197,11 @@ tui_init(void)
style_init(STYLE_ITEM_SEL, COLOR_YELLOW, COLOR_BLACK, A_BOLD);
style_init(STYLE_ITEM_HOVER, COLOR_WHITE, COLOR_BLUE, 0);
style_init(STYLE_ITEM_HOVER_SEL, COLOR_YELLOW, COLOR_BLUE, A_BOLD);
+ style_init(STYLE_PREV, COLOR_WHITE, COLOR_BLACK, A_DIM);
pane_init((tag_pane = &pane_left), tag_pane_input, tag_pane_vis);
pane_init((track_pane = &pane_right), track_pane_input, track_pane_vis);
- pane_init((cmd_pane = &pane_bot), cmd_input, cmd_vis);
+ pane_init((cmd_pane = &pane_bot), cmd_pane_input, cmd_pane_vis);
pane_sel = &pane_left;
pane_top_sel = pane_sel;
@@ -279,8 +279,6 @@ data_load(void)
tracks = LIST_HEAD;
tags = LIST_HEAD;
-
- playlist = LIST_HEAD;
tags_sel = LIST_HEAD;
datadir = getenv("TMUS_DATA");
@@ -296,23 +294,11 @@ data_load(void)
if (!strcmp(ent->d_name, ".."))
continue;
- tag = malloc(sizeof(struct tag));
- ASSERT(tag != NULL);
- tag->fname = strdup(ent->d_name);
- ASSERT(tag->fname != NULL);
- tag->fpath = aprintf("%s/%s", datadir, ent->d_name);
- ASSERT(tag->fpath != NULL);
- tag->name = sanitized(tag->fname);
- ASSERT(tag->name != NULL);
- tag->link = LINK_EMPTY;
+ tag = tag_init(datadir, ent->d_name);
list_push_back(&tags, LINK(tag));
-
tracks_load(tag);
}
closedir(dir);
-
- autoplay = 0;
- shuffle = 0;
}
void
@@ -322,10 +308,17 @@ data_save(void)
}
void
+data_free(void)
+{
+ /* TODO free track info */
+}
+
+void
tracks_load(struct tag *tag)
{
+ struct track *track, *track_iter;
struct dirent *ent;
- struct track *track;
+ struct link *iter;
struct ref *ref;
DIR *dir;
@@ -340,9 +333,28 @@ tracks_load(struct tag *tag)
continue;
track = track_init(tag->fpath, ent->d_name);
+
+ track->tags = LIST_HEAD;
ref = ref_init(tag);
+ ASSERT(ref != NULL);
list_push_back(&track->tags, LINK(ref));
- list_push_back(&tracks, LINK(track));
+
+ ref = ref_init(track);
+ ASSERT(ref != NULL);
+ list_push_back(&tag->tracks, LINK(ref));
+
+ for (iter = tracks.next; iter; iter = iter->next) {
+ track_iter = UPCAST(iter, struct ref)->data;
+ if (track->fid == track_iter->fid)
+ break;
+ }
+
+ if (!iter) {
+ ref = ref_init(track);
+ ASSERT(ref != NULL);
+ list_push_back(&tracks, LINK(ref));
+ }
+
}
closedir(dir);
}
@@ -414,19 +426,23 @@ wchar_t *
track_name_gen(const wchar_t *text, int fwd, int reset)
{
static struct link *cur;
+ struct link *iter;
struct track *track;
if (reset) {
cur = tracks.next;
- } else if (cur) {
- cur = fwd ? cur->next : cur->prev;
+ iter = cur;
+ } else {
+ iter = fwd ? cur->next : cur->prev;
}
- while (cur != &tracks && cur) {
- track = UPCAST(cur, struct track);
- if (wcsstr(track->name, text))
+ while (iter && iter != &tracks) {
+ track = UPCAST(iter, struct ref)->data;
+ if (wcsstr(track->name, text)) {
+ cur = iter;
return wcsdup(track->name);
- cur = fwd ? cur->next : cur->prev;
+ }
+ iter = fwd ? iter->next : iter->prev;
}
return NULL;
@@ -439,6 +455,7 @@ toggle_current_tag(void)
struct track *track;
struct tag *tag;
struct ref *ref;
+ int in_tags, in_playlist;
link = link_iter(tags.next, tag_nav.sel);
ASSERT(link != NULL);
@@ -453,16 +470,13 @@ toggle_current_tag(void)
}
/* rebuild the full playlist */
- refs_free(&playlist);
+ refs_free(&player->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));
- }
+ for (iter = tag->tracks.next; iter; iter = iter->next) {
+ ref = ref_init(UPCAST(iter, struct ref)->data);
+ ASSERT(ref != NULL);
+ list_push_back(&player->playlist, LINK(ref));
}
}
}
@@ -478,11 +492,9 @@ tag_pane_input(wint_t c)
listnav_update_sel(&tag_nav, tag_nav.sel + 1);
return 1;
case KEY_SPACE:
- player->next = NULL;
toggle_current_tag();
return 1;
case KEY_ENTER:
- player->next = NULL;
refs_free(&tags_sel);
toggle_current_tag();
return 1;
@@ -522,16 +534,20 @@ tag_pane_vis(struct pane *pane, int sel)
style_on(pane->win, STYLE_ITEM_HOVER_SEL);
else if (sel && index == tag_nav.sel)
style_on(pane->win, STYLE_ITEM_HOVER);
+ else if (index == tag_nav.sel)
+ style_on(pane->win, STYLE_PREV);
else if (tsel)
style_on(pane->win, STYLE_ITEM_SEL);
wmove(pane->win, 1 + index - tag_nav.wmin, 0);
wprintw(pane->win, "%*.*s", pane->w, pane->w, tag->name);
- if (index == tag_nav.sel && tsel)
+ if (sel && index == tag_nav.sel && tsel)
style_off(pane->win, STYLE_ITEM_HOVER_SEL);
- else if (index == tag_nav.sel)
+ else if (sel && index == tag_nav.sel)
style_off(pane->win, STYLE_ITEM_HOVER);
+ else if (index == tag_nav.sel)
+ style_off(pane->win, STYLE_PREV);
else if (tsel)
style_off(pane->win, STYLE_ITEM_SEL);
}
@@ -551,10 +567,9 @@ track_pane_input(wint_t c)
listnav_update_sel(&track_nav, track_nav.sel + 1);
return 1;
case KEY_ENTER:
- link = link_iter(playlist.next, track_nav.sel);
+ link = link_iter(player->playlist.next, track_nav.sel);
ASSERT(link != NULL);
track = UPCAST(link, struct ref)->data;
- player->track = track;
player_play_track(track);
return 1;
case KEY_PPAGE:
@@ -580,11 +595,11 @@ track_pane_vis(struct pane *pane, int sel)
werase(pane->win);
pane_title(pane, "Tracks", sel);
- listnav_update_bounds(&track_nav, 0, list_len(&playlist));
+ listnav_update_bounds(&track_nav, 0, list_len(&player->playlist));
listnav_update_wlen(&track_nav, pane->h - 1);
index = 0;
- for (iter = playlist.next; iter; iter = iter->next, index++) {
+ for (iter = player->playlist.next; iter; iter = iter->next, index++) {
track = UPCAST(iter, struct ref)->data;
if (index < track_nav.wmin) continue;
@@ -594,6 +609,8 @@ track_pane_vis(struct pane *pane, int sel)
style_on(pane->win, STYLE_ITEM_HOVER_SEL);
else if (sel && index == track_nav.sel)
style_on(pane->win, STYLE_ITEM_HOVER);
+ else if (index == track_nav.sel)
+ style_on(pane->win, STYLE_PREV);
else if (track == player->track)
style_on(pane->win, STYLE_ITEM_SEL);
@@ -604,6 +621,8 @@ track_pane_vis(struct pane *pane, int sel)
style_off(pane->win, STYLE_ITEM_HOVER_SEL);
else if (sel && index == track_nav.sel)
style_off(pane->win, STYLE_ITEM_HOVER);
+ else if (index == track_nav.sel)
+ style_off(pane->win, STYLE_PREV);
else if (track == player->track)
style_off(pane->win, STYLE_ITEM_SEL);
}
@@ -634,7 +653,7 @@ play_track(const wchar_t *query)
struct link *iter;
for (iter = tracks.next; iter; iter = iter->next) {
- track = UPCAST(iter, struct track);
+ track = UPCAST(iter, struct ref)->data;
if (wcsstr(track->name, query)) {
player_play_track(track);
return 1;
@@ -645,7 +664,7 @@ play_track(const wchar_t *query)
}
int
-cmd_input(wint_t c)
+cmd_pane_input(wint_t c)
{
wchar_t *res;
@@ -730,7 +749,7 @@ cmd_input(wint_t c)
}
void
-cmd_vis(struct pane *pane, int sel)
+cmd_pane_vis(struct pane *pane, int sel)
{
static wchar_t *linebuf = NULL;
static int linecap = 0;
@@ -741,20 +760,27 @@ cmd_vis(struct pane *pane, int sel)
werase(pane->win);
+ /* TODO add clear_line func to fill with spaces instead of
+ * filling buffer */
+
/* static line buffer for perf */
- if (pane->w + 1 > linecap) {
- linecap = MAX(linecap, pane->w + 1);
+ if (pane->w > linecap) {
+ linecap = MAX(linecap, pane->w);
linebuf = realloc(linebuf, linecap * sizeof(wchar_t));
}
end = linebuf + linecap;
- wmove(pane->win, 0, 0);
+ /* track name */
style_on(pane->win, STYLE_TITLE);
- wprintw(pane->win, " %-*.*ls\n", pane->w - 1, pane->w - 1,
- player->track ? player->track->name : L"");
+ pane_clearln(pane, 0);
+ if (player->track) {
+ swprintf(linebuf, linecap, L"%ls", player->track->name);
+ mvwaddwstr(pane->win, 0, 1, linebuf);
+ }
style_off(pane->win, STYLE_TITLE);
if (player->loaded) {
+ /* status line */
line = linebuf;
line += swprintf(line, end - line, L"%c ",
player_state_chars[player->state]);
@@ -779,27 +805,31 @@ cmd_vis(struct pane *pane, int sel)
list_len(&player->queue));
}
- if (autoplay) {
+ if (player->autoplay) {
line += swprintf(line, end - line, L" | AUTOPLAY");
}
- if (shuffle) {
+ if (player->shuffle) {
line += swprintf(line, end - line, L" | SHUFFLE");
}
- line += swprintf(line, end - line, L"%*s", pane->w, L" ");
-
ATTR_ON(pane->win, A_REVERSE);
+ pane_clearln(pane, 1);
mvwaddwstr(pane->win, 1, 0, linebuf);
ATTR_OFF(pane->win, A_REVERSE);
} else if (player->msg) {
+ /* player message */
line = linebuf;
line += swprintf(line, linecap, L"[PLAYER] %s", player->msg);
- line += swprintf(line, end - line, L"%*s", pane->w, L" ");
+ line += swprintf(line, end - line, L"%*.*s",
+ pane->w, pane->w, L" ");
+
+ pane_clearln(pane, 1);
mvwaddwstr(pane->win, 1, 0, linebuf);
}
if (sel || cmd_show) {
+ /* cmd and search input */
line = linebuf;
cmd = history->cmd;
@@ -818,8 +848,8 @@ cmd_vis(struct pane *pane, int sel)
offset = wcslen(linebuf);
line += swprintf(line, end - line, L"%ls", cmd->buf);
- line += swprintf(line, end - line, L"%*s", pane->w, L" ");
+ pane_clearln(pane, 2);
mvwaddwstr(pane->win, 2, 0, linebuf);
if (sel) { /* show cursor in text */
@@ -837,7 +867,7 @@ queue_hover(void)
{
struct link *link;
- link = link_iter(playlist.next, track_nav.sel);
+ link = link_iter(player->playlist.next, track_nav.sel);
ASSERT(link != NULL);
player_queue_append(UPCAST(link, struct ref)->data);
}
@@ -860,11 +890,7 @@ main_input(wint_t c)
break;
case KEY_RIGHT:
if (!player->loaded) break;
- if (player->time_end > player->time_pos + 10) {
- player_seek(player->time_pos + 10);
- } else {
- player_next();
- }
+ player_seek(MIN(player->time_pos + 10, player->time_end));
break;
case L'y':
queue_hover();
@@ -884,16 +910,15 @@ main_input(wint_t c)
player_prev();
break;
case L'w':
- autoplay ^= 1;
+ player->autoplay ^= 1;
break;
case L'g':
- player->next = NULL;
- shuffle ^= 1;
+ player->shuffle ^= 1;
break;
case L'b':
player_seek(0);
break;
- case L's':
+ case L'x':
if (player->state == PLAYER_STATE_PLAYING) {
player_stop();
} else {
@@ -949,43 +974,6 @@ usercmd_save(const wchar_t *args)
return 0;
}
-void
-update_player(void)
-{
- static struct track *first = NULL;
- struct track *track;
- struct link *iter;
- int index;
-
- player_update();
-
- if (list_empty(&playlist)) first = NULL;
-
- /* dont start autoplay before the first song was chosen */
- if (!player->next && first) {
- iter = NULL;
- if (shuffle) {
- /* TODO better algorithm for random sequence */
- index = rand() % list_len(&playlist);
- iter = link_iter(playlist.next, index);
- ASSERT(iter != NULL);
- } else if (player->loaded) {
- iter = playlist.next;
- for (; iter; iter = iter->next) {
- track = UPCAST(iter, struct ref)->data;
- if (track == player->track)
- break;
- }
- iter = iter->next;
- }
- if (!iter) iter = playlist.next;
-
- player->next = UPCAST(iter, struct ref)->data;
- } else {
- first = player->track;
- }
-}
-
int
main(int argc, const char **argv)
{
@@ -996,7 +984,7 @@ main(int argc, const char **argv)
c = KEY_RESIZE;
do {
- update_player();
+ player_update();
if (c == KEY_RESIZE) {
tui_resize();
diff --git a/src/pane.c b/src/pane.c
@@ -29,6 +29,16 @@ pane_resize(struct pane *pane, int sx, int sy, int ex, int ey)
}
void
+pane_clearln(struct pane *pane, int y)
+{
+ int i;
+
+ wmove(pane->win, y, 0);
+ for (i = 0; i < pane->w; i++)
+ waddch(pane->win, ' ');
+}
+
+void
pane_free(struct pane *pane)
{
delwin(pane->win);
diff --git a/src/pane.h b/src/pane.h
@@ -21,5 +21,6 @@ struct pane {
void pane_init(struct pane *pane, pane_handler handle, pane_updater update);
void pane_resize(struct pane *pane, int sx, int sy, int ex, int ey);
+void pane_clearln(struct pane *pane, int y);
void pane_free(struct pane *p);
diff --git a/src/player.c b/src/player.c
@@ -63,10 +63,17 @@ player_init(void)
player->queue = LIST_HEAD;
player->history = LIST_HEAD;
+
+ player->playlist = LIST_HEAD;
+
player->track = NULL;
player->state = PLAYER_STATE_PAUSED;
- player->next = NULL;
+ player->autoplay = 0;
+
+ player->shuffle = 0;
+
+ player->action = PLAYER_ACTION_NONE;
player->seek_delay = 0;
@@ -93,6 +100,37 @@ player_free(void)
}
void
+player_play_next(struct track *prev)
+{
+ struct link *iter;
+ struct track *track;
+ int index;
+
+ if (list_empty(&player->playlist))
+ return;
+
+ if (player->shuffle) {
+ /* TODO better algorithm for random sequence */
+ index = rand() % list_len(&player->playlist);
+ iter = link_iter(player->playlist.next, index);
+ ASSERT(iter != NULL);
+ } else if (player->loaded) {
+ iter = player->playlist.next;
+ for (; iter; iter = iter->next) {
+ track = UPCAST(iter, struct ref)->data;
+ if (track == prev)
+ break;
+ }
+ if (iter) iter = iter->next;
+ }
+
+ if (!iter) iter = player->playlist.next;
+ track = UPCAST(iter, struct ref)->data;
+
+ player_play_track(track);
+}
+
+void
player_update(void)
{
struct mpd_status *status;
@@ -100,6 +138,20 @@ player_update(void)
struct ref *ref;
const char *tmp;
+ status = mpd_run_status(player->conn);
+ ASSERT(status != NULL);
+
+ if (!mpd_run_current_song(player->conn)) {
+ /* if autoplay and another track just finished,
+ * or there are tracks in queue to be played */
+ if (player->track && player->autoplay
+ || !list_empty(&player->queue)) {
+ player->action = PLAYER_ACTION_PLAY_NEXT;
+ }
+ }
+
+ free(status);
+
if (player->action != PLAYER_ACTION_NONE) {
handle_mpd_status(mpd_run_clear(player->conn));
@@ -111,6 +163,9 @@ player_update(void)
ref = UPCAST(list_pop_front(&player->history),
struct ref);
+ /* TODO keep index instead until new track is played */
+ /* TODO create slimmer player_backend interface */
+
/* dont add current song to history */
player->track = NULL;
@@ -123,9 +178,8 @@ player_update(void)
struct ref);
player_play_track(ref->data);
ref_free(ref);
- } else if (player->next) {
- player_play_track(player->next);
- player->next = NULL;
+ } else {
+ player_play_next(player->track);
}
break;
default:
@@ -134,9 +188,24 @@ player_update(void)
player->action = PLAYER_ACTION_NONE;
}
+ /* TODO move prev / next handling to own functions */
+
status = mpd_run_status(player->conn);
ASSERT(status != NULL);
+ 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;
+ }
+
switch (mpd_status_get_state(status)) {
case MPD_STATE_PAUSE:
player->state = PLAYER_STATE_PAUSED;
@@ -158,18 +227,6 @@ player_update(void)
player_play();
}
- 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;
- }
mpd_status_free(status);
}
@@ -213,16 +270,14 @@ player_play_track(struct track *track)
struct link *link;
int status;
- player->next = NULL;
if (player->track && player->track != track) {
list_push_front(&player->history,
LINK(ref_init(player->track)));
}
- player->track = track;
handle_mpd_status(mpd_run_clear(player->conn));
- status = mpd_run_add(player->conn, player->track->fpath);
+ status = mpd_run_add(player->conn, track->fpath);
if (handle_mpd_status(status))
return PLAYER_ERR;
@@ -230,6 +285,8 @@ player_play_track(struct track *track)
if (handle_mpd_status(status))
return PLAYER_ERR;
+ player->track = track;
+
return PLAYER_OK;
}
diff --git a/src/player.h b/src/player.h
@@ -36,9 +36,14 @@ struct player {
/* TODO move implementation details to source file */
struct mpd_connection *conn;
+ /* TODO combine with index */
+ /* for navigating forward and backwards in time */
struct link queue;
struct link history;
+ /* list of track refs to choose from on prev / next */
+ struct link playlist;
+
/* last player track */
struct track *track;
@@ -49,15 +54,11 @@ struct player {
/* stopped, paused or playing */
int state;
- /* TODO: replace with JIT solution */
- /* track to play when queue is empty
- * and player_next is called */
- struct track *next;
-
- /* automatically start playing player->next
- * when queue is empty */
+ /* automatically select new tracks when queue empty */
int autoplay;
+ int shuffle;
+
int action;
/* number of frames to wait before unpausing after
diff --git a/src/ref.c b/src/ref.c
@@ -7,7 +7,7 @@ ref_init(void *data)
struct ref *ref;
ref = malloc(sizeof(struct ref));
- ASSERT(ref != NULL);
+ if (!ref) return NULL;
ref->link = LINK_EMPTY;
ref->data = data;
return ref;
diff --git a/src/tag.c b/src/tag.c
@@ -1,4 +1,38 @@
#include "tag.h"
#include "link.h"
+#include "ref.h"
+#include <string.h>
+struct tag *
+tag_init(const char *path, const char *fname)
+{
+ struct tag *tag;
+
+ tag = malloc(sizeof(struct tag));
+ ASSERT(tag != NULL);
+
+ tag->fname = strdup(fname);
+ ASSERT(tag->fname != NULL);
+
+ tag->fpath = aprintf("%s/%s", path, fname);
+ ASSERT(tag->fpath != NULL);
+
+ tag->name = sanitized(tag->fname);
+ ASSERT(tag->name != NULL);
+
+ tag->link = LINK_EMPTY;
+
+ tag->tracks = LIST_HEAD;
+
+ return tag;
+}
+
+void
+tag_free(struct tag *tag)
+{
+ free(tag->fname);
+ free(tag->fpath);
+ free(tag->name);
+ refs_free(&tag->tracks);
+}
diff --git a/src/tag.h b/src/tag.h
@@ -7,6 +7,10 @@ struct tag {
char *name;
char *fname, *fpath;
+ struct link tracks;
+
struct link link;
};
+struct tag *tag_init(const char *path, const char *fname);
+void tag_free(struct tag *tag);
diff --git a/src/track.c b/src/track.c
@@ -2,24 +2,32 @@
#include <wchar.h>
#include <string.h>
+#include <sys/stat.h>
struct track *
-track_init(const char *dir, const char *file)
+track_init(const char *dir, const char *fname)
{
struct track *track;
+ struct stat info;
track = malloc(sizeof(struct track));
ASSERT(track != NULL);
- track->fname = strdup(file);
+ track->fname = strdup(fname);
ASSERT(track->fname != NULL);
- track->fpath = aprintf("%s/%s", dir, file);
+ track->fpath = aprintf("%s/%s", dir, fname);
ASSERT(track->fpath != NULL);
track->name = calloc(strlen(track->fname) + 1, sizeof(wchar_t));
+ ASSERT(track->name != NULL);
mbstowcs(track->name, track->fname, strlen(track->fname) + 1);
- track->link = LINK_EMPTY;
+ if (!stat(track->fpath, &info)) {
+ track->fid = info.st_ino;
+ } else {
+ track->fid = -1;
+ }
+
track->tags = LIST_HEAD;
return track;
diff --git a/src/track.h b/src/track.h
@@ -8,8 +8,7 @@ struct track {
wchar_t *name;
struct link tags;
char *fname, *fpath;
-
- struct link link;
+ int fid;
};
struct track *track_init(const char *dir, const char *file);
diff --git a/src/util.c b/src/util.c
@@ -41,10 +41,17 @@ done:
}
void
-panic(const char *msg, const char *file, int line)
+panic(const char *file, int line, const char *msg, ...)
{
+ va_list ap;
+
endwin();
- fprintf(stderr, "Panic at %s:%i (%s)\n", file, line, msg);
+ fprintf(stderr, "Panic at %s:%i (", file, line);
+ va_start(ap, msg);
+ vfprintf(stderr, msg, ap);
+ va_end(ap);
+ fprintf(stderr, ")\n");
+
exit(1);
}
diff --git a/src/util.h b/src/util.h
@@ -6,12 +6,12 @@
#define MIN(a, b) ((a) > (b) ? (b) : (a))
#define ARRLEN(x) (sizeof(x)/sizeof((x)[0]))
-#define PANIC(...) panic("" __VA_ARGS__, __FILE__, __LINE__)
+#define PANIC(...) panic(__FILE__, __LINE__, "" __VA_ARGS__)
#define ASSERT(x) assert((x), __FILE__, __LINE__, #x)
int strnwidth(const char *s, int n);
-void panic(const char *msg, const char *file, int line);
+void panic(const char *file, int line, const char *msg, ...);
void assert(int cond, const char *file, int line, const char *condstr);
char *aprintf(const char *fmtstr, ...);