Modify version string to post-release version 0.18.101
[gmpc.git] / src / tray-icon2.c
blob0fffeacbd93d26dfdb638afaa98983c64ca0c3d9
1 /* Gnome Music Player Client (GMPC)
2 * Copyright (C) 2004-2009 Qball Cow <qball@sarine.nl>
3 * Project homepage: http://gmpc.wikia.com/
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 <libmpd/libmpd.h>
22 #include <string.h>
23 #include <config.h>
24 #include "main.h"
25 #include "playlist3.h"
26 #include "vala/gmpc-progress.h"
27 #include "gmpc-metaimage.h"
28 #include "misc.h"
31 /* name of config field */
32 #define TRAY_ICON2_ID "tray-icon2"
34 GtkStatusIcon *tray_icon2_gsi = NULL;
36 static gchar *current_song_checksum = NULL;
38 static void tray_icon2_status_changed(MpdObj *mi, ChangedStatusType what, void *userdata);
39 static void tray_icon2_connection_changed(MpdObj *mi, int connect,void *user_data);
40 static void tray_icon2_create_tooltip_real(int position);
41 static gboolean tray_icon2_tooltip_destroy(void);
42 /**
43 * Tooltip
45 GtkWidget *tray_icon2_tooltip = NULL;
46 GtkWidget *tray_icon2_tooltip_pb = NULL;
47 guint tray_icon2_tooltip_timeout = 0;
48 enum{
49 TI2_AT_TOOLTIP,
50 TI2_AT_UPPER_LEFT,
51 TI2_AT_UPPER_RIGHT,
52 TI2_AT_LOWER_LEFT,
53 TI2_AT_LOWER_RIGHT,
54 TI2_AT_NUM_OPTIONS
56 /**
57 * Preferences
59 static GtkBuilder *tray_icon2_preferences_xml = NULL;
60 void popup_timeout_changed(void);
61 void popup_position_changed(GtkComboBox *om);
62 void popup_enable_toggled(GtkToggleButton *but);
63 void tray_enable_toggled(GtkToggleButton *but);
64 void tray_icon2_preferences_pm_combo_changed(GtkComboBox *cm, gpointer data);
65 /**
66 * Tray icon
69 gboolean tray_icon2_get_available(void)
71 if(tray_icon2_gsi) {
72 if(gtk_status_icon_is_embedded(tray_icon2_gsi) &&
73 gtk_status_icon_get_visible(tray_icon2_gsi)) {
74 return TRUE;
77 return FALSE;
79 /**
80 * click on the tray icon
82 static void tray_icon2_activate(GtkStatusIcon *gsi, gpointer user_data)
84 pl3_toggle_hidden();
86 /**
87 * Right mouse press on tray icon
90 static void tray_icon2_seek_event(GtkWidget * pb, guint seek_time, gpointer user_data)
92 int state = cfg_get_single_value_as_int_with_default(config, TRAY_ICON2_ID, "tooltip-timeout", 5);
93 mpd_player_seek(connection, (int)seek_time);
94 if(tray_icon2_tooltip_timeout)
96 g_source_remove(tray_icon2_tooltip_timeout);
98 tray_icon2_tooltip_timeout = g_timeout_add_seconds(state*2, (GSourceFunc)tray_icon2_tooltip_destroy, NULL);
100 static void tray_icon2_populate_menu(GtkStatusIcon *gsi,guint button, guint activate_time, gpointer user_data)
102 GtkWidget *item;
103 GtkWidget *menu = gtk_menu_new();
105 if(mpd_check_connected(connection))
107 if(mpd_server_check_command_allowed(connection, "play"))
109 if(mpd_player_get_state(connection) == MPD_STATUS_STATE_PLAY)
111 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_MEDIA_PAUSE, NULL);
112 }else{
113 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_MEDIA_PLAY, NULL);
115 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
116 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(play_song), NULL);
119 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_MEDIA_STOP, NULL);
120 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
121 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(stop_song), NULL);
123 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_MEDIA_NEXT, NULL);
124 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
125 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(next_song), NULL);
128 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_MEDIA_PREVIOUS, NULL);
129 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
130 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(prev_song), NULL);
131 item = gtk_separator_menu_item_new();
132 gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
135 else
137 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CONNECT, NULL);
138 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
139 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(connect_to_mpd), NULL);
140 item = gtk_separator_menu_item_new();
141 gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
143 item = gtk_image_menu_item_new_with_mnemonic(_("Pla_ylist"));
144 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
145 gtk_image_new_from_stock("gtk-justify-fill", GTK_ICON_SIZE_MENU));
146 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
147 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(create_playlist3), NULL);
150 item = gtk_separator_menu_item_new();
151 gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
153 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT,NULL);
154 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
155 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(main_quit), NULL);
156 gtk_widget_show_all(menu);
157 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, gtk_status_icon_position_menu, gsi, button, activate_time);
159 static void tray_icon2_embedded_changed(GtkStatusIcon *icon,GParamSpec *arg1, gpointer data)
161 if(!gtk_status_icon_is_embedded(icon))
163 /* the widget isn't embedded anymore */
164 create_playlist3();
168 * Initialize the tray icon
170 static int tray_icon2_button_press_event(gpointer tray, GdkEventButton *event, gpointer data)
172 if(event->button == 2)
174 play_song();
176 else
178 return FALSE;
181 return TRUE;
184 static int tray_icon2_button_scroll_event(gpointer tray, GdkEventScroll *event, gpointer data)
186 if(event->direction == GDK_SCROLL_UP) {
187 if(mpd_server_check_command_allowed(connection, "volume") && mpd_status_get_volume(connection) >=0)
188 volume_up();
189 }else if (event->direction == GDK_SCROLL_DOWN) {
190 if(mpd_server_check_command_allowed(connection, "volume") && mpd_status_get_volume(connection) >=0)
191 volume_down();
192 }else if (event->direction == GDK_SCROLL_LEFT) {
193 prev_song();
194 }else if (event->direction == GDK_SCROLL_RIGHT) {
195 next_song();
197 return TRUE;
199 /* hack to delay tooltip showup on tray-icon*/
200 GTimeVal current = {0,0};
201 static gboolean tray_icon2_tooltip_query(GtkStatusIcon *icon,
202 gint x, gint y,
203 gboolean keyboard_mode,
204 GtkTooltip *tooltip,
205 gpointer user_data)
207 if(!keyboard_mode)
209 if(tray_icon2_tooltip == NULL){
210 GTimeVal now;
211 if(current.tv_sec == 0) {
212 g_get_current_time(&current);
213 return FALSE;
216 g_get_current_time(&now);
217 if((now.tv_sec - current.tv_sec ) > 5) {
218 current.tv_sec = 0;
219 return FALSE;
221 if(current.tv_sec < now.tv_sec)
223 current.tv_sec = 0;
224 tray_icon2_create_tooltip_real(TI2_AT_TOOLTIP);
225 return TRUE;
229 return FALSE;
232 static void tray_icon2_init(void)
235 if(cfg_get_single_value_as_int_with_default(config, TRAY_ICON2_ID, "enable", TRUE))
237 tray_icon2_gsi = gtk_status_icon_new_from_icon_name ("gmpc-tray-disconnected");
238 #if GTK_CHECK_VERSION(2,15,0)
239 gtk_status_icon_set_has_tooltip(GTK_STATUS_ICON(tray_icon2_gsi), TRUE);
240 #endif
242 /* connect the (sparse) signals */
243 g_signal_connect(G_OBJECT(tray_icon2_gsi), "popup-menu", G_CALLBACK(tray_icon2_populate_menu), NULL);
244 g_signal_connect(G_OBJECT(tray_icon2_gsi), "activate", G_CALLBACK(tray_icon2_activate), NULL);
245 g_signal_connect(G_OBJECT(tray_icon2_gsi), "notify::embedded", G_CALLBACK(tray_icon2_embedded_changed), NULL);
246 if(gtk_check_version(2, 15, 0) == NULL)
248 g_signal_connect(G_OBJECT(tray_icon2_gsi), "button-press-event", G_CALLBACK(tray_icon2_button_press_event), NULL);
249 g_signal_connect(G_OBJECT(tray_icon2_gsi), "scroll-event", G_CALLBACK(tray_icon2_button_scroll_event), NULL);
251 g_signal_connect(G_OBJECT(tray_icon2_gsi), "query-tooltip", G_CALLBACK(tray_icon2_tooltip_query), NULL);
253 /* Make sure the icons are up2date */
254 tray_icon2_connection_changed(connection, mpd_check_connected(connection), NULL);
258 * Destroy and cleanup
260 static void tray_icon2_destroy(void)
262 if(tray_icon2_gsi)
264 g_object_unref(tray_icon2_gsi);
265 tray_icon2_gsi = NULL;
267 /* free the currnet song checksum */
268 if(current_song_checksum) {
269 g_free(current_song_checksum);
270 current_song_checksum = NULL;
274 * Get enabled
276 static gboolean tray_icon2_get_enabled(void)
278 return cfg_get_single_value_as_int_with_default(config, TRAY_ICON2_ID, "enable", TRUE);
281 * Set Disabled
283 static void tray_icon2_set_enabled(int enabled)
285 cfg_set_single_value_as_int(config, TRAY_ICON2_ID, "enable", enabled);
286 if(enabled) {
287 if(!tray_icon2_gsi) {
288 tray_icon2_init();
289 tray_icon2_status_changed(connection, MPD_CST_SONGID, NULL);
290 } else {
291 gtk_status_icon_set_visible(GTK_STATUS_ICON(tray_icon2_gsi), TRUE);
293 } else {
294 if(tray_icon2_gsi) {
295 gtk_status_icon_set_visible(GTK_STATUS_ICON(tray_icon2_gsi), FALSE);
300 * TOOLTIP
302 static gboolean has_buttons = FALSE;
303 static GtkWidget *play_button = NULL;
305 static gboolean tray_icon2_tooltip_destroy(void)
307 tray_icon2_tooltip_pb = NULL;
308 gtk_widget_destroy(tray_icon2_tooltip);
309 tray_icon2_tooltip = NULL;
310 /* remove timeout, this is for when it doesn't get called from inside the timeout */
311 if(tray_icon2_tooltip_timeout)
313 g_source_remove(tray_icon2_tooltip_timeout);
315 tray_icon2_tooltip_timeout = 0;
316 has_buttons = FALSE;
317 /* remove the timeout */
318 return FALSE;
321 static gboolean tray_icon2_tooltip_button_press_event(GtkWidget *box, GdkEventButton *event, GtkWidget *vbox)
323 if((event == NULL || event->button == 3) && !has_buttons)
325 GtkWidget *hbox,*button;
326 int state = cfg_get_single_value_as_int_with_default(config, TRAY_ICON2_ID, "tooltip-timeout", 5);
327 if(tray_icon2_tooltip_timeout)
329 g_source_remove(tray_icon2_tooltip_timeout);
331 tray_icon2_tooltip_timeout = g_timeout_add_seconds(state*2, (GSourceFunc)tray_icon2_tooltip_destroy, NULL);
333 has_buttons = TRUE;
335 hbox = gtk_hbox_new(TRUE, 6);
336 /* prev */
337 button = gtk_button_new();
338 gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_stock(GTK_STOCK_MEDIA_PREVIOUS,GTK_ICON_SIZE_BUTTON));
339 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
340 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(prev_song), NULL);
341 /* stop */
342 button = gtk_button_new();
343 gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_stock(GTK_STOCK_MEDIA_STOP,GTK_ICON_SIZE_BUTTON));
344 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
345 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(stop_song), NULL);
346 /* pause/play */
347 state = mpd_player_get_state(connection);
348 if(state != MPD_PLAYER_PLAY)
350 play_button = button = gtk_button_new();
351 gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY,GTK_ICON_SIZE_BUTTON));
352 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
353 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(play_song), NULL);
355 else
357 play_button = button = gtk_button_new();
358 gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_stock(GTK_STOCK_MEDIA_PAUSE,GTK_ICON_SIZE_BUTTON));
360 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
361 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(play_song), NULL);
363 /* next */
364 button = gtk_button_new();
365 gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_stock(GTK_STOCK_MEDIA_NEXT,GTK_ICON_SIZE_BUTTON));
367 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
368 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(next_song), NULL);
370 gtk_widget_show_all(hbox);
371 gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, TRUE,0);
373 return TRUE;
375 tray_icon2_tooltip_destroy();
376 return TRUE;
380 static void tray_icon2_create_tooltip_real(int position)
382 int x=0,y=0,monitor;
383 GdkScreen *screen;
384 GtkWidget *pl3_win = playlist3_get_window();
385 GtkWidget *hbox = NULL;
386 GtkWidget *vbox = NULL;
387 GtkWidget *label = NULL;
388 GtkWidget *event = NULL;
389 GtkWidget *coverimg = NULL;
390 GdkColormap *colormap;
391 mpd_Song *song = NULL;
392 int tooltip_timeout = cfg_get_single_value_as_int_with_default(config, TRAY_ICON2_ID, "tooltip-timeout", 5);
393 int state = 0;
394 int x_offset = cfg_get_single_value_as_int_with_default(config, TRAY_ICON2_ID, "x-offset", 0);
395 int y_offset = cfg_get_single_value_as_int_with_default(config, TRAY_ICON2_ID, "y-offset", 0);
398 song = mpd_playlist_get_current_song(connection);
400 * if the tooltip still exists destroy it...
402 if(tray_icon2_tooltip)
404 /* Do a check to avoid ugly redraws */
405 mpd_Song *song2 = g_object_get_data(G_OBJECT(tray_icon2_tooltip), "song");
406 if(song2 && song ){
407 if(song->file && song2->file && strcmp(song2->file, song->file) == 0)
409 if(tray_icon2_tooltip_timeout)
411 g_source_remove(tray_icon2_tooltip_timeout);
413 tray_icon2_tooltip_timeout = g_timeout_add_seconds(tooltip_timeout, (GSourceFunc)tray_icon2_tooltip_destroy, NULL);
414 return;
417 if(tray_icon2_tooltip_timeout)
419 g_source_remove(tray_icon2_tooltip_timeout);
420 tray_icon2_tooltip_timeout = 0;
422 tray_icon2_tooltip_pb = NULL;
423 gtk_widget_destroy(tray_icon2_tooltip);
424 tray_icon2_tooltip = NULL;
425 //tray_icon2_tooltip_destroy();
427 /* If gmpc is fullscreen, don't show the tooltip */
428 if(pl3_window_is_fullscreen())
429 return;
431 * Creat the tootlip window
433 tray_icon2_tooltip = gtk_window_new(GTK_WINDOW_POPUP);
434 screen = gtk_window_get_screen(GTK_WINDOW(tray_icon2_tooltip));
437 if (gdk_screen_is_composited(screen))
439 colormap = gdk_screen_get_rgba_colormap(screen);
440 if(colormap)
441 gtk_widget_set_colormap(tray_icon2_tooltip, colormap);
442 gtk_window_set_opacity(GTK_WINDOW(tray_icon2_tooltip), 0.9);
446 /* causes the border */
447 gtk_widget_modify_bg(GTK_WIDGET(tray_icon2_tooltip), GTK_STATE_NORMAL, &(pl3_win->style->black));
448 gtk_container_set_border_width(GTK_CONTAINER(tray_icon2_tooltip),1);
449 gtk_window_set_default_size(GTK_WINDOW(tray_icon2_tooltip), 300,-1);
450 gtk_window_set_transient_for(GTK_WINDOW(tray_icon2_tooltip), GTK_WINDOW(pl3_win));
453 * Tooltip exists from 2 parts..
454 * ------------------
455 * | 1 | |
456 * | | 2 |
457 * ------------------
459 hbox = gtk_hbox_new(FALSE,0);
460 gtk_container_add(GTK_CONTAINER(tray_icon2_tooltip), hbox);
464 * In first box we have image/coverart
465 * Re-use the gmpc-metaimage widget
468 coverimg = gmpc_metaimage_new_size(META_ALBUM_ART,80);
469 gmpc_metaimage_set_squared(GMPC_METAIMAGE(coverimg), TRUE);
470 gmpc_metaimage_set_connection(GMPC_METAIMAGE(coverimg), connection);
471 gmpc_metaimage_set_no_cover_icon(GMPC_METAIMAGE(coverimg),(char *)"gmpc");
473 * Force an update if mpd is playing
475 state = mpd_player_get_state(connection);
476 if(state == MPD_PLAYER_PLAY || state == MPD_PLAYER_PAUSE) {
477 gmpc_metaimage_update_cover(GMPC_METAIMAGE(coverimg), connection, MPD_CST_SONGID,NULL);
478 } else {
479 gmpc_metaimage_set_cover_na(GMPC_METAIMAGE(coverimg));
482 if(mpd_check_connected(connection) && mpd_player_get_consume(connection) && mpd_playlist_get_playlist_length(connection) < 100 )
484 gchar *temp = g_strdup_printf("%i", mpd_playlist_get_playlist_length(connection));
485 gmpc_metaimage_set_image_text(GMPC_METAIMAGE(coverimg), temp);
486 g_free(temp);
489 * Pack the widget in a eventbox so we can set background color
491 event = gtk_event_box_new();
492 gtk_widget_set_size_request(event, 86,86);
493 gtk_widget_modify_bg(GTK_WIDGET(event), GTK_STATE_NORMAL, &(pl3_win->style->bg[GTK_STATE_SELECTED]));
494 gtk_container_add(GTK_CONTAINER(event), coverimg);
495 gtk_box_pack_start(GTK_BOX(hbox), event, FALSE,TRUE,0);
499 * Right (2) view
502 * Create white background label box
504 event = gtk_event_box_new();
505 vbox = gtk_vbox_new(FALSE, 0);
506 gtk_widget_modify_bg(GTK_WIDGET(event), GTK_STATE_NORMAL, &(pl3_win->style->light[GTK_STATE_NORMAL]));
507 gtk_container_set_border_width(GTK_CONTAINER(vbox),3);
508 gtk_container_add(GTK_CONTAINER(event), vbox);
509 gtk_box_pack_start(GTK_BOX(hbox), event, TRUE,TRUE,0);
511 if(!has_buttons){
512 g_signal_connect(G_OBJECT(hbox), "button-press-event", G_CALLBACK(tray_icon2_tooltip_button_press_event), vbox);
516 * If there is a song, show show song info
518 if(song)
520 int i;
521 char buffer[256];
522 int size_offset = cfg_get_single_value_as_int_with_default(config, TRAY_ICON2_ID, "size-offset", 1024);
523 size_offset = (size_offset < 100)?1024:size_offset;
525 /** Artist label */
526 if(song->title || song->file || song->name)
528 gchar *test = g_strdup_printf("<span size='%i' weight='bold'>[%%title%%|%%shortfile%%][ (%%name%%)]</span>", 14*size_offset);
529 mpd_song_markup_escaped(buffer, 256,test,song);
530 q_free(test);
531 label = gtk_label_new("");
532 gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
533 gtk_misc_set_alignment(GTK_MISC(label), 0,0.5);
534 gtk_label_set_markup(GTK_LABEL(label), buffer);
535 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE,FALSE,0);
537 if(song->artist)
539 gchar *test = g_strdup_printf("<span size='%i'>%%artist%%</span>", 10*size_offset);
540 label = gtk_label_new("");
541 gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
542 mpd_song_markup_escaped(buffer, 256,test,song);
543 q_free(test);
544 gtk_label_set_markup(GTK_LABEL(label), buffer);
545 gtk_misc_set_alignment(GTK_MISC(label), 0,0.5);
547 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE,FALSE,0);
549 if(song->album)
551 gchar *test = g_strdup_printf("<span size='%i'>%%album%%[ (%%year%%)]</span>", 8*size_offset);
552 label = gtk_label_new("");
553 gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
554 mpd_song_markup_escaped(buffer, 256,test,song);
555 q_free(test);
556 gtk_misc_set_alignment(GTK_MISC(label), 0,0.5);
557 gtk_label_set_markup(GTK_LABEL(label), buffer);
558 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE,FALSE,0);
560 tray_icon2_tooltip_pb = (GtkWidget *) gmpc_progress_new();
561 gmpc_progress_set_hide_text(GMPC_PROGRESS(tray_icon2_tooltip_pb), TRUE);
562 /* Update the progressbar */
563 gmpc_progress_set_time(GMPC_PROGRESS(tray_icon2_tooltip_pb),
564 mpd_status_get_total_song_time(connection),
565 mpd_status_get_elapsed_song_time(connection));
568 g_signal_connect(G_OBJECT(tray_icon2_tooltip_pb), "seek-event", G_CALLBACK(tray_icon2_seek_event), NULL);
570 gtk_widget_modify_bg(GTK_WIDGET(tray_icon2_tooltip_pb), GTK_STATE_NORMAL, &(pl3_win->style->light[GTK_STATE_NORMAL]));
571 g_object_set_data_full(G_OBJECT(tray_icon2_tooltip), "song", mpd_songDup(song),(GDestroyNotify)mpd_freeSong);
572 gtk_box_pack_start(GTK_BOX(vbox), tray_icon2_tooltip_pb, TRUE,FALSE,0);
574 i = mpd_player_get_next_song_id(connection);
575 if(i > 0){
576 mpd_Song *next_psong = mpd_playlist_get_song(connection, i);
577 if(next_psong)
579 gchar *test = g_strdup_printf("<span size='%i'>%s: <i>[[%%title%% - &[%%artist%%]]|%%shortfile%%]</i></span>",
580 7*size_offset,_("Next"));
581 label = gtk_label_new("");
582 gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
583 mpd_song_markup_escaped(buffer, 256,test,next_psong);
584 q_free(test);
585 gtk_misc_set_alignment(GTK_MISC(label), 0,0.5);
586 gtk_label_set_markup(GTK_LABEL(label), buffer);
587 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE,FALSE,0);
588 mpd_freeSong(next_psong);
591 } else {
592 gchar *value = g_markup_printf_escaped("<span size='large'>%s</span>", _("Gnome Music Player Client"));
593 label = gtk_label_new("");
594 gtk_label_set_markup(GTK_LABEL(label),value);
595 gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
596 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE,TRUE,0);
597 g_free(value);
600 * Position the popup
602 if(position == TI2_AT_TOOLTIP && tray_icon2_get_available())
605 GdkRectangle rect, rect2;
606 GtkOrientation orientation;
607 if(gtk_status_icon_get_geometry(tray_icon2_gsi, &screen, &rect, &orientation))
609 monitor = gdk_screen_get_monitor_at_point(screen, rect.x, rect.y);
610 gdk_screen_get_monitor_geometry(screen, monitor, &rect2);
611 /* Get Y */
612 y= rect.y+rect.height+5-rect2.y+y_offset;
613 /* if the lower part falls off the screen, move it up */
614 if((y+95) > rect2.height) {
615 y = rect.y - 95 - 5;
617 if(y < 0) y =0;
619 /* Get X */
620 x = rect.x - 300/2-rect2.x+x_offset;
621 if((x+300) > rect2.width){
622 if(orientation == GTK_ORIENTATION_VERTICAL) {
623 x = rect2.width+-300-rect.width-5;
624 } else {
625 x = rect2.width - 300;
628 if(x<0) {
629 if(orientation == GTK_ORIENTATION_VERTICAL) {
630 x = rect.width+5;
631 } else {
632 x = 0;
636 gtk_window_move(GTK_WINDOW(tray_icon2_tooltip), rect2.x+x,rect2.y+y);
637 } else
638 if (position == TI2_AT_UPPER_LEFT)
640 GdkRectangle rect2;
641 screen =gtk_widget_get_screen(pl3_win);
643 monitor = gdk_screen_get_monitor_at_window(screen, pl3_win->window);
644 gdk_screen_get_monitor_geometry(screen, monitor, &rect2);
645 gtk_window_move(GTK_WINDOW(tray_icon2_tooltip), rect2.x+5+x_offset,rect2.y+5+y_offset);
646 } else if (position == TI2_AT_UPPER_RIGHT) {
647 GdkRectangle rect2;
648 screen =gtk_widget_get_screen(pl3_win);
650 monitor = gdk_screen_get_monitor_at_window(screen, pl3_win->window);
651 gdk_screen_get_monitor_geometry(screen, monitor, &rect2);
652 /** Set Y = 0; */
653 y = rect2.y+5;
654 /** X is upper right - width */
655 x = rect2.x+rect2.width-5-300;
656 gtk_window_move(GTK_WINDOW(tray_icon2_tooltip), x+x_offset,y+y_offset);
657 } else if (position == TI2_AT_LOWER_LEFT)
659 GdkRectangle rect2;
660 screen =gtk_widget_get_screen(pl3_win);
662 monitor = gdk_screen_get_monitor_at_window(screen, pl3_win->window);
663 gdk_screen_get_monitor_geometry(screen, monitor, &rect2);
664 /** Set Y = window height - size; */
665 y = rect2.y+rect2.height-5-95;
666 /** X =5 */
667 x = rect2.x+ 5;
668 gtk_window_move(GTK_WINDOW(tray_icon2_tooltip), x+x_offset,y+y_offset);
669 } else
671 GdkRectangle rect2;
672 screen =gtk_widget_get_screen(pl3_win);
674 monitor = gdk_screen_get_monitor_at_window(screen, pl3_win->window);
675 gdk_screen_get_monitor_geometry(screen, monitor, &rect2);
676 /** Set Y = window height - size; */
677 y = rect2.y+rect2.height-5-95;
678 /** X =window width - width */
679 x = rect2.x+rect2.width-5-300;
680 gtk_window_move(GTK_WINDOW(tray_icon2_tooltip), x+x_offset,y+y_offset);
683 gtk_widget_show_all(tray_icon2_tooltip);
686 if(has_buttons){
687 has_buttons = FALSE;
688 tray_icon2_tooltip_button_press_event(hbox,NULL, vbox);
691 * Destroy it after 5 seconds
693 tray_icon2_tooltip_timeout = g_timeout_add_seconds(tooltip_timeout, (GSourceFunc)tray_icon2_tooltip_destroy, NULL);
696 void tray_icon2_create_tooltip(void)
698 int state = cfg_get_single_value_as_int_with_default(config,TRAY_ICON2_ID, "tooltip-position", TI2_AT_TOOLTIP);
699 tray_icon2_create_tooltip_real(state);
702 static void tray_icon2_status_changed(MpdObj *mi, ChangedStatusType what, void *userdata)
704 char buffer[256];
705 mpd_Song *song = mpd_playlist_get_current_song(connection);
706 if(what&(MPD_CST_SONGID)|| what&MPD_CST_SONGPOS || what&MPD_CST_PLAYLIST)
708 /**
709 * If enabled by user, show the tooltip.
710 * But only if playing or paused.
713 if(cfg_get_single_value_as_int_with_default(config, TRAY_ICON2_ID, "show-tooltip", TRUE))
715 int state = mpd_player_get_state(connection);
716 gchar *new_checksum;
717 new_checksum = mpd_song_checksum(song);
718 if(state == MPD_PLAYER_PLAY || state == MPD_PLAYER_PAUSE)
720 if(current_song_checksum == NULL || strcmp(current_song_checksum, new_checksum))
721 tray_icon2_create_tooltip();
723 if(current_song_checksum){
724 g_free(current_song_checksum);
725 current_song_checksum = NULL;
727 current_song_checksum = new_checksum;
730 if(tray_icon2_gsi)
732 mpd_song_markup(buffer, 256,"[%name%: ][%title%|%shortfile%][ - %artist%]",song);
733 //gtk_status_icon_set_tooltip(tray_icon2_gsi,buffer);
737 /* update the progress bar if available */
738 if(what&MPD_CST_ELAPSED_TIME)
740 if(tray_icon2_tooltip && tray_icon2_tooltip_pb)
742 gmpc_progress_set_time(GMPC_PROGRESS(tray_icon2_tooltip_pb),
743 mpd_status_get_total_song_time(connection),
744 mpd_status_get_elapsed_song_time(connection));
747 if(tray_icon2_gsi == NULL)
748 return;
751 if(what&MPD_CST_STATE)
753 int state = mpd_player_get_state(connection);
754 if(state == MPD_PLAYER_PLAY){
755 mpd_song_markup(buffer, 256,"[%name%: ][%title%|%shortfile%][ - %artist%]",song);
756 gtk_status_icon_set_from_icon_name(tray_icon2_gsi, "gmpc-tray-play");
757 //gtk_status_icon_set_tooltip(tray_icon2_gsi,buffer);
758 if(has_buttons)
760 gtk_button_set_image(GTK_BUTTON(play_button), gtk_image_new_from_stock(GTK_STOCK_MEDIA_PAUSE, GTK_ICON_SIZE_BUTTON));
762 } else if(state == MPD_PLAYER_PAUSE){
764 gtk_status_icon_set_from_icon_name(tray_icon2_gsi, "gmpc-tray-pause");
765 //gtk_status_icon_set_tooltip(tray_icon2_gsi,_("Gnome Music Player Client"));
766 if(has_buttons)
768 gtk_button_set_image(GTK_BUTTON(play_button), gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_BUTTON));
770 } else {
772 gtk_status_icon_set_from_icon_name(tray_icon2_gsi, "gmpc-tray");
773 //gtk_status_icon_set_tooltip(tray_icon2_gsi,_("Gnome Music Player Client"));
774 if(has_buttons)
776 gtk_button_set_image(GTK_BUTTON(play_button), gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_BUTTON));
782 * Show right icon when (dis)connected
784 static void tray_icon2_connection_changed(MpdObj *mi, int connect,void *user_data)
786 if(tray_icon2_gsi == NULL)
787 return;
789 if(connect) {
790 tray_icon2_status_changed(mi, MPD_CST_STATE,NULL);
791 } else {
792 /* Set the disconnect image, and reset the GtkTooltip */
793 gtk_status_icon_set_from_icon_name(tray_icon2_gsi, "gmpc-tray-disconnected");
794 /* Destroy notification */
795 if(tray_icon2_tooltip)
796 tray_icon2_tooltip_destroy();
801 * PREFERENCES
805 void tray_enable_toggled(GtkToggleButton *but)
807 debug_printf(DEBUG_INFO,"tray-icon.c: changing tray icon %i\n", gtk_toggle_button_get_active(but));
808 cfg_set_single_value_as_int(config, TRAY_ICON2_ID, "enable", (int)gtk_toggle_button_get_active(but));
809 if(cfg_get_single_value_as_int_with_default(config, TRAY_ICON2_ID, "enable", 1)) {
810 tray_icon2_set_enabled(TRUE);
811 } else {
812 tray_icon2_set_enabled(FALSE);
816 /* this sets all the settings in the notification area preferences correct */
817 static void tray_update_settings(void)
819 gtk_toggle_button_set_active((GtkToggleButton *)
820 gtk_builder_get_object(tray_icon2_preferences_xml, "ck_tray_enable"),
821 cfg_get_single_value_as_int_with_default(config, TRAY_ICON2_ID, "enable", DEFAULT_TRAY_ICON_ENABLE));
824 void popup_enable_toggled(GtkToggleButton *but)
826 cfg_set_single_value_as_int(config, TRAY_ICON2_ID, "show-tooltip", gtk_toggle_button_get_active(but));
830 void popup_position_changed(GtkComboBox *om)
832 cfg_set_single_value_as_int(config, TRAY_ICON2_ID, "tooltip-position", gtk_combo_box_get_active(om));
835 void popup_timeout_changed(void)
837 cfg_set_single_value_as_int(config, TRAY_ICON2_ID, "tooltip-timeout",
838 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(gtk_builder_get_object(tray_icon2_preferences_xml, "popup_timeout"))));
841 static void update_popup_settings(void)
843 gtk_toggle_button_set_active((GtkToggleButton *)
844 gtk_builder_get_object(tray_icon2_preferences_xml, "ck_popup_enable"),
845 cfg_get_single_value_as_int_with_default(config, TRAY_ICON2_ID, "show-tooltip", 1));
846 gtk_combo_box_set_active(GTK_COMBO_BOX(gtk_builder_get_object(tray_icon2_preferences_xml, "om_popup_position")),
847 cfg_get_single_value_as_int_with_default(config, TRAY_ICON2_ID, "tooltip-position", 0));
848 gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_builder_get_object(tray_icon2_preferences_xml, "popup_timeout")),
849 cfg_get_single_value_as_int_with_default(config, TRAY_ICON2_ID, "tooltip-timeout", 5));
852 static void tray_icon2_preferences_destroy(GtkWidget *container)
854 if(tray_icon2_preferences_xml) {
855 GtkWidget *vbox =(GtkWidget *) gtk_builder_get_object(tray_icon2_preferences_xml, "tray-pref-vbox");
856 gtk_container_remove(GTK_CONTAINER(container),vbox);
857 g_object_unref(tray_icon2_preferences_xml);
858 tray_icon2_preferences_xml = NULL;
861 void tray_icon2_preferences_pm_combo_changed(GtkComboBox *cm, gpointer data)
863 int level = gtk_combo_box_get_active(cm);
864 cfg_set_single_value_as_int(config, "Default","min-error-level", level);
866 static void tray_icon2_preferences_construct(GtkWidget *container)
868 gchar *path = gmpc_get_full_glade_path("preferences-trayicon.ui");
869 tray_icon2_preferences_xml = gtk_builder_new();
870 gtk_builder_add_from_file(tray_icon2_preferences_xml, path, NULL);
871 q_free(path);
873 if(tray_icon2_preferences_xml) {
874 GtkWidget *vbox =(GtkWidget *) gtk_builder_get_object(tray_icon2_preferences_xml, "tray-pref-vbox");
875 gtk_container_add(GTK_CONTAINER(container),vbox);
876 tray_update_settings();
877 update_popup_settings();
878 gtk_builder_connect_signals(tray_icon2_preferences_xml, NULL);
880 gtk_combo_box_set_active(GTK_COMBO_BOX(gtk_builder_get_object(tray_icon2_preferences_xml, "pm-combo")),
881 cfg_get_single_value_as_int_with_default(config, "Default","min-error-level", ERROR_INFO));
884 gmpcPrefPlugin tray_icon2_preferences = {
885 tray_icon2_preferences_construct,
886 tray_icon2_preferences_destroy
889 gmpcPlugin tray_icon2_plug = {
890 .name = N_("Notification"),
891 .version = {0,0,0},
892 .plugin_type = GMPC_INTERNALL,
893 .init = tray_icon2_init,
894 .destroy = tray_icon2_destroy,
895 .mpd_status_changed = tray_icon2_status_changed,
896 .mpd_connection_changed = tray_icon2_connection_changed,
897 .set_enabled = tray_icon2_set_enabled,
898 .get_enabled = tray_icon2_get_enabled,
899 .pref = &tray_icon2_preferences