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.
21 #include <glib/gstdio.h>
22 #include <gdk/gdkkeysyms.h>
23 #include <libmpd/libmpd.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);
54 GtkListStore
*playlist_editor_store
= NULL
;
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();
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
105 void playlist_editor_init(void)
112 static gchar
*old_playlist
= NULL
;
113 void playlist_editor_destroy(void)
115 if(playlist_editor_browser_ref
!= NULL
)
119 path
= gtk_tree_row_reference_get_path(playlist_editor_browser_ref
);
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
;
139 g_free(old_playlist
);
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
)
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
;
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
))
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
);
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
);
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);
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
));
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
));
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
));
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);
259 if (old_playlist
&& g_utf8_collate(pl_path
, old_playlist
) == 0)
266 playlist_editor_browser_playlist_editor_selected(model
, NULL
, &iter
, data
);
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
)
282 else if (b
->playlist
->path
== NULL
&& a
->playlist
->path
!= NULL
)
284 else if (a
->playlist
->path
&& b
->playlist
->path
)
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
);
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)
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
)
324 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store
), &iter
, PL_NAME
, &name
, -1);
325 val
= strcmp(name
, data
->playlist
->path
);
329 GtkTreePath
*path
= 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);
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
);
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)
345 playlist_editor_browser_playlist_editor_changed(playlist_editor_icon_view
, NULL
);
348 gtk_tree_path_free(path
);
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
);
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);
370 valid
= gtk_list_store_remove(playlist_editor_store
, &iter
);
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
);
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);
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);
411 static gboolean
gufg_validate_callback(GmpcUrlFetchingGui
*a
, const gchar
*url
, void *user_data
)
413 /* TODO add validator here, well probly url-fetcher validator */
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");
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
;
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
);
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
));
459 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view
)),
461 for (it
= g_list_first(list
); it
; it
= g_list_next(it
))
463 GtkTreePath
*path
= it
->data
;
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
);
474 gmpc_url_fetching_gui_new(gufg_parse_callback
, pl_path
, gufg_validate_callback
, NULL
, g_object_unref
);
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
));
485 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view
)),
487 for (it
= g_list_first(list
); it
; it
= g_list_next(it
))
489 GtkTreePath
*path
= it
->data
;
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
);
501 GtkTreeSelection
*sel
= gtk_tree_view_get_selection(tree
);
502 GtkTreeModel
*model
= gtk_tree_view_get_model(tree
);
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
;
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
);
522 static void playlist_editor_list_add_songs(GtkButton
* button
, GtkTreeView
* tree
)
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
;
532 if (gtk_tree_model_get_iter(model
, &iter
, path
))
535 gtk_tree_model_get(model
, &iter
, MPDDATA_MODEL_COL_PATH
, &song_path
, -1);
536 mpd_playlist_queue_add(connection
, song_path
);
541 mpd_playlist_queue_commit(connection
);
542 g_list_foreach(list
, (GFunc
) gtk_tree_path_free
, NULL
);
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
)
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
);
573 playlist3_message_show(pl3_messages
, message
,USER_FEEDBACK
);
574 playlist3_message_add_widget(pl3_messages
, delete);
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
)
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
);
613 playlist3_message_show(pl3_messages
, message
,USER_FEEDBACK
);
614 playlist3_message_add_widget(pl3_messages
, delete);
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
);
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
)
639 GtkWidget
*pl3_win
= playlist3_get_window();
641 gtk_dialog_new_with_buttons(_("New Playlist"), NULL
, GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
642 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
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
);
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();
676 gtk_widget_destroy(dialog
);
679 static void playlist_editor_rename_playlist(GtkWidget
* item
, gpointer data
)
682 char *name
= g_object_get_data(G_OBJECT(item
), "path");
684 gtk_dialog_new_with_buttons(_("Rename Playlist"), NULL
, GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
685 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
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
);
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();
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
);
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
));
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
;
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
);
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);
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
);
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
);
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))
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
);
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
);
837 g_list_foreach(list
, (GFunc
) gtk_tree_path_free
, NULL
);
841 gtk_widget_show_all(menu
);
842 gtk_menu_popup(GTK_MENU(menu
), NULL
, NULL
, NULL
, NULL
, 0, event
->time
);
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
));
865 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view
)),
867 for (it
= g_list_first(list
); it
; it
= g_list_next(it
))
869 GtkTreePath
*path
= it
->data
;
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
);
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)
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 */
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
);
906 mpd_database_playlist_list_add(connection
, pl_path
, path
);
907 mpd_database_playlist_move(connection
, pl_path
, length
, id
+ 1);
909 liter
= g_list_next(liter
);
913 g_list_foreach(list
, (GFunc
) gtk_tree_path_free
, NULL
);
917 GList
*liter
= g_list_last(paste_list
);;
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
);
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
));
937 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view
)),
939 for (it
= g_list_first(list
); it
; it
= g_list_next(it
))
941 GtkTreePath
*path
= it
->data
;
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
);
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)
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 */
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
);
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 */
983 liter
= g_list_next(liter
);
987 g_list_foreach(list
, (GFunc
) gtk_tree_path_free
, NULL
);
991 GList
*liter
= g_list_last(paste_list
);
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
);
1006 static void playlist_editor_row_activated(GtkTreeView
* tree
, GtkTreePath
* path
, GtkTreeViewColumn
* column
,
1009 GtkTreeModel
*model
= gtk_tree_view_get_model(tree
);
1011 if (gtk_tree_model_get_iter(model
, &iter
, path
))
1014 gtk_tree_model_get(model
, &iter
, MPDDATA_MODEL_COL_MPDSONG
, &song
, -1);
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
;
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
));
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
);
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
),
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
)
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
),
1143 if (!mpd_server_check_version(connection, 0, 13, 0))
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
));
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
);
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
);
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
)
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))
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
);
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
);
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
);
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
);