[DataView] Fix bold of playing song, italic 'prioritized songs'
[gmpc.git] / src / playlist3.c
blob0543834ea3c57a8bf4172a938a1b3fe832db03e9
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 <gdk/gdkkeysyms.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <config.h>
25 #include "main.h"
26 #include "plugin.h"
27 #include "misc.h"
28 #include "playlist3.h"
29 #include "preferences.h"
30 #include "revision.h"
31 #include "gmpc-metaimage.h"
32 #include "gmpc-extras.h"
33 #include "GUI/cmd.h"
34 #include "GUI/status_icon.h"
35 #include "GUI/title_header.h"
36 #include "GUI/control_window.h"
38 #define ALBUM_SIZE 42
40 #define LOG_DOMAIN "Playlist"
42 /* Drag and drop Target table */
43 static GtkTargetEntry target_table[] =
45 {(gchar *) "x-url/http", 0, 0},
46 {(gchar *) "_NETSCAPE_URL", 0, 1},
47 {(gchar *) "text/uri-list", 0, 2},
48 {(gchar *) "audio/*", 0, 3},
49 {(gchar *) "audio/x-scpls", 0, 4},
50 {(gchar *) "internal-drop", 0, 99}
53 GtkWidget *metaimage_album_art = NULL;
54 GtkWidget *metaimage_artist_art = NULL;
55 GmpcFavoritesButton *favorites_button = NULL;
57 GtkCellRenderer *sidebar_text = NULL;
58 /**
59 * Widgets used in the header.
60 * and the new progresbar
62 static GtkWidget *new_pb = NULL;
64 /**
65 * Indicates the zoom level and the previous zoom level.
67 int pl3_zoom = PLAYLIST_NO_ZOOM;
68 int pl3_old_zoom = PLAYLIST_NO_ZOOM;
70 static void playlist_zoom_level_changed(void);
71 void playlist_zoom_in(void);
72 void playlist_zoom_out(void);
75 void pl3_pb_seek_event(GtkWidget * pb, guint seek_time, gpointer user_data);
77 void set_browser_format(void);
78 void set_playlist_format(void);
80 gboolean playlist_player_volume_changed(GtkWidget * vol_but, double new_vol);
82 /* Glade declarations, otherwise these would be static */
83 void about_window(void);
84 int pl3_cat_tree_button_press_event(GtkTreeView *, GdkEventButton *);
85 int pl3_cat_tree_button_release_event(GtkTreeView *, GdkEventButton *);
86 int pl3_window_key_release_event(GtkWidget * mw, GdkEventKey * event);
88 void cur_song_center_enable_tb(GtkToggleButton *);
89 void show_cover_case_tb(GtkToggleButton * but);
90 void save_possize_enable_tb(GtkToggleButton *);
91 void playlist_menu_repeat_changed(GtkToggleAction *);
92 void playlist_menu_single_mode_changed(GtkToggleAction * );
93 void playlist_menu_consume_changed(GtkToggleAction * );
95 void playlist_menu_random_changed(GtkToggleAction *);
96 void playlist_menu_artist_image_changed(GtkToggleAction *);
97 void hide_on_close_enable_tb(GtkToggleButton * but);
98 gboolean pl3_close(void);
99 static void pl3_update_profiles_menu(GmpcProfiles * prof, const int changed, const int col, const gchar * id);
100 gboolean playlist3_enter_notify_event(GtkWidget * wid, GdkEventCrossing * event, gpointer data);
101 gboolean playlist3_leave_notify_event(GtkWidget * wid, GdkEventCrossing * event, gpointer data);
102 gboolean pl3_window_focus_out_event(GtkWidget *window, GdkEventFocus *event, gpointer data);
104 static void pl3_profiles_changed(GmpcProfiles * prof, const int changed, const int col, const gchar * id);
105 static void playlist3_server_output_changed(GtkWidget * item, gpointer data);
106 static void playlist3_fill_server_menu(void);
107 void playlist3_server_update_db(void);
109 void easy_command_help_window(void);
111 void pl3_style_set_event(GtkWidget *widget, GtkStyle *previous_style, gpointer user_data);
113 void pl3_sidebar_plugins_init(void);
115 /* Old category browser style */
116 static int old_type = -1;
118 /* interface description */
119 GtkBuilder *pl3_xml = NULL;
120 /* category treeview-store */
121 GtkTreeModel *pl3_tree = NULL;
123 /* size */
124 static GtkAllocation pl3_wsize = { 0, 0, 0, 0 };
126 static int pl3_hidden = TRUE;
128 static void playlist_status_changed(MpdObj * mi, ChangedStatusType what, void *userdata);
130 /* Playlist "Plugin" */
131 static void playlist_pref_construct(GtkWidget * container);
132 static void playlist_pref_destroy(GtkWidget * container);
134 static GtkBuilder *playlist_pref_xml = NULL;
136 void ck_search_as_you_type(GtkToggleButton * but);
139 /* Get the type of the selected row..
140 * -1 means no row selected
142 int pl3_cat_get_selected_browser(void)
144 return old_type;
151 * Extras for better integration
154 void init_extra_playlist_state(void);
155 void enable_extra_playlist(GtkToggleAction *action);
157 /**************************************************
158 * Category Tree
160 static void pl3_initialize_tree(void)
162 int i;
163 GtkTreePath *path;
164 GtkTreeSelection *sel;
165 GtkWidget *cat_tree = GTK_WIDGET(gtk_builder_get_object(pl3_xml, "cat_tree"));
167 INIT_TIC_TAC()
169 path = gtk_tree_path_new_from_string("0");
170 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtk_builder_get_object(pl3_xml, "cat_tree")));
171 TEC("Get selection");
172 for (i = 0; i < num_plugins; i++)
174 if (gmpc_plugin_is_browser(plugins[i]))
176 if (gmpc_plugin_get_enabled(plugins[i]))
178 gmpc_plugin_browser_add(plugins[i], cat_tree);
181 TEC("setup %s", gmpc_plugin_get_name(plugins[i]))
184 gtk_tree_view_set_cursor(GTK_TREE_VIEW(gtk_builder_get_object(pl3_xml, "cat_tree")), path, NULL, FALSE);
185 TEC("set cursor");
186 gtk_tree_path_free(path);
187 TEC("finish set");
192 * Function to handle a change in category.
194 static void pl3_cat_sel_changed(GtkTreeSelection * selec, gpointer * userdata)
196 GtkTreeView *tree = (GtkTreeView *) gtk_builder_get_object(pl3_xml, "cat_tree");
197 GtkTreeModel *model = gtk_tree_view_get_model(tree);
198 GtkTreeIter iter;
199 GtkWidget *container = GTK_WIDGET(gtk_builder_get_object(pl3_xml, "browser_container"));
200 if (!model)
201 return;
202 if (gtk_tree_selection_get_selected(selec, &model, &iter))
204 gint type;
206 gtk_tree_model_get(model, &iter, PL3_CAT_TYPE, &type, -1);
210 * Start switching side view (if type changed )
212 if (old_type != -1)
214 gmpc_plugin_browser_unselected(plugins[plugin_get_pos(old_type)], container);
216 old_type = -1;
217 if(type > -1)
219 /** if type changed give a selected signal */
220 if ((old_type != type))
222 gmpc_plugin_browser_selected(plugins[plugin_get_pos(type)], container);
227 * update old value, so get_selected_category is correct before calling selection_changed
229 old_type = type;
231 } else
233 if (old_type != -1)
235 gmpc_plugin_browser_unselected(plugins[plugin_get_pos(old_type)], container);
237 old_type = -1;
238 gtk_tree_model_get_iter_first(model, &iter);
239 gtk_tree_selection_select_iter(selec, &iter);
241 pl3_option_menu_activate();
245 /* handle right mouse clicks on the cat tree view */
246 /* gonna be a big function*/
247 int pl3_cat_tree_button_press_event(GtkTreeView * tree, GdkEventButton * event)
249 GtkTreeSelection *sel = gtk_tree_view_get_selection(tree);
250 if (event->button != 3 || gtk_tree_selection_count_selected_rows(sel) < 2 || !mpd_check_connected(connection))
252 return FALSE;
254 return TRUE;
259 void pl3_option_menu_activate(void)
262 GtkWidget *tree = GTK_WIDGET(gtk_builder_get_object(pl3_xml, "cat_tree"));
263 int i;
264 gint type = pl3_cat_get_selected_browser();
265 int menu_items = 0;
266 GdkEventButton *event = NULL;
267 GtkWidget *menu = NULL;
268 GtkUIManager *ui = GTK_UI_MANAGER(gtk_builder_get_object(pl3_xml, "uimanager1"));
269 GtkMenuItem *m_item = GTK_MENU_ITEM(gtk_ui_manager_get_widget(ui, "/menubartest/menu_option"));
271 //gtk_menu_item_set_submenu(m_item, NULL);
273 if (!mpd_check_connected(connection) || type == -1)
274 return;
276 menu = gtk_menu_new();
278 for (i = 0; i < num_plugins; i++)
280 if (gmpc_plugin_is_browser(plugins[i]))
282 menu_items += gmpc_plugin_browser_cat_right_mouse_menu(plugins[i], menu, type, tree, event);
285 if (menu_items)
287 gtk_widget_show_all(menu);
288 gtk_menu_item_set_submenu(m_item, menu);
289 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_option")), TRUE);
290 } else
292 g_object_ref_sink(menu);
293 g_object_unref(menu);
294 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_option")), FALSE);
300 int pl3_cat_tree_button_release_event(GtkTreeView * tree, GdkEventButton * event)
302 int i;
303 gint type = pl3_cat_get_selected_browser();
304 int menu_items = 0;
305 GtkWidget *menu = NULL;
307 if (type == -1 || !mpd_check_connected(connection) || event->button != 3)
309 /* no selections, or no usefull one.. so propagate the signal */
310 return FALSE;
313 menu = gtk_menu_new();
315 for (i = 0; i < num_plugins; i++)
317 if (gmpc_plugin_is_browser(plugins[i]))
319 menu_items += gmpc_plugin_browser_cat_right_mouse_menu(plugins[i], menu, type, GTK_WIDGET(tree), event);
323 if (menu_items)
325 gtk_widget_show_all(menu);
326 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
327 /*event->button */ 0, event->time);
328 } else
330 g_object_ref_sink(menu);
331 g_object_unref(menu);
333 return TRUE;
336 void pl3_sidebar_plugins_init(void)
338 int i;
339 for (i = 0; i < num_plugins; i++)
341 // This is implicitely done inside sidebar_init
342 // if (gmpc_plugin_is_sidebar(plugins[i]))
344 gmpc_plugin_sidebar_init(plugins[i]);
349 /**********************************************************
350 * MISC
352 static GtkWidget *control_window = NULL;
353 static gboolean pl3_win_state_event(GtkWidget * window, GdkEventWindowState * event, gpointer data)
355 GtkWidget *vbox1 = GTK_WIDGET(gtk_builder_get_object(pl3_xml, "vbox1"));
356 GtkWidget *p = GTK_WIDGET(gtk_builder_get_object(pl3_xml, "alignment1"));
357 GtkWidget *h = GTK_WIDGET(gtk_builder_get_object(pl3_xml, "hbox1"));
358 GtkWidget *b = (GTK_WIDGET(gtk_builder_get_object(pl3_xml, "menubartest")));
359 if (((event->new_window_state) & GDK_WINDOW_STATE_FULLSCREEN))
361 if(control_window == NULL) {
362 control_window = create_control_window(window);
363 gtk_box_pack_start(GTK_BOX(vbox1), control_window, FALSE, FALSE, 0);
365 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(pl3_xml, "sidebar")));
366 gtk_widget_hide(p);
367 gtk_widget_hide(h);
368 gtk_widget_hide(b);
369 } else if ((event->changed_mask) & GDK_WINDOW_STATE_FULLSCREEN)
371 control_window_destroy(control_window);
372 control_window = NULL;
373 playlist_zoom_level_changed();
374 gtk_widget_show(p);
375 gtk_widget_show(h);
376 gtk_widget_show(b);
378 return FALSE;
382 * This avoids the 'keybinding help' to become sticky when moving the window, or chainging
383 * focus to other window.
385 gboolean pl3_window_focus_out_event(GtkWidget *window, GdkEventFocus *event, gpointer data)
387 return FALSE;
391 gboolean pl3_window_is_fullscreen(void)
393 GtkWidget *win = playlist3_get_window();
394 GdkWindowState state = 0;
395 if (gtk_widget_get_window(win))
396 state = gdk_window_get_state(gtk_widget_get_window(win));
397 return (state & GDK_WINDOW_STATE_FULLSCREEN) ? TRUE : FALSE;
401 gboolean pl3_window_fullscreen(void)
403 GtkWidget *win = playlist3_get_window();
405 if (pl3_zoom < PLAYLIST_MINI)
407 if (pl3_window_is_fullscreen())
409 gtk_window_unfullscreen(GTK_WINDOW(win));
410 } else
412 gtk_window_fullscreen(GTK_WINDOW(win));
415 return FALSE;
419 int pl3_window_key_release_event(GtkWidget * mw, GdkEventKey * event)
421 return FALSE;
423 int pl3_window_key_press_event(GtkWidget * mw, GdkEventKey * event)
425 int i = 0;
426 gint type = pl3_cat_get_selected_browser();
428 * Following key's are only valid when connected
430 if (!mpd_check_connected(connection))
432 return FALSE;
434 for (i = 0; i < num_plugins; i++)
436 if (gmpc_plugin_is_browser(plugins[i]))
438 gmpc_plugin_browser_key_press_event(plugins[i], mw, event, type);
441 if(event->keyval == GDK_KEY_colon)
443 show_command_line();
444 return TRUE;
446 if((event->state&GDK_MOD1_MASK) > 0)
448 guint kev = event->keyval;
449 if(kev >= GDK_KEY_0 && kev <= GDK_KEY_9)
451 guint i_index = 0;
452 GtkTreeIter iter;
453 kev-=GDK_KEY_0;
454 if (gtk_tree_model_get_iter_first(pl3_tree, &iter))
456 if(kev == 0) kev+=10;
458 gint new_type =0 ;
459 gtk_tree_model_get(pl3_tree, &iter, PL3_CAT_TYPE, &new_type, -1);
460 if(new_type >= 0) i_index++;
461 if(i_index == kev && new_type >= 0)
463 GtkWidget *cat_tree = GTK_WIDGET(gtk_builder_get_object(pl3_xml, "cat_tree"));
464 GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(cat_tree));
466 // if this is allready selected, do +10. this allows us to go up to 20 browsers.
467 if(new_type == old_type && gtk_tree_selection_iter_is_selected(select, &iter)) {
468 kev+=10;
469 }else{
470 gtk_tree_selection_select_iter(select, &iter);
471 return FALSE;
474 }while(gtk_tree_model_iter_next(pl3_tree, &iter));
479 /* don't propagate */
480 return FALSE;
484 * Close the playlist and save position/size
486 gboolean pl3_close(void)
488 /* only save when window is PLAYLIST_SMALL or NO ZOOM */
489 if (pl3_xml != NULL)
491 GtkWidget *window = playlist3_get_window();
492 int maximized = FALSE;
493 if (gtk_widget_get_window(window))
495 GdkWindowState state = gdk_window_get_state(gtk_widget_get_window(window));
496 maximized = ((state & GDK_WINDOW_STATE_MAXIMIZED) > 0);
498 cfg_set_single_value_as_int(config, "playlist", "maximized", maximized);
500 gtk_window_get_position(GTK_WINDOW(window), &pl3_wsize.x, &pl3_wsize.y);
502 cfg_set_single_value_as_int(config, "playlist", "xpos", pl3_wsize.x);
503 cfg_set_single_value_as_int(config, "playlist", "ypos", pl3_wsize.y);
505 if (pl3_zoom <= PLAYLIST_SMALL)
507 gtk_window_get_size(GTK_WINDOW(window), &pl3_wsize.width, &pl3_wsize.height);
508 g_log(LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "pl3_close: save size: %i %i\n", pl3_wsize.width, pl3_wsize.height);
509 cfg_set_single_value_as_int(config, "playlist", "width", pl3_wsize.width);
510 cfg_set_single_value_as_int(config, "playlist", "height", pl3_wsize.height);
514 if (cfg_get_single_value_as_int_with_default(config, "playlist", "hide-on-close", FALSE))
516 if (tray_icon2_get_available())
518 pl3_toggle_hidden();
519 return TRUE;
521 gtk_window_iconify(GTK_WINDOW(playlist3_get_window()));
522 return TRUE;
526 * Quit the program
528 main_quit();
529 return TRUE;
534 * Hide the playlist.
535 * Before hiding save current size and position
537 int pl3_hide(void)
539 GtkWidget *pl3_win = playlist3_get_window();
540 if (!tray_icon2_get_available())
542 gtk_window_iconify(GTK_WINDOW(pl3_win));
543 return 1;
545 if (pl3_xml != NULL && !pl3_hidden)
547 GtkWidget *window = playlist3_get_window();
548 int maximized = FALSE;
549 if (gtk_widget_get_window(window))
551 GdkWindowState state = gdk_window_get_state(gtk_widget_get_window(window));
552 maximized = ((state & GDK_WINDOW_STATE_MAXIMIZED) > 0);
554 cfg_set_single_value_as_int(config, "playlist", "maximized", maximized);
555 /** Save position
557 gtk_window_get_position(GTK_WINDOW(pl3_win), &pl3_wsize.x, &pl3_wsize.y);
558 cfg_set_single_value_as_int(config, "playlist", "xpos", pl3_wsize.x);
559 cfg_set_single_value_as_int(config, "playlist", "ypos", pl3_wsize.y);
560 /* save size, only when in SMALL or no zoom mode
562 if (pl3_zoom <= PLAYLIST_SMALL)
564 gtk_window_get_size(GTK_WINDOW(pl3_win), &pl3_wsize.width, &pl3_wsize.height);
565 g_log(LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "pl3_hide: save size: %i %i\n", pl3_wsize.width, pl3_wsize.height);
566 cfg_set_single_value_as_int(config, "playlist", "width", pl3_wsize.width);
567 cfg_set_single_value_as_int(config, "playlist", "height", pl3_wsize.height);
569 gtk_widget_hide(pl3_win);
570 pl3_hidden = TRUE;
572 #ifdef HAVE_APP_INDICATOR
573 tray_icon2_update_menu();
574 #endif
575 return TRUE;
579 /* create the playlist view
580 * This is done only once, for the rest its hidden, but still there
582 void pl3_show_and_position_window(void)
584 GtkWidget *pl3_win;
585 if (!pl3_xml)
586 return;
587 pl3_win = playlist3_get_window();
588 if (pl3_wsize.x > 0 || pl3_wsize.y > 0)
590 gtk_window_move(GTK_WINDOW(pl3_win), pl3_wsize.x, pl3_wsize.y);
592 if (pl3_wsize.height > 0 && pl3_wsize.width > 0)
594 g_log(LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "restore size %i %i\n", pl3_wsize.width, pl3_wsize.height);
595 gtk_window_resize(GTK_WINDOW(pl3_win), pl3_wsize.width, pl3_wsize.height);
597 gtk_widget_show(pl3_win);
598 gtk_window_present(GTK_WINDOW(pl3_win));
603 gboolean playlist3_window_is_hidden(void)
605 return pl3_hidden;
609 void pl3_toggle_hidden(void)
611 if (pl3_hidden)
613 create_playlist3();
614 } else
616 pl3_hide();
621 static void playlist3_source_drag_data_recieved(GtkWidget * widget,
622 GdkDragContext * context,
623 gint x,
624 gint y, GtkSelectionData * data, guint info, guint time_recieved)
626 if (info != 99)
628 int found = 0;
629 const guchar *url_data = gtk_selection_data_get_data(data);
630 int i;
631 if (url_data)
634 gchar **url = g_uri_list_extract_uris(url_data);
635 for (i = 0; url && url[i]; i++)
637 gchar *scheme = g_uri_parse_scheme(url[i]);
638 /* Don't add lines withouth an actual scheme. */
639 if (scheme)
641 gchar *fu = g_uri_unescape_string(url[i], NULL);
642 url_start_real(fu);
643 g_free(fu);
644 g_free(scheme);
647 if (url)
648 g_strfreev(url);
651 gtk_drag_finish(context, found, FALSE, time_recieved);
652 } else
654 MpdData *mdata;
655 gchar **stripped;
656 int i;
657 guchar *odata = gtk_selection_data_get_text(data);
658 stripped = g_strsplit((gchar *) odata, "\n", 0);
659 g_free(odata);
660 if (gdk_drag_context_get_actions(context)== GDK_ACTION_MOVE)
662 mpd_playlist_clear(connection);
664 mpd_database_search_start(connection, TRUE);
665 for (i = 0; stripped && stripped[i]; i++)
667 gchar **request = g_strsplit(stripped[i], ":", 2);
668 mpd_database_search_add_constraint(connection, mpd_misc_get_tag_by_name(request[0]), request[1]);
669 g_strfreev(request);
671 mdata = mpd_database_search_commit(connection);
672 for (; mdata; mdata = mpd_data_get_next(mdata))
674 mpd_playlist_queue_add(connection, mdata->song->file);
676 mpd_playlist_queue_commit(connection);
677 if (gdk_drag_context_get_actions(context)== GDK_ACTION_MOVE)
679 mpd_player_play(connection);
682 g_strfreev(stripped);
683 gtk_drag_finish(context, TRUE, FALSE, time_recieved);
689 * Progresbar
691 void pl3_pb_seek_event(GtkWidget * pb, guint seek_time, gpointer user_data)
693 mpd_player_seek(connection, (int)seek_time);
698 static void about_dialog_activate(GtkWidget * dialog, const gchar * uri, gpointer data)
700 open_uri(uri);
704 /***
705 * Handle a connect/Disconnect
707 static void playlist_connection_changed(MpdObj * mi, int connect, gpointer data)
709 GtkWidget *pl3_win = playlist3_get_window();
710 /* Set menu items */
711 if (connect)
713 char **handlers;
714 gboolean found = FALSE;
715 gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(pl3_xml, "vbox_playlist_player")), TRUE);
716 gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(pl3_xml, "hpaned1-hbox")), TRUE);
718 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDConnect")), FALSE);
719 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDDisconnect")), TRUE);
720 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDPassword")), TRUE);
721 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_view")), TRUE);
722 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_option")), TRUE);
724 /* Check if MPD supports 'file://' (so local files). */
725 /* TODO: make this a separate function */
726 handlers = mpd_server_get_url_handlers(connection);
727 if (handlers)
729 int i=0;
730 for(; !found && handlers != NULL && handlers[i] != NULL; i++) {
731 if(g_utf8_collate(handlers[i], "file://") == 0) {
732 found = TRUE;
735 g_strfreev(handlers);
737 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "open_local_file")), found);
738 } else
740 gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(pl3_xml, "vbox_playlist_player")), FALSE);
741 gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(pl3_xml, "hpaned1-hbox")), FALSE);
743 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDConnect")), TRUE);
744 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDDisconnect")), FALSE);
745 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDPassword")), FALSE);
746 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_view")), FALSE);
747 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_option")), FALSE);
748 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "open_local_file")), FALSE);
750 /** Set back to the current borwser, and update window title */
751 if (connect)
753 gchar *string = NULL;
754 GtkTreeIter iter;
755 GtkTreeSelection *selec = gtk_tree_view_get_selection((GtkTreeView *) gtk_builder_get_object(pl3_xml,
756 "cat_tree"));
757 GtkTreeModel *model = GTK_TREE_MODEL(pl3_tree);
758 if (gtk_tree_model_get_iter_first(model, &iter))
760 gtk_tree_selection_select_iter(selec, &iter);
762 if (gmpc_profiles_get_number_of_profiles(gmpc_profiles) > 1)
764 gchar *id = gmpc_profiles_get_current(gmpc_profiles);
765 if (id)
767 string =
768 g_strdup_printf("[%s] %s - %s %s", gmpc_profiles_get_name(gmpc_profiles, id), _("GMPC"),
769 _("Connected to"), mpd_get_hostname(mi));
770 g_free(id);
773 if (!string)
774 string = g_strdup_printf("%s - %s %s", _("GMPC"), _("Connected to"), mpd_get_hostname(mi));
775 gtk_window_set_title(GTK_WINDOW(pl3_win), string);
776 g_free(string);
777 } else
779 gchar *string = NULL;
781 if (gmpc_profiles_get_number_of_profiles(gmpc_profiles) > 1)
783 gchar *id = gmpc_profiles_get_current(gmpc_profiles);
784 if (id)
786 string =
787 g_strdup_printf("[%s] %s - %s", gmpc_profiles_get_name(gmpc_profiles, id), _("GMPC"),
788 _("Disconnected"));
789 g_free(id);
792 if (!string)
793 string = g_strdup_printf("%s - %s", _("GMPC"), _("Disconnected"));
794 gtk_window_set_title(GTK_WINDOW(pl3_win), string);
795 g_free(string);
799 * make the playlist update itself
801 playlist_status_changed(connection,
802 MPD_CST_STATE | MPD_CST_SONGID | MPD_CST_NEXTSONG |
803 MPD_CST_ELAPSED_TIME | MPD_CST_VOLUME |
804 MPD_CST_REPEAT | MPD_CST_RANDOM | MPD_CST_PERMISSION
805 | MPD_CST_SINGLE_MODE | MPD_CST_CONSUME_MODE | MPD_CST_UPDATING, NULL);
808 * Also need updating
810 pl3_option_menu_activate();
811 pl3_tool_menu_update();
813 playlist3_fill_server_menu();
816 * update interface
817 * items that are caused by the plugin.
819 pl3_update_go_menu();
823 void pl3_style_set_event( GtkWidget *widget,
824 GtkStyle *previous_style,
825 gpointer user_data)
827 if (cfg_get_single_value_as_int_with_default(config, "Default", "use-dark-style-header", TRUE))
829 gtk_rc_parse_string("widget \"*header*\" style \"dark\"");
832 static gboolean pl3_cat_select_function(GtkTreeSelection *select, GtkTreeModel *model, GtkTreePath *path, gboolean cur_select, gpointer data)
834 GtkTreeIter iter;
835 if(gtk_tree_model_get_iter(model, &iter, path))
837 gint type =0 ;
838 gtk_tree_model_get(model, &iter, PL3_CAT_TYPE, &type, -1);
839 if(type >= 0) return TRUE;
841 return FALSE;
844 void create_playlist3(void)
846 GtkWidget *pb,*ali;
847 GtkCellRenderer *renderer;
848 GtkWidget *tree;
849 GtkTreeSelection *sel;
850 GtkTreeViewColumn *column = NULL;
851 gchar *path = NULL;
852 GtkTreeIter iter;
853 GError *error = NULL;
854 INIT_TIC_TAC();
855 /* indicate that the playlist is not hidden */
856 pl3_hidden = FALSE;
859 * If the playlist already exists,
860 * It is probably coming from a hidden state,
861 * so re-position the window
863 if (pl3_xml != NULL)
865 pl3_show_and_position_window();
866 return;
873 /** Ambiance / Radiance theme "dark" header */
874 if (cfg_get_single_value_as_int_with_default(config, "Default", "use-dark-style-header", TRUE))
876 gtk_rc_parse_string("widget \"*header*\" style \"dark\"");
879 /** use background color for the sidebar treeview cells */
880 gtk_rc_parse_string (
881 "style \"sidebar-treeview\"\n"
882 "{\n"
883 " GtkTreeView::odd-row-color = @bg_color\n"
884 " GtkTreeView::even-row-color = @bg_color\n"
885 "}\n"
886 "widget \"*.sidebar.*\" style \"sidebar-treeview\"");
888 /** menubar */
889 gtk_rc_parse_string (
890 "style \"menubar-style\"\n"
891 "{\n"
892 " GtkMenuBar::shadow-type = none\n"
893 "}\n"
894 "widget \"*.menubar\" style \"menubar-style\"\n");
896 /* initial, setting the url hook */
897 // TODO
898 // gtk_about_dialog_set_url_hook((GtkAboutDialogActivateLinkFunc) about_dialog_activate, NULL, NULL);
899 TEC("Setup dialog url hook")
900 /* load gui desciption */
901 path = gmpc_get_full_glade_path("playlist3.ui");
902 TEC("get path")
903 pl3_xml = gtk_builder_new();
904 TEC("create builder")
905 if(gtk_builder_add_from_file(pl3_xml, path,&error) == 0)
908 * Check if the file is loaded, if not then show an error message and abort the program
909 if (pl3_xml == NULL)
912 g_log(LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Failed to open playlist3.glade: %s\n", error->message);
913 abort();
915 g_free(path);
919 // update style.
920 GtkWidget *widget = (GtkWidget *)gtk_builder_get_object(pl3_xml, "cat_tree");
921 GtkStyleContext *ct = gtk_widget_get_style_context(widget);
922 gtk_style_context_add_class(ct, GTK_STYLE_CLASS_SIDEBAR);
924 TEC("Load builder file")
926 /* create tree store for the "category" view */
927 if (pl3_tree == NULL)
929 GType types[] =
931 G_TYPE_INT, /* row type, see free_type struct */
932 G_TYPE_STRING, /* display name */
933 G_TYPE_STRING, /* full path and stuff for backend */
934 G_TYPE_STRING, /* icon id */
935 G_TYPE_INT, /* ordering */
936 G_TYPE_INT, /* Bold */
937 G_TYPE_STRING, /* stock id */
938 G_TYPE_BOOLEAN /* Show text */
940 /* song id, song title */
941 pl3_tree = (GtkTreeModel *) gmpc_tools_liststore_sort_new();
942 gtk_list_store_set_column_types(GTK_LIST_STORE(pl3_tree), PL3_CAT_NROWS, types);
944 TEC("Setup pl3_tree")
946 tree = GTK_WIDGET(gtk_builder_get_object(pl3_xml, "cat_tree"));
947 gtk_tree_selection_set_select_function(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)),
948 pl3_cat_select_function, pl3_tree, NULL);
950 gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(pl3_tree));
951 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
952 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(sel), GTK_SELECTION_BROWSE);
953 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(tree), TRUE);
954 // Enable tooltip on the treeview.
955 gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(tree), PL3_CAT_TITLE);
957 sidebar_text = renderer = GTK_CELL_RENDERER(my_cell_renderer_new());
958 g_object_set(G_OBJECT(renderer), "xalign", 0.5,NULL);
959 column = gtk_tree_view_column_new();
960 gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column),GTK_TREE_VIEW_COLUMN_AUTOSIZE);
962 gtk_tree_view_column_pack_start(column, renderer, TRUE);
963 g_object_set(G_OBJECT(renderer), "stock-size", GTK_ICON_SIZE_MENU, NULL);
965 int w, h;
966 if (gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &w, &h))
968 g_object_set(G_OBJECT(renderer), "height", h+10, NULL);
969 g_object_set(G_OBJECT(renderer), "image-width", w,NULL);
972 gtk_tree_view_column_set_attributes(column, renderer,
973 "icon-name", PL3_CAT_ICON_ID,
974 "stock-id", PL3_CAT_STOCK_ID,
975 "text", PL3_CAT_TITLE,
976 "weight", PL3_CAT_BOLD,
977 "show_text", PL3_CAT_SHOW_TEXT, NULL);
978 g_object_set(renderer, "weight-set", TRUE, NULL);
980 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
981 gtk_tree_view_set_search_column(GTK_TREE_VIEW(tree), PL3_CAT_TITLE);
982 g_signal_connect_after(G_OBJECT(sel), "changed", G_CALLBACK(pl3_cat_sel_changed), NULL);
984 TEC("setup cat_tree");
986 /* initialize the category view */
987 pl3_initialize_tree();
989 TEC("Init category tree")
990 gtk_widget_show(GTK_WIDGET(gtk_builder_get_object(pl3_xml, "vbox_playlist_player")));
993 * The new progress bar
995 pb = (GtkWidget *) gtk_builder_get_object(pl3_xml, "hbox_progress");
996 gtk_widget_show(pb);
997 g_signal_connect(G_OBJECT(pb), "seek-event", G_CALLBACK(pl3_pb_seek_event), NULL);
999 new_pb = pb;
1001 TEC("Init progress bar")
1002 /* Make sure change is applied */
1004 playlist3_new_header();
1006 pl3_sidebar_plugins_init();
1008 TEC("Init header")
1009 if (!cfg_get_single_value_as_int_with_default(config, "Interface", "hide-favorites-icon", FALSE))
1011 favorites_button = gmpc_favorites_button_new();
1012 ali = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
1013 gtk_container_add(GTK_CONTAINER(ali), GTK_WIDGET(favorites_button));
1014 gtk_box_pack_start(GTK_BOX(gtk_builder_get_object(pl3_xml, "hbox10")), GTK_WIDGET(ali), FALSE, FALSE, 0);
1015 gtk_widget_show_all(GTK_WIDGET(ali));
1016 TEC("Init fav icon")
1018 playlist_status_changed(connection,
1019 MPD_CST_STATE | MPD_CST_SONGID | MPD_CST_NEXTSONG |
1020 MPD_CST_ELAPSED_TIME | MPD_CST_VOLUME |
1021 MPD_CST_REPEAT | MPD_CST_RANDOM | MPD_CST_PERMISSION
1022 | MPD_CST_SINGLE_MODE | MPD_CST_CONSUME_MODE, NULL);
1023 g_signal_connect(G_OBJECT(gtk_builder_get_object(pl3_xml, "volume_button")),
1024 "value_changed", G_CALLBACK(playlist_player_volume_changed), NULL);
1026 TEC("Signal setup")
1028 /* Restore values from config */
1029 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION
1030 (gtk_builder_get_object
1031 (pl3_xml, "ViewShowArtistImage")),
1032 cfg_get_single_value_as_int_with_default
1033 (config, "playlist", "cover-image-enable", 0));
1035 /* connect signals that are defined in the gui description */
1036 gtk_builder_connect_signals(pl3_xml,NULL);
1038 TEC("connect signals")
1040 /* select the current playlist */
1041 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(pl3_tree), &iter))
1043 gtk_tree_selection_select_iter(sel, &iter);
1046 TEC("Select view")
1048 * Insert new custom widget
1050 metaimage_album_art = gmpc_metaimage_new(META_ALBUM_ART);
1052 /* Hide when requested. */
1053 if (cfg_get_single_value_as_int_with_default(config, "Interface", "hide-album-art", FALSE))
1055 gmpc_metaimage_set_is_visible(GMPC_METAIMAGE(metaimage_album_art), FALSE);
1057 gtk_box_pack_start(GTK_BOX
1058 (gtk_builder_get_object(pl3_xml, "hbox_playlist_player")), metaimage_album_art, FALSE, TRUE, 0);
1060 gtk_box_reorder_child(GTK_BOX
1061 (gtk_builder_get_object(pl3_xml, "hbox_playlist_player")), metaimage_album_art, 0);
1062 gmpc_metaimage_set_size(GMPC_METAIMAGE(metaimage_album_art), ALBUM_SIZE);
1063 gmpc_metaimage_set_no_cover_icon(GMPC_METAIMAGE(metaimage_album_art), (char *)"gmpc");
1064 gmpc_metaimage_set_connection(GMPC_METAIMAGE(metaimage_album_art), connection);
1065 /** make sure size is updated */
1066 gmpc_metaimage_set_cover_na(GMPC_METAIMAGE(metaimage_album_art));
1068 metaimage_artist_art = gmpc_metaimage_new(META_ARTIST_ART);
1069 gtk_container_add(GTK_CONTAINER(gtk_builder_get_object(pl3_xml, "sidebar_artist_image_alignment")), metaimage_artist_art);
1071 gmpc_metaimage_set_no_cover_icon(GMPC_METAIMAGE(metaimage_artist_art), (char *)"no-artist");
1072 gmpc_metaimage_set_loading_cover_icon(GMPC_METAIMAGE(metaimage_artist_art), (char *)"fetching-artist");
1073 gmpc_metaimage_set_connection(GMPC_METAIMAGE(metaimage_artist_art), connection);
1074 if (!cfg_get_single_value_as_int_with_default(config, "playlist", "cover-image-enable", FALSE))
1076 gmpc_metaimage_set_is_visible(GMPC_METAIMAGE(metaimage_artist_art), FALSE);
1078 gmpc_metaimage_set_squared(GMPC_METAIMAGE(metaimage_artist_art), FALSE);
1079 gmpc_metaimage_set_size(GMPC_METAIMAGE(metaimage_artist_art), 145);
1081 TEC("Setup metaimages")
1082 /* restore the window's position and size, if the user wants this. */
1083 if (cfg_get_single_value_as_int_with_default(config, "playlist", "savepossize", 1))
1085 int maximized = cfg_get_single_value_as_int_with_default(config, "playlist", "maximized", 0);
1086 /* Load values from config file */
1087 pl3_wsize.x = cfg_get_single_value_as_int_with_default(config, "playlist", "xpos", 0);
1088 pl3_wsize.y = cfg_get_single_value_as_int_with_default(config, "playlist", "ypos", 0);
1089 pl3_wsize.width = cfg_get_single_value_as_int_with_default(config, "playlist", "width", 0);
1090 pl3_wsize.height = cfg_get_single_value_as_int_with_default(config, "playlist", "height", 0);
1091 TEC("get settings")
1092 /* restore location + position */
1093 /*pl3_show_and_position_window(); */
1095 if (pl3_wsize.x > 0 || pl3_wsize.y > 0)
1097 gtk_window_move(GTK_WINDOW(playlist3_get_window()), pl3_wsize.x, pl3_wsize.y);
1099 TEC("move window settings")
1100 if (pl3_wsize.height > 0 && pl3_wsize.width > 0)
1102 g_log(LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "restore size %i %i\n", pl3_wsize.width, pl3_wsize.height);
1103 gtk_window_resize(GTK_WINDOW(playlist3_get_window()), pl3_wsize.width, pl3_wsize.height);
1105 TEC("set pane window settings")
1106 if (maximized)
1107 gtk_window_maximize(GTK_WINDOW(playlist3_get_window()));
1108 TEC("maximize pane window settings")
1110 * restore zoom level
1113 gtk_widget_show(playlist3_get_window());
1114 TEC("Show window")
1115 pl3_zoom = cfg_get_single_value_as_int_with_default(config, "playlist", "zoomlevel", PLAYLIST_NO_ZOOM);
1116 playlist_zoom_level_changed();
1117 TEC("zoom level")
1119 #ifdef HAVE_APP_INDICATOR
1120 tray_icon2_update_menu();
1121 #endif
1123 TEC("Restore state")
1124 pl3_update_go_menu();
1125 TEC("Go menu")
1126 /* make it update itself */
1127 pl3_update_profiles_menu(gmpc_profiles, GMPC_PROFILES_ACTION_ADDED, -1, NULL);
1128 g_signal_connect(G_OBJECT(gmpc_profiles), "changed", G_CALLBACK(pl3_update_profiles_menu), NULL);
1129 g_signal_connect(G_OBJECT(gmpc_profiles), "changed", G_CALLBACK(pl3_profiles_changed), NULL);
1131 TEC("Update profiles")
1133 * Set as drag destination
1135 gtk_drag_dest_set(GTK_WIDGET(gtk_builder_get_object(pl3_xml, "hbox_playlist_player")),
1136 GTK_DEST_DEFAULT_ALL,
1137 target_table, 6, GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_DEFAULT | GDK_ACTION_MOVE);
1138 g_signal_connect(G_OBJECT
1139 (gtk_builder_get_object(pl3_xml, "hbox_playlist_player")),
1140 "drag_data_received", G_CALLBACK (playlist3_source_drag_data_recieved), NULL);
1142 TEC("setup drag")
1146 playlist_connection_changed(connection, FALSE, NULL);
1148 g_signal_connect(G_OBJECT(playlist3_get_window()), "window-state-event", G_CALLBACK(pl3_win_state_event), NULL);
1150 TEC("signal connn changed")
1152 g_signal_connect(G_OBJECT(playlist3_get_window()), "style-set", G_CALLBACK(pl3_style_set_event), NULL);
1155 * Add status icons
1157 main_window_init_default_status_icons();
1158 main_window_update_status_icons();
1160 TEC("Update status icon")
1161 /* Update extra */
1162 init_extra_playlist_state();
1163 TEC("Setup extra playlist")
1165 // Add window to GtkApplication.
1166 gtk_application_add_window(gmpc_application, playlist3_get_window());
1171 * Helper functions
1173 GtkListStore *playlist3_get_category_tree_store(void)
1175 if (pl3_xml == NULL)
1176 return NULL;
1177 return GTK_LIST_STORE(pl3_tree);
1181 GtkTreeView *playlist3_get_category_tree_view(void)
1183 if (pl3_xml == NULL)
1184 return NULL;
1185 return (GtkTreeView *) gtk_builder_get_object(pl3_xml, "cat_tree");
1188 GtkWidget* playlist3_get_widget_by_id(const char *id) {
1189 return (GtkWidget *) gtk_builder_get_object(pl3_xml, id);
1193 /****************************************************************************************
1194 * PREFERENCES *
1195 ****************************************************************************************/
1196 /* prototyping for glade */
1197 void ck_stop_on_exit_toggled_cb(GtkToggleButton * but, gpointer data);
1198 void ck_show_tooltip_enable_tb(GtkToggleButton * but);
1200 G_MODULE_EXPORT void show_cover_case_tb(GtkToggleButton * but)
1202 int bool1 = gtk_toggle_button_get_active(but);
1203 cfg_set_single_value_as_int(config, "metaimage", "addcase", bool1);
1204 pixbuf_cache_clear();
1205 gmpc_meta_watcher_force_reload_cb(gmw);
1209 G_MODULE_EXPORT void ck_stop_on_exit_toggled_cb(GtkToggleButton * but, gpointer data)
1211 int bool1 = gtk_toggle_button_get_active(but);
1212 cfg_set_single_value_as_int(config, "connection", "stop-on-exit", bool1);
1216 G_MODULE_EXPORT void hide_on_close_enable_tb(GtkToggleButton * but)
1218 int bool1 = gtk_toggle_button_get_active(but);
1219 cfg_set_single_value_as_int(config, "playlist", "hide-on-close", bool1);
1223 G_MODULE_EXPORT void cur_song_center_enable_tb(GtkToggleButton * but)
1225 int bool1 = gtk_toggle_button_get_active(but);
1226 cfg_set_single_value_as_int(config, "playlist", "st_cur_song", bool1);
1230 G_MODULE_EXPORT void save_possize_enable_tb(GtkToggleButton * but)
1232 int bool1 = gtk_toggle_button_get_active(but);
1233 cfg_set_single_value_as_int(config, "playlist", "savepossize", bool1);
1237 G_MODULE_EXPORT void ck_show_tooltip_enable_tb(GtkToggleButton * but)
1239 int bool1 = gtk_toggle_button_get_active(but);
1240 cfg_set_single_value_as_int(config, "GmpcTreeView", "show-tooltip", bool1);
1244 G_MODULE_EXPORT void ck_search_as_you_type(GtkToggleButton * but)
1246 int bool1 = gtk_toggle_button_get_active(but);
1247 cfg_set_single_value_as_int(config, "general", "search-as-you-type", bool1);
1251 static void playlist_pref_destroy(GtkWidget * container)
1253 if (playlist_pref_xml)
1255 GtkWidget *vbox = (GtkWidget *) gtk_builder_get_object(playlist_pref_xml,
1256 "playlist-vbox");
1257 gtk_container_remove(GTK_CONTAINER(container), vbox);
1258 g_object_unref(playlist_pref_xml);
1259 playlist_pref_xml = NULL;
1264 void playlist_pref_construct(GtkWidget * container)
1266 GError *error = NULL;
1267 gchar *path = gmpc_get_full_glade_path("preferences-playlist.ui");
1268 playlist_pref_xml = gtk_builder_new();
1270 gtk_builder_add_from_file(playlist_pref_xml, path, &error);
1271 if(error) {
1272 g_warning("Failed to open builder file: %s", error->message);
1273 g_error_free(error);
1274 return;
1276 if (playlist_pref_xml)
1278 GtkWidget *vbox = (GtkWidget *) gtk_builder_get_object(playlist_pref_xml,
1279 "playlist-vbox");
1280 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
1281 (gtk_builder_get_object
1282 (playlist_pref_xml, "ck_ps")),
1283 cfg_get_single_value_as_int_with_default(config, "playlist", "st_cur_song", 0));
1284 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
1285 (gtk_builder_get_object
1286 (playlist_pref_xml, "ck_possize")),
1287 cfg_get_single_value_as_int_with_default(config, "playlist", "savepossize", 1));
1288 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
1289 (gtk_builder_get_object
1290 (playlist_pref_xml, "ck_hide_on_close")),
1291 cfg_get_single_value_as_int_with_default(config, "playlist", "hide-on-close", 0));
1293 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
1294 (gtk_builder_get_object
1295 (playlist_pref_xml, "ck_stop_on_exit")),
1296 cfg_get_single_value_as_int_with_default(config, "connection", "stop-on-exit", 0));
1298 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
1299 (gtk_builder_get_object
1300 (playlist_pref_xml, "ck_cover_case")),
1301 cfg_get_single_value_as_int_with_default(config, "metaimage", "addcase", TRUE));
1303 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
1304 (gtk_builder_get_object
1305 (playlist_pref_xml, "ck_show_tooltip")),
1306 cfg_get_single_value_as_int_with_default
1307 (config, "GmpcTreeView", "show-tooltip", TRUE));
1309 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
1310 (gtk_builder_get_object
1311 (playlist_pref_xml, "ck_search_as_you_type")),
1312 cfg_get_single_value_as_int_with_default(config, "general", "search-as-you-type",
1313 0));
1314 gtk_container_add(GTK_CONTAINER(container), vbox);
1315 gtk_widget_show_all(vbox);
1316 gtk_builder_connect_signals(playlist_pref_xml, NULL);
1318 g_free(path);
1323 * Menu Callback functions
1326 void playlist_menu_repeat_changed(GtkToggleAction * action)
1328 int active = gtk_toggle_action_get_active(action);
1329 if (active != mpd_player_get_repeat(connection))
1331 mpd_player_set_repeat(connection, active);
1336 void playlist_menu_random_changed(GtkToggleAction *action)
1338 int active = gtk_toggle_action_get_active(action);
1339 if (active != mpd_player_get_random(connection))
1341 mpd_player_set_random(connection, active);
1346 void playlist_menu_single_mode_changed(GtkToggleAction * action)
1348 int active = gtk_toggle_action_get_active(action);
1349 if (active != mpd_player_get_single(connection))
1351 mpd_player_set_single(connection, active);
1356 void playlist_menu_consume_changed(GtkToggleAction * action)
1358 int active = gtk_toggle_action_get_active(action);
1359 if (active != mpd_player_get_consume(connection))
1361 mpd_player_set_consume(connection, active);
1367 * This is artist image
1368 * FIXME: Rename
1370 void playlist_menu_artist_image_changed(GtkToggleAction *ta)
1372 int active = gtk_toggle_action_get_active(ta);
1373 cfg_set_single_value_as_int(config, "playlist", "cover-image-enable", active);
1374 if(pl3_zoom < PLAYLIST_SMALL)
1376 gmpc_metaimage_set_is_visible(GMPC_METAIMAGE(metaimage_artist_art), active);
1377 if (active)
1378 gtk_widget_show(metaimage_artist_art);
1383 /***
1384 * Zooming functions
1386 void playlist_zoom_out(void)
1388 /* Do not change zoom level when fullscreen */
1389 if(pl3_window_is_fullscreen())
1390 return;
1391 if ((pl3_zoom + 1) >= PLAYLIST_ZOOM_LEVELS)
1392 return;
1393 pl3_old_zoom = pl3_zoom;
1394 pl3_zoom++;
1395 playlist_zoom_level_changed();
1399 void playlist_zoom_in(void)
1401 /* Do not change zoom level when fullscreen */
1402 if(pl3_window_is_fullscreen())
1403 return;
1404 if (pl3_zoom <= PLAYLIST_NO_ZOOM)
1405 return;
1406 pl3_old_zoom = pl3_zoom;
1407 pl3_zoom--;
1408 playlist_zoom_level_changed();
1410 static void update_show_text(gboolean state)
1412 GtkTreeView *tree = (GtkTreeView *) gtk_builder_get_object(pl3_xml, "cat_tree");
1413 GtkTreeModel *model = gtk_tree_view_get_model(tree);
1414 GtkTreeIter iter;
1415 if(gtk_tree_model_get_iter_first(model, &iter))
1418 gtk_list_store_set(GTK_LIST_STORE(model), &iter, PL3_CAT_SHOW_TEXT, state, -1);
1419 }while(gtk_tree_model_iter_next(model, &iter));
1424 * FIXME: Needs propper grouping and cleaning up
1426 static void playlist_zoom_level_changed(void)
1428 gboolean st_shown;
1429 GtkWidget *pl3_win = playlist3_get_window();
1430 printf("playlist3 zoom level changed\n");
1432 if (pl3_old_zoom <= PLAYLIST_SMALL)
1434 gtk_window_get_size(GTK_WINDOW(pl3_win), &pl3_wsize.width, &pl3_wsize.height);
1435 cfg_set_single_value_as_int(config, "playlist", "width", pl3_wsize.width);
1436 cfg_set_single_value_as_int(config, "playlist", "height", pl3_wsize.height);
1437 g_log(LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "save size: %i %i\n", pl3_wsize.width, pl3_wsize.height);
1440 if (pl3_old_zoom == PLAYLIST_MINI && pl3_zoom != PLAYLIST_MINI)
1442 GtkWidget *box =GTK_WIDGET(gtk_builder_get_object(pl3_xml, "pl3_button_control_box"));
1443 GtkWidget *top = GTK_WIDGET(gtk_builder_get_object(pl3_xml, "hbox10"));
1444 GtkWidget *vtop = GTK_WIDGET(gtk_builder_get_object(pl3_xml, "vbox_playlist_player"));
1445 /* add my own reference */
1446 g_object_ref(box);
1447 gtk_container_remove(GTK_CONTAINER(vtop), box);
1448 gtk_box_pack_end(GTK_BOX(top), box, FALSE, TRUE, 0);
1449 gtk_box_reorder_child(GTK_BOX(top), box, 0);
1450 /* release my reference */
1451 g_object_unref(box);
1452 gtk_widget_show(box);
1453 gmpc_progress_set_hide_text(GMPC_PROGRESS(new_pb), FALSE);
1455 if (pl3_old_zoom != PLAYLIST_MINI && pl3_zoom == PLAYLIST_MINI)
1457 GtkWidget *box = GTK_WIDGET(gtk_builder_get_object(pl3_xml, "pl3_button_control_box"));
1458 GtkWidget *top = GTK_WIDGET(gtk_builder_get_object(pl3_xml, "hbox10"));
1459 GtkWidget *vtop = GTK_WIDGET(gtk_builder_get_object(pl3_xml, "vbox_playlist_player"));
1460 /* add my own reference */
1461 g_object_ref(box);
1462 gtk_container_remove(GTK_CONTAINER(top), box);
1463 gtk_box_pack_end(GTK_BOX(vtop), box, FALSE, TRUE, 3);
1464 /* release my reference */
1465 g_object_unref(box);
1466 gtk_widget_show(box);
1468 gmpc_progress_set_hide_text(GMPC_PROGRESS(new_pb), TRUE);
1471 /* Show full view */
1472 gtk_widget_show(GTK_WIDGET(gtk_builder_get_object(pl3_xml, "hpaned1-hbox")));
1473 gtk_widget_show(GTK_WIDGET(gtk_builder_get_object(pl3_xml, "hbox1")));
1474 gtk_widget_show(GTK_WIDGET(gtk_builder_get_object(pl3_xml, "hbox10")));
1475 /** Menu Bar */
1476 /** BUTTON BOX */
1477 gtk_widget_show(GTK_WIDGET(gtk_builder_get_object(pl3_xml, "pl3_button_control_box")));
1479 gtk_window_set_resizable(GTK_WINDOW(pl3_win), TRUE);
1480 if (pl3_wsize.width > 0 && pl3_wsize.height > 0 && pl3_old_zoom == PLAYLIST_MINI)
1482 g_log(LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "restore size %i %i\n", pl3_wsize.width, pl3_wsize.height);
1483 gtk_window_resize(GTK_WINDOW(pl3_win), pl3_wsize.width, pl3_wsize.height);
1485 gtk_widget_show(GTK_WIDGET(gtk_builder_get_object(pl3_xml, "sidebar")));
1487 if (cfg_get_single_value_as_int_with_default(config, "playlist", "cover-image-enable", FALSE))
1489 gmpc_metaimage_set_is_visible(GMPC_METAIMAGE(metaimage_artist_art), TRUE);
1490 gtk_widget_show(metaimage_artist_art);
1492 gtk_action_set_visible(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_go")),TRUE);
1493 gtk_action_set_visible(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_option")),TRUE);
1495 update_show_text(TRUE);
1496 gmpc_sidebar_plugins_update_state(GMPC_PLUGIN_SIDEBAR_STATE_FULL);
1498 /* Now start hiding */
1499 switch (pl3_zoom)
1501 case PLAYLIST_NO_ZOOM:
1502 break;
1503 case PLAYLIST_MINI:
1504 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(pl3_xml, "hpaned1-hbox")));
1505 gtk_action_set_visible(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_option")),FALSE);
1506 gtk_action_set_visible(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_go")),FALSE);
1507 if (pl3_win)
1509 if (gdk_window_get_state(gtk_widget_get_window(pl3_win)) & GDK_WINDOW_STATE_MAXIMIZED)
1511 gtk_window_unmaximize(GTK_WINDOW(pl3_win));
1514 if (gdk_window_get_state(gtk_widget_get_window(pl3_win)) & GDK_WINDOW_STATE_FULLSCREEN)
1516 gtk_window_unfullscreen(GTK_WINDOW(pl3_win));
1519 gtk_window_set_resizable(GTK_WINDOW(pl3_win), FALSE);
1521 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(pl3_xml, "sidebar")));
1522 break;
1523 case PLAYLIST_SMALL:
1524 gmpc_metaimage_set_is_visible(GMPC_METAIMAGE(metaimage_artist_art), FALSE);
1525 update_show_text(FALSE);
1526 gmpc_sidebar_plugins_update_state(GMPC_PLUGIN_SIDEBAR_STATE_COLLAPSED);
1527 gtk_widget_grab_focus(pl3_win);
1528 default:
1529 break;
1531 /** Save zoom level
1533 cfg_set_single_value_as_int(config, "playlist", "zoomlevel", pl3_zoom);
1538 * Update the window to status changes in mpd
1540 static void playlist_status_changed(MpdObj * mi, ChangedStatusType what, void *userdata)
1542 char buffer[1024];
1543 GtkWidget *pl3_win = playlist3_get_window();
1545 * if the window isn't there yet, return
1547 if (!pl3_xml)
1548 return;
1549 control_window_status_update(mi, what, control_window);
1551 * Player state changed
1553 if (what & MPD_CST_STATE)
1555 mpd_Song *song = mpd_playlist_get_current_song(connection);
1556 int state = mpd_player_get_state(mi);
1557 switch (state)
1559 case MPD_PLAYER_PLAY:
1561 gchar *markup = cfg_get_single_value_as_string_with_default(config,
1562 "playlist", /* Category */
1563 "window-markup",/* Key */
1564 /* default value */
1565 "[%title% - &[%artist%]]|%name%|%shortfile%"
1568 * Update the image in the menu
1570 gtk_action_set_stock_id(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDPlayPause")), "gtk-media-pause");
1571 gtk_image_set_from_stock(GTK_IMAGE
1572 (gtk_builder_get_object
1573 (pl3_xml, "play_button_image")), "gtk-media-pause",
1574 GTK_ICON_SIZE_MENU);
1577 * Update window title
1579 mpd_song_markup(buffer, 1024, markup, mpd_playlist_get_current_song(connection));
1581 if (gmpc_profiles_get_number_of_profiles(gmpc_profiles) > 1)
1583 gchar *id = gmpc_profiles_get_current(gmpc_profiles);
1584 if (id)
1586 gchar *string = g_strdup_printf("[%s] %s", gmpc_profiles_get_name(gmpc_profiles,
1587 id), buffer);
1588 gtk_window_set_title(GTK_WINDOW(pl3_win), string);
1589 g_free(id);
1590 g_free(string);
1592 } else
1593 gtk_window_set_title(GTK_WINDOW(pl3_win), buffer);
1595 g_free(markup);
1596 break;
1598 case MPD_PLAYER_PAUSE:
1600 gchar *markup = cfg_get_single_value_as_string_with_default(config,
1601 "playlist", /* Category */
1602 "window-markup",/* Key */
1603 /* default value */
1604 "[%title% - &[%artist%]]|%name%|%shortfile%"
1606 /** Update menu and button images */
1608 gtk_action_set_stock_id(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDPlayPause")), "gtk-media-play");
1609 gtk_image_set_from_stock(GTK_IMAGE
1610 (gtk_builder_get_object
1611 (pl3_xml, "play_button_image")), "gtk-media-play",
1612 GTK_ICON_SIZE_MENU);
1614 * Set paused in Window string
1616 mpd_song_markup(buffer, 1024 - strlen(_("paused") - 4),
1617 markup, mpd_playlist_get_current_song(connection));
1618 /* Append translated paused */
1619 strcat(buffer, " (");
1620 strcat(buffer, _("paused"));
1621 strcat(buffer, ")");
1623 if (gmpc_profiles_get_number_of_profiles(gmpc_profiles) > 1)
1625 gchar *id = gmpc_profiles_get_current(gmpc_profiles);
1626 if (id)
1628 gchar *string = g_strdup_printf("[%s] %s", gmpc_profiles_get_name(gmpc_profiles,
1629 id), buffer);
1630 gtk_window_set_title(GTK_WINDOW(pl3_win), string);
1631 g_free(id);
1632 g_free(string);
1634 } else
1635 gtk_window_set_title(GTK_WINDOW(pl3_win), buffer);
1636 g_free(markup);
1637 break;
1639 default:
1640 gtk_action_set_stock_id(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDPlayPause")), "gtk-media-play");
1641 /* Make sure it's reset correctly */
1642 gmpc_progress_set_time(GMPC_PROGRESS(new_pb), 0, 0);
1644 gtk_image_set_from_stock(GTK_IMAGE
1645 (gtk_builder_get_object
1646 (pl3_xml, "play_button_image")), "gtk-media-play",
1647 GTK_ICON_SIZE_MENU);
1648 if (gmpc_profiles_get_number_of_profiles(gmpc_profiles) > 1)
1650 gchar *id = gmpc_profiles_get_current(gmpc_profiles);
1651 if (id)
1653 gchar *string = g_strdup_printf("[%s] %s", gmpc_profiles_get_name(gmpc_profiles,
1654 id), _("GMPC"));
1655 gtk_window_set_title(GTK_WINDOW(pl3_win), string);
1656 g_free(id);
1657 g_free(string);
1659 } else
1660 gtk_window_set_title(GTK_WINDOW(pl3_win), _("GMPC"));
1662 playlist3_update_header();
1664 if(favorites_button != NULL)
1666 if (state == MPD_PLAYER_PLAY || state == MPD_PLAYER_PAUSE)
1668 gmpc_favorites_button_set_song(favorites_button, song);
1669 } else
1671 gmpc_favorites_button_set_song(favorites_button, NULL);
1676 * Handle song change or Playlist change
1677 * Anything that can change metadta
1679 if (what & MPD_CST_SONGID || what & MPD_CST_SONGPOS || what & MPD_CST_PLAYLIST)
1681 playlist3_update_header();
1682 /* make is update markups and stuff */
1683 playlist_status_changed(mi, MPD_CST_STATE, NULL);
1686 * set repeat buttons in menu correct
1688 if (what & MPD_CST_REPEAT)
1690 if (mpd_check_connected(connection))
1692 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_builder_get_object(pl3_xml, "MPDRepeat")),
1693 mpd_player_get_repeat(connection));
1697 if (what & MPD_CST_RANDOM)
1699 if (mpd_check_connected(connection))
1701 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_builder_get_object(pl3_xml, "MPDRandom")),
1702 mpd_player_get_random(connection));
1705 if (what & (MPD_CST_RANDOM | MPD_CST_REPEAT | MPD_CST_SINGLE_MODE | MPD_CST_CONSUME_MODE))
1707 main_window_update_status_icons();
1709 if (what & MPD_CST_SINGLE_MODE)
1711 if (mpd_check_connected(connection))
1713 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_builder_get_object(pl3_xml, "MPDSingleMode")),
1714 mpd_player_get_single(connection));
1718 if (what & MPD_CST_CONSUME_MODE)
1720 if (mpd_check_connected(connection))
1722 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_builder_get_object(pl3_xml, "MPDConsumeMode")),
1723 mpd_player_get_consume(connection));
1726 if (what & MPD_CST_ELAPSED_TIME)
1728 if (mpd_check_connected(connection))
1730 int totalTime = mpd_status_get_total_song_time(connection);
1731 int elapsedTime = mpd_status_get_elapsed_song_time(connection);
1732 gmpc_progress_set_time(GMPC_PROGRESS(new_pb), totalTime, elapsedTime);
1733 } else
1736 gmpc_progress_set_time(GMPC_PROGRESS(new_pb), 0, 0);
1739 if (what & MPD_CST_PERMISSION)
1741 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDSingleMode")),
1743 mpd_check_connected(connection) &&
1744 mpd_server_check_command_allowed(connection, "single") == MPD_SERVER_COMMAND_ALLOWED
1747 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDConsumeMode")),
1749 mpd_check_connected(connection) &&
1750 mpd_server_check_command_allowed(connection, "consume") == MPD_SERVER_COMMAND_ALLOWED
1753 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDPlayPause")),
1755 mpd_check_connected(connection) &&
1756 mpd_server_check_command_allowed(connection, "play") == MPD_SERVER_COMMAND_ALLOWED
1759 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDNext")),
1761 mpd_check_connected(connection) &&
1762 mpd_server_check_command_allowed(connection, "next") == MPD_SERVER_COMMAND_ALLOWED
1765 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDPrevious")),
1767 mpd_check_connected(connection) &&
1768 mpd_server_check_command_allowed(connection, "previous") == MPD_SERVER_COMMAND_ALLOWED
1771 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDStop")),
1773 mpd_check_connected(connection) &&
1774 mpd_server_check_command_allowed(connection, "stop") == MPD_SERVER_COMMAND_ALLOWED
1777 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDRepeat")),
1779 mpd_check_connected(connection) &&
1780 mpd_server_check_command_allowed(connection, "repeat") == MPD_SERVER_COMMAND_ALLOWED
1783 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDRandom")),
1785 mpd_check_connected(connection)&&
1786 mpd_server_check_command_allowed(connection, "random") == MPD_SERVER_COMMAND_ALLOWED
1789 /* Also update volume stuff */
1790 what = what|MPD_CST_VOLUME;
1793 if (what & MPD_CST_VOLUME)
1795 GtkWidget *volume_button = GTK_WIDGET(gtk_builder_get_object(pl3_xml, "volume_button"));
1796 int new_volume = mpd_status_get_volume(connection);
1797 if (new_volume >= 0 &&
1798 mpd_server_check_command_allowed(connection, "setvol") == MPD_SERVER_COMMAND_ALLOWED
1801 int volume = gtk_scale_button_get_value(GTK_SCALE_BUTTON(volume_button))/100.0;
1802 gtk_widget_show(GTK_WIDGET(volume_button));
1803 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDMuted")),
1804 TRUE
1806 /* don't do anything if nothing is changed */
1807 if (new_volume != volume)
1809 gtk_scale_button_set_value(GTK_SCALE_BUTTON(volume_button),new_volume/100.0f);
1811 } else
1813 gtk_scale_button_set_value(GTK_SCALE_BUTTON(volume_button),0);
1814 gtk_widget_hide(GTK_WIDGET(volume_button));
1815 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "MPDMuted")),
1816 FALSE
1820 if (what & MPD_CST_SERVER_ERROR)
1822 gchar *error = mpd_status_get_mpd_error(mi);
1823 if (error)
1825 gchar *mes = g_markup_printf_escaped("%s: '%s'",
1826 _("MPD Reported the following error"),
1827 error);
1828 playlist3_show_error_message(mes, ERROR_WARNING);
1829 g_free(mes);
1830 g_free(error);
1833 if (what & MPD_CST_OUTPUT)
1835 playlist3_fill_server_menu();
1837 if (what & MPD_CST_NEXTSONG)
1840 GtkWidget *next_button = GTK_WIDGET(gtk_builder_get_object(pl3_xml, "next_button"));
1841 if (next_button)
1843 int i = mpd_player_get_next_song_id(mi);
1844 if (i >= 0)
1846 mpd_Song *song = mpd_playlist_get_song(mi, i);
1847 if (song)
1849 mpd_song_markup(buffer, 1024, "[%title% - &[%artist%]]|%shortfile%", song);
1850 gtk_widget_set_tooltip_text(next_button, buffer);
1851 mpd_freeSong(song);
1852 } else
1853 gtk_widget_set_tooltip_text(next_button, "");
1854 } else
1855 gtk_widget_set_tooltip_text(next_button, "");
1860 gboolean playlist_player_volume_changed(GtkWidget * vol_but, double new_vol)
1862 int volume = new_vol*100; //gtk_scale_button_get_value(GTK_SCALE_BUTTON(vol_but)) * 100;
1863 int new_volume = mpd_status_get_volume(connection);
1864 if (new_volume >= 0 && new_volume != volume)
1866 mpd_status_set_volume(connection, volume);
1867 return FALSE;
1869 return FALSE;
1873 void about_window(void)
1875 gchar *path = gmpc_get_full_glade_path("aboutdialog.ui");
1876 GtkBuilder *xml = gtk_builder_new();
1877 GtkWidget *dialog = NULL;
1878 gtk_builder_add_from_file(xml, path, NULL);
1879 dialog = (GtkWidget *) gtk_builder_get_object(xml, "aboutdialog");
1881 gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(playlist3_get_window()));
1882 gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ON_PARENT);
1883 g_free(path);
1885 if (strlen(revision))
1887 path = g_strdup_printf("%s\nRevision: %s", VERSION, revision);
1888 } else
1890 path = g_strdup_printf("%s\n%s\n", VERSION, GMPC_TAGLINE);
1892 gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog), GMPC_COPYRIGHT);
1893 gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(dialog), _("Gnome Music Player Client"));
1894 gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog), GMPC_WEBSITE);
1895 gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), path);
1897 g_free(path);
1898 gtk_widget_show(dialog);
1899 gtk_dialog_run(GTK_DIALOG(dialog));
1900 gtk_widget_destroy(dialog);
1901 g_object_unref(xml);
1905 /****************************************************
1906 * Interface stuff
1908 void pl3_update_go_menu(void)
1910 int i = 0;
1911 int items = 0;
1912 GtkWidget *menu = NULL;
1913 GtkAccelGroup *group = playlist3_get_accel_group();
1914 GtkUIManager *ui = GTK_UI_MANAGER(gtk_builder_get_object(pl3_xml, "uimanager1"));
1915 GtkMenuItem *m_item = GTK_MENU_ITEM(gtk_ui_manager_get_widget(ui, "/menubartest/menu_go"));
1916 /***
1917 * Remove any old menu
1919 gtk_menu_item_set_submenu(m_item, NULL);
1921 * Create a new menu
1923 menu = gtk_menu_new();
1924 gtk_menu_set_accel_group(GTK_MENU(menu), group);
1925 if (mpd_check_connected(connection))
1927 for (i = 0; i < num_plugins; i++)
1929 if (gmpc_plugin_is_browser(plugins[i]))
1931 items += gmpc_plugin_browser_add_go_menu(plugins[i], menu);
1937 * Attach menu
1939 if (items)
1941 gtk_widget_show_all(menu);
1942 gtk_menu_item_set_submenu(m_item, menu);
1943 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_go")), TRUE);
1944 } else
1946 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_go")), FALSE);
1947 g_object_ref_sink(menu);
1948 g_object_unref(menu);
1953 static void pl3_profile_selected(GtkRadioMenuItem * radio, gpointer data)
1955 if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(radio)))
1957 gchar *uid = g_object_get_data(G_OBJECT(radio), "uid");
1958 if (!uid)
1960 return;
1962 connection_set_current_profile(uid);
1963 if (mpd_check_connected(connection))
1965 mpd_disconnect(connection);
1966 connect_to_mpd();
1972 static void pl3_profiles_changed(GmpcProfiles * prof, const int changed, const int col, const gchar * id)
1974 if (!mpd_check_connected(connection))
1976 playlist_connection_changed(connection, 0, NULL);
1981 static void pl3_update_profiles_menu(GmpcProfiles * prof, const int changed, const int col, const gchar * id)
1983 int items = 0;
1984 GtkWidget *menu = NULL;
1985 gchar *current = gmpc_profiles_get_current(gmpc_profiles);
1986 GList *iter, *mult;
1987 GtkUIManager *ui = GTK_UI_MANAGER(gtk_builder_get_object(pl3_xml, "uimanager1"));
1988 GtkMenuItem *m_item = GTK_MENU_ITEM(gtk_ui_manager_get_widget(ui, "/menubartest/menu_music/menu_profiles"));
1989 /* check if there is anything changed that is important for us. */
1991 if (changed == GMPC_PROFILES_ACTION_COL_CHANGED && col != GMPC_PROFILES_COLUMN_NAME)
1993 g_free(current);
1994 return;
1996 /***
1997 * Remove any old menu
1999 gtk_menu_item_set_submenu(m_item, NULL);
2001 * Create a new menu
2003 menu = gtk_menu_new();
2005 mult = gmpc_profiles_get_profiles_ids(gmpc_profiles);
2006 if (mult)
2008 GSList *group = NULL;
2009 iter = mult;
2012 /** Get profile name */
2013 const gchar *value = gmpc_profiles_get_name(gmpc_profiles, (char *)iter->data);
2014 GtkWidget *item = gtk_radio_menu_item_new_with_label(group, value);
2015 /* get new group */
2016 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item));
2017 /* add to the menu */
2018 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2020 /* check the current profile */
2021 if (!strcmp((char *)(iter->data), current))
2023 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);
2027 * Attach click handler
2029 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(pl3_profile_selected), NULL);
2031 /** Attach the uid to the handler */
2032 value = g_strdup((char *)(iter->data));
2033 g_object_set_data_full(G_OBJECT(item), "uid", (gpointer) value, g_free);
2035 items++;
2036 } while ((iter = g_list_next(iter)));
2037 g_list_free(mult);
2042 * Attach menu
2044 if (items)
2046 gtk_widget_show_all(menu);
2047 gtk_menu_item_set_submenu(m_item , menu);
2048 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_profiles")), TRUE);
2049 } else
2051 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_profiles")), FALSE);
2052 g_object_ref_sink(menu);
2053 g_object_unref(menu);
2055 g_free(current);
2059 static void playlist3_server_output_changed(GtkWidget * item, gpointer data)
2061 int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item), "id"));
2062 int state = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item));
2063 mpd_server_set_output_device(connection, id, state);
2068 void playlist3_server_update_db(void)
2070 mpd_database_update_dir(connection, "/");
2074 static GList *server_menu_items = NULL;
2075 static void playlist3_fill_server_menu(void)
2077 GtkUIManager *ui = GTK_UI_MANAGER(gtk_builder_get_object(pl3_xml, "uimanager1"));
2078 GtkMenuItem *m_item = GTK_MENU_ITEM(gtk_ui_manager_get_widget(ui, "/menubartest/menu_server"));
2079 /** Clear old items */
2080 if(server_menu_items != NULL)
2082 g_list_foreach(server_menu_items, (GFunc)gtk_widget_destroy, NULL);
2083 g_list_free(server_menu_items);
2084 server_menu_items = NULL;
2087 /* if connected fill with items */
2088 if (mpd_check_connected(connection))
2090 GtkWidget *menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(m_item));
2091 GtkWidget *menu_item = NULL;
2092 int i = 0;
2093 MpdData *data = NULL;
2095 data = mpd_server_get_output_devices(connection);
2096 if(data)
2098 menu_item = gtk_separator_menu_item_new();
2099 server_menu_items = g_list_append(server_menu_items, menu_item);
2100 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
2102 for (; data; data = mpd_data_get_next(data))
2104 menu_item = gtk_check_menu_item_new_with_label(data->output_dev->name);
2105 server_menu_items = g_list_append(server_menu_items, menu_item);
2106 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_item), data->output_dev->enabled ? TRUE : FALSE);
2107 gtk_widget_add_accelerator(menu_item, "activate",
2108 gtk_ui_manager_get_accel_group(GTK_UI_MANAGER(ui)),
2109 GDK_KEY_1 + i, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
2111 g_signal_connect(G_OBJECT(menu_item), "toggled", G_CALLBACK(playlist3_server_output_changed), NULL);
2112 g_object_set_data(G_OBJECT(menu_item), "id", GINT_TO_POINTER(data->output_dev->id));
2113 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
2114 i++;
2116 gtk_widget_show_all(menu);
2117 /* Server Menu Item */
2118 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_server")), TRUE);
2119 } else
2121 /* Server Menu Item */
2122 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_server")), FALSE);
2128 * new header
2130 /* glue code */
2132 extern GmpcBrowsersMetadata *browsers_metadata;
2134 void info2_activate(void)
2136 GtkTreeView *tree = (GtkTreeView *) gtk_builder_get_object(pl3_xml, "cat_tree");
2137 gmpc_browsers_metadata_select_browser(browsers_metadata, tree);
2141 void info2_fill_song_view(mpd_Song * song)
2143 info2_activate();
2144 gmpc_browsers_metadata_set_song(browsers_metadata, song);
2148 void info2_fill_artist_view(const gchar * artist)
2150 info2_activate();
2151 gmpc_browsers_metadata_set_artist(browsers_metadata, artist);
2155 void info2_fill_album_view(const gchar * artist, const gchar * album)
2157 info2_activate();
2158 gmpc_browsers_metadata_set_album(browsers_metadata, artist, album);
2162 void playlist3_insert_browser(GtkTreeIter * iter, gint position)
2164 GtkTreeIter it, *sib = NULL;
2165 gint pos = 0;
2166 GtkTreeModel *model = GTK_TREE_MODEL(pl3_tree);
2167 if (gtk_tree_model_get_iter_first(model, &it))
2171 gtk_tree_model_get(model, &it, PL3_CAT_ORDER, &pos, -1);
2172 if (position <= pos)
2173 sib = &it;
2174 } while (sib == NULL && gtk_tree_model_iter_next(model, &it));
2177 // first check breaks recursion. Do not check for header when adding a header.
2178 // Next check checks if the header is allready there.
2179 if(position%1000 != 0 && (pos-pos%1000) != (position-position%1000))
2181 // insert category
2182 pos = position-position%1000;
2184 if(pos == PL3_CAT_BROWSER_LIBRARY)
2186 playlist3_insert_browser(&it, PL3_CAT_BROWSER_LIBRARY);
2187 gtk_list_store_set(GTK_LIST_STORE(pl3_tree), &it,
2188 PL3_CAT_TYPE,-1, PL3_CAT_TITLE, _("Library"),PL3_CAT_BOLD, PANGO_WEIGHT_ULTRABOLD,-1);
2189 sib = &it;
2190 gtk_list_store_insert_after(GTK_LIST_STORE(pl3_tree), iter, sib);
2192 else if (pos == PL3_CAT_BROWSER_ONLINE_MEDIA)
2194 playlist3_insert_browser(&it, PL3_CAT_BROWSER_ONLINE_MEDIA);
2195 gtk_list_store_set(GTK_LIST_STORE(pl3_tree), &it,
2196 PL3_CAT_TYPE,-1, PL3_CAT_TITLE, _("Online Media"),PL3_CAT_BOLD, PANGO_WEIGHT_ULTRABOLD,-1);
2197 sib = &it;
2198 gtk_list_store_insert_after(GTK_LIST_STORE(pl3_tree), iter, sib);
2200 else if (pos == PL3_CAT_BROWSER_MISC)
2202 playlist3_insert_browser(&it, PL3_CAT_BROWSER_MISC);
2203 gtk_list_store_set(GTK_LIST_STORE(pl3_tree), &it,
2204 PL3_CAT_TYPE,-1, PL3_CAT_TITLE, _("Misc."),PL3_CAT_BOLD, PANGO_WEIGHT_ULTRABOLD,-1);
2205 sib = &it;
2206 gtk_list_store_insert_after(GTK_LIST_STORE(pl3_tree), iter, sib);
2208 else
2210 // Insert item.
2211 gtk_list_store_insert_before(GTK_LIST_STORE(pl3_tree), iter, sib);
2214 else
2216 gtk_list_store_insert_before(GTK_LIST_STORE(pl3_tree), iter, sib);
2218 gtk_list_store_set(GTK_LIST_STORE(pl3_tree), iter, PL3_CAT_ORDER, position, PL3_CAT_BOLD, PANGO_WEIGHT_NORMAL, -1);
2223 * Category editing
2226 void playlist3_destroy(void)
2228 GtkWidget *win = playlist3_get_window();
2229 if(server_menu_items) g_list_free(server_menu_items);
2230 gtk_widget_destroy(win);
2231 g_object_unref(pl3_xml);
2234 GtkWidget *playlist3_get_window(void)
2236 return GTK_WIDGET(gtk_builder_get_object(pl3_xml, "pl3_win"));
2240 /***
2241 * Help menu
2243 /* Make glade happy */
2244 void url_visit_website(void);
2245 void url_getting_help(void);
2247 void url_visit_website(void)
2249 open_uri(GMPC_WEBSITE);
2253 void url_getting_help(void)
2255 open_uri(GMPC_BUGTRACKER);
2259 gmpcPrefPlugin playlist_gpp =
2261 .construct = playlist_pref_construct,
2262 .destroy = playlist_pref_destroy
2265 gmpcPlugin playlist_plug =
2267 .name = N_("Interface"),
2268 .version = {1, 1, 1},
2269 .plugin_type = GMPC_INTERNALL,
2270 .mpd_status_changed = &playlist_status_changed,
2271 .mpd_connection_changed = &playlist_connection_changed,
2272 .pref = &playlist_gpp,
2277 * Tool menu
2280 void pl3_tool_menu_update(void)
2282 int i;
2283 int menu_items = 0;
2284 GtkWidget *menu = NULL;
2285 GtkAccelGroup *group = gtk_accel_group_new();
2286 GtkUIManager *ui = GTK_UI_MANAGER(gtk_builder_get_object(pl3_xml, "uimanager1"));
2287 GtkMenuItem *m_item = GTK_MENU_ITEM(gtk_ui_manager_get_widget(ui, "/menubartest/menu_tool"));
2288 gtk_menu_item_set_submenu(m_item, NULL);
2289 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_tool")), FALSE);
2290 if (!mpd_check_connected(connection))
2291 return;
2293 menu = gtk_menu_new();
2294 gtk_menu_set_accel_group(GTK_MENU(menu), group);
2295 g_object_unref(group);
2296 gtk_window_add_accel_group(GTK_WINDOW(playlist3_get_window()), group);
2297 for (i = 0; i < num_plugins; i++)
2299 menu_items += gmpc_plugin_tool_menu_integration(plugins[i], GTK_MENU(menu));
2301 if (menu_items)
2303 gtk_widget_show_all(menu);
2304 gtk_menu_item_set_submenu(m_item, menu);
2305 gtk_action_set_sensitive(GTK_ACTION(gtk_builder_get_object(pl3_xml, "menu_tool")), TRUE);
2306 } else
2308 g_object_ref_sink(menu);
2309 g_object_unref(menu);
2314 void easy_command_help_window(void)
2316 if (gmpc_easy_command)
2317 gmpc_easy_command_help_window(gmpc_easy_command, NULL);
2323 * Extra wrappings for menu
2325 extern gmpcPlugin extraplaylist_plugin;
2326 void enable_extra_playlist(GtkToggleAction *action)
2328 gboolean state = gtk_toggle_action_get_active(action);
2329 if(extraplaylist_plugin.set_enabled)
2331 if(extraplaylist_plugin.get_enabled() != state)
2333 extraplaylist_plugin.set_enabled(state);
2336 preferences_window_update();
2340 void init_extra_playlist_state(void)
2342 GtkToggleAction *action = GTK_TOGGLE_ACTION(gtk_builder_get_object(pl3_xml, "ViewExtraPlaylist"));
2343 if(extraplaylist_plugin.get_enabled)
2345 gtk_toggle_action_set_active(action, extraplaylist_plugin.get_enabled());
2349 GtkAccelGroup *playlist3_get_accel_group(void)
2351 static GtkAccelGroup *group = NULL;
2352 if(group == NULL) {
2353 group = gtk_accel_group_new();
2354 gtk_window_add_accel_group(GTK_WINDOW(playlist3_get_window()), group);
2356 return group;
2359 void open_local_file(void)
2361 char **handlers;
2362 gboolean found = FALSE;
2363 if(!mpd_check_connected(connection))
2364 return;
2366 /* Check if MPD supports 'file://' (so local files). */
2367 handlers = mpd_server_get_url_handlers(connection);
2368 if (handlers)
2370 int i=0;
2371 for(; !found && handlers != NULL && handlers[i] != NULL; i++) {
2372 if(g_utf8_collate(handlers[i], "file://") == 0) {
2373 found = TRUE;
2376 g_strfreev(handlers);
2378 /* error message or file open */
2379 if(!found) {
2380 /* Message not found */
2381 GtkWidget *gmd = gtk_message_dialog_new(
2382 (GtkWindow*)playlist3_get_window(),
2383 GTK_DIALOG_MODAL,
2384 GTK_MESSAGE_ERROR,
2385 GTK_BUTTONS_CLOSE,
2387 "To playback local files, you need to be connected "
2388 "using unix socket.\n"
2389 "See the MPD website for more information."
2392 gtk_dialog_run(GTK_DIALOG(gmd));
2393 gtk_widget_destroy(GTK_WIDGET(gmd));
2394 }else {
2395 GtkWidget *fmd = gtk_file_chooser_dialog_new(
2396 "Select a local file",
2397 (GtkWindow*)playlist3_get_window(),
2398 GTK_FILE_CHOOSER_ACTION_OPEN,
2399 GTK_STOCK_CLOSE,
2400 GTK_RESPONSE_CLOSE,
2401 GTK_STOCK_OPEN,
2402 GTK_RESPONSE_OK,
2403 NULL);
2404 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(fmd), TRUE);
2405 switch(gtk_dialog_run(GTK_DIALOG(fmd)))
2407 case GTK_RESPONSE_OK:
2409 GSList *iter;
2410 GSList *uris = gtk_file_chooser_get_uris(GTK_FILE_CHOOSER(fmd));
2411 for(iter = uris;
2412 iter != NULL;
2413 iter = g_slist_next(iter))
2415 char *uri = g_uri_unescape_string(iter->data,NULL);
2416 url_start_real(uri);
2417 g_free(uri);
2419 g_slist_foreach (uris, (GFunc) g_free, NULL);
2420 g_slist_free (uris);
2421 break;
2423 default:
2424 break;
2426 gtk_widget_destroy(GTK_WIDGET(fmd));
2430 void show_user_manual(void);
2431 void show_user_manual(void)
2433 open_help("ghelp:gmpc");
2436 GmpcPluginSidebarState playlist3_get_sidebar_state(void)
2438 return pl3_zoom == PLAYLIST_NO_ZOOM ? GMPC_PLUGIN_SIDEBAR_STATE_FULL:GMPC_PLUGIN_SIDEBAR_STATE_COLLAPSED;
2440 /* vim: set noexpandtab ts=4 sw=4 sts=4 tw=80: */