summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--callbacks.c74
-rw-r--r--callbacks.h12
-rw-r--r--cdumb.c3
-rw-r--r--cflac.c3
-rw-r--r--cgme.c3
-rw-r--r--cmp3.c3
-rw-r--r--codec.h1
-rw-r--r--csid.cpp3
-rw-r--r--cvorbis.c3
-rw-r--r--deadbeef.glade39
-rw-r--r--gtkplaylist.c46
-rw-r--r--gtkplaylist.h2
-rw-r--r--interface.c33
-rw-r--r--playlist.c307
-rw-r--r--playlist.h8
15 files changed, 460 insertions, 80 deletions
diff --git a/callbacks.c b/callbacks.c
index c4d98b9c..830ef250 100644
--- a/callbacks.c
+++ b/callbacks.c
@@ -64,7 +64,7 @@ main_playlist_init (GtkWidget *widget) {
main_playlist.header = lookup_widget (mainwin, "header");
main_playlist.scrollbar = lookup_widget (mainwin, "playscroll");
main_playlist.pcurr = &playlist_current_ptr;
- main_playlist.count = &pl_count;
+ main_playlist.pcount = &pl_count;
main_playlist.iterator = PL_MAIN;
main_playlist.multisel = 1;
main_playlist.scrollpos = 0;
@@ -94,7 +94,7 @@ search_playlist_init (GtkWidget *widget) {
assert (search_playlist.header);
assert (search_playlist.scrollbar);
// main_playlist.pcurr = &search_current;
- search_playlist.count = &search_count;
+ search_playlist.pcount = &search_count;
search_playlist.multisel = 0;
search_playlist.iterator = PL_SEARCH;
search_playlist.scrollpos = 0;
@@ -691,3 +691,73 @@ on_searchlist_realize (GtkWidget *widget,
+
+void
+on_playlist_load_activate (GtkMenuItem *menuitem,
+ gpointer user_data)
+{
+ GtkWidget *dlg = gtk_file_chooser_dialog_new ("Load Playlist", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
+
+ GtkFileFilter* flt;
+ flt = gtk_file_filter_new ();
+ gtk_file_filter_set_name (flt, "DeaDBeeF playlist files (*.dbpl)");
+ gtk_file_filter_add_pattern (flt, "*.dbpl");
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), flt);
+
+ if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_OK)
+ {
+ gchar *fname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dlg));
+ gtk_widget_destroy (dlg);
+ if (fname) {
+ int res = pl_load (fname);
+ printf ("load result: %d\n", res);
+ g_free (fname);
+ gtkplaylist_t *ps = &main_playlist;
+ gtkpl_setup_scrollbar (ps);
+ gtkpl_draw_playlist (ps, 0, 0, ps->playlist->allocation.width, ps->playlist->allocation.height);
+ gtkpl_expose (ps, 0, 0, ps->playlist->allocation.width, ps->playlist->allocation.height);
+ search_refresh ();
+ }
+ }
+ else {
+ gtk_widget_destroy (dlg);
+ }
+}
+
+
+void
+on_playlist_save_activate (GtkMenuItem *menuitem,
+ gpointer user_data)
+{
+
+}
+
+
+void
+on_playlist_save_as_activate (GtkMenuItem *menuitem,
+ gpointer user_data)
+{
+ GtkWidget *dlg = gtk_file_chooser_dialog_new ("Save Playlist As", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
+
+ GtkFileFilter* flt;
+ flt = gtk_file_filter_new ();
+ gtk_file_filter_set_name (flt, "DeaDBeeF playlist files (*.dbpl)");
+ gtk_file_filter_add_pattern (flt, "*.dbpl");
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), flt);
+
+ if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_OK)
+ {
+ gchar *fname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dlg));
+ gtk_widget_destroy (dlg);
+
+ if (fname) {
+ int res = pl_save (fname);
+ printf ("save res: %d\n", res);
+ g_free (fname);
+ }
+ }
+ else {
+ gtk_widget_destroy (dlg);
+ }
+}
+
diff --git a/callbacks.h b/callbacks.h
index 8fbb5668..1daf45ed 100644
--- a/callbacks.h
+++ b/callbacks.h
@@ -391,3 +391,15 @@ on_playlist_motion_notify_event (GtkWidget *widget,
void
on_playscroll_value_changed (GtkRange *range,
gpointer user_data);
+
+void
+on_playlist_load_activate (GtkMenuItem *menuitem,
+ gpointer user_data);
+
+void
+on_playlist_save_activate (GtkMenuItem *menuitem,
+ gpointer user_data);
+
+void
+on_playlist_save_as_activate (GtkMenuItem *menuitem,
+ gpointer user_data);
diff --git a/cdumb.c b/cdumb.c
index 2f2f7dcd..42c0077a 100644
--- a/cdumb.c
+++ b/cdumb.c
@@ -799,6 +799,7 @@ codec_t cdumb = {
.read = cdumb_read,
.seek = cdumb_seek,
.insert = cdumb_insert,
- .getexts = cdumb_getexts
+ .getexts = cdumb_getexts,
+ .id = "stddumb"
};
diff --git a/cflac.c b/cflac.c
index 48a7396c..6d8f2d3e 100644
--- a/cflac.c
+++ b/cflac.c
@@ -426,5 +426,6 @@ codec_t cflac = {
.read = cflac_read,
.seek = cflac_seek,
.insert = cflac_insert,
- .getexts = cflac_getexts
+ .getexts = cflac_getexts,
+ .id = "stdflac"
};
diff --git a/cgme.c b/cgme.c
index e0fc8eb8..372f05d8 100644
--- a/cgme.c
+++ b/cgme.c
@@ -191,6 +191,7 @@ codec_t cgme = {
.insert = cgme_insert,
.getexts = cgme_getexts,
.numvoices = cgme_numvoices,
- .mutevoice = cgme_mutevoice
+ .mutevoice = cgme_mutevoice,
+ .id = "stdgme"
};
diff --git a/cmp3.c b/cmp3.c
index 1a0fadde..30082ffd 100644
--- a/cmp3.c
+++ b/cmp3.c
@@ -1321,7 +1321,8 @@ codec_t cmp3 = {
.read = cmp3_read,
.seek = cmp3_seek,
.insert = cmp3_insert,
- .getexts = cmp3_getexts
+ .getexts = cmp3_getexts,
+ .id = "stdmp3"
};
diff --git a/codec.h b/codec.h
index f01b614c..4890a8ed 100644
--- a/codec.h
+++ b/codec.h
@@ -40,6 +40,7 @@ typedef struct codec_s {
const char ** (*getexts) (void);
int (*numvoices) (void);
void (*mutevoice) (int voice, int mute);
+ const char *id; // codec id used for playlist serialization
fileinfo_t info;
} codec_t;
diff --git a/csid.cpp b/csid.cpp
index 0060b69e..8e2717a4 100644
--- a/csid.cpp
+++ b/csid.cpp
@@ -507,6 +507,7 @@ codec_t csid = {
csid_insert,
csid_getexts,
csid_numvoices,
- csid_mutevoice
+ csid_mutevoice,
+ "stdsid"
};
diff --git a/cvorbis.c b/cvorbis.c
index a21c9b06..0e00de5b 100644
--- a/cvorbis.c
+++ b/cvorbis.c
@@ -178,6 +178,7 @@ codec_t cvorbis = {
.read = cvorbis_read,
.seek = cvorbis_seek,
.insert = cvorbis_insert,
- .getexts = cvorbis_getexts
+ .getexts = cvorbis_getexts,
+ .id = "stdogg"
};
diff --git a/deadbeef.glade b/deadbeef.glade
index f4147637..f0e12741 100644
--- a/deadbeef.glade
+++ b/deadbeef.glade
@@ -190,6 +190,33 @@
<widget class="GtkMenu" id="playlist1_menu">
<child>
+ <widget class="GtkMenuItem" id="playlist_load">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Load</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_playlist_load_activate" last_modification_time="Sun, 09 Aug 2009 19:04:52 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="playlist_save">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Save</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_playlist_save_activate" last_modification_time="Sun, 09 Aug 2009 19:04:52 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="playlist_save_as">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Save As</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_playlist_save_as_activate" last_modification_time="Sun, 09 Aug 2009 19:04:52 GMT"/>
+ </widget>
+ </child>
+
+ <child>
<widget class="GtkMenuItem" id="order1">
<property name="visible">True</property>
<property name="label" translatable="yes">Order</property>
@@ -203,7 +230,7 @@
<property name="visible">True</property>
<property name="label" translatable="yes">Linear</property>
<property name="use_underline">True</property>
- <property name="active">False</property>
+ <property name="active">True</property>
<signal name="activate" handler="on_order_linear_activate" last_modification_time="Sat, 08 Aug 2009 12:26:33 GMT"/>
</widget>
</child>
@@ -213,7 +240,7 @@
<property name="visible">True</property>
<property name="label" translatable="yes">Shuffle</property>
<property name="use_underline">True</property>
- <property name="active">False</property>
+ <property name="active">True</property>
<property name="group">order_linear</property>
<signal name="activate" handler="on_order_shuffle_activate" last_modification_time="Sat, 08 Aug 2009 12:26:33 GMT"/>
</widget>
@@ -224,7 +251,7 @@
<property name="visible">True</property>
<property name="label" translatable="yes">Random</property>
<property name="use_underline">True</property>
- <property name="active">False</property>
+ <property name="active">True</property>
<property name="group">order_linear</property>
<signal name="activate" handler="on_order_random_activate" last_modification_time="Sat, 08 Aug 2009 12:26:33 GMT"/>
</widget>
@@ -248,7 +275,7 @@
<property name="visible">True</property>
<property name="label" translatable="yes">Loop All</property>
<property name="use_underline">True</property>
- <property name="active">False</property>
+ <property name="active">True</property>
<signal name="activate" handler="on_loop_all_activate" last_modification_time="Sat, 08 Aug 2009 12:26:33 GMT"/>
</widget>
</child>
@@ -258,7 +285,7 @@
<property name="visible">True</property>
<property name="label" translatable="yes">Loop Single Song</property>
<property name="use_underline">True</property>
- <property name="active">False</property>
+ <property name="active">True</property>
<property name="group">loop_all</property>
<signal name="activate" handler="on_loop_single_activate" last_modification_time="Sat, 08 Aug 2009 12:26:33 GMT"/>
</widget>
@@ -269,7 +296,7 @@
<property name="visible">True</property>
<property name="label" translatable="yes">Don't Loop</property>
<property name="use_underline">True</property>
- <property name="active">False</property>
+ <property name="active">True</property>
<property name="group">loop_all</property>
<signal name="activate" handler="on_loop_disable_activate" last_modification_time="Sat, 08 Aug 2009 12:26:33 GMT"/>
</widget>
diff --git a/gtkplaylist.c b/gtkplaylist.c
index a633ee9b..63eb0306 100644
--- a/gtkplaylist.c
+++ b/gtkplaylist.c
@@ -133,7 +133,7 @@ void
gtkpl_setup_scrollbar (gtkplaylist_t *ps) {
GtkWidget *playlist = ps->playlist;
int h = playlist->allocation.height / rowheight;
- int size = (*ps->count);
+ int size = (*ps->pcount);
if (h >= size) {
size = 0;
}
@@ -241,14 +241,13 @@ gtkpl_draw_pl_row (gtkplaylist_t *ps, cairo_t *cr, int row, playItem_t *it) {
}
cairo_set_font_size (cr, rowheight-4);
// draw as columns
- char dur[10];
- if (it->duration < 0) { // means not initialized yet
- strcpy (dur, "-:--");
- }
- else {
- int min = (int)it->duration/60;
- int sec = (int)(it->duration-min*60);
- snprintf (dur, 10, "%d:%02d", min, sec);
+ char dur[10] = "-:--";
+ if (it) {
+ if (it->duration >= 0) {
+ int min = (int)it->duration/60;
+ int sec = (int)(it->duration-min*60);
+ snprintf (dur, 10, "%d:%02d", min, sec);
+ }
}
const char *columns[pl_ncolumns] = {
"",
@@ -323,13 +322,13 @@ gtkpl_draw_playlist (gtkplaylist_t *ps, int x, int y, int w, int h) {
int row2;
int row2_full;
row1 = max (0, y / rowheight + ps->scrollpos);
- row2 = min ((*ps->count), (y+h) / rowheight + ps->scrollpos + 1);
+ row2 = min ((*ps->pcount), (y+h) / rowheight + ps->scrollpos + 1);
row2_full = (y+h) / rowheight + ps->scrollpos + 1;
- //printf ("drawing row %d (nvis=%d)\n", row2_full, ps->nvisiblerows);
// draw background
playItem_t *it = gtkpl_get_for_idx (ps, ps->scrollpos);
playItem_t *it_copy = it;
for (row = row1; row < row2_full; row++) {
+ //printf ("drawing row %d (nvis=%d), row1=%d, row2=%d, row2_full=%d\n", row, ps->nvisiblerows, row1, row2, row2_full);
gtkpl_draw_pl_row_back (ps, cr, row, it);
if (it) {
it = it->next[ps->iterator];
@@ -338,6 +337,7 @@ gtkpl_draw_playlist (gtkplaylist_t *ps, int x, int y, int w, int h) {
it = it_copy;
int idx = 0;
for (row = row1; row < row2; row++, idx++) {
+ //printf ("drawing row %d (nvis=%d), row1=%d, row2=%d, row2_full=%d\n", row, ps->nvisiblerows, row1, row2, row2_full);
gtkpl_draw_pl_row (ps, cr, row, it);
it = it->next[ps->iterator];
}
@@ -431,7 +431,7 @@ static int shift_sel_anchor = -1;
void
gtkpl_mouse1_pressed (gtkplaylist_t *ps, int state, int ex, int ey, double time) {
// cursor must be set here, but selection must be handled in keyrelease
- if ((*ps->count) == 0) {
+ if ((*ps->pcount) == 0) {
return;
}
GtkWidget *widget = ps->playlist;
@@ -440,7 +440,7 @@ gtkpl_mouse1_pressed (gtkplaylist_t *ps, int state, int ex, int ey, double time)
ps->lastpos[1] = ey;
// select item
int y = ey/rowheight + ps->scrollpos;
- if (y < 0 || y >= (*ps->count)) {
+ if (y < 0 || y >= (*ps->pcount)) {
y = -1;
}
@@ -463,7 +463,7 @@ gtkpl_mouse1_pressed (gtkplaylist_t *ps, int state, int ex, int ey, double time)
int sel = y;
if (y == -1) {
- y = (*ps->count) - 1;
+ y = (*ps->pcount) - 1;
}
int prev = ps->row;
ps->row = y;
@@ -627,7 +627,7 @@ gtkpl_handle_scroll_event (gtkplaylist_t *ps, int direction) {
GtkWidget *range = ps->scrollbar;;
GtkWidget *playlist = ps->playlist;
int h = playlist->allocation.height / rowheight;
- int size = (*ps->count);
+ int size = (*ps->pcount);
if (h >= size) {
size = 0;
}
@@ -777,8 +777,8 @@ gtkpl_keypress (gtkplaylist_t *ps, int keyval, int state) {
}
else if (keyval == GDK_Delete) {
pl_delete_selected ();
- if (ps->row >= (*ps->count)) {
- ps->row = (*ps->count) - 1;
+ if (ps->row >= (*ps->pcount)) {
+ ps->row = (*ps->pcount) - 1;
}
gtkpl_setup_scrollbar (ps);
gtkpl_draw_playlist (ps, 0, 0, widget->allocation.width, widget->allocation.height);
@@ -786,7 +786,7 @@ gtkpl_keypress (gtkplaylist_t *ps, int keyval, int state) {
search_refresh ();
return;
}
- else if (keyval == GDK_Down && ps->row < (*ps->count) - 1) {
+ else if (keyval == GDK_Down && ps->row < (*ps->pcount) - 1) {
ps->row++;
if (ps->row > ps->scrollpos + widget->allocation.height / rowheight - 1) {
newscroll = ps->row - widget->allocation.height / rowheight + 1;
@@ -798,10 +798,10 @@ gtkpl_keypress (gtkplaylist_t *ps, int keyval, int state) {
newscroll = ps->row;
}
}
- else if (keyval == GDK_Page_Down && ps->row < (*ps->count) - 1) {
+ else if (keyval == GDK_Page_Down && ps->row < (*ps->pcount) - 1) {
ps->row += 10;
- if (ps->row >= (*ps->count)) {
- ps->row = (*ps->count) - 1;
+ if (ps->row >= (*ps->pcount)) {
+ ps->row = (*ps->pcount) - 1;
}
if (ps->row > ps->scrollpos + widget->allocation.height / rowheight - 1) {
newscroll = ps->row - widget->allocation.height / rowheight + 1;
@@ -816,8 +816,8 @@ gtkpl_keypress (gtkplaylist_t *ps, int keyval, int state) {
newscroll = ps->row;
}
}
- else if (keyval == GDK_End && ps->row != (*ps->count) - 1) {
- ps->row = (*ps->count) - 1;
+ else if (keyval == GDK_End && ps->row != (*ps->pcount) - 1) {
+ ps->row = (*ps->pcount) - 1;
if (ps->row > ps->scrollpos + widget->allocation.height / rowheight - 1) {
newscroll = ps->row - widget->allocation.height / rowheight + 1;
}
diff --git a/gtkplaylist.h b/gtkplaylist.h
index e886c6af..d913f01a 100644
--- a/gtkplaylist.h
+++ b/gtkplaylist.h
@@ -42,7 +42,7 @@ typedef struct {
GdkPixmap *backbuf;
// parameters
playItem_t **pcurr; // pointer to current item
- int *count; // pointer to count of items in list
+ int *pcount; // pointer to count of items in list
int iterator; // index into next array of playItem_t struct
int lastpos[2]; // last mouse position (for playlist widget)
int multisel; // if it uses multiple selection
diff --git a/interface.c b/interface.c
index ea3e68bc..b3dad19d 100644
--- a/interface.c
+++ b/interface.c
@@ -53,6 +53,9 @@ create_mainwin (void)
GtkWidget *crop1;
GtkWidget *playlist1;
GtkWidget *playlist1_menu;
+ GtkWidget *playlist_load;
+ GtkWidget *playlist_save;
+ GtkWidget *playlist_save_as;
GtkWidget *order1;
GtkWidget *order1_menu;
GSList *order_linear_group = NULL;
@@ -199,6 +202,18 @@ create_mainwin (void)
playlist1_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (playlist1), playlist1_menu);
+ playlist_load = gtk_menu_item_new_with_mnemonic ("Load");
+ gtk_widget_show (playlist_load);
+ gtk_container_add (GTK_CONTAINER (playlist1_menu), playlist_load);
+
+ playlist_save = gtk_menu_item_new_with_mnemonic ("Save");
+ gtk_widget_show (playlist_save);
+ gtk_container_add (GTK_CONTAINER (playlist1_menu), playlist_save);
+
+ playlist_save_as = gtk_menu_item_new_with_mnemonic ("Save As");
+ gtk_widget_show (playlist_save_as);
+ gtk_container_add (GTK_CONTAINER (playlist1_menu), playlist_save_as);
+
order1 = gtk_menu_item_new_with_mnemonic ("Order");
gtk_widget_show (order1);
gtk_container_add (GTK_CONTAINER (playlist1_menu), order1);
@@ -210,16 +225,19 @@ create_mainwin (void)
order_linear_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (order_linear));
gtk_widget_show (order_linear);
gtk_container_add (GTK_CONTAINER (order1_menu), order_linear);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (order_linear), TRUE);
order_shuffle = gtk_radio_menu_item_new_with_mnemonic (order_linear_group, "Shuffle");
order_linear_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (order_shuffle));
gtk_widget_show (order_shuffle);
gtk_container_add (GTK_CONTAINER (order1_menu), order_shuffle);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (order_shuffle), TRUE);
order_random = gtk_radio_menu_item_new_with_mnemonic (order_linear_group, "Random");
order_linear_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (order_random));
gtk_widget_show (order_random);
gtk_container_add (GTK_CONTAINER (order1_menu), order_random);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (order_random), TRUE);
looping1 = gtk_menu_item_new_with_mnemonic ("Looping");
gtk_widget_show (looping1);
@@ -232,16 +250,19 @@ create_mainwin (void)
loop_all_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (loop_all));
gtk_widget_show (loop_all);
gtk_container_add (GTK_CONTAINER (looping1_menu), loop_all);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (loop_all), TRUE);
loop_single = gtk_radio_menu_item_new_with_mnemonic (loop_all_group, "Loop Single Song");
loop_all_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (loop_single));
gtk_widget_show (loop_single);
gtk_container_add (GTK_CONTAINER (looping1_menu), loop_single);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (loop_single), TRUE);
loop_disable = gtk_radio_menu_item_new_with_mnemonic (loop_all_group, "Don't Loop");
loop_all_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (loop_disable));
gtk_widget_show (loop_disable);
gtk_container_add (GTK_CONTAINER (looping1_menu), loop_disable);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (loop_disable), TRUE);
menuitem4 = gtk_menu_item_new_with_mnemonic ("_Help");
gtk_widget_show (menuitem4);
@@ -444,6 +465,15 @@ create_mainwin (void)
g_signal_connect ((gpointer) crop1, "activate",
G_CALLBACK (on_crop1_activate),
NULL);
+ g_signal_connect ((gpointer) playlist_load, "activate",
+ G_CALLBACK (on_playlist_load_activate),
+ NULL);
+ g_signal_connect ((gpointer) playlist_save, "activate",
+ G_CALLBACK (on_playlist_save_activate),
+ NULL);
+ g_signal_connect ((gpointer) playlist_save_as, "activate",
+ G_CALLBACK (on_playlist_save_as_activate),
+ NULL);
g_signal_connect ((gpointer) order_linear, "activate",
G_CALLBACK (on_order_linear_activate),
NULL);
@@ -599,6 +629,9 @@ create_mainwin (void)
GLADE_HOOKUP_OBJECT (mainwin, crop1, "crop1");
GLADE_HOOKUP_OBJECT (mainwin, playlist1, "playlist1");
GLADE_HOOKUP_OBJECT (mainwin, playlist1_menu, "playlist1_menu");
+ GLADE_HOOKUP_OBJECT (mainwin, playlist_load, "playlist_load");
+ GLADE_HOOKUP_OBJECT (mainwin, playlist_save, "playlist_save");
+ GLADE_HOOKUP_OBJECT (mainwin, playlist_save_as, "playlist_save_as");
GLADE_HOOKUP_OBJECT (mainwin, order1, "order1");
GLADE_HOOKUP_OBJECT (mainwin, order1_menu, "order1_menu");
GLADE_HOOKUP_OBJECT (mainwin, order_linear, "order_linear");
diff --git a/playlist.c b/playlist.c
index ced45522..ee162673 100644
--- a/playlist.c
+++ b/playlist.c
@@ -38,6 +38,10 @@
#include "messages.h"
#include "playback.h"
+codec_t *codecs[] = {
+ &cdumb, &cvorbis, &cflac, &cgme, &cmp3, &csid, NULL
+};
+
#define SKIP_BLANK_CUE_TRACKS 1
playItem_t *playlist_head[PL_MAX_ITERATORS];
@@ -265,9 +269,6 @@ pl_insert_file (playItem_t *after, const char *fname, int (*cb)(playItem_t *it,
eol++;
// match by codec
- codec_t *codecs[] = {
- &cdumb, &cvorbis, &cflac, &cgme, &cmp3, &csid, NULL
- };
for (int i = 0; codecs[i]; i++) {
if (codecs[i]->getexts && codecs[i]->insert) {
const char **exts = codecs[i]->getexts ();
@@ -339,43 +340,6 @@ pl_add_file (const char *fname, int (*cb)(playItem_t *it, void *data), void *use
return 0;
}
return -1;
-// {{{ original pl_add_file
-#if 0
- if (!fname) {
- return -1;
- }
- // detect codec
- codec_t *codec = NULL;
- const char *eol = fname + strlen (fname) - 1;
- while (eol > fname && *eol != '.') {
- eol--;
- }
- eol++;
-
- // match by codec
- codec_t *codecs[] = {
- &cdumb, &cvorbis, &cflac, &cgme, &cmp3, &csid, NULL
- };
- playItem_t *after = playlist_tail;
- for (int i = 0; codecs[i]; i++) {
- if (codecs[i]->getexts && codecs[i]->insert) {
- const char **exts = codecs[i]->getexts ();
- if (exts) {
- for (int e = 0; exts[e]; e++) {
- if (!strcasecmp (exts[e], eol)) {
- playItem_t *inserted = NULL;
- if ((inserted = codecs[i]->insert (after, fname)) != NULL) {
- return 0;
- }
- }
- }
- }
- }
- }
-
- return -1;
-#endif
-// }}}
}
int
@@ -916,3 +880,266 @@ pl_set_loop_mode (int mode) {
pl_loop_mode = mode;
}
+int
+pl_save (const char *fname) {
+ const char magic[] = "DBPL";
+ uint8_t majorver = 1;
+ uint8_t minorver = 0;
+ FILE *fp = fopen (fname, "w+b");
+ if (!fp) {
+ return -1;
+ }
+ if (fwrite (magic, 1, 4, fp) != 4) {
+ goto save_fail;
+ }
+ if (fwrite (&majorver, 1, 1, fp) != 1) {
+ goto save_fail;
+ }
+ if (fwrite (&minorver, 1, 1, fp) != 1) {
+ goto save_fail;
+ }
+ uint32_t cnt = pl_count;
+ if (fwrite (&cnt, 1, 4, fp) != 4) {
+ goto save_fail;
+ }
+ for (playItem_t *it = playlist_head[PL_MAIN]; it; it = it->next[PL_MAIN]) {
+ uint16_t l;
+ uint8_t ll;
+ l = strlen (it->fname);
+ if (fwrite (&l, 1, 2, fp) != 2) {
+ goto save_fail;
+ }
+ if (fwrite (it->fname, 1, l, fp) != l) {
+ goto save_fail;
+ }
+ ll = strlen (it->codec->id);
+ if (fwrite (&ll, 1, 1, fp) != 1) {
+ goto save_fail;
+ }
+ if (fwrite (it->codec->id, 1, ll, fp) != ll) {
+ goto save_fail;
+ }
+ l = it->tracknum;
+ if (fwrite (&l, 1, 2, fp) != 2) {
+ goto save_fail;
+ }
+ if (fwrite (&it->timestart, 1, 4, fp) != 4) {
+ goto save_fail;
+ }
+ if (fwrite (&it->timeend, 1, 4, fp) != 4) {
+ goto save_fail;
+ }
+ if (fwrite (&it->duration, 1, 4, fp) != 4) {
+ goto save_fail;
+ }
+#if 0
+ uint8_t ft = it->filetype ? strlen (it->filetype) : 0;
+ if (fwrite (&ft, 1, 1, fp) != 1) {
+ goto save_fail;
+ }
+ if (ft) {
+ if (fwrite (it->filetype, 1, ft, fp) != ft) {
+ goto save_fail;
+ }
+ }
+#endif
+ int16_t nm = 0;
+ metaInfo_t *m;
+ for (m = it->meta; m; m = m->next) {
+ nm++;
+ }
+ if (fwrite (&nm, 1, 2, fp) != 2) {
+ goto save_fail;
+ }
+ for (m = it->meta; m; m = m->next) {
+ l = strlen (m->key);
+ if (fwrite (&l, 1, 2, fp) != 2) {
+ goto save_fail;
+ }
+ if (l) {
+ if (fwrite (m->key, 1, l, fp) != l) {
+ goto save_fail;
+ }
+ }
+ l = strlen (m->value);
+ if (fwrite (&l, 1, 2, fp) != 2) {
+ goto save_fail;
+ }
+ if (l) {
+ if (fwrite (m->value, 1, l, fp) != l) {
+ goto save_fail;
+ }
+ }
+ }
+ }
+ fclose (fp);
+ return 0;
+save_fail:
+ fclose (fp);
+ unlink (fname);
+ return -1;
+}
+
+int
+pl_load (const char *fname) {
+ pl_free ();
+ uint8_t majorver = 1;
+ uint8_t minorver = 0;
+ FILE *fp = fopen (fname, "rb");
+ if (!fp) {
+ return -1;
+ }
+ char magic[4];
+ if (fread (magic, 1, 4, fp) != 4) {
+ goto load_fail;
+ }
+ if (strncmp (magic, "DBPL", 4)) {
+ goto load_fail;
+ }
+ if (fread (&majorver, 1, 1, fp) != 1) {
+ goto load_fail;
+ }
+ if (majorver != 1) {
+ goto load_fail;
+ }
+ if (fread (&minorver, 1, 1, fp) != 1) {
+ goto load_fail;
+ }
+ if (minorver != 0) {
+ goto load_fail;
+ }
+ uint32_t cnt;
+ if (fread (&cnt, 1, 4, fp) != 4) {
+ goto load_fail;
+ }
+ playItem_t *it = NULL;
+ for (uint32_t i = 0; i < cnt; i++) {
+ it = malloc (sizeof (playItem_t));
+ if (!it) {
+ goto load_fail;
+ }
+ memset (it, 0, sizeof (playItem_t));
+ uint16_t l;
+ // fname
+ if (fread (&l, 1, 2, fp) != 2) {
+ goto load_fail;
+ }
+ it->fname = malloc (l+1);
+ if (fread (it->fname, 1, l, fp) != l) {
+ goto load_fail;
+ }
+ it->fname[l] = 0;
+ // codec
+ uint8_t ll;
+ if (fread (&ll, 1, 1, fp) != 1) {
+ goto load_fail;
+ }
+ if (ll >= 20) {
+ goto load_fail;
+ }
+ char codec[20];
+ if (fread (codec, 1, ll, fp) != ll) {
+ goto load_fail;
+ }
+ codec[ll] = 0;
+ for (int c = 0; codecs[c]; c++) {
+ if (!strcmp (codec, codecs[c]->id)) {
+ it->codec = codecs[c];
+ }
+ }
+ if (!it->codec) {
+ goto load_fail;
+ }
+ // tracknum
+ if (fread (&l, 1, 2, fp) != 2) {
+ goto load_fail;
+ }
+ it->tracknum = l;
+ // timestart
+ if (fread (&it->timestart, 1, 4, fp) != 4) {
+ goto load_fail;
+ }
+ // timeend
+ if (fread (&it->timeend, 1, 4, fp) != 4) {
+ goto load_fail;
+ }
+ // duration
+ if (fread (&it->duration, 1, 4, fp) != 4) {
+ goto load_fail;
+ }
+#if 0
+ // filetype
+ uint8_t ft;
+ if (fread (&ft, 1, 1, fp) != 1) {
+ goto load_fail;
+ }
+ if (ft) {
+ it->filetype = malloc (ft+1)
+ if (fread (it->filetype, 1, ft, fp) != ft) {
+ goto load_fail;
+ }
+ it->filetype[ft] = 0;
+ }
+#endif
+ // printf ("loading file %s\n", it->fname);
+ int16_t nm = 0;
+ if (fread (&nm, 1, 2, fp) != 2) {
+ goto load_fail;
+ }
+ for (int i = 0; i < nm; i++) {
+ char key[1024];
+ char value[1024];
+ const char *valid_keys[] = {
+ "title",
+ "artist",
+ "album",
+ "vendor",
+ "year",
+ "genre",
+ "comment",
+ "track",
+ "band",
+ NULL
+ };
+
+ if (fread (&l, 1, 2, fp) != 2) {
+ goto load_fail;
+ }
+ if (!l || l >= 1024) {
+ goto load_fail;
+ }
+ if (fread (key, 1, l, fp) != l) {
+ goto load_fail;
+ }
+ key[l] = 0;
+ if (fread (&l, 1, 2, fp) != 2) {
+ goto load_fail;
+ }
+ if (!l || l >= 1024) {
+ goto load_fail;
+ }
+ if (fread (value, 1, l, fp) != l) {
+ goto load_fail;
+ }
+ value[l] = 0;
+ //printf ("%s=%s\n", key, value);
+ for (int n = 0; valid_keys[n]; n++) {
+ if (!strcmp (valid_keys[n], key)) {
+ pl_add_meta (it, valid_keys[n], value);
+ break;
+ }
+ }
+ }
+ pl_insert_item (playlist_tail[PL_MAIN], it);
+ }
+ fclose (fp);
+ return 0;
+load_fail:
+ fclose (fp);
+ if (it) {
+ pl_item_free (it);
+ }
+ pl_free ();
+ return -1;
+}
+
diff --git a/playlist.h b/playlist.h
index 1147b0f1..52836d9c 100644
--- a/playlist.h
+++ b/playlist.h
@@ -39,8 +39,6 @@ typedef struct playItem_s {
const char *filetype; // e.g. MP3 or OGG
struct playItem_s *next[PL_MAX_ITERATORS]; // next item in linked list
struct playItem_s *prev[PL_MAX_ITERATORS]; // prev item in linked list
-// struct playItem_s *shufflenext; // next item in shuffle list
-// struct playItem_s *searchnext; // next in search results list
struct metaInfo_s *meta; // linked list storing metainfo
unsigned selected : 1;
} playItem_t;
@@ -130,4 +128,10 @@ pl_set_order (int order);
void
pl_set_loop_mode (int mode);
+int
+pl_save (const char *fname);
+
+int
+pl_load (const char *fname);
+
#endif // __PLAYLIST_H