Modify version string to post-release version 0.20.95
[gmpc-playlistsort.git] / src / plugin.c
blobc58964ea7d67edc7fbd2039d15dfa46685081a91
1 /* gmpc-playlistsort (GMPC plugin)
2 * Copyright (C) 2006-2009 Qball Cow <qball@sarine.nl>
3 * Project homepage: http://gmpcwiki.sarine.nl/
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include <gtk/gtk.h>
21 #include <gmpc/plugin.h>
22 #include <glade/glade.h>
23 #include <libmpd/libmpd-internal.h>
24 #include <gmpc/misc.h>
26 void playlistsort_set_enabled(int enabled);
27 int playlistsort_get_enabled(void);
29 int playlistsort_tool_menu(GtkWidget *menu);
31 extern GtkTreeModel *playlist;
32 /* Allow gmpc to check the version the plugin is compiled against */
33 int plugin_api_version = PLUGIN_API_VERSION;
35 /**
36 * Define the plugin structure
38 gmpcPlugin plugin = {
39 /* name */
40 .name = "Playlist sorter",
41 /* version */
42 .version = {0,15,0},
43 /* type */
44 .plugin_type = GMPC_PLUGIN_NO_GUI,
45 /** enable/disable */
46 .get_enabled = playlistsort_get_enabled,
47 .set_enabled = playlistsort_set_enabled,
49 .tool_menu_integration = playlistsort_tool_menu
52 GList *items = NULL;
53 GtkListStore *tag_list = NULL;
54 typedef struct{
55 GtkWidget *combo;
56 GtkWidget *box;
57 GtkWidget *button;
58 }Item;
64 int playlistsort_get_enabled(void)
66 return cfg_get_single_value_as_int_with_default(config, "playlistsort", "enable", TRUE);
68 void playlistsort_set_enabled(int enabled)
70 cfg_set_single_value_as_int(config, "playlistsort", "enable", enabled);
71 pl3_tool_menu_update();
73 int playlistsort_sort(gpointer aa, gpointer bb, gpointer data)
75 MpdData_real *a = *(MpdData_real **)aa;
76 MpdData_real *b = *(MpdData_real **)bb;
77 int retv =0;
78 int i;
79 int *field = ((gint *)(data));
80 /** Filter */
81 if(!a && !b) return 0;
82 if(!a) return -1;
83 if(!b) return 1;
85 for(i=0;field[i] != -1;i++)
87 int do_int = 0;
88 char *sa= NULL, *sb = NULL;
89 switch(field[i])
92 case MPD_TAG_ITEM_TITLE:
93 sa = a->song->title;
94 sb = b->song->title;
95 break;
96 case MPD_TAG_ITEM_ARTIST:
97 sa = a->song->artist;
98 sb = b->song->artist;
99 break;
100 case MPD_TAG_ITEM_ALBUM:
101 sa = a->song->album;
102 sb = b->song->album;
103 break;
104 case MPD_TAG_ITEM_GENRE:
105 sa = a->song->genre;
106 sb = b->song->genre;
107 break;
108 case MPD_TAG_ITEM_TRACK:
110 sa = a->song->track;
111 sb = b->song->track;
112 do_int = 1;
113 break;
114 case MPD_TAG_ITEM_NAME:
115 sa = a->song->name;
116 sb = b->song->name;
117 break;
118 case MPD_TAG_ITEM_COMPOSER:
119 sa = a->song->composer;
120 sb = b->song->composer;
121 break;
122 case MPD_TAG_ITEM_PERFORMER:
123 sa = a->song->performer;
124 sb = b->song->performer;
125 break;
126 case MPD_TAG_ITEM_COMMENT:
127 sa = a->song->comment;
128 sb = b->song->comment;
129 break;
130 case MPD_TAG_ITEM_DISC:
131 sa = a->song->disc;
132 sb = b->song->disc;
133 break;
134 case MPD_TAG_ITEM_DATE:
135 sa = a->song->date;
136 sb = b->song->date;
137 break;
138 case MPD_TAG_ITEM_FILENAME:
139 sa = a->song->file;
140 sb = b->song->file;
141 break;
142 default:
143 g_assert(FALSE);
144 return 0;
146 if(sa && sb){
148 if(do_int == 0)
150 gchar *aa,*bb;
151 aa = g_utf8_strdown(sa, -1);
152 bb = g_utf8_strdown(sb, -1);
153 retv = g_utf8_collate(aa,bb);
154 g_free(aa);
155 g_free(bb);
156 }else{
157 gint64 aa,bb;
158 aa = g_ascii_strtoll(sa, NULL, 10);
159 bb = g_ascii_strtoll(sb, NULL, 10);
160 retv = (gint)aa-bb;
163 else if(sa == sb) retv = 0;
164 else if (sa == NULL) retv = -1;
165 else retv = 1;
167 if(retv != 0)
169 return retv;
172 return 0;
174 void playlistsort_start_field()
176 GList *node, *list=NULL;
177 GtkTreeIter iter;
178 int i;
179 int *fields= g_malloc0((g_list_length(items)+1)*sizeof(int));
180 GList *a;
181 MpdData *data2,*data = mpd_playlist_get_changes(connection, -1);
183 i=0;
184 for(a = g_list_first(items);a;a = g_list_next(a)){
185 Item *ii = a->data;
186 fields[i] = gtk_combo_box_get_active(GTK_COMBO_BOX(ii->combo));
187 fields[i+1] = -1;
188 i++;
190 data2 = misc_sort_mpddata(data,(GCompareDataFunc)playlistsort_sort,(gpointer)fields);
192 // mpd_playlist_clear(connection);
194 for(data2 = mpd_data_get_first(data2); data2;data2 = mpd_data_get_next(data2))
196 mpd_playlist_queue_add(connection, data2->song->file);
199 i=0;
200 for(data = mpd_data_get_first(data); data;data = mpd_data_get_next(data))
202 mpd_playlist_move_id(connection, data->song->id, i);
203 //mpd_playlist_queue_add(connection, data->song->file);
204 i++;
206 g_free(fields);
207 /**/
210 mpd_playlist_queue_commit(connection);
212 void fancy_remove(GtkWidget *button, Item *ii)
214 items = g_list_remove(items, ii);
215 gtk_widget_destroy(ii->box);
216 g_free(ii);
218 void add_fancy(GtkWidget *button, GtkWidget *box)
220 GtkCellRenderer *renderer;
221 GtkWidget *hbox = NULL;
222 Item *ii = NULL;
223 ii = g_malloc0(sizeof(Item));
224 items = g_list_append(items, ii);
226 ii->combo = gtk_combo_box_new();
227 ii->box = gtk_hbox_new(FALSE,6);
230 gtk_combo_box_set_model(GTK_COMBO_BOX(ii->combo), GTK_TREE_MODEL(tag_list));
231 renderer = gtk_cell_renderer_text_new();
232 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(ii->combo), renderer, TRUE);
233 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(ii->combo), renderer, "text", 1, NULL);
235 gtk_combo_box_set_active(GTK_COMBO_BOX(ii->combo), 0);
236 gtk_box_pack_start(GTK_BOX(ii->box), ii->combo, TRUE, TRUE, 0);
237 ii->button = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
238 g_signal_connect(G_OBJECT(ii->button), "clicked", G_CALLBACK(fancy_remove), ii);
239 gtk_box_pack_start(GTK_BOX(ii->box), ii->button,FALSE, TRUE, 0);
242 gtk_box_pack_start(GTK_BOX(box), ii->box, TRUE, TRUE, 0);
243 gtk_widget_show_all(box);
245 extern GladeXML *pl3_xml;
246 void playlistsort_start()
248 Item *ii = NULL;
249 GtkWidget *dialog = NULL;
250 GtkWidget *hbox, *label,*selector, *box;
251 GtkWidget *button;
252 GtkCellRenderer *renderer;
253 int i;
254 dialog = gtk_dialog_new_with_buttons("Sort Playlist",GTK_WINDOW(glade_xml_get_widget(pl3_xml, "pl3_win")),
255 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
256 GTK_STOCK_CANCEL,
257 GTK_RESPONSE_REJECT,
258 GTK_STOCK_OK,
259 GTK_RESPONSE_ACCEPT,
260 NULL);
263 hbox = gtk_hbox_new(FALSE,6);
264 gtk_container_set_border_width(GTK_CONTAINER(hbox), 9);
265 /** add label */
266 label = gtk_label_new("Sort field:");
267 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
268 /** Add selector */
270 ii = g_malloc0(sizeof(Item));
273 ii->combo = gtk_combo_box_new();
274 ii->box = gtk_hbox_new(FALSE,6);
275 tag_list = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING);
276 gtk_combo_box_set_model(GTK_COMBO_BOX(ii->combo), GTK_TREE_MODEL(tag_list));
277 renderer = gtk_cell_renderer_text_new();
278 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(ii->combo), renderer, TRUE);
279 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(ii->combo), renderer, "text", 1, NULL);
282 for(i=0;i< MPD_TAG_ITEM_ANY;i++)
284 GtkTreeIter iter;
285 gtk_list_store_append(tag_list, &iter);
286 gtk_list_store_set(tag_list, &iter, 0, i, 1, mpdTagItemKeys[i],-1);
288 gtk_combo_box_set_active(GTK_COMBO_BOX(ii->combo), 0);
289 gtk_box_pack_start(GTK_BOX(ii->box), ii->combo, TRUE, TRUE, 0);
290 gtk_box_pack_start(GTK_BOX(hbox), ii->box, TRUE, TRUE, 0);
291 items = g_list_append(items, ii);
293 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0);
294 button = gtk_button_new_from_stock(GTK_STOCK_ADD);
295 gtk_box_pack_end(GTK_BOX(GTK_DIALOG(dialog)->vbox), button, FALSE, TRUE, 0);
296 g_signal_connect(button, "clicked", G_CALLBACK(add_fancy), GTK_DIALOG(dialog)->vbox);
298 gtk_widget_show_all(dialog);
299 switch(gtk_dialog_run(GTK_DIALOG(dialog)))
301 case GTK_RESPONSE_ACCEPT:
302 playlistsort_start_field();
303 default:
304 break;
306 gtk_list_store_clear(tag_list);
307 g_object_unref(tag_list);
308 tag_list = NULL;
309 g_list_foreach(items, (GFunc)g_free, NULL);
310 g_list_free(items);
311 items = NULL;
313 gtk_widget_destroy(dialog);
316 int playlistsort_tool_menu(GtkWidget *menu)
318 GtkWidget *item;
319 if(!playlistsort_get_enabled()) return;
320 item = gtk_image_menu_item_new_with_label("Playlist Sort");
321 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
322 gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU));
323 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
324 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlistsort_start), NULL);
325 return 1;