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_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
));
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
));
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
));
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);
260 if (old_playlist
&& g_utf8_collate(pl_path
, old_playlist
) == 0)
267 playlist_editor_browser_playlist_editor_selected(model
, NULL
, &iter
, data
);
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
)
283 else if (b
->playlist
->path
== NULL
&& a
->playlist
->path
!= NULL
)
285 else if (a
->playlist
->path
&& b
->playlist
->path
)
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
);
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)
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
)
325 gtk_tree_model_get(GTK_TREE_MODEL(playlist_editor_store
), &iter
, PL_NAME
, &name
, -1);
326 val
= strcmp(name
, data
->playlist
->path
);
330 GtkTreePath
*path
= 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);
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
);
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)
346 playlist_editor_browser_playlist_editor_changed(playlist_editor_icon_view
, NULL
);
349 gtk_tree_path_free(path
);
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
);
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);
371 valid
= gtk_list_store_remove(playlist_editor_store
, &iter
);
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
);
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);
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);
412 static gboolean
gufg_validate_callback(GmpcUrlFetchingGui
*a
, const gchar
*url
, void *user_data
)
414 /* TODO add validator here, well probly url-fetcher validator */
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");
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
;
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
);
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
));
460 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view
)),
462 for (it
= g_list_first(list
); it
; it
= g_list_next(it
))
464 GtkTreePath
*path
= it
->data
;
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
);
475 gmpc_url_fetching_gui_new(gufg_parse_callback
, pl_path
, gufg_validate_callback
, NULL
, g_object_unref
);
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
));
486 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view
)),
488 for (it
= g_list_first(list
); it
; it
= g_list_next(it
))
490 GtkTreePath
*path
= it
->data
;
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
);
502 GtkTreeSelection
*sel
= gtk_tree_view_get_selection(tree
);
503 GtkTreeModel
*model
= gtk_tree_view_get_model(tree
);
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
;
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
);
523 static void playlist_editor_list_add_songs(GtkButton
* button
, GtkTreeView
* tree
)
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
;
533 if (gtk_tree_model_get_iter(model
, &iter
, path
))
536 gtk_tree_model_get(model
, &iter
, MPDDATA_MODEL_COL_PATH
, &song_path
, -1);
537 mpd_playlist_queue_add(connection
, song_path
);
542 mpd_playlist_queue_commit(connection
);
543 g_list_foreach(list
, (GFunc
) gtk_tree_path_free
, NULL
);
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
)
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
);
574 playlist3_message_show(pl3_messages
, message
,USER_FEEDBACK
);
575 playlist3_message_add_widget(pl3_messages
, delete);
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
)
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
);
614 playlist3_message_show(pl3_messages
, message
,USER_FEEDBACK
);
615 playlist3_message_add_widget(pl3_messages
, delete);
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
);
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
)
640 GtkWidget
*pl3_win
= playlist3_get_window();
642 gtk_dialog_new_with_buttons(_("New Playlist"), NULL
, GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
643 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
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
);
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();
677 gtk_widget_destroy(dialog
);
680 static void playlist_editor_rename_playlist(GtkWidget
* item
, gpointer data
)
683 char *name
= g_object_get_data(G_OBJECT(item
), "path");
685 gtk_dialog_new_with_buttons(_("Rename Playlist"), NULL
, GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
686 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
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
);
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();
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
);
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
));
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
;
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
);
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);
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
);
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
);
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))
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
);
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
);
838 g_list_foreach(list
, (GFunc
) gtk_tree_path_free
, NULL
);
842 gtk_widget_show_all(menu
);
843 gtk_menu_popup(GTK_MENU(menu
), NULL
, NULL
, NULL
, NULL
, 0, event
->time
);
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
));
866 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view
)),
868 for (it
= g_list_first(list
); it
; it
= g_list_next(it
))
870 GtkTreePath
*path
= it
->data
;
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
);
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)
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 */
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
);
907 mpd_database_playlist_list_add(connection
, pl_path
, path
);
908 mpd_database_playlist_move(connection
, pl_path
, length
, id
+ 1);
910 liter
= g_list_next(liter
);
914 g_list_foreach(list
, (GFunc
) gtk_tree_path_free
, NULL
);
918 GList
*liter
= g_list_last(paste_list
);;
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
);
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
));
938 gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(playlist_editor_icon_view
)),
940 for (it
= g_list_first(list
); it
; it
= g_list_next(it
))
942 GtkTreePath
*path
= it
->data
;
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
);
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)
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 */
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
);
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 */
984 liter
= g_list_next(liter
);
988 g_list_foreach(list
, (GFunc
) gtk_tree_path_free
, NULL
);
992 GList
*liter
= g_list_last(paste_list
);
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
);
1007 static void playlist_editor_browser_init(void)
1009 GtkCellRenderer
*renderer
= NULL
;
1010 GtkTreeViewColumn
*column
= NULL
;
1011 GtkWidget
*tree
= NULL
;
1012 GtkWidget
*sw
= NULL
;
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
));
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
);
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
),
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
)
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
),
1126 if (!mpd_server_check_version(connection, 0, 13, 0))
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
));
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
);
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
);
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
)
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))
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
);
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
);
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
);
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
);