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.
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
;
36 * Define the plugin structure
40 .name
= "Playlist sorter",
44 .plugin_type
= GMPC_PLUGIN_NO_GUI
,
46 .get_enabled
= playlistsort_get_enabled
,
47 .set_enabled
= playlistsort_set_enabled
,
49 .tool_menu_integration
= playlistsort_tool_menu
53 GtkListStore
*tag_list
= NULL
;
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
;
79 int *field
= ((gint
*)(data
));
81 if(!a
&& !b
) return 0;
85 for(i
=0;field
[i
] != -1;i
++)
88 char *sa
= NULL
, *sb
= NULL
;
92 case MPD_TAG_ITEM_TITLE
:
96 case MPD_TAG_ITEM_ARTIST
:
100 case MPD_TAG_ITEM_ALBUM
:
104 case MPD_TAG_ITEM_GENRE
:
108 case MPD_TAG_ITEM_TRACK
:
114 case MPD_TAG_ITEM_NAME
:
118 case MPD_TAG_ITEM_COMPOSER
:
119 sa
= a
->song
->composer
;
120 sb
= b
->song
->composer
;
122 case MPD_TAG_ITEM_PERFORMER
:
123 sa
= a
->song
->performer
;
124 sb
= b
->song
->performer
;
126 case MPD_TAG_ITEM_COMMENT
:
127 sa
= a
->song
->comment
;
128 sb
= b
->song
->comment
;
130 case MPD_TAG_ITEM_DISC
:
134 case MPD_TAG_ITEM_DATE
:
138 case MPD_TAG_ITEM_FILENAME
:
151 aa
= g_utf8_strdown(sa
, -1);
152 bb
= g_utf8_strdown(sb
, -1);
153 retv
= g_utf8_collate(aa
,bb
);
158 aa
= g_ascii_strtoll(sa
, NULL
, 10);
159 bb
= g_ascii_strtoll(sb
, NULL
, 10);
163 else if(sa
== sb
) retv
= 0;
164 else if (sa
== NULL
) retv
= -1;
174 void playlistsort_start_field()
176 GList
*node
, *list
=NULL
;
179 int *fields
= g_malloc0((g_list_length(items
)+1)*sizeof(int));
181 MpdData
*data2
,*data
= mpd_playlist_get_changes(connection
, -1);
184 for(a
= g_list_first(items
);a
;a
= g_list_next(a
)){
186 fields
[i
] = gtk_combo_box_get_active(GTK_COMBO_BOX(ii
->combo
));
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);
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);
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
);
218 void add_fancy(GtkWidget
*button
, GtkWidget
*box
)
220 GtkCellRenderer
*renderer
;
221 GtkWidget
*hbox
= 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()
249 GtkWidget
*dialog
= NULL
;
250 GtkWidget
*hbox
, *label
,*selector
, *box
;
252 GtkCellRenderer
*renderer
;
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
,
263 hbox
= gtk_hbox_new(FALSE
,6);
264 gtk_container_set_border_width(GTK_CONTAINER(hbox
), 9);
266 label
= gtk_label_new("Sort field:");
267 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, TRUE
, 0);
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
++)
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();
306 gtk_list_store_clear(tag_list
);
307 g_object_unref(tag_list
);
309 g_list_foreach(items
, (GFunc
)g_free
, NULL
);
313 gtk_widget_destroy(dialog
);
316 int playlistsort_tool_menu(GtkWidget
*menu
)
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
);