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.
21 #include <libmpd/libmpd.h>
25 #include "playlist3.h"
26 #include "vala/gmpc-progress.h"
27 #include "gmpc-metaimage.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);
45 GtkWidget
*tray_icon2_tooltip
= NULL
;
46 GtkWidget
*tray_icon2_tooltip_pb
= NULL
;
47 guint tray_icon2_tooltip_timeout
= 0;
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
);
69 gboolean
tray_icon2_get_available(void)
72 if(gtk_status_icon_is_embedded(tray_icon2_gsi
) &&
73 gtk_status_icon_get_visible(tray_icon2_gsi
)) {
80 * click on the tray icon
82 static void tray_icon2_activate(GtkStatusIcon
*gsi
, gpointer user_data
)
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
)
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
);
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
);
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 */
168 * Initialize the tray icon
170 static int tray_icon2_button_press_event(gpointer tray
, GdkEventButton
*event
, gpointer data
)
172 if(event
->button
== 2)
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)
189 }else if (event
->direction
== GDK_SCROLL_DOWN
) {
190 if(mpd_server_check_command_allowed(connection
, "volume") && mpd_status_get_volume(connection
) >=0)
192 }else if (event
->direction
== GDK_SCROLL_LEFT
) {
194 }else if (event
->direction
== GDK_SCROLL_RIGHT
) {
199 /* hack to delay tooltip showup on tray-icon*/
200 GTimeVal current
= {0,0};
201 static gboolean
tray_icon2_tooltip_query(GtkStatusIcon
*icon
,
203 gboolean keyboard_mode
,
209 if(tray_icon2_tooltip
== NULL
){
211 if(current
.tv_sec
== 0) {
212 g_get_current_time(¤t
);
216 g_get_current_time(&now
);
217 if((now
.tv_sec
- current
.tv_sec
) > 5) {
221 if(current
.tv_sec
< now
.tv_sec
)
224 tray_icon2_create_tooltip_real(TI2_AT_TOOLTIP
);
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
);
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)
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
;
276 static gboolean
tray_icon2_get_enabled(void)
278 return cfg_get_single_value_as_int_with_default(config
, TRAY_ICON2_ID
, "enable", TRUE
);
283 static void tray_icon2_set_enabled(int enabled
)
285 cfg_set_single_value_as_int(config
, TRAY_ICON2_ID
, "enable", enabled
);
287 if(!tray_icon2_gsi
) {
289 tray_icon2_status_changed(connection
, MPD_CST_SONGID
, NULL
);
291 gtk_status_icon_set_visible(GTK_STATUS_ICON(tray_icon2_gsi
), TRUE
);
295 gtk_status_icon_set_visible(GTK_STATUS_ICON(tray_icon2_gsi
), FALSE
);
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;
317 /* remove the timeout */
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
);
335 hbox
= gtk_hbox_new(TRUE
, 6);
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
);
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
);
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
);
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
);
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);
375 tray_icon2_tooltip_destroy();
380 static void tray_icon2_create_tooltip_real(int position
)
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);
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");
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
);
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())
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
);
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..
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
);
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
);
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);
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);
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
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
;
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
);
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);
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
);
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);
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
);
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
);
576 mpd_Song
*next_psong
= mpd_playlist_get_song(connection
, i
);
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
);
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
);
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);
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
);
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
) {
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;
625 x
= rect2
.width
- 300;
629 if(orientation
== GTK_ORIENTATION_VERTICAL
) {
636 gtk_window_move(GTK_WINDOW(tray_icon2_tooltip
), rect2
.x
+x
,rect2
.y
+y
);
638 if (position
== TI2_AT_UPPER_LEFT
)
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
) {
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
);
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
)
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;
668 gtk_window_move(GTK_WINDOW(tray_icon2_tooltip
), x
+x_offset
,y
+y_offset
);
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
);
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
)
705 mpd_Song
*song
= mpd_playlist_get_current_song(connection
);
706 if(what
&(MPD_CST_SONGID
)|| what
&MPD_CST_SONGPOS
|| what
&MPD_CST_PLAYLIST
)
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
);
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
;
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
)
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);
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"));
768 gtk_button_set_image(GTK_BUTTON(play_button
), gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY
, GTK_ICON_SIZE_BUTTON
));
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"));
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
)
790 tray_icon2_status_changed(mi
, MPD_CST_STATE
,NULL
);
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();
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
);
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
);
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"),
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