summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c447
1 files changed, 439 insertions, 8 deletions
diff --git a/main.c b/main.c
index 0e6d281..9ba07d3 100644
--- a/main.c
+++ b/main.c
@@ -3,15 +3,66 @@
#include "library.h"
#include "luigi.h"
#include "memory.h"
+#include "plat.h"
+#include "playlist.h"
+
+typedef struct {
+ UITable* tab;
+ Playlist* p;
+} Playlist_UI;
+
+typedef struct {
+ int idx;
+ UIMenu* menu;
+} PS_Ctx;
Library lib;
Player pl;
+Playlist queue, playlist;
+Playlist_UI queue_ui, playlist_ui;
UIButton* play_button;
UISlider* seek_slider;
UIImageDisplay* cover_image;
UILabel* title_text;
UILabel* album_text;
UILabel* artist_text;
+UIButton* playlist_select;
+UITable* libtab;
+char filter_text[64];
+char playlist_names[64][64];
+
+void ui_update_playlist(void) {
+ playlist_ui.tab->itemCount = playlist.cnt;
+ UITableResizeColumns(playlist_ui.tab);
+ UIElementRefresh(&playlist_ui.tab->e);
+ playlist_select->label = UIStringCopy(
+ playlist.name,
+ -1
+ );
+ playlist_select->labelBytes = strlen(playlist.name);
+ UIElementRefresh(playlist_select->e.parent);
+}
+
+void ui_update_queue(void) {
+ queue_ui.tab->itemCount = queue.cnt;
+ UITableResizeColumns(queue_ui.tab);
+ UIElementRefresh(&queue_ui.tab->e);
+}
+
+void ui_add_to_playlist(void* cp) {
+ playlist_add(&playlist, cp);
+ ui_update_playlist();
+}
+
+void ui_add_to_queue(void* cp) {
+ playlist_add(&queue, cp);
+ ui_update_queue();
+}
+
+void ui_queue_next(void* cp) {
+ playlist_add_first(&queue, cp);
+ ui_update_queue();
+}
void ui_update_play(void) {
UI_FREE(play_button->label);
@@ -52,6 +103,162 @@ void ui_update_seek(void) {
UIElementRefresh((UIElement*)seek_slider);
}
+int filter_msg(
+ UIElement* el,
+ UIMessage msg,
+ int di,
+ void* dp
+) {
+ UITextbox* tb = (UITextbox*)el;
+ (void)di;
+ (void)dp;
+ int s = sizeof filter_text - 1;
+ if (msg == UI_MSG_VALUE_CHANGED) {
+ if (!tb->bytes) {
+ filter_text[0] = 0;
+ libtab->itemCount = lib.cnt;
+ UIElementRefresh((UIElement*)libtab);
+ return 0;
+ }
+ if (s > tb->bytes)
+ s = tb->bytes - 1;
+ memcpy(filter_text, tb->string, s);
+ filter_text[tb->bytes] = 0;
+ filter_library(&lib, filter_text);
+ libtab->itemCount = lib.fcnt;
+ UIElementRefresh((UIElement*)libtab);
+ }
+ return 0;
+}
+
+int new_msg(
+ UIElement* el,
+ UIMessage msg,
+ int di,
+ void* dp
+) {
+ char* buf;
+ const char* r;
+ int e;
+ (void)di;
+ (void)dp;
+ if (msg == UI_MSG_CLICKED) {
+ r = UIDialogShow(
+ el->window,
+ 0,
+ "%s%t\n%b%b",
+ "Name",
+ &buf,
+ "Okay",
+ "Cancel"
+ );
+ if (!strcmp(r, "Okay")) {
+ init_playlist(&playlist);
+ memcpy(playlist.name, buf, sizeof playlist.name);
+ e = sizeof playlist.name - 1;
+ if (playlist.name[e]) playlist.name[e] = 0;
+ ui_update_playlist();
+ }
+ }
+ return 0;
+}
+
+int save_msg(
+ UIElement* el,
+ UIMessage msg,
+ int di,
+ void* dp
+) {
+ char* buf;
+ const char* r;
+ int e;
+ (void)di;
+ (void)dp;
+ if (msg == UI_MSG_CLICKED) {
+ if (!playlist.name[0]) {
+ r = UIDialogShow(
+ el->window,
+ 0,
+ "%s%t\n%b%b",
+ "Name",
+ &buf,
+ "Okay",
+ "Cancel"
+ );
+ if (!strcmp(r, "Okay")) {
+ memcpy(playlist.name, buf, sizeof playlist.name);
+ e = sizeof playlist.name - 1;
+ if (playlist.name[e]) playlist.name[e] = 0;
+ ui_update_playlist();
+ } else {
+ return 0;
+ }
+ }
+ playlist_save(&playlist);
+ }
+ return 0;
+}
+
+void ps_select(void* cp) {
+ int idx;
+ const char* n;
+ idx = (int)(uintptr_t)cp;
+ n = playlist_names[idx];
+ if (playlist_load(&lib, &playlist, n))
+ ui_update_playlist();
+}
+
+void ps_iter(void* u, const char* path) {
+ PS_Ctx* ctx = u;
+ UIMenu* menu;
+ const char* name;
+ int nl;
+ menu = ctx->menu;
+ name = path + strlen(path);
+ for (; name != path && *name != '/'; name--);
+ for (nl = 0; name[nl] && name[nl] != '.'; nl++);
+ name++; /* this fails if library path is bad xDDD */
+ nl--; /* ... or if the path doesn't have an extension */
+ memcpy(playlist_names[ctx->idx], name, nl);
+ playlist_names[ctx->idx][nl] = 0;
+ UIMenuAddItem(
+ menu,
+ 0,
+ name,
+ nl,
+ ps_select,
+ (void*)(uintptr_t)ctx->idx
+ );
+ ctx->idx++;
+}
+
+int ps_msg(
+ UIElement* el,
+ UIMessage msg,
+ int di,
+ void* dp
+) {
+ (void)di;
+ (void)dp;
+ if (msg == UI_MSG_CLICKED) {
+ UIMenu* menu;
+ char buf[256];
+ PS_Ctx ctx;
+ get_playlist_dir(buf);
+ if (dir_exist(buf)) {
+ menu = UIMenuCreate(
+ &el->window->e,
+ 0
+ );
+ ctx.menu = menu;
+ ctx.idx = 0;
+ iter_dir(buf, ps_iter, &ctx);
+ UIMenuShow(menu);
+ }
+ }
+ return 0;
+}
+
int libtab_msg(
UIElement* el,
UIMessage msg,
@@ -59,35 +266,44 @@ int libtab_msg(
void* dp
) {
Song* song;
+ int* ind;
(void)di;
(void)dp;
+ ind = filter_text[0]? lib.filtered: lib.indices;
if (msg == UI_MSG_TABLE_GET_ITEM) {
UITableGetItem *m = (UITableGetItem*)dp;
- song = &lib.songs[lib.indices[m->index]];
+ song = &lib.songs[ind[m->index]];
m->isSelected = 0;
switch (m->column) {
case 0:
return snprintf(
m->buffer,
m->bufferBytes,
+ "%d",
+ song->track
+ );
+ case 1:
+ return snprintf(
+ m->buffer,
+ m->bufferBytes,
"%s",
song->name
);
- case 1:
+ case 2:
return snprintf(
m->buffer,
m->bufferBytes,
"%s",
song->artist
);
- case 2:
+ case 3:
return snprintf(
m->buffer,
m->bufferBytes,
"%s",
song->album
);
- case 3:
+ case 4:
return snprintf(
m->buffer,
m->bufferBytes,
@@ -102,13 +318,139 @@ int libtab_msg(
el->window->cursorX,
el->window->cursorY
);
- song = &lib.songs[lib.indices[hit]];
+ song = &lib.songs[ind[hit]];
play_song(&pl, song);
ui_update_play();
+ } else if (msg == UI_MSG_RIGHT_DOWN) {
+ UIMenu* menu;
+ int hit = UITableHitTest(
+ (UITable*)el,
+ el->window->cursorX,
+ el->window->cursorY
+ );
+ song = &lib.songs[ind[hit]];
+ menu = UIMenuCreate(
+ &el->window->e,
+ UI_MENU_NO_SCROLL
+ );
+ UIMenuAddItem(
+ menu,
+ 0,
+ "Add to Playlist",
+ -1,
+ ui_add_to_playlist,
+ song
+ );
+ UIMenuAddItem(
+ menu,
+ 0,
+ "Add to Queue",
+ -1,
+ ui_add_to_queue,
+ song
+ );
+ UIMenuAddItem(
+ menu,
+ 0,
+ "Queue Next",
+ -1,
+ ui_queue_next,
+ song
+ );
+ UIMenuShow(menu);
}
return 0;
}
+int playlist_tab_msg(
+ UIElement* el,
+ UIMessage msg,
+ int di,
+ void* dp
+) {
+ Playlist* p = el->cp;
+ Song* song;
+ int* ind;
+ (void)di;
+ ind = filter_text[0]? lib.filtered: lib.indices;
+ if (msg == UI_MSG_TABLE_GET_ITEM) {
+ UITableGetItem *m = (UITableGetItem*)dp;
+ song = p->songs[m->index];
+ switch (m->column) {
+ case 0:
+ return snprintf(
+ m->buffer,
+ m->bufferBytes,
+ "%d",
+ song->track
+ );
+ case 1:
+ return snprintf(
+ m->buffer,
+ m->bufferBytes,
+ "%s",
+ song->name
+ );
+ case 2:
+ return snprintf(
+ m->buffer,
+ m->bufferBytes,
+ "%s",
+ song->artist
+ );
+ case 3:
+ return snprintf(
+ m->buffer,
+ m->bufferBytes,
+ "%s",
+ song->album
+ );
+ default: return 0;
+ }
+ } else if (msg == UI_MSG_RIGHT_DOWN) {
+ if (p == &playlist) {
+ UIMenu* menu;
+ int hit = UITableHitTest(
+ (UITable*)el,
+ el->window->cursorX,
+ el->window->cursorY
+ );
+ song = playlist.songs[hit];
+ menu = UIMenuCreate(
+ &el->window->e,
+ UI_MENU_NO_SCROLL
+ );
+ UIMenuAddItem(
+ menu,
+ 0,
+ "Add to Queue",
+ -1,
+ ui_add_to_queue,
+ song
+ );
+ UIMenuAddItem(
+ menu,
+ 0,
+ "Queue Next",
+ -1,
+ ui_queue_next,
+ song
+ );
+ UIMenuShow(menu);
+ }
+ } else if (msg == UI_MSG_LEFT_UP) {
+ int hit = UITableHitTest(
+ (UITable*)el,
+ el->window->cursorX,
+ el->window->cursorY
+ );
+ song = &lib.songs[ind[hit]];
+ if (play_song(&pl, song))
+ ui_update_play();
+ }
+ return 0;
+}
+
int playpause_msg(
UIElement* el,
UIMessage msg,
@@ -178,13 +520,32 @@ int seek_msg(
return 0;
}
+void ui_create_playlist(
+ UIElement* pa,
+ Playlist_UI* pu,
+ Playlist* p
+) {
+ UITable* tab;
+ tab = UITableCreate(
+ pa,
+ UI_ELEMENT_H_FILL | UI_ELEMENT_V_FILL,
+ "Track\tTitle\tArtist\tAlbum"
+ );
+ tab->itemCount = p->cnt;
+ tab->e.messageUser = playlist_tab_msg;
+ tab->e.cp = p;
+ UITableResizeColumns(tab);
+ pu->tab = tab;
+ pu->p = p;
+}
+
int prog_main(void* mem) {
Arena liba;
UIWindow* wi;
UISplitPane* split1, * split2, * split3;
- UIPanel* plib, * pctrl, * plist, * pqueue;
- UITable* libtab;
+ UIPanel* plib, * pctrl, * plist, * pqueue, * row;
int r;
+ srand(time(0));
memory_init(mem);
init_arena(
&liba,
@@ -193,6 +554,8 @@ int prog_main(void* mem) {
);
build_library(&liba, &lib, library_path);
init_player(&pl);
+ init_playlist(&queue);
+ init_playlist(&playlist);
UIInitialise();
wi = UIWindowCreate(
0,
@@ -280,6 +643,7 @@ int prog_main(void* mem) {
"Queue",
5
);
+ ui_create_playlist(&pqueue->e, &queue_ui, &queue);
plist = UIPanelCreate(&split2->e, UI_PANEL_GRAY);
plist->gap = 5;
@@ -290,6 +654,57 @@ int prog_main(void* mem) {
"Playlist",
8
);
+ playlist_select = UIButtonCreate(
+ &plist->e,
+ 0,
+ "",
+ 0
+ );
+ playlist_select->e.messageUser = ps_msg;
+ row = UIPanelCreate(
+ &plist->e,
+ UI_PANEL_HORIZONTAL |
+ UI_ELEMENT_H_FILL
+ );
+ UIButtonCreate(
+ &row->e,
+ 0,
+ "New",
+ -1
+ )->e.messageUser = new_msg;
+ UIButtonCreate(
+ &row->e,
+ 0,
+ "Save",
+ -1
+ )->e.messageUser = save_msg;
+ UISpacerCreate(&row->e, 0, 10, 0);
+ UIButtonCreate(
+ &row->e,
+ 0,
+ "Play",
+ -1
+ );
+ UIButtonCreate(
+ &row->e,
+ 0,
+ "Play Shuffled",
+ -1
+ );
+ UISpacerCreate(&row->e, 0, 10, 0);
+ UIButtonCreate(
+ &row->e,
+ 0,
+ "Enqueue",
+ -1
+ );
+ UIButtonCreate(
+ &row->e,
+ 0,
+ "Enqueue Shuffled",
+ -1
+ );
+ ui_create_playlist(&plist->e, &playlist_ui, &playlist);
plib = UIPanelCreate(&split2->e, UI_PANEL_GRAY);
plib->gap = 5;
plib->border = UI_RECT_1(5);
@@ -299,10 +714,26 @@ int prog_main(void* mem) {
"Library",
7
);
+ row = UIPanelCreate(
+ &plib->e,
+ UI_PANEL_HORIZONTAL |
+ UI_ELEMENT_H_FILL
+ );
+ UILabelCreate(
+ &row->e,
+ 0,
+ "Filter",
+ -1
+ );
+ UISpacerCreate(&row->e, 0, 10, 0);
+ UITextboxCreate(
+ &row->e,
+ UI_ELEMENT_H_FILL
+ )->e.messageUser = filter_msg;
libtab = UITableCreate(
&plib->e,
UI_ELEMENT_H_FILL | UI_ELEMENT_V_FILL,
- "Track\tArtist\tAlbum\tFilename"
+ "Track\tTitle\tArtist\tAlbum\tFilename"
);
libtab->itemCount = lib.cnt;
libtab->e.messageUser = libtab_msg;