Fix casting error (model->treeview)
[gmpc.git] / src / browsers / playlist3-playlist-editor.c
blobae44a209aa06bc6dbbed4d364bed992cdd5a2cc6
1 /* Gnome Music Player Client (GMPC)
2 * Copyright (C) 2004-2012 Qball Cow <qball@gmpclient.org>
3 * Project homepage: http://gmpclient.org/
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 <glib/gstdio.h>
22 #include <gdk/gdkkeysyms.h>
23 #include <libmpd/libmpd.h>
24 #include <string.h>
25 #include "main.h"
26 #include "playlist3.h"
27 #include "gmpc-mpddata-model.h"
28 #include "gmpc-mpddata-treeview.h"
29 #include "gmpc-mpddata-model-sort.h"
30 #include "gmpc-extras.h"
31 #include "browsers/playlist3-playlist-editor.h"
32 #include "Widgets/mpd-async-request.h"
34 #define DEFAULT_MARKUP_BROWSER "[%name%: &[%artist% - ]%title%]|%name%|[%artist% - ]%title%|%shortfile%|"
36 static GtkTreeRowReference *playlist_editor_browser_ref = NULL;
37 static GtkWidget *playlist_editor_browser = NULL;
38 static GtkWidget *playlist_editor_song_tree = NULL;
39 static void playlist_editor_status_changed(MpdObj * mi, ChangedStatusType what, void *data);
40 static int playlist_editor_add_go_menu(GtkWidget *);
41 GtkWidget *playlist_editor_icon_view = NULL;
42 GmpcMpdDataModelSort *playlist_editor_list_store = NULL;
43 void playlist_editor_fill_list_real(void);
44 static void playlist_editor_save_myself(void);
46 enum
48 PL_NAME,
49 PL_MTIME,
50 PL_IMAGE,
51 PL_NUM_COLS
54 GtkListStore *playlist_editor_store = NULL;
56 /**
57 * Enable/Disable plugin
59 static int playlist_editor_get_enabled(void)
61 return cfg_get_single_value_as_int_with_default(config, "playlist-plugin", "enable", TRUE);
64 static void playlist_editor_set_enabled(int enabled)
66 cfg_set_single_value_as_int(config, "playlist-plugin", "enable", enabled);
67 if (enabled && !playlist_editor_browser_ref)
69 GtkTreeView *tree = playlist3_get_category_tree_view();
70 playlist_editor_browser_add((GtkWidget *) tree);
71 } else if (!enabled && playlist_editor_browser_ref)
73 playlist_editor_destroy();
77 /**
78 * Browser extension
80 gmpcPlBrowserPlugin playlist_editor_gbp = {
81 .add = playlist_editor_browser_add, /* Add */
82 .selected = playlist_editor_browser_selected, /* Selected */
83 .unselected = playlist_editor_browser_unselected, /* Unselected */
84 .cat_right_mouse_menu = playlist_editor_browser_cat_menu, /* */
85 .add_go_menu = playlist_editor_add_go_menu
88 gmpcPlugin playlist_editor_plugin = {
89 .name = "Playlist Editor",
90 .version = {0, 15, 0},
91 .plugin_type = GMPC_PLUGIN_PL_BROWSER | GMPC_INTERNALL,
92 .init = playlist_editor_init,
93 .destroy = playlist_editor_destroy,
94 .browser = &playlist_editor_gbp,
95 .mpd_status_changed = playlist_editor_status_changed,
96 .mpd_connection_changed = playlist_editor_conn_changed,
97 .get_enabled = playlist_editor_get_enabled,
98 .set_enabled = playlist_editor_set_enabled,
99 .save_yourself = playlist_editor_save_myself
103 * Init plugin
105 void playlist_editor_init(void)
110 * Destroy Plugin
112 static gchar *old_playlist = NULL;
113 void playlist_editor_destroy(void)
115 if(playlist_editor_browser_ref != NULL)
117 GtkTreeIter iter;
118 GtkTreePath *path;
119 path = gtk_tree_row_reference_get_path(playlist_editor_browser_ref);
120 if (path)
122 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(gtk_tree_row_reference_get_model(playlist_editor_browser_ref)), &iter, path))
124 gtk_list_store_remove(GTK_LIST_STORE(gtk_tree_row_reference_get_model(playlist_editor_browser_ref)), &iter);
126 gtk_tree_path_free(path);
128 gtk_tree_row_reference_free(playlist_editor_browser_ref);
129 playlist_editor_browser_ref = NULL;
132 if (playlist_editor_browser)
134 gtk_widget_destroy(playlist_editor_browser);
135 playlist_editor_browser = NULL;
137 if (old_playlist)
139 g_free(old_playlist);
140 old_playlist = NULL;
145 * Connection changed
147 static gboolean pl3_editor_disabled = FALSE;
148 void playlist_editor_set_disabled(void)
150 pl3_editor_disabled = TRUE;
151 if(playlist_editor_browser != NULL)
152 gtk_widget_set_sensitive(GTK_WIDGET(playlist_editor_browser), FALSE);
155 void playlist_editor_conn_changed(MpdObj * mi, int connect, void *userdata)
157 if(connect == 1) {
158 pl3_editor_disabled = FALSE;
159 if(playlist_editor_browser != NULL)
160 gtk_widget_set_sensitive(GTK_WIDGET(playlist_editor_browser), TRUE);
162 playlist_editor_fill_list_real();
165 void playlist_editor_browser_add(GtkWidget * cat_tree)
167 GtkListStore *store = playlist3_get_category_tree_store();
168 GtkTreePath *path = NULL;
169 GtkTreeIter iter;
170 gint pos = cfg_get_single_value_as_int_with_default(config, "playlist-plugin", "position", 6);
172 /* Check if enabled */
173 if (!cfg_get_single_value_as_int_with_default(config, "playlist-plugin", "enable", TRUE))
174 return;
176 playlist3_insert_browser(&iter, PL3_CAT_BROWSER_LIBRARY+pos%PL3_CAT_BROWSER_LIBRARY);
177 gtk_list_store_set(store, &iter,
178 PL3_CAT_TYPE, playlist_editor_plugin.id,
179 PL3_CAT_TITLE, _("Playlist Editor"), PL3_CAT_ICON_ID, "media-playlist", -1);
181 * Clean up old row reference if it exists
183 if (playlist_editor_browser_ref)
185 gtk_tree_row_reference_free(playlist_editor_browser_ref);
186 playlist_editor_browser_ref = NULL;
189 * create row reference
191 path = gtk_tree_model_get_path(GTK_TREE_MODEL(playlist3_get_category_tree_store()), &iter);
192 if (path)
194 playlist_editor_browser_ref =
195 gtk_tree_row_reference_new(GTK_TREE_MODEL(playlist3_get_category_tree_store()), path);
196 gtk_tree_path_free(path);
201 static MpdData *__playlist_editor_async_function(MpdObj * mi, gpointer function_data)
203 MpdData *data = mpd_database_get_playlist_content(mi, (gchar *) function_data);
204 g_free(function_data);
205 return data;
208 static void __playlist_editor_async_callback(MpdData * data, gpointer callback_data)
210 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(playlist_editor_list_store), data);
211 gtk_widget_set_sensitive(playlist_editor_browser, TRUE);
214 static void playlist_editor_browser_playlist_editor_selected(GtkTreeModel * model, GtkTreePath * path,
215 GtkTreeIter * iter, gpointer userdata)
217 gchar *pl_path = NULL;
218 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store), iter, PL_NAME, &pl_path, -1);
219 if (pl_path)
221 gtk_widget_set_sensitive(playlist_editor_browser, FALSE);
222 gmpc_data_view_set_playlist_name(GTK_TREE_VIEW(playlist_editor_song_tree),pl_path);
223 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(playlist_editor_list_store), NULL);
224 gmpc_mpddata_model_sort_set_playlist(GMPC_MPDDATA_MODEL_SORT(playlist_editor_list_store), pl_path);
225 mpd_async_request(__playlist_editor_async_callback, NULL, __playlist_editor_async_function, g_strdup(pl_path));
226 if (old_playlist)
227 g_free(old_playlist);
228 old_playlist = pl_path;
232 /* always forces an update */
233 static void playlist_editor_browser_playlist_editor_changed(GtkWidget * giv, gpointer data)
235 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view));
236 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(playlist_editor_icon_view));
237 GtkTreeIter iter;
238 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(playlist_editor_list_store), NULL);
239 gmpc_mpddata_model_sort_set_playlist(GMPC_MPDDATA_MODEL_SORT(playlist_editor_list_store), NULL);
240 /* Need to catch wrong changed signals here */
241 if (gtk_tree_selection_get_selected(sel, &model, &iter))
243 playlist_editor_browser_playlist_editor_selected(model, NULL, &iter, data);
248 static void playlist_editor_browser_playlist_editor_changed_real(GtkWidget * giv, gpointer data)
250 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view));
251 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(playlist_editor_icon_view));
252 GtkTreeIter iter;
253 /* Need to catch wrong changed signals here */
254 if (gtk_tree_selection_get_selected(sel, &model, &iter))
256 gchar *pl_path = NULL;
257 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, PL_NAME, &pl_path, -1);
258 if (pl_path)
260 if (old_playlist && g_utf8_collate(pl_path, old_playlist) == 0)
262 g_free(pl_path);
263 return;
265 g_free(pl_path);
267 playlist_editor_browser_playlist_editor_selected(model, NULL, &iter, data);
268 return;
270 /* Clear if nothing found */
271 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(playlist_editor_list_store), NULL);
272 gmpc_mpddata_model_sort_set_playlist(GMPC_MPDDATA_MODEL_SORT(playlist_editor_list_store), NULL);
275 static gint __sort_func(gpointer aa, gpointer bb, gpointer c)
277 MpdData_real *a = *(MpdData_real **) aa;
278 MpdData_real *b = *(MpdData_real **) bb;
279 if (a->type == MPD_DATA_TYPE_PLAYLIST && b->type == MPD_DATA_TYPE_PLAYLIST)
281 if (a->playlist->path == NULL && b->playlist->path != NULL)
282 return -1;
283 else if (b->playlist->path == NULL && a->playlist->path != NULL)
284 return 1;
285 else if (a->playlist->path && b->playlist->path)
287 int val;
288 gchar *sa, *sb;
289 sa = g_utf8_strdown(a->playlist->path, -1);
290 sb = g_utf8_strdown(b->playlist->path, -1);
291 val = g_utf8_collate(sa, sb);
292 g_free(sa);
293 g_free(sb);
294 return val;
297 return a->type - b->type;
300 void playlist_editor_fill_list(void)
302 if (!mpd_server_has_idle(connection))
304 playlist_editor_fill_list_real();
308 void playlist_editor_fill_list_real(void)
310 GtkTreeIter iter;
311 if (playlist_editor_browser && !pl3_editor_disabled)
313 gboolean valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(playlist_editor_store), &iter);
314 MpdData *data = mpd_database_playlist_list(connection);
315 data = misc_sort_mpddata(data, (GCompareDataFunc) __sort_func, NULL);
316 for (; data; data = mpd_data_get_next(data))
318 if (data->type == MPD_DATA_TYPE_PLAYLIST)
320 loop:
321 if (valid)
323 char *name = NULL;
324 int val = 0;
325 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store), &iter, PL_NAME, &name, -1);
326 val = strcmp(name, data->playlist->path);
328 if (val == 0)
330 GtkTreePath *path = NULL;
331 gchar *mtime = NULL;
332 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store), &iter, PL_MTIME, &mtime, -1);
333 gtk_list_store_set(playlist_editor_store, &iter, PL_MTIME, data->playlist->mtime, -1);
334 /* do nothing */
335 path = gtk_tree_model_get_path(GTK_TREE_MODEL(playlist_editor_store), &iter);
336 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(playlist_editor_store), &iter);
337 if (path)
339 if (gtk_tree_selection_path_is_selected
340 (gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view)), path))
342 if (mtime == NULL || data->playlist->mtime == NULL
343 || strcmp(mtime, data->playlist->mtime) != 0)
345 /* update view */
346 playlist_editor_browser_playlist_editor_changed(playlist_editor_icon_view, NULL);
349 gtk_tree_path_free(path);
351 g_free(mtime);
352 } else if (val > 0)
354 GtkTreeIter niter;
355 GdkPixbuf *pb = NULL;
356 if (g_utf8_collate(data->playlist->path, _("Favorites")))
358 pb = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "media-playlist", 32, 0, NULL);
359 } else
361 pb = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "emblem-favorite", 32, 0, NULL);
363 gtk_list_store_insert_before(playlist_editor_store, &niter, &iter);
364 gtk_list_store_set(playlist_editor_store, &niter, PL_NAME, data->playlist->path, PL_MTIME,
365 data->playlist->mtime, PL_IMAGE, pb, -1);
366 if (pb)
367 g_object_unref(pb);
368 } else
371 valid = gtk_list_store_remove(playlist_editor_store, &iter);
372 g_free(name);
373 goto loop;
375 g_free(name);
377 } else
379 GdkPixbuf *pb = NULL;
381 if (g_utf8_collate(data->playlist->path, _("Favorites")))
383 pb = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "media-playlist", 32, 0, NULL);
384 } else
386 pb = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "emblem-favorite", 32, 0, NULL);
388 gtk_list_store_append(playlist_editor_store, &iter);
389 gtk_list_store_set(playlist_editor_store, &iter, PL_NAME, data->playlist->path, PL_MTIME,
390 data->playlist->mtime, PL_IMAGE, pb, -1);
391 if (pb)
392 g_object_unref(pb);
398 while (valid)
400 valid = gtk_list_store_remove(playlist_editor_store, &iter);
404 /* if(playlist_editor_icon_view)
405 gtk_tree_selection_selected_foreach(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view)),
406 playlist_editor_browser_playlist_editor_selected, NULL);
409 /***
410 * Add url
412 static gboolean gufg_validate_callback(GmpcUrlFetchingGui *a, const gchar *url, void *user_data)
414 /* TODO add validator here, well probly url-fetcher validator */
415 return TRUE;
418 static void gufg_set_progress(gdouble prog, gpointer a)
420 gmpc_url_fetching_gui_set_progress(GMPC_URL_FETCHING_GUI(a), prog);
422 static void gufg_set_error(const gchar *error_msg, gpointer a)
424 gmpc_url_fetching_gui_set_error(GMPC_URL_FETCHING_GUI(a), error_msg);
426 static void gufg_set_result(GList *result, gpointer a)
428 const gchar *playlist_name = g_object_get_data(G_OBJECT(a), "playlist-name");
429 if(playlist_name)
431 GList *iter;
432 for(iter = g_list_first(result); iter; iter = g_list_next(iter))
434 mpd_database_playlist_list_add(connection, playlist_name, (const gchar *)iter->data);
437 gmpc_url_fetching_gui_set_completed(GMPC_URL_FETCHING_GUI(a));
439 static void gufg_parse_callback(GmpcUrlFetchingGui * a, const gchar * url,gpointer data)
441 gchar *playlist_name = (gchar *)data;
442 if(url != NULL)
444 gmpc_url_fetching_gui_set_processing(a);
445 g_object_set_data_full(G_OBJECT(a), "playlist-name", playlist_name, g_free);
446 url_start_custom(url,gufg_set_error, gufg_set_result,gufg_set_progress, a);
447 return;
449 else{
450 g_free(playlist_name);
452 gmpc_url_fetching_gui_set_completed(a);
454 static void playlist_editor_list_add_url(GtkButton * button, GtkTreeView * tree)
456 /* Get playlist name */
457 gchar *pl_path = NULL;
458 GtkTreeModel *model_view = gtk_tree_view_get_model(GTK_TREE_VIEW(playlist_editor_icon_view));
459 GList *it, *list =
460 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view)),
461 &model_view);
462 for (it = g_list_first(list); it; it = g_list_next(it))
464 GtkTreePath *path = it->data;
465 GtkTreeIter iter;
466 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist_editor_store), &iter, path) && !pl_path)
468 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store), &iter, PL_NAME, &pl_path, -1);
471 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
472 g_list_free(list);
473 if(pl_path)
475 gmpc_url_fetching_gui_new(gufg_parse_callback, pl_path, gufg_validate_callback, NULL, g_object_unref);
478 /*********
479 * Playlist list handling
481 static void playlist_editor_list_delete_songs(GtkButton * button, GtkTreeView * tree)
483 gchar *pl_path = NULL;
484 GtkTreeModel *model_view = gtk_tree_view_get_model(GTK_TREE_VIEW(playlist_editor_icon_view));
485 GList *it, *list =
486 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view)),
487 &model_view);
488 for (it = g_list_first(list); it; it = g_list_next(it))
490 GtkTreePath *path = it->data;
491 GtkTreeIter iter;
492 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist_editor_store), &iter, path) && !pl_path)
494 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store), &iter, PL_NAME, &pl_path, -1);
497 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
498 g_list_free(list);
500 if (pl_path)
502 GtkTreeSelection *sel = gtk_tree_view_get_selection(tree);
503 GtkTreeModel *model = gtk_tree_view_get_model(tree);
504 GList *data;
505 list = gtk_tree_selection_get_selected_rows(sel, &model);
506 for (data = g_list_last(list); data; data = g_list_previous(data))
508 GtkTreePath *path = data->data;
509 GtkTreeIter iter;
510 if (gtk_tree_model_get_iter(model, &iter, path))
512 int *pos = gtk_tree_path_get_indices(path);
513 mpd_database_playlist_list_delete(connection, pl_path, pos[0]);
516 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
517 g_list_free(list);
519 g_free(pl_path);
523 static void playlist_editor_list_add_songs(GtkButton * button, GtkTreeView * tree)
525 int songs = 0;
526 GtkTreeSelection *sel = gtk_tree_view_get_selection(tree);
527 GtkTreeModel *model = gtk_tree_view_get_model(tree);
528 GList *data, *list = gtk_tree_selection_get_selected_rows(sel, &model);
529 for (data = g_list_first(list); data; data = g_list_next(data))
531 GtkTreePath *path = data->data;
532 GtkTreeIter iter;
533 if (gtk_tree_model_get_iter(model, &iter, path))
535 gchar *song_path;
536 gtk_tree_model_get(model, &iter, MPDDATA_MODEL_COL_PATH, &song_path, -1);
537 mpd_playlist_queue_add(connection, song_path);
538 songs++;
539 g_free(song_path);
542 mpd_playlist_queue_commit(connection);
543 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
544 g_list_free(list);
547 static void playlist_editor_list_replace_songs(GtkButton * button, GtkTreeView * tree)
549 mpd_playlist_clear(connection);
550 playlist_editor_list_add_songs(button, tree);
551 mpd_player_play(connection);
554 static void playlist_editor_clear_playlist_real(GtkWidget * item, gpointer data)
556 gchar *path = g_object_get_data(G_OBJECT(item), "path");
557 mpd_database_playlist_clear(connection, path);
558 playlist_editor_browser_playlist_editor_changed(playlist_editor_icon_view, NULL);
561 static void playlist_editor_clear_playlist(GtkWidget * item, gpointer data)
563 GtkWidget *delete;
564 gchar *path = g_object_get_data(G_OBJECT(item), "path");
565 gchar *message = g_strdup_printf(_("Are you sure you want to clear the playlist: '%s'"), path);
567 delete = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
569 g_object_set_data_full(G_OBJECT(delete), "path", g_strdup(path), g_free);
570 g_signal_connect(G_OBJECT(delete), "clicked",
571 G_CALLBACK(playlist_editor_clear_playlist_real), NULL);
573 /* show message */
574 playlist3_message_show(pl3_messages, message,USER_FEEDBACK);
575 playlist3_message_add_widget(pl3_messages, delete);
576 g_free(message);
579 static void playlist_editor_load_playlist(GtkWidget * item, gpointer data)
581 gchar *path = g_object_get_data(G_OBJECT(item), "path");
582 mpd_playlist_queue_load(connection, path);
583 mpd_playlist_queue_commit(connection);
586 static void playlist_editor_replace_playlist(GtkWidget * item, gpointer data)
588 gchar *path = g_object_get_data(G_OBJECT(item), "path");
589 mpd_playlist_clear(connection);
590 mpd_playlist_queue_load(connection, path);
591 mpd_playlist_queue_commit(connection);
592 mpd_player_play(connection);
594 static void playlist_editor_delete_playlist_real(GtkWidget * item, gpointer data)
596 gchar *path = g_object_get_data(G_OBJECT(item), "path");
597 mpd_database_delete_playlist(connection, path);
598 playlist_editor_fill_list();
601 static void playlist_editor_delete_playlist(GtkWidget * item, gpointer data)
603 GtkWidget *delete;
604 gchar *path = g_object_get_data(G_OBJECT(item), "path");
605 gchar *message = g_strdup_printf(_("Are you sure you want to delete the playlist: '%s'"), path);
607 delete = gtk_button_new_from_stock(GTK_STOCK_DELETE);
609 g_object_set_data_full(G_OBJECT(delete), "path", g_strdup(path), g_free);
610 g_signal_connect(G_OBJECT(delete), "clicked",
611 G_CALLBACK(playlist_editor_delete_playlist_real), NULL);
613 /* show message */
614 playlist3_message_show(pl3_messages, message,USER_FEEDBACK);
615 playlist3_message_add_widget(pl3_messages, delete);
616 g_free(message);
619 static void playlist_editor_new_entry_changed(GtkEntry * entry, GtkWidget * button)
621 if (strlen(gtk_entry_get_text(entry)) > 0)
623 /* todo check existing */
624 gtk_widget_set_sensitive(button, TRUE);
625 } else
627 gtk_widget_set_sensitive(button, FALSE);
631 static void playlist_editor_new_entry_activate(GtkEntry * entry, GtkWidget * button)
633 if (strlen(gtk_entry_get_text(entry)) > 0)
634 g_signal_emit_by_name(G_OBJECT(button), "clicked");
637 static void playlist_editor_new_playlist(GtkWidget * item, gpointer data)
639 int done = 0;
640 GtkWidget *pl3_win = playlist3_get_window();
641 GtkWidget *dialog =
642 gtk_dialog_new_with_buttons(_("New Playlist"), NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
643 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
644 NULL);
645 GtkWidget *button = NULL;
646 GtkWidget *hbox = gtk_hbox_new(FALSE, 6);
647 GtkWidget *label = gtk_label_new(_("Name:"));
648 GtkWidget *entry = gtk_entry_new();
649 gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
650 gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(pl3_win));
651 button = gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_NEW, GTK_RESPONSE_ACCEPT);
652 g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(playlist_editor_new_entry_changed), button);
653 g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(playlist_editor_new_entry_activate), button);
654 gtk_widget_set_sensitive(button, FALSE);
655 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), hbox, TRUE, TRUE, 0);
657 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
658 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, FALSE, 0);
659 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, FALSE, 0);
660 gtk_container_set_border_width(GTK_CONTAINER(hbox), 9);
661 gtk_container_set_border_width(GTK_CONTAINER(dialog), 3);
662 gtk_widget_show_all(dialog);
663 while (!done)
665 switch (gtk_dialog_run(GTK_DIALOG(dialog)))
667 case GTK_RESPONSE_ACCEPT:
668 g_object_set_data_full(G_OBJECT(item), "playlist", g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))), g_free);
669 mpd_database_playlist_clear(connection, gtk_entry_get_text(GTK_ENTRY(entry)));
670 playlist_editor_fill_list();
672 default:
673 done = TRUE;
674 break;
677 gtk_widget_destroy(dialog);
680 static void playlist_editor_rename_playlist(GtkWidget * item, gpointer data)
682 int done = 0;
683 char *name = g_object_get_data(G_OBJECT(item), "path");
684 GtkWidget *dialog =
685 gtk_dialog_new_with_buttons(_("Rename Playlist"), NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
686 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
687 NULL);
688 GtkWidget *button = NULL;
689 GtkWidget *hbox = gtk_hbox_new(FALSE, 6);
690 GtkWidget *label = gtk_label_new(_("Name:"));
691 GtkWidget *entry = gtk_entry_new();
692 button = gtk_dialog_add_button(GTK_DIALOG(dialog), _("Rename"), GTK_RESPONSE_ACCEPT);
693 g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(playlist_editor_new_entry_changed), button);
694 gtk_entry_set_text(GTK_ENTRY(entry), name);
695 gtk_widget_set_sensitive(button, FALSE);
696 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(dialog)), hbox, TRUE, TRUE, 0);
698 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
699 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, FALSE, 0);
700 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, FALSE, 0);
701 gtk_container_set_border_width(GTK_CONTAINER(hbox), 9);
702 gtk_container_set_border_width(GTK_CONTAINER(dialog), 3);
704 gtk_widget_show_all(dialog);
705 while (!done)
707 switch (gtk_dialog_run(GTK_DIALOG(dialog)))
709 case GTK_RESPONSE_ACCEPT:
710 mpd_database_playlist_rename(connection, name, gtk_entry_get_text(GTK_ENTRY(entry)));
711 playlist_editor_fill_list();
712 default:
713 done = TRUE;
714 break;
717 gtk_widget_destroy(dialog);
720 static gboolean playlist_editor_key_released(GtkTreeView * tree, GdkEventButton * button, gpointer data)
722 if (button->button == 3)
724 GtkTreeSelection *sel = gtk_tree_view_get_selection(tree);
726 GtkWidget *menu = gtk_menu_new();
727 GtkWidget *item = NULL;
728 if (gtk_tree_selection_count_selected_rows(sel) > 0)
730 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD, NULL);
731 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
732 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_list_add_songs), tree);
734 item = gtk_image_menu_item_new_with_label(_("Replace"));
735 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
736 gtk_image_new_from_stock(GTK_STOCK_REDO, GTK_ICON_SIZE_MENU));
737 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
738 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_list_replace_songs), tree);
739 if (mpd_server_check_version(connection, 0, 13, 0))
741 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_REMOVE, NULL);
742 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
743 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_list_delete_songs), tree);
748 * add url to playlist
750 item = gtk_image_menu_item_new_with_label(_("Add URL"));
751 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
752 gtk_image_new_from_icon_name("add-url", GTK_ICON_SIZE_MENU));
753 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
755 //gmpc_mpddata_treeview_right_mouse_intergration(GMPC_MPDDATA_TREEVIEW(tree), GTK_MENU(menu));
756 //g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_list_add_url), tree);
758 gtk_widget_show_all(menu);
759 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, button->time);
760 return TRUE;
762 return FALSE;
765 static gboolean playlist_editor_key_pressed(GtkWidget * giv, GdkEventKey * event, gpointer data)
767 if (event->keyval == GDK_KEY_Delete)
769 playlist_editor_list_delete_songs(NULL, GTK_TREE_VIEW(giv));
772 return FALSE;
775 static gboolean playlist_editor_browser_button_release_event(GtkWidget * giv, GdkEventButton * event, gpointer data)
777 if (event->button == 3)
779 GtkTreeModel *model_view = gtk_tree_view_get_model(GTK_TREE_VIEW(playlist_editor_icon_view));
780 GtkWidget *menu = gtk_menu_new();
781 GtkWidget *item = NULL;
782 GList *list = NULL;
783 /* New */
784 if (mpd_server_check_version(connection, 0, 13, 0))
786 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL);
787 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
788 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_new_playlist), NULL);
791 list = gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(giv)), &model_view);
792 if (list)
794 char *path = NULL;
795 GtkTreeIter iter;
796 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist_editor_store), &iter, (GtkTreePath *) list->data))
798 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store), &iter, PL_NAME, &path, -1);
800 /* replace */
801 item = gtk_image_menu_item_new_with_label(_("Replace"));
802 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
803 gtk_image_new_from_stock(GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU));
804 g_object_set_data_full(G_OBJECT(item), "path", g_strdup(path), g_free);
805 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item);
806 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_replace_playlist), NULL);
807 /* load */
808 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD, NULL);
809 g_object_set_data_full(G_OBJECT(item), "path", g_strdup(path), g_free);
810 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item);
811 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_load_playlist), NULL);
813 /* delete */
814 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_DELETE, NULL);
815 g_object_set_data_full(G_OBJECT(item), "path", g_strdup(path), g_free);
816 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
817 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_delete_playlist), NULL);
819 if (mpd_server_check_version(connection, 0, 13, 0))
821 /* delete */
822 item = gtk_image_menu_item_new_with_label(_("Rename"));
823 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
824 gtk_image_new_from_stock(GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU));
825 g_object_set_data_full(G_OBJECT(item), "path", g_strdup(path), g_free);
826 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
827 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_rename_playlist), NULL);
829 /* clear */
830 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
831 g_object_set_data_full(G_OBJECT(item), "path", g_strdup(path), g_free);
832 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
833 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_clear_playlist), NULL);
836 g_free(path);
838 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
839 g_list_free(list);
842 gtk_widget_show_all(menu);
843 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, event->time);
844 return TRUE;
846 return FALSE;
849 static void playtime_changed(GmpcMpdDataModel * model, gulong playtime)
854 * Selected songs are cut, now it has to be deleted
856 static void playlist_editor_cut_songs(GtkTreeView * tree)
858 playlist_editor_list_delete_songs(NULL, tree);
861 static void playlist_editor_paste_after_songs(GtkTreeView * tree, GList * paste_list)
863 gchar *pl_path = NULL;
864 GtkTreeModel *model_view = gtk_tree_view_get_model(GTK_TREE_VIEW(playlist_editor_icon_view));
865 GList *it, *list =
866 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view)),
867 &model_view);
868 for (it = g_list_first(list); it; it = g_list_next(it))
870 GtkTreePath *path = it->data;
871 GtkTreeIter iter;
872 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist_editor_store), &iter, path) && !pl_path)
874 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store), &iter, PL_NAME, &pl_path, -1);
877 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
878 g_list_free(list);
880 if (pl_path)
882 /* grab the selection from the tree */
883 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
884 /* check if where connected */
885 /* see if there is a row selected */
886 if (gtk_tree_selection_count_selected_rows(selection) > 0)
888 GList *llist = NULL;
889 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree));
890 /* start a command list */
891 /* grab the selected songs */
892 list = gtk_tree_selection_get_selected_rows(selection, &model);
893 /* grab the last song that is selected */
894 llist = g_list_last(list);
895 /* remove every selected song one by one */
896 if (llist)
898 int id;
899 char *path = NULL;
900 int *indices = gtk_tree_path_get_indices((GtkTreePath *) llist->data);
901 int length = GMPC_MPDDATA_MODEL(model)->num_rows;
902 GList *liter = g_list_first(paste_list);
903 id = indices[0];
904 while (liter)
906 path = liter->data;
907 mpd_database_playlist_list_add(connection, pl_path, path);
908 mpd_database_playlist_move(connection, pl_path, length, id + 1);
909 length++;
910 liter = g_list_next(liter);
913 /* free list */
914 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
915 g_list_free(list);
916 } else
918 GList *liter = g_list_last(paste_list);;
919 while (liter)
921 char *path = liter->data;
922 mpd_database_playlist_list_add(connection, pl_path, path);
923 liter = g_list_previous(liter);
927 gtk_tree_selection_unselect_all(selection);
928 g_free(pl_path);
933 static void playlist_editor_paste_before_songs(GtkTreeView * tree, GList * paste_list)
935 gchar *pl_path = NULL;
936 GtkTreeModel *model_view = gtk_tree_view_get_model(GTK_TREE_VIEW(playlist_editor_icon_view));
937 GList *it, *list =
938 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view)),
939 &model_view);
940 for (it = g_list_first(list); it; it = g_list_next(it))
942 GtkTreePath *path = it->data;
943 GtkTreeIter iter;
944 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist_editor_store), &iter, path) && !pl_path)
946 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store), &iter, PL_NAME, &pl_path, -1);
949 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
950 g_list_free(list);
951 if (pl_path)
954 /* grab the selection from the tree */
955 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
957 /* check if where connected */
958 /* see if there is a row selected */
959 if (gtk_tree_selection_count_selected_rows(selection) > 0)
961 GList *llist = NULL;
962 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree));
963 /* start a command list */
964 /* grab the selected songs */
965 list = gtk_tree_selection_get_selected_rows(selection, &model);
966 /* grab the last song that is selected */
967 llist = g_list_first(list);
968 /* remove every selected song one by one */
969 if (llist)
971 int id;
972 int *indices = gtk_tree_path_get_indices((GtkTreePath *) llist->data);
973 int length = GMPC_MPDDATA_MODEL(model)->num_rows;
974 GList *liter = g_list_first(paste_list);
975 id = indices[0];
977 while (liter)
979 char *path = liter->data;
980 mpd_database_playlist_list_add(connection, pl_path, path);
981 mpd_database_playlist_move(connection, pl_path, length, id);
982 /* length one longer */
983 length++;
984 liter = g_list_next(liter);
987 /* free list */
988 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
989 g_list_free(list);
990 } else
992 GList *liter = g_list_last(paste_list);
993 while (liter)
995 char *path = liter->data;
996 mpd_database_playlist_list_add(connection, pl_path, path);
997 liter = g_list_previous(liter);
1002 gtk_tree_selection_unselect_all(selection);
1003 g_free(pl_path);
1007 static void playlist_editor_browser_init(void)
1009 GtkCellRenderer *renderer = NULL;
1010 GtkTreeViewColumn *column = NULL;
1011 GtkWidget *tree = NULL;
1012 GtkWidget *sw = NULL;
1013 /* */
1014 playlist_editor_browser = gtk_hpaned_new();
1015 gmpc_paned_size_group_add_paned(GMPC_PANED_SIZE_GROUP(paned_size_group), GTK_PANED(playlist_editor_browser));
1016 /** browser */
1017 sw = gtk_scrolled_window_new(NULL, NULL);
1018 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1019 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
1021 gtk_paned_add1(GTK_PANED(playlist_editor_browser), sw);
1023 /* icon view */
1024 playlist_editor_store = gtk_list_store_new(PL_NUM_COLS, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF);
1026 playlist_editor_icon_view = tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(playlist_editor_store)); //gtk_icon_view_new_with_model(GTK_TREE_MODEL(playlist_editor_store));
1027 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree), TRUE);
1029 column = gtk_tree_view_column_new();
1030 gtk_tree_view_column_set_title(column, _("Playlists"));
1031 renderer = gtk_cell_renderer_pixbuf_new();
1032 gtk_tree_view_column_pack_start(column, renderer, FALSE);
1033 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", PL_IMAGE);
1034 renderer = gtk_cell_renderer_text_new();
1035 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1036 gtk_tree_view_column_add_attribute(column, renderer, "text", PL_NAME);
1037 gtk_tree_view_insert_column(GTK_TREE_VIEW(tree), column, -1);
1039 /* gtk_icon_view_set_selection_mode(GTK_ICON_VIEW(tree), GTK_SELECTION_BROWSE);
1040 gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(tree), PL_IMAGE);
1041 gtk_icon_view_set_text_column(GTK_ICON_VIEW(tree), PL_NAME); */
1042 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)), GTK_SELECTION_BROWSE);
1043 gtk_container_add(GTK_CONTAINER(sw), tree);
1045 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree))), "changed",
1046 G_CALLBACK(playlist_editor_browser_playlist_editor_changed_real), NULL);
1047 // g_signal_connect(G_OBJECT(tree), "item-activated", G_CALLBACK(playlist_editor_browser_activate_cursor_item), NULL);
1048 g_signal_connect(G_OBJECT(tree), "button-release-event", G_CALLBACK(playlist_editor_browser_button_release_event),
1049 NULL);
1051 /* file list */
1053 sw = gtk_scrolled_window_new(NULL, NULL);
1054 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1055 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
1057 // gtk_box_pack_start(GTK_BOX(playlist_editor_browser), sw, TRUE, TRUE,0);
1058 gtk_paned_add2(GTK_PANED(playlist_editor_browser), sw);
1060 playlist_editor_list_store = gmpc_mpddata_model_sort_new();
1061 gmpc_mpddata_model_disable_image(GMPC_MPDDATA_MODEL(playlist_editor_list_store));
1062 g_signal_connect(G_OBJECT(playlist_editor_list_store), "playtime_changed", G_CALLBACK(playtime_changed), NULL);
1064 playlist_editor_song_tree = tree = gmpc_data_view_new("playlist-browser",
1065 GMPC_DATA_VIEW_VIEW_TYPE_PLAYLIST);
1066 gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(playlist_editor_list_store));
1068 /* Copy paste routines */
1069 // g_signal_connect(G_OBJECT(tree), "cut", G_CALLBACK(playlist_editor_cut_songs), NULL);
1070 // g_signal_connect(G_OBJECT(tree), "paste-after", G_CALLBACK(playlist_editor_paste_after_songs), NULL);
1071 // g_signal_connect(G_OBJECT(tree), "paste-before", G_CALLBACK(playlist_editor_paste_before_songs), NULL);
1073 gtk_container_add(GTK_CONTAINER(sw), tree);
1074 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(tree), TRUE);
1076 // g_signal_connect(G_OBJECT(tree), "button-release-event", G_CALLBACK(playlist_editor_key_released), NULL);
1077 // g_signal_connect(G_OBJECT(tree), "key-press-event", G_CALLBACK(playlist_editor_key_pressed), NULL);
1078 g_object_ref_sink(playlist_editor_browser);
1080 gtk_widget_show_all(playlist_editor_browser);
1082 gtk_widget_set_sensitive(GTK_WIDGET(playlist_editor_browser), !pl3_editor_disabled);
1085 void playlist_editor_browser_selected(GtkWidget * container)
1087 if (!playlist_editor_browser)
1089 playlist_editor_browser_init();
1090 playlist_editor_fill_list_real();
1092 gtk_container_add(GTK_CONTAINER(container), playlist_editor_browser);
1093 gtk_widget_show_all(playlist_editor_browser);
1096 void playlist_editor_browser_unselected(GtkWidget * container)
1098 gtk_container_remove(GTK_CONTAINER(container), playlist_editor_browser);
1101 int playlist_editor_browser_cat_menu(GtkWidget * menu, int type, GtkWidget * tree, GdkEventButton * event)
1103 if (type == playlist_editor_plugin.id)
1106 return 0;
1109 static void playlist_editor_add_to_new(GtkWidget * item, gpointer data)
1111 gpointer cb_data = g_object_get_data(G_OBJECT(item), "cb-data");
1112 void (*callback) (GtkWidget * item, gpointer data) = data;
1114 playlist_editor_new_playlist(item, NULL);
1115 callback(item, cb_data);
1119 void playlist_editor_right_mouse(GtkWidget * menu, void (*add_to_playlist) (GtkWidget *menu, gpointer data),
1120 gpointer cb_data)
1122 GtkWidget *sitem;
1123 GtkWidget *item;
1124 GtkWidget *smenu;
1126 if (!mpd_server_check_version(connection, 0, 13, 0))
1128 return;
1131 smenu = gtk_menu_new();
1133 sitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL);
1134 g_object_set_data(G_OBJECT(sitem), "cb-data", cb_data);
1135 g_signal_connect(G_OBJECT(sitem), "activate", G_CALLBACK(playlist_editor_add_to_new), add_to_playlist);
1136 gtk_menu_shell_append(GTK_MENU_SHELL(smenu), sitem);
1139 MpdData *data = mpd_database_playlist_list(connection);
1140 data = misc_sort_mpddata(data, (GCompareDataFunc) __sort_func, NULL);
1141 for (; data; data = mpd_data_get_next(data))
1143 if (data->type == MPD_DATA_TYPE_PLAYLIST)
1146 sitem = gtk_image_menu_item_new_with_label(data->playlist->path);
1147 if (g_utf8_collate(data->playlist->path, _("Favorites")) == 0)
1149 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(sitem),
1150 gtk_image_new_from_icon_name("emblem-favorite", GTK_ICON_SIZE_MENU));
1151 } else
1153 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(sitem),
1154 gtk_image_new_from_icon_name("media-playlist", GTK_ICON_SIZE_MENU));
1156 g_object_set_data_full(G_OBJECT(sitem), "playlist", g_strdup(data->playlist->path), g_free);
1157 gtk_menu_shell_append(GTK_MENU_SHELL(smenu), sitem);
1158 g_signal_connect(G_OBJECT(sitem), "activate", G_CALLBACK(add_to_playlist), cb_data);
1159 gtk_widget_show(sitem);
1164 /* Add */
1165 item = gtk_menu_item_new_with_label(_("Add to playlist"));
1166 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), smenu);
1167 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1168 gtk_widget_show(item);
1170 gtk_widget_show(smenu);
1173 static void playlist_editor_status_changed(MpdObj * mi, ChangedStatusType what, void *data)
1175 if (what & MPD_CST_STORED_PLAYLIST)
1177 playlist_editor_fill_list_real();
1181 static void playlist_editor_activate(GtkWidget * item, gpointer data)
1183 GtkTreeSelection *selec = gtk_tree_view_get_selection((GtkTreeView *) playlist3_get_category_tree_view());
1185 if (playlist_editor_browser_ref)
1187 GtkTreePath *path = gtk_tree_row_reference_get_path(playlist_editor_browser_ref);
1188 if (path)
1190 gtk_tree_selection_select_path(selec, path);
1191 gtk_tree_path_free(path);
1196 static void favorites_add_current_song(void)
1198 mpd_Song *song = mpd_playlist_get_current_song(connection);
1199 if (song != NULL && song->file != NULL)
1201 if(favorites)
1203 gmpc_favorites_list_set_favorite(favorites, song->file,
1204 !gmpc_favorites_list_is_favorite(favorites, song->file));
1205 playlist3_show_error_message(_("Added playing song to favorites list."), ERROR_INFO);
1210 static int playlist_editor_add_go_menu(GtkWidget * menu)
1212 GtkWidget *item = NULL;
1213 if (!cfg_get_single_value_as_int_with_default(config, "playlist-plugin", "enable", 1))
1214 return 0;
1215 item = gtk_image_menu_item_new_with_label(_("Playlist Editor"));
1216 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
1217 gtk_image_new_from_icon_name("media-playlist", GTK_ICON_SIZE_MENU));
1219 gtk_widget_add_accelerator(GTK_WIDGET(item),
1220 "activate", gtk_menu_get_accel_group(GTK_MENU(menu)), GDK_KEY_F5, 0, GTK_ACCEL_VISIBLE);
1221 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1222 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_activate), NULL);
1223 /** */
1224 item = gtk_image_menu_item_new_with_label(_("Add Current Song to favorites"));
1225 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
1226 gtk_image_new_from_icon_name("emblem-favorite", GTK_ICON_SIZE_MENU));
1227 gtk_widget_add_accelerator(GTK_WIDGET(item), "activate", gtk_menu_get_accel_group(GTK_MENU(menu)), GDK_KEY_Return,
1228 GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
1229 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(favorites_add_current_song), NULL);
1231 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1233 return 1;
1236 static void playlist_editor_save_myself(void)
1238 if (playlist_editor_browser_ref)
1240 GtkTreePath *path = gtk_tree_row_reference_get_path(playlist_editor_browser_ref);
1241 if (path)
1243 gint *indices = gtk_tree_path_get_indices(path);
1244 cfg_set_single_value_as_int(config, "playlist-plugin", "position", indices[0]);
1245 gtk_tree_path_free(path);