Add new gmpc-data-view (DOES NOT WORK COMPLETELY)
[gmpc.git] / src / browsers / playlist3-playlist-editor.c
blob47bea6bf143bd7f615b55f57ab80440f0a4ac0ce
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_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(playlist_editor_list_store), NULL);
223 gmpc_mpddata_model_sort_set_playlist(GMPC_MPDDATA_MODEL_SORT(playlist_editor_list_store), pl_path);
224 mpd_async_request(__playlist_editor_async_callback, NULL, __playlist_editor_async_function, g_strdup(pl_path));
225 if (old_playlist)
226 g_free(old_playlist);
227 old_playlist = pl_path;
231 /* always forces an update */
232 static void playlist_editor_browser_playlist_editor_changed(GtkWidget * giv, gpointer data)
234 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view));
235 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(playlist_editor_icon_view));
236 GtkTreeIter iter;
237 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(playlist_editor_list_store), NULL);
238 gmpc_mpddata_model_sort_set_playlist(GMPC_MPDDATA_MODEL_SORT(playlist_editor_list_store), NULL);
239 /* Need to catch wrong changed signals here */
240 if (gtk_tree_selection_get_selected(sel, &model, &iter))
242 playlist_editor_browser_playlist_editor_selected(model, NULL, &iter, data);
247 static void playlist_editor_browser_playlist_editor_changed_real(GtkWidget * giv, gpointer data)
249 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view));
250 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(playlist_editor_icon_view));
251 GtkTreeIter iter;
252 /* Need to catch wrong changed signals here */
253 if (gtk_tree_selection_get_selected(sel, &model, &iter))
255 gchar *pl_path = NULL;
256 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, PL_NAME, &pl_path, -1);
257 if (pl_path)
259 if (old_playlist && g_utf8_collate(pl_path, old_playlist) == 0)
261 g_free(pl_path);
262 return;
264 g_free(pl_path);
266 playlist_editor_browser_playlist_editor_selected(model, NULL, &iter, data);
267 return;
269 /* Clear if nothing found */
270 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(playlist_editor_list_store), NULL);
271 gmpc_mpddata_model_sort_set_playlist(GMPC_MPDDATA_MODEL_SORT(playlist_editor_list_store), NULL);
274 static gint __sort_func(gpointer aa, gpointer bb, gpointer c)
276 MpdData_real *a = *(MpdData_real **) aa;
277 MpdData_real *b = *(MpdData_real **) bb;
278 if (a->type == MPD_DATA_TYPE_PLAYLIST && b->type == MPD_DATA_TYPE_PLAYLIST)
280 if (a->playlist->path == NULL && b->playlist->path != NULL)
281 return -1;
282 else if (b->playlist->path == NULL && a->playlist->path != NULL)
283 return 1;
284 else if (a->playlist->path && b->playlist->path)
286 int val;
287 gchar *sa, *sb;
288 sa = g_utf8_strdown(a->playlist->path, -1);
289 sb = g_utf8_strdown(b->playlist->path, -1);
290 val = g_utf8_collate(sa, sb);
291 g_free(sa);
292 g_free(sb);
293 return val;
296 return a->type - b->type;
299 void playlist_editor_fill_list(void)
301 if (!mpd_server_has_idle(connection))
303 playlist_editor_fill_list_real();
307 void playlist_editor_fill_list_real(void)
309 GtkTreeIter iter;
310 if (playlist_editor_browser && !pl3_editor_disabled)
312 gboolean valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(playlist_editor_store), &iter);
313 MpdData *data = mpd_database_playlist_list(connection);
314 data = misc_sort_mpddata(data, (GCompareDataFunc) __sort_func, NULL);
315 for (; data; data = mpd_data_get_next(data))
317 if (data->type == MPD_DATA_TYPE_PLAYLIST)
319 loop:
320 if (valid)
322 char *name = NULL;
323 int val = 0;
324 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store), &iter, PL_NAME, &name, -1);
325 val = strcmp(name, data->playlist->path);
327 if (val == 0)
329 GtkTreePath *path = NULL;
330 gchar *mtime = NULL;
331 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store), &iter, PL_MTIME, &mtime, -1);
332 gtk_list_store_set(playlist_editor_store, &iter, PL_MTIME, data->playlist->mtime, -1);
333 /* do nothing */
334 path = gtk_tree_model_get_path(GTK_TREE_MODEL(playlist_editor_store), &iter);
335 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(playlist_editor_store), &iter);
336 if (path)
338 if (gtk_tree_selection_path_is_selected
339 (gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view)), path))
341 if (mtime == NULL || data->playlist->mtime == NULL
342 || strcmp(mtime, data->playlist->mtime) != 0)
344 /* update view */
345 playlist_editor_browser_playlist_editor_changed(playlist_editor_icon_view, NULL);
348 gtk_tree_path_free(path);
350 g_free(mtime);
351 } else if (val > 0)
353 GtkTreeIter niter;
354 GdkPixbuf *pb = NULL;
355 if (g_utf8_collate(data->playlist->path, _("Favorites")))
357 pb = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "media-playlist", 32, 0, NULL);
358 } else
360 pb = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "emblem-favorite", 32, 0, NULL);
362 gtk_list_store_insert_before(playlist_editor_store, &niter, &iter);
363 gtk_list_store_set(playlist_editor_store, &niter, PL_NAME, data->playlist->path, PL_MTIME,
364 data->playlist->mtime, PL_IMAGE, pb, -1);
365 if (pb)
366 g_object_unref(pb);
367 } else
370 valid = gtk_list_store_remove(playlist_editor_store, &iter);
371 g_free(name);
372 goto loop;
374 g_free(name);
376 } else
378 GdkPixbuf *pb = NULL;
380 if (g_utf8_collate(data->playlist->path, _("Favorites")))
382 pb = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "media-playlist", 32, 0, NULL);
383 } else
385 pb = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "emblem-favorite", 32, 0, NULL);
387 gtk_list_store_append(playlist_editor_store, &iter);
388 gtk_list_store_set(playlist_editor_store, &iter, PL_NAME, data->playlist->path, PL_MTIME,
389 data->playlist->mtime, PL_IMAGE, pb, -1);
390 if (pb)
391 g_object_unref(pb);
397 while (valid)
399 valid = gtk_list_store_remove(playlist_editor_store, &iter);
403 /* if(playlist_editor_icon_view)
404 gtk_tree_selection_selected_foreach(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view)),
405 playlist_editor_browser_playlist_editor_selected, NULL);
408 /***
409 * Add url
411 static gboolean gufg_validate_callback(GmpcUrlFetchingGui *a, const gchar *url, void *user_data)
413 /* TODO add validator here, well probly url-fetcher validator */
414 return TRUE;
417 static void gufg_set_progress(gdouble prog, gpointer a)
419 gmpc_url_fetching_gui_set_progress(GMPC_URL_FETCHING_GUI(a), prog);
421 static void gufg_set_error(const gchar *error_msg, gpointer a)
423 gmpc_url_fetching_gui_set_error(GMPC_URL_FETCHING_GUI(a), error_msg);
425 static void gufg_set_result(GList *result, gpointer a)
427 const gchar *playlist_name = g_object_get_data(G_OBJECT(a), "playlist-name");
428 if(playlist_name)
430 GList *iter;
431 for(iter = g_list_first(result); iter; iter = g_list_next(iter))
433 mpd_database_playlist_list_add(connection, playlist_name, (const gchar *)iter->data);
436 gmpc_url_fetching_gui_set_completed(GMPC_URL_FETCHING_GUI(a));
438 static void gufg_parse_callback(GmpcUrlFetchingGui * a, const gchar * url,gpointer data)
440 gchar *playlist_name = (gchar *)data;
441 if(url != NULL)
443 gmpc_url_fetching_gui_set_processing(a);
444 g_object_set_data_full(G_OBJECT(a), "playlist-name", playlist_name, g_free);
445 url_start_custom(url,gufg_set_error, gufg_set_result,gufg_set_progress, a);
446 return;
448 else{
449 g_free(playlist_name);
451 gmpc_url_fetching_gui_set_completed(a);
453 static void playlist_editor_list_add_url(GtkButton * button, GtkTreeView * tree)
455 /* Get playlist name */
456 gchar *pl_path = NULL;
457 GtkTreeModel *model_view = gtk_tree_view_get_model(GTK_TREE_VIEW(playlist_editor_icon_view));
458 GList *it, *list =
459 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view)),
460 &model_view);
461 for (it = g_list_first(list); it; it = g_list_next(it))
463 GtkTreePath *path = it->data;
464 GtkTreeIter iter;
465 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist_editor_store), &iter, path) && !pl_path)
467 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store), &iter, PL_NAME, &pl_path, -1);
470 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
471 g_list_free(list);
472 if(pl_path)
474 gmpc_url_fetching_gui_new(gufg_parse_callback, pl_path, gufg_validate_callback, NULL, g_object_unref);
477 /*********
478 * Playlist list handling
480 static void playlist_editor_list_delete_songs(GtkButton * button, GtkTreeView * tree)
482 gchar *pl_path = NULL;
483 GtkTreeModel *model_view = gtk_tree_view_get_model(GTK_TREE_VIEW(playlist_editor_icon_view));
484 GList *it, *list =
485 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view)),
486 &model_view);
487 for (it = g_list_first(list); it; it = g_list_next(it))
489 GtkTreePath *path = it->data;
490 GtkTreeIter iter;
491 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist_editor_store), &iter, path) && !pl_path)
493 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store), &iter, PL_NAME, &pl_path, -1);
496 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
497 g_list_free(list);
499 if (pl_path)
501 GtkTreeSelection *sel = gtk_tree_view_get_selection(tree);
502 GtkTreeModel *model = gtk_tree_view_get_model(tree);
503 GList *data;
504 list = gtk_tree_selection_get_selected_rows(sel, &model);
505 for (data = g_list_last(list); data; data = g_list_previous(data))
507 GtkTreePath *path = data->data;
508 GtkTreeIter iter;
509 if (gtk_tree_model_get_iter(model, &iter, path))
511 int *pos = gtk_tree_path_get_indices(path);
512 mpd_database_playlist_list_delete(connection, pl_path, pos[0]);
515 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
516 g_list_free(list);
518 g_free(pl_path);
522 static void playlist_editor_list_add_songs(GtkButton * button, GtkTreeView * tree)
524 int songs = 0;
525 GtkTreeSelection *sel = gtk_tree_view_get_selection(tree);
526 GtkTreeModel *model = gtk_tree_view_get_model(tree);
527 GList *data, *list = gtk_tree_selection_get_selected_rows(sel, &model);
528 for (data = g_list_first(list); data; data = g_list_next(data))
530 GtkTreePath *path = data->data;
531 GtkTreeIter iter;
532 if (gtk_tree_model_get_iter(model, &iter, path))
534 gchar *song_path;
535 gtk_tree_model_get(model, &iter, MPDDATA_MODEL_COL_PATH, &song_path, -1);
536 mpd_playlist_queue_add(connection, song_path);
537 songs++;
538 g_free(song_path);
541 mpd_playlist_queue_commit(connection);
542 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
543 g_list_free(list);
546 static void playlist_editor_list_replace_songs(GtkButton * button, GtkTreeView * tree)
548 mpd_playlist_clear(connection);
549 playlist_editor_list_add_songs(button, tree);
550 mpd_player_play(connection);
553 static void playlist_editor_clear_playlist_real(GtkWidget * item, gpointer data)
555 gchar *path = g_object_get_data(G_OBJECT(item), "path");
556 mpd_database_playlist_clear(connection, path);
557 playlist_editor_browser_playlist_editor_changed(playlist_editor_icon_view, NULL);
560 static void playlist_editor_clear_playlist(GtkWidget * item, gpointer data)
562 GtkWidget *delete;
563 gchar *path = g_object_get_data(G_OBJECT(item), "path");
564 gchar *message = g_strdup_printf(_("Are you sure you want to clear the playlist: '%s'"), path);
566 delete = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
568 g_object_set_data_full(G_OBJECT(delete), "path", g_strdup(path), g_free);
569 g_signal_connect(G_OBJECT(delete), "clicked",
570 G_CALLBACK(playlist_editor_clear_playlist_real), NULL);
572 /* show message */
573 playlist3_message_show(pl3_messages, message,USER_FEEDBACK);
574 playlist3_message_add_widget(pl3_messages, delete);
575 g_free(message);
578 static void playlist_editor_load_playlist(GtkWidget * item, gpointer data)
580 gchar *path = g_object_get_data(G_OBJECT(item), "path");
581 mpd_playlist_queue_load(connection, path);
582 mpd_playlist_queue_commit(connection);
585 static void playlist_editor_replace_playlist(GtkWidget * item, gpointer data)
587 gchar *path = g_object_get_data(G_OBJECT(item), "path");
588 mpd_playlist_clear(connection);
589 mpd_playlist_queue_load(connection, path);
590 mpd_playlist_queue_commit(connection);
591 mpd_player_play(connection);
593 static void playlist_editor_delete_playlist_real(GtkWidget * item, gpointer data)
595 gchar *path = g_object_get_data(G_OBJECT(item), "path");
596 mpd_database_delete_playlist(connection, path);
597 playlist_editor_fill_list();
600 static void playlist_editor_delete_playlist(GtkWidget * item, gpointer data)
602 GtkWidget *delete;
603 gchar *path = g_object_get_data(G_OBJECT(item), "path");
604 gchar *message = g_strdup_printf(_("Are you sure you want to delete the playlist: '%s'"), path);
606 delete = gtk_button_new_from_stock(GTK_STOCK_DELETE);
608 g_object_set_data_full(G_OBJECT(delete), "path", g_strdup(path), g_free);
609 g_signal_connect(G_OBJECT(delete), "clicked",
610 G_CALLBACK(playlist_editor_delete_playlist_real), NULL);
612 /* show message */
613 playlist3_message_show(pl3_messages, message,USER_FEEDBACK);
614 playlist3_message_add_widget(pl3_messages, delete);
615 g_free(message);
618 static void playlist_editor_new_entry_changed(GtkEntry * entry, GtkWidget * button)
620 if (strlen(gtk_entry_get_text(entry)) > 0)
622 /* todo check existing */
623 gtk_widget_set_sensitive(button, TRUE);
624 } else
626 gtk_widget_set_sensitive(button, FALSE);
630 static void playlist_editor_new_entry_activate(GtkEntry * entry, GtkWidget * button)
632 if (strlen(gtk_entry_get_text(entry)) > 0)
633 g_signal_emit_by_name(G_OBJECT(button), "clicked");
636 static void playlist_editor_new_playlist(GtkWidget * item, gpointer data)
638 int done = 0;
639 GtkWidget *pl3_win = playlist3_get_window();
640 GtkWidget *dialog =
641 gtk_dialog_new_with_buttons(_("New Playlist"), NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
642 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
643 NULL);
644 GtkWidget *button = NULL;
645 GtkWidget *hbox = gtk_hbox_new(FALSE, 6);
646 GtkWidget *label = gtk_label_new(_("Name:"));
647 GtkWidget *entry = gtk_entry_new();
648 gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
649 gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(pl3_win));
650 button = gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_NEW, GTK_RESPONSE_ACCEPT);
651 g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(playlist_editor_new_entry_changed), button);
652 g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(playlist_editor_new_entry_activate), button);
653 gtk_widget_set_sensitive(button, FALSE);
654 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), hbox, TRUE, TRUE, 0);
656 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
657 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, FALSE, 0);
658 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, FALSE, 0);
659 gtk_container_set_border_width(GTK_CONTAINER(hbox), 9);
660 gtk_container_set_border_width(GTK_CONTAINER(dialog), 3);
661 gtk_widget_show_all(dialog);
662 while (!done)
664 switch (gtk_dialog_run(GTK_DIALOG(dialog)))
666 case GTK_RESPONSE_ACCEPT:
667 g_object_set_data_full(G_OBJECT(item), "playlist", g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))), g_free);
668 mpd_database_playlist_clear(connection, gtk_entry_get_text(GTK_ENTRY(entry)));
669 playlist_editor_fill_list();
671 default:
672 done = TRUE;
673 break;
676 gtk_widget_destroy(dialog);
679 static void playlist_editor_rename_playlist(GtkWidget * item, gpointer data)
681 int done = 0;
682 char *name = g_object_get_data(G_OBJECT(item), "path");
683 GtkWidget *dialog =
684 gtk_dialog_new_with_buttons(_("Rename Playlist"), NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
685 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
686 NULL);
687 GtkWidget *button = NULL;
688 GtkWidget *hbox = gtk_hbox_new(FALSE, 6);
689 GtkWidget *label = gtk_label_new(_("Name:"));
690 GtkWidget *entry = gtk_entry_new();
691 button = gtk_dialog_add_button(GTK_DIALOG(dialog), _("Rename"), GTK_RESPONSE_ACCEPT);
692 g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(playlist_editor_new_entry_changed), button);
693 gtk_entry_set_text(GTK_ENTRY(entry), name);
694 gtk_widget_set_sensitive(button, FALSE);
695 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(dialog)), hbox, TRUE, TRUE, 0);
697 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
698 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, FALSE, 0);
699 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, FALSE, 0);
700 gtk_container_set_border_width(GTK_CONTAINER(hbox), 9);
701 gtk_container_set_border_width(GTK_CONTAINER(dialog), 3);
703 gtk_widget_show_all(dialog);
704 while (!done)
706 switch (gtk_dialog_run(GTK_DIALOG(dialog)))
708 case GTK_RESPONSE_ACCEPT:
709 mpd_database_playlist_rename(connection, name, gtk_entry_get_text(GTK_ENTRY(entry)));
710 playlist_editor_fill_list();
711 default:
712 done = TRUE;
713 break;
716 gtk_widget_destroy(dialog);
719 static gboolean playlist_editor_key_released(GtkTreeView * tree, GdkEventButton * button, gpointer data)
721 if (button->button == 3)
723 GtkTreeSelection *sel = gtk_tree_view_get_selection(tree);
725 GtkWidget *menu = gtk_menu_new();
726 GtkWidget *item = NULL;
727 if (gtk_tree_selection_count_selected_rows(sel) > 0)
729 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD, NULL);
730 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
731 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_list_add_songs), tree);
733 item = gtk_image_menu_item_new_with_label(_("Replace"));
734 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
735 gtk_image_new_from_stock(GTK_STOCK_REDO, GTK_ICON_SIZE_MENU));
736 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
737 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_list_replace_songs), tree);
738 if (mpd_server_check_version(connection, 0, 13, 0))
740 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_REMOVE, NULL);
741 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
742 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_list_delete_songs), tree);
747 * add url to playlist
749 item = gtk_image_menu_item_new_with_label(_("Add URL"));
750 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
751 gtk_image_new_from_icon_name("add-url", GTK_ICON_SIZE_MENU));
752 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
754 gmpc_mpddata_treeview_right_mouse_intergration(GMPC_MPDDATA_TREEVIEW(tree), GTK_MENU(menu));
755 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_list_add_url), tree);
757 gtk_widget_show_all(menu);
758 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, button->time);
759 return TRUE;
761 return FALSE;
764 static gboolean playlist_editor_key_pressed(GtkWidget * giv, GdkEventKey * event, gpointer data)
766 if (event->keyval == GDK_KEY_Delete)
768 playlist_editor_list_delete_songs(NULL, GTK_TREE_VIEW(giv));
771 return FALSE;
774 static gboolean playlist_editor_browser_button_release_event(GtkWidget * giv, GdkEventButton * event, gpointer data)
776 if (event->button == 3)
778 GtkTreeModel *model_view = gtk_tree_view_get_model(GTK_TREE_VIEW(playlist_editor_icon_view));
779 GtkWidget *menu = gtk_menu_new();
780 GtkWidget *item = NULL;
781 GList *list = NULL;
782 /* New */
783 if (mpd_server_check_version(connection, 0, 13, 0))
785 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL);
786 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
787 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_new_playlist), NULL);
790 list = gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(giv)), &model_view);
791 if (list)
793 char *path = NULL;
794 GtkTreeIter iter;
795 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist_editor_store), &iter, (GtkTreePath *) list->data))
797 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store), &iter, PL_NAME, &path, -1);
799 /* replace */
800 item = gtk_image_menu_item_new_with_label(_("Replace"));
801 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
802 gtk_image_new_from_stock(GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU));
803 g_object_set_data_full(G_OBJECT(item), "path", g_strdup(path), g_free);
804 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item);
805 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_replace_playlist), NULL);
806 /* load */
807 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD, NULL);
808 g_object_set_data_full(G_OBJECT(item), "path", g_strdup(path), g_free);
809 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item);
810 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_load_playlist), NULL);
812 /* delete */
813 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_DELETE, NULL);
814 g_object_set_data_full(G_OBJECT(item), "path", g_strdup(path), g_free);
815 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
816 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_delete_playlist), NULL);
818 if (mpd_server_check_version(connection, 0, 13, 0))
820 /* delete */
821 item = gtk_image_menu_item_new_with_label(_("Rename"));
822 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
823 gtk_image_new_from_stock(GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU));
824 g_object_set_data_full(G_OBJECT(item), "path", g_strdup(path), g_free);
825 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
826 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_rename_playlist), NULL);
828 /* clear */
829 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
830 g_object_set_data_full(G_OBJECT(item), "path", g_strdup(path), g_free);
831 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
832 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_clear_playlist), NULL);
835 g_free(path);
837 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
838 g_list_free(list);
841 gtk_widget_show_all(menu);
842 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, event->time);
843 return TRUE;
845 return FALSE;
848 static void playtime_changed(GmpcMpdDataModel * model, gulong playtime)
853 * Selected songs are cut, now it has to be deleted
855 static void playlist_editor_cut_songs(GtkTreeView * tree)
857 playlist_editor_list_delete_songs(NULL, tree);
860 static void playlist_editor_paste_after_songs(GtkTreeView * tree, GList * paste_list)
862 gchar *pl_path = NULL;
863 GtkTreeModel *model_view = gtk_tree_view_get_model(GTK_TREE_VIEW(playlist_editor_icon_view));
864 GList *it, *list =
865 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view)),
866 &model_view);
867 for (it = g_list_first(list); it; it = g_list_next(it))
869 GtkTreePath *path = it->data;
870 GtkTreeIter iter;
871 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist_editor_store), &iter, path) && !pl_path)
873 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store), &iter, PL_NAME, &pl_path, -1);
876 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
877 g_list_free(list);
879 if (pl_path)
881 /* grab the selection from the tree */
882 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
883 /* check if where connected */
884 /* see if there is a row selected */
885 if (gtk_tree_selection_count_selected_rows(selection) > 0)
887 GList *llist = NULL;
888 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree));
889 /* start a command list */
890 /* grab the selected songs */
891 list = gtk_tree_selection_get_selected_rows(selection, &model);
892 /* grab the last song that is selected */
893 llist = g_list_last(list);
894 /* remove every selected song one by one */
895 if (llist)
897 int id;
898 char *path = NULL;
899 int *indices = gtk_tree_path_get_indices((GtkTreePath *) llist->data);
900 int length = GMPC_MPDDATA_MODEL(model)->num_rows;
901 GList *liter = g_list_first(paste_list);
902 id = indices[0];
903 while (liter)
905 path = liter->data;
906 mpd_database_playlist_list_add(connection, pl_path, path);
907 mpd_database_playlist_move(connection, pl_path, length, id + 1);
908 length++;
909 liter = g_list_next(liter);
912 /* free list */
913 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
914 g_list_free(list);
915 } else
917 GList *liter = g_list_last(paste_list);;
918 while (liter)
920 char *path = liter->data;
921 mpd_database_playlist_list_add(connection, pl_path, path);
922 liter = g_list_previous(liter);
926 gtk_tree_selection_unselect_all(selection);
927 g_free(pl_path);
932 static void playlist_editor_paste_before_songs(GtkTreeView * tree, GList * paste_list)
934 gchar *pl_path = NULL;
935 GtkTreeModel *model_view = gtk_tree_view_get_model(GTK_TREE_VIEW(playlist_editor_icon_view));
936 GList *it, *list =
937 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view)),
938 &model_view);
939 for (it = g_list_first(list); it; it = g_list_next(it))
941 GtkTreePath *path = it->data;
942 GtkTreeIter iter;
943 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist_editor_store), &iter, path) && !pl_path)
945 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store), &iter, PL_NAME, &pl_path, -1);
948 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
949 g_list_free(list);
950 if (pl_path)
953 /* grab the selection from the tree */
954 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
956 /* check if where connected */
957 /* see if there is a row selected */
958 if (gtk_tree_selection_count_selected_rows(selection) > 0)
960 GList *llist = NULL;
961 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree));
962 /* start a command list */
963 /* grab the selected songs */
964 list = gtk_tree_selection_get_selected_rows(selection, &model);
965 /* grab the last song that is selected */
966 llist = g_list_first(list);
967 /* remove every selected song one by one */
968 if (llist)
970 int id;
971 int *indices = gtk_tree_path_get_indices((GtkTreePath *) llist->data);
972 int length = GMPC_MPDDATA_MODEL(model)->num_rows;
973 GList *liter = g_list_first(paste_list);
974 id = indices[0];
976 while (liter)
978 char *path = liter->data;
979 mpd_database_playlist_list_add(connection, pl_path, path);
980 mpd_database_playlist_move(connection, pl_path, length, id);
981 /* length one longer */
982 length++;
983 liter = g_list_next(liter);
986 /* free list */
987 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
988 g_list_free(list);
989 } else
991 GList *liter = g_list_last(paste_list);
992 while (liter)
994 char *path = liter->data;
995 mpd_database_playlist_list_add(connection, pl_path, path);
996 liter = g_list_previous(liter);
1001 gtk_tree_selection_unselect_all(selection);
1002 g_free(pl_path);
1006 static void playlist_editor_row_activated(GtkTreeView * tree, GtkTreePath * path, GtkTreeViewColumn * column,
1007 gpointer user_data)
1009 GtkTreeModel *model = gtk_tree_view_get_model(tree);
1010 GtkTreeIter iter;
1011 if (gtk_tree_model_get_iter(model, &iter, path))
1013 mpd_Song *song;
1014 gtk_tree_model_get(model, &iter, MPDDATA_MODEL_COL_MPDSONG, &song, -1);
1015 if (song->file)
1017 play_path(song->file);
1022 static void playlist_editor_browser_init(void)
1024 GtkCellRenderer *renderer = NULL;
1025 GtkTreeViewColumn *column = NULL;
1026 GtkWidget *tree = NULL;
1027 GtkWidget *sw = NULL;
1028 /* */
1029 playlist_editor_browser = gtk_hpaned_new();
1030 gmpc_paned_size_group_add_paned(GMPC_PANED_SIZE_GROUP(paned_size_group), GTK_PANED(playlist_editor_browser));
1031 /** browser */
1032 sw = gtk_scrolled_window_new(NULL, NULL);
1033 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1034 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
1036 gtk_paned_add1(GTK_PANED(playlist_editor_browser), sw);
1038 /* icon view */
1039 playlist_editor_store = gtk_list_store_new(PL_NUM_COLS, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF);
1041 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));
1042 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree), TRUE);
1044 column = gtk_tree_view_column_new();
1045 gtk_tree_view_column_set_title(column, _("Playlists"));
1046 renderer = gtk_cell_renderer_pixbuf_new();
1047 gtk_tree_view_column_pack_start(column, renderer, FALSE);
1048 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", PL_IMAGE);
1049 renderer = gtk_cell_renderer_text_new();
1050 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1051 gtk_tree_view_column_add_attribute(column, renderer, "text", PL_NAME);
1052 gtk_tree_view_insert_column(GTK_TREE_VIEW(tree), column, -1);
1054 /* gtk_icon_view_set_selection_mode(GTK_ICON_VIEW(tree), GTK_SELECTION_BROWSE);
1055 gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(tree), PL_IMAGE);
1056 gtk_icon_view_set_text_column(GTK_ICON_VIEW(tree), PL_NAME); */
1057 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)), GTK_SELECTION_BROWSE);
1058 gtk_container_add(GTK_CONTAINER(sw), tree);
1060 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree))), "changed",
1061 G_CALLBACK(playlist_editor_browser_playlist_editor_changed_real), NULL);
1062 // g_signal_connect(G_OBJECT(tree), "item-activated", G_CALLBACK(playlist_editor_browser_activate_cursor_item), NULL);
1063 g_signal_connect(G_OBJECT(tree), "button-release-event", G_CALLBACK(playlist_editor_browser_button_release_event),
1064 NULL);
1066 /* file list */
1068 sw = gtk_scrolled_window_new(NULL, NULL);
1069 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1070 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
1072 // gtk_box_pack_start(GTK_BOX(playlist_editor_browser), sw, TRUE, TRUE,0);
1073 gtk_paned_add2(GTK_PANED(playlist_editor_browser), sw);
1075 playlist_editor_list_store = gmpc_mpddata_model_sort_new();
1076 gmpc_mpddata_model_disable_image(GMPC_MPDDATA_MODEL(playlist_editor_list_store));
1077 g_signal_connect(G_OBJECT(playlist_editor_list_store), "playtime_changed", G_CALLBACK(playtime_changed), NULL);
1079 playlist_editor_song_tree = tree =
1080 gmpc_mpddata_treeview_new("playlist-browser", FALSE, GTK_TREE_MODEL(playlist_editor_list_store));
1081 gmpc_mpddata_treeview_enable_click_fix(GMPC_MPDDATA_TREEVIEW(playlist_editor_song_tree));
1083 /* Copy paste routines */
1084 g_signal_connect(G_OBJECT(tree), "cut", G_CALLBACK(playlist_editor_cut_songs), NULL);
1085 g_signal_connect(G_OBJECT(tree), "paste-after", G_CALLBACK(playlist_editor_paste_after_songs), NULL);
1086 g_signal_connect(G_OBJECT(tree), "paste-before", G_CALLBACK(playlist_editor_paste_before_songs), NULL);
1088 g_signal_connect(G_OBJECT(tree), "row-activated", G_CALLBACK(playlist_editor_row_activated), NULL);
1090 gtk_container_add(GTK_CONTAINER(sw), tree);
1091 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(tree), TRUE);
1093 g_signal_connect(G_OBJECT(tree), "button-release-event", G_CALLBACK(playlist_editor_key_released), NULL);
1094 g_signal_connect(G_OBJECT(tree), "key-press-event", G_CALLBACK(playlist_editor_key_pressed), NULL);
1095 g_object_ref_sink(playlist_editor_browser);
1097 gtk_widget_show_all(playlist_editor_browser);
1099 gtk_widget_set_sensitive(GTK_WIDGET(playlist_editor_browser), !pl3_editor_disabled);
1102 void playlist_editor_browser_selected(GtkWidget * container)
1104 if (!playlist_editor_browser)
1106 playlist_editor_browser_init();
1107 playlist_editor_fill_list_real();
1109 gtk_container_add(GTK_CONTAINER(container), playlist_editor_browser);
1110 gtk_widget_show_all(playlist_editor_browser);
1113 void playlist_editor_browser_unselected(GtkWidget * container)
1115 gtk_container_remove(GTK_CONTAINER(container), playlist_editor_browser);
1118 int playlist_editor_browser_cat_menu(GtkWidget * menu, int type, GtkWidget * tree, GdkEventButton * event)
1120 if (type == playlist_editor_plugin.id)
1123 return 0;
1126 static void playlist_editor_add_to_new(GtkWidget * item, gpointer data)
1128 gpointer cb_data = g_object_get_data(G_OBJECT(item), "cb-data");
1129 void (*callback) (GtkWidget * item, gpointer data) = data;
1131 playlist_editor_new_playlist(item, NULL);
1132 callback(item, cb_data);
1136 void playlist_editor_right_mouse(GtkWidget * menu, void (*add_to_playlist) (GtkWidget * menu, gpointer data),
1137 gpointer cb_data)
1139 GtkWidget *sitem;
1140 GtkWidget *item;
1141 GtkWidget *smenu;
1143 if (!mpd_server_check_version(connection, 0, 13, 0))
1145 return;
1148 smenu = gtk_menu_new();
1150 sitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL);
1151 g_object_set_data(G_OBJECT(sitem), "cb-data", cb_data);
1152 g_signal_connect(G_OBJECT(sitem), "activate", G_CALLBACK(playlist_editor_add_to_new), add_to_playlist);
1153 gtk_menu_shell_append(GTK_MENU_SHELL(smenu), sitem);
1156 MpdData *data = mpd_database_playlist_list(connection);
1157 data = misc_sort_mpddata(data, (GCompareDataFunc) __sort_func, NULL);
1158 for (; data; data = mpd_data_get_next(data))
1160 if (data->type == MPD_DATA_TYPE_PLAYLIST)
1163 sitem = gtk_image_menu_item_new_with_label(data->playlist->path);
1164 if (g_utf8_collate(data->playlist->path, _("Favorites")) == 0)
1166 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(sitem),
1167 gtk_image_new_from_icon_name("emblem-favorite", GTK_ICON_SIZE_MENU));
1168 } else
1170 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(sitem),
1171 gtk_image_new_from_icon_name("media-playlist", GTK_ICON_SIZE_MENU));
1173 g_object_set_data_full(G_OBJECT(sitem), "playlist", g_strdup(data->playlist->path), g_free);
1174 gtk_menu_shell_append(GTK_MENU_SHELL(smenu), sitem);
1175 g_signal_connect(G_OBJECT(sitem), "activate", G_CALLBACK(add_to_playlist), cb_data);
1176 gtk_widget_show(sitem);
1181 /* Add */
1182 item = gtk_menu_item_new_with_label(_("Add to playlist"));
1183 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), smenu);
1184 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1185 gtk_widget_show(item);
1187 gtk_widget_show(smenu);
1190 static void playlist_editor_status_changed(MpdObj * mi, ChangedStatusType what, void *data)
1192 if (what & MPD_CST_STORED_PLAYLIST)
1194 playlist_editor_fill_list_real();
1198 static void playlist_editor_activate(GtkWidget * item, gpointer data)
1200 GtkTreeSelection *selec = gtk_tree_view_get_selection((GtkTreeView *) playlist3_get_category_tree_view());
1202 if (playlist_editor_browser_ref)
1204 GtkTreePath *path = gtk_tree_row_reference_get_path(playlist_editor_browser_ref);
1205 if (path)
1207 gtk_tree_selection_select_path(selec, path);
1208 gtk_tree_path_free(path);
1213 static void favorites_add_current_song(void)
1215 mpd_Song *song = mpd_playlist_get_current_song(connection);
1216 if (song != NULL && song->file != NULL)
1218 if(favorites)
1220 gmpc_favorites_list_set_favorite(favorites, song->file,
1221 !gmpc_favorites_list_is_favorite(favorites, song->file));
1222 playlist3_show_error_message(_("Added playing song to favorites list."), ERROR_INFO);
1227 static int playlist_editor_add_go_menu(GtkWidget * menu)
1229 GtkWidget *item = NULL;
1230 if (!cfg_get_single_value_as_int_with_default(config, "playlist-plugin", "enable", 1))
1231 return 0;
1232 item = gtk_image_menu_item_new_with_label(_("Playlist Editor"));
1233 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
1234 gtk_image_new_from_icon_name("media-playlist", GTK_ICON_SIZE_MENU));
1236 gtk_widget_add_accelerator(GTK_WIDGET(item),
1237 "activate", gtk_menu_get_accel_group(GTK_MENU(menu)), GDK_KEY_F5, 0, GTK_ACCEL_VISIBLE);
1238 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1239 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(playlist_editor_activate), NULL);
1240 /** */
1241 item = gtk_image_menu_item_new_with_label(_("Add Current Song to favorites"));
1242 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
1243 gtk_image_new_from_icon_name("emblem-favorite", GTK_ICON_SIZE_MENU));
1244 gtk_widget_add_accelerator(GTK_WIDGET(item), "activate", gtk_menu_get_accel_group(GTK_MENU(menu)), GDK_KEY_Return,
1245 GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
1246 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(favorites_add_current_song), NULL);
1248 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1250 return 1;
1253 static void playlist_editor_save_myself(void)
1255 if (playlist_editor_browser_ref)
1257 GtkTreePath *path = gtk_tree_row_reference_get_path(playlist_editor_browser_ref);
1258 if (path)
1260 gint *indices = gtk_tree_path_get_indices(path);
1261 cfg_set_single_value_as_int(config, "playlist-plugin", "position", indices[0]);
1262 gtk_tree_path_free(path);