1 /*************************************************************************/
2 /* Copyright (C) 2007-2009 sujith <m.sujith@gmail.com>                   */
3 /* Copyright (C) 2009-2014 matias <mati86dl@gmail.com>                   */
4 /*                                                                       */
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 3 of the License, or     */
8 /* (at your option) any later version.                                   */
9 /*                                                                       */
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.                          */
14 /*                                                                       */
15 /* You should have received a copy of the GNU General Public License     */
16 /* along with this program.  If not, see <http://www.gnu.org/licenses/>. */
17 /*************************************************************************/
18 
19 #if HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22 
23 #include "pragha-toolbar.h"
24 
25 #if defined(GETTEXT_PACKAGE)
26 #include <glib/gi18n-lib.h>
27 #else
28 #include <glib/gi18n.h>
29 #endif
30 
31 #include <gdk/gdkkeysyms.h>
32 
33 #include "pragha-simple-widgets.h"
34 #include "pragha-utils.h"
35 
36 static void pragha_toolbar_finalize (GObject *object);
37 
38 static void pragha_toolbar_set_remaning_mode (PraghaToolbar *toolbar, gboolean remaning_mode);
39 gboolean    pragha_toolbar_get_remaning_mode (PraghaToolbar *toolbar);
40 
41 
42 struct _PraghaToolbar {
43 #if GTK_CHECK_VERSION (3, 12, 0)
44 	GtkHeaderBar   __parent__;
45 #else
46 	GtkToolbar      __parent__;
47 #endif
48 	PraghaAlbumArt *albumart;
49 
50 	GtkWidget      *track_progress_bar;
51 
52 	PraghaToolbarButton *prev_button;
53 	PraghaToolbarButton *play_button;
54 	PraghaToolbarButton *stop_button;
55 	PraghaToolbarButton *next_button;
56 	PraghaToolbarButton *unfull_button;
57 	GtkWidget      *vol_button;
58 	GtkWidget      *extra_button_box;
59 
60 	GtkWidget      *track_length_label;
61 	GtkWidget      *track_time_label;
62 	GtkWidget      *now_playing_label;
63 	GtkWidget      *extention_box;
64 
65 	gboolean       remaning_mode;
66 };
67 
68 enum {
69 	PROP_0,
70 	PROP_VOLUME,
71 	PROP_REMANING_MODE,
72 	PROP_LAST
73 };
74 
75 static GParamSpec *properties[PROP_LAST] = { 0 };
76 
77 enum
78 {
79 	PREV_ACTIVATED,
80 	PLAY_ACTIVATED,
81 	STOP_ACTIVATED,
82 	NEXT_ACTIVATED,
83 	ALBUM_ART_ACTIVATED,
84 	TRACK_INFO_ACTIVATED,
85 	TRACK_PROGRESS_ACTIVATED,
86 	UNFULL_ACTIVATED,
87 	TRACK_TIME_ACTIVATED,
88 	LAST_SIGNAL
89 };
90 
91 static int signals[LAST_SIGNAL] = { 0 };
92 
93 #if GTK_CHECK_VERSION (3, 12, 0)
G_DEFINE_TYPE(PraghaToolbar,pragha_toolbar,GTK_TYPE_HEADER_BAR)94 G_DEFINE_TYPE(PraghaToolbar, pragha_toolbar, GTK_TYPE_HEADER_BAR)
95 #else
96 G_DEFINE_TYPE(PraghaToolbar, pragha_toolbar, GTK_TYPE_TOOLBAR)
97 #endif
98 
99 void
100 pragha_toolbar_update_progress (PraghaToolbar *toolbar, gint length, gint progress)
101 {
102 	gdouble fraction = 0;
103 	gchar *tot_length = NULL, *cur_pos = NULL, *str_length = NULL, *str_cur_pos = NULL;
104 
105 	cur_pos = convert_length_str(progress);
106 	str_cur_pos = g_markup_printf_escaped ("<small>%s</small>", cur_pos);
107 
108 	if (length == 0 || !pragha_toolbar_get_remaning_mode (toolbar)) {
109 		tot_length = convert_length_str(length);
110 		str_length = g_markup_printf_escaped ("<small>%s</small>", tot_length);
111 	}
112 	else {
113 		tot_length = convert_length_str(length - progress);
114 		str_length = g_markup_printf_escaped ("<small>- %s</small>", tot_length);
115 	}
116 
117 	gtk_label_set_markup (GTK_LABEL(toolbar->track_time_label), str_cur_pos);
118 	gtk_label_set_markup (GTK_LABEL(toolbar->track_length_label), str_length);
119 
120 	gtk_tooltip_trigger_tooltip_query(gtk_widget_get_display (toolbar->track_length_label));
121 
122 	if(length) {
123 		fraction = (gdouble) progress / (gdouble)length;
124 		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(toolbar->track_progress_bar), fraction);
125 	}
126 
127 	g_free(cur_pos);
128 	g_free(str_cur_pos);
129 
130 	g_free(tot_length);
131 	g_free(str_length);
132 }
133 
134 void
pragha_toolbar_set_title(PraghaToolbar * toolbar,PraghaMusicobject * mobj)135 pragha_toolbar_set_title (PraghaToolbar *toolbar, PraghaMusicobject *mobj)
136 {
137 	gchar *str = NULL, *str_title = NULL;
138 
139 	const gchar *file = pragha_musicobject_get_file (mobj);
140 	const gchar *title = pragha_musicobject_get_title (mobj);
141 	const gchar *artist = pragha_musicobject_get_artist (mobj);
142 	const gchar *album = pragha_musicobject_get_album (mobj);
143 
144 	if(string_is_not_empty(title))
145 		str_title = g_strdup(title);
146 	else
147 		str_title = get_display_filename(file, FALSE);
148 
149 	if(string_is_not_empty(artist) && string_is_not_empty(album))
150 		str = g_markup_printf_escaped (_("%s <small><span weight=\"light\">by</span></small> %s <small><span weight=\"light\">in</span></small> %s"),
151 		                               str_title,
152 		                               artist,
153 		                               album);
154 	else if(string_is_not_empty(artist))
155 		str = g_markup_printf_escaped (_("%s <small><span weight=\"light\">by</span></small> %s"),
156 		                                str_title,
157 		                                artist);
158 	else if(string_is_not_empty(album))
159 		str = g_markup_printf_escaped (_("%s <small><span weight=\"light\">in</span></small> %s"),
160 		                                str_title,
161 		                                album);
162 	else
163 		str = g_markup_printf_escaped("%s", str_title);
164 
165 	gtk_label_set_markup(GTK_LABEL(toolbar->now_playing_label), str);
166 
167 	g_free(str_title);
168 	g_free(str);
169 }
170 
171 static void
pragha_toolbar_unset_song_info(PraghaToolbar * toolbar)172 pragha_toolbar_unset_song_info(PraghaToolbar *toolbar)
173 {
174 	gtk_label_set_markup(GTK_LABEL(toolbar->now_playing_label), _("<b>Not playing</b>"));
175 	gtk_label_set_markup(GTK_LABEL(toolbar->track_length_label),  "<small>--:--</small>");
176 	gtk_label_set_markup(GTK_LABEL(toolbar->track_time_label),    "<small>00:00</small>");
177 
178 	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(toolbar->track_progress_bar), 0);
179 
180 	pragha_album_art_set_path(toolbar->albumart, NULL);
181 }
182 
183 static void
pragha_toolbar_timer_label_event_change_mode(GtkWidget * widget,GdkEventButton * event,PraghaToolbar * toolbar)184 pragha_toolbar_timer_label_event_change_mode (GtkWidget      *widget,
185                                               GdkEventButton *event,
186                                               PraghaToolbar  *toolbar)
187 {
188 	pragha_toolbar_set_remaning_mode (toolbar,
189 		!pragha_toolbar_get_remaning_mode (toolbar));
190 }
191 
192 void
pragha_toolbar_set_image_album_art(PraghaToolbar * toolbar,const gchar * uri)193 pragha_toolbar_set_image_album_art (PraghaToolbar *toolbar, const gchar *uri)
194 {
195 	pragha_album_art_set_path (toolbar->albumart, uri);
196 }
197 
198 /* Grab focus on current playlist when press Up or Down and move between controls with Left or Right */
199 
200 /*static gboolean
201 panel_button_key_press (GtkWidget *win, GdkEventKey *event, PraghaApplication *pragha)
202 {
203 	gboolean ret = FALSE;
204 
205 	if (event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_Down ||
206 	    event->keyval == GDK_KEY_Page_Up || event->keyval == GDK_KEY_Page_Down) {
207 		ret = pragha_playlist_propagate_event(pragha->cplaylist, event);
208 	}
209 
210 	return ret;
211 }*/
212 
213 /*
214  * Emit signals..
215  */
216 
217 static gboolean
play_button_handler(GtkButton * button,PraghaToolbar * toolbar)218 play_button_handler(GtkButton *button, PraghaToolbar *toolbar)
219 {
220 	g_signal_emit (toolbar, signals[PLAY_ACTIVATED], 0);
221 
222 	return TRUE;
223 }
224 
225 static gboolean
stop_button_handler(GtkButton * button,PraghaToolbar * toolbar)226 stop_button_handler(GtkButton *button, PraghaToolbar *toolbar)
227 {
228 	g_signal_emit (toolbar, signals[STOP_ACTIVATED], 0);
229 
230 	return TRUE;
231 }
232 
233 static gboolean
prev_button_handler(GtkButton * button,PraghaToolbar * toolbar)234 prev_button_handler(GtkButton *button, PraghaToolbar *toolbar)
235 {
236 	g_signal_emit (toolbar, signals[PREV_ACTIVATED], 0);
237 
238 	return TRUE;
239 }
240 
241 static gboolean
next_button_handler(GtkButton * button,PraghaToolbar * toolbar)242 next_button_handler(GtkButton *button, PraghaToolbar *toolbar)
243 {
244 	g_signal_emit (toolbar, signals[NEXT_ACTIVATED], 0);
245 
246 	return TRUE;
247 }
248 
249 static gboolean
unfull_button_handler(GtkButton * button,PraghaToolbar * toolbar)250 unfull_button_handler (GtkButton *button, PraghaToolbar *toolbar)
251 {
252 	g_signal_emit (toolbar, signals[UNFULL_ACTIVATED], 0);
253 
254 	return TRUE;
255 }
256 
257 static gboolean
pragha_toolbar_album_art_activated(GtkWidget * event_box,GdkEventButton * event,PraghaToolbar * toolbar)258 pragha_toolbar_album_art_activated (GtkWidget      *event_box,
259                                     GdkEventButton *event,
260                                     PraghaToolbar  *toolbar)
261 {
262 	if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS)
263 #if GTK_CHECK_VERSION (3, 12, 0)
264 		if (!gtk_header_bar_get_show_close_button(GTK_HEADER_BAR(toolbar)))
265 #endif
266 		g_signal_emit (toolbar, signals[ALBUM_ART_ACTIVATED], 0);
267 
268 	return FALSE;
269 }
270 
271 static gboolean
pragha_toolbar_song_label_event_edit(GtkWidget * event_box,GdkEventButton * event,PraghaToolbar * toolbar)272 pragha_toolbar_song_label_event_edit (GtkWidget      *event_box,
273                                       GdkEventButton *event,
274                                       PraghaToolbar  *toolbar)
275 {
276 	if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS)
277 #if GTK_CHECK_VERSION (3, 12, 0)
278 		if (!gtk_header_bar_get_show_close_button(GTK_HEADER_BAR(toolbar)))
279 #endif
280 		g_signal_emit (toolbar, signals[TRACK_INFO_ACTIVATED], 0);
281 
282 	return FALSE;
283 }
284 
285 static void
pragha_toolbar_progress_bar_event_seek(GtkWidget * widget,GdkEventButton * event,PraghaToolbar * toolbar)286 pragha_toolbar_progress_bar_event_seek (GtkWidget *widget,
287                                         GdkEventButton *event,
288                                         PraghaToolbar *toolbar)
289 {
290 	GtkAllocation allocation;
291 	gdouble fraction = 0;
292 
293 	if (event->button != 1)
294 		return;
295 
296 	gtk_widget_get_allocation(widget, &allocation);
297 
298 	fraction = (gdouble) event->x / allocation.width;
299 
300 	g_signal_emit (toolbar, signals[TRACK_PROGRESS_ACTIVATED], 0, fraction);
301 }
302 
303 /*
304  * Callbacks that response to gstreamer signals.
305  */
306 
307 void
pragha_toolbar_update_buffering_cb(PraghaBackend * backend,gint percent,gpointer user_data)308 pragha_toolbar_update_buffering_cb (PraghaBackend *backend, gint percent, gpointer user_data)
309 {
310 	PraghaToolbar *toolbar = user_data;
311 
312 	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(toolbar->track_progress_bar), (gdouble)percent/100);
313 }
314 
315 void
pragha_toolbar_update_playback_progress(PraghaBackend * backend,gpointer user_data)316 pragha_toolbar_update_playback_progress(PraghaBackend *backend, gpointer user_data)
317 {
318 	gint length = 0, newsec = 0;
319 	PraghaMusicobject *mobj = NULL;
320 
321 	PraghaToolbar *toolbar = user_data;
322 
323 	newsec = GST_TIME_AS_SECONDS(pragha_backend_get_current_position(backend));
324 
325 	if (newsec > 0) {
326 		mobj = pragha_backend_get_musicobject (backend);
327 		length = pragha_musicobject_get_length (mobj);
328 
329 		if (length > 0) {
330 			pragha_toolbar_update_progress (toolbar, length, newsec);
331 		}
332 		else {
333 			gint nlength = GST_TIME_AS_SECONDS(pragha_backend_get_current_length(backend));
334 			pragha_musicobject_set_length (mobj, nlength);
335 		}
336 	}
337 }
338 
339 void
pragha_toolbar_playback_state_cb(PraghaBackend * backend,GParamSpec * pspec,gpointer user_data)340 pragha_toolbar_playback_state_cb (PraghaBackend *backend, GParamSpec *pspec, gpointer user_data)
341 {
342 	PraghaToolbar *toolbar = user_data;
343 	PraghaBackendState state = pragha_backend_get_state (backend);
344 
345 	gboolean playing = (state != ST_STOPPED);
346 
347 	gtk_widget_set_sensitive (GTK_WIDGET(toolbar->prev_button), playing);
348 
349 	pragha_toolbar_button_set_icon_name (toolbar->play_button,
350 	                                     (state == ST_PLAYING) ? "media-playback-pause" : "media-playback-start");
351 	gtk_widget_set_sensitive (GTK_WIDGET(toolbar->stop_button), playing);
352 	gtk_widget_set_sensitive (GTK_WIDGET(toolbar->next_button), playing);
353 
354 	if (playing == FALSE)
355 		pragha_toolbar_unset_song_info(toolbar);
356 }
357 
358 void
pragha_toolbar_show_ramaning_time_cb(PraghaToolbar * toolbar,GParamSpec * pspec,gpointer user_data)359 pragha_toolbar_show_ramaning_time_cb (PraghaToolbar *toolbar, GParamSpec *pspec, gpointer user_data)
360 {
361 	PraghaBackend *backend = user_data;
362 	pragha_toolbar_update_playback_progress (backend, toolbar);
363 }
364 
365 /*
366  * Show the unfullscreen button according to the state of the window.
367  */
368 
369 gboolean
pragha_toolbar_window_state_event(GtkWidget * widget,GdkEventWindowState * event,PraghaToolbar * toolbar)370 pragha_toolbar_window_state_event (GtkWidget *widget, GdkEventWindowState *event, PraghaToolbar *toolbar)
371 {
372 	if (event->type == GDK_WINDOW_STATE && (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN)) {
373 		gtk_widget_set_visible(GTK_WIDGET(toolbar->unfull_button), (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0);
374 	}
375 
376 	return FALSE;
377 }
378 
379 /*
380  * Public api.
381  */
382 
383 #if GTK_CHECK_VERSION (3, 12, 0)
384 void
pragha_toolbar_set_style(PraghaToolbar * toolbar,gboolean system_titlebar)385 pragha_toolbar_set_style (PraghaToolbar *toolbar, gboolean system_titlebar)
386 {
387 	GtkStyleContext *context;
388 	context = gtk_widget_get_style_context (GTK_WIDGET(toolbar));
389 
390 	if (system_titlebar) {
391 		gtk_style_context_remove_class (context, "header-bar");
392 		gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOOLBAR);
393 		gtk_style_context_add_class (context, GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
394 	}
395 	else {
396 		gtk_style_context_remove_class (context, GTK_STYLE_CLASS_TOOLBAR);
397 		gtk_style_context_remove_class (context, GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
398 		gtk_style_context_add_class (context, "header-bar");
399 	}
400 
401 	gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(toolbar), !system_titlebar);
402 }
403 #endif
404 
405 void
pragha_toolbar_add_extention_widget(PraghaToolbar * toolbar,GtkWidget * widget)406 pragha_toolbar_add_extention_widget(PraghaToolbar *toolbar, GtkWidget *widget)
407 {
408 	GList *list;
409 	GtkWidget *children;
410 
411 	list = gtk_container_get_children (GTK_CONTAINER(toolbar->extention_box));
412 	if(list) {
413 		children = list->data;
414 		gtk_container_remove(GTK_CONTAINER(toolbar->extention_box), children);
415 		gtk_widget_destroy(GTK_WIDGET(children));
416 		g_list_free(list);
417 	}
418 	gtk_container_add(GTK_CONTAINER(toolbar->extention_box), widget);
419 }
420 
421 void
pragha_toolbar_add_extra_button(PraghaToolbar * toolbar,GtkWidget * widget)422 pragha_toolbar_add_extra_button (PraghaToolbar *toolbar, GtkWidget *widget)
423 {
424 	GList *list;
425 	GtkWidget *children;
426 
427 	list = gtk_container_get_children (GTK_CONTAINER(toolbar->extra_button_box));
428 	if(list) {
429 		children = list->data;
430 		gtk_container_remove(GTK_CONTAINER(toolbar->extra_button_box), children);
431 		gtk_widget_destroy(GTK_WIDGET(children));
432 		g_list_free(list);
433 	}
434 	gtk_container_add(GTK_CONTAINER(toolbar->extra_button_box), widget);
435 }
436 
437 
438 const gchar*
pragha_toolbar_get_progress_text(PraghaToolbar * toolbar)439 pragha_toolbar_get_progress_text(PraghaToolbar *toolbar)
440 {
441 	return gtk_label_get_text (GTK_LABEL(toolbar->track_time_label));
442 }
443 
444 const gchar*
pragha_toolbar_get_length_text(PraghaToolbar * toolbar)445 pragha_toolbar_get_length_text(PraghaToolbar *toolbar)
446 {
447 	return gtk_label_get_text (GTK_LABEL(toolbar->track_length_label));
448 }
449 
450 PraghaAlbumArt *
pragha_toolbar_get_album_art(PraghaToolbar * toolbar)451 pragha_toolbar_get_album_art(PraghaToolbar *toolbar)
452 {
453 	return toolbar->albumart;
454 }
455 
456 /*
457  * Pragha toolbar creation and destruction.
458  */
459 
460 GtkWidget *
pragha_toolbar_get_song_box(PraghaToolbar * toolbar)461 pragha_toolbar_get_song_box (PraghaToolbar *toolbar)
462 {
463 	PraghaPreferences *preferences;
464 	PraghaAlbumArt *albumart;
465 	PraghaContainer *box;
466 	GtkWidget *hbox, *vbox_aling, *vbox, *top_hbox, *botton_hbox;
467 	GtkWidget *album_art_frame,*title, *title_event_box, *extention_box;
468 	GtkWidget *progress_bar, *progress_bar_event_box, *time_label, *time_align, *length_label, *length_align, *length_event_box;
469 
470 	const GBindingFlags binding_flags =
471 		G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL;
472 
473 	preferences = pragha_preferences_get();
474 
475 	/*
476 	 * Main box that allow expand.
477 	 */
478 	box = pragha_container_new ();
479 
480  	/*
481  	 * Main box: [Album][Song info]
482  	 */
483 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
484 	gtk_box_pack_start (GTK_BOX(box), hbox, TRUE, TRUE, 0);
485 
486 	album_art_frame = gtk_event_box_new ();
487 	gtk_event_box_set_visible_window(GTK_EVENT_BOX(album_art_frame), FALSE);
488 	g_signal_connect(G_OBJECT (album_art_frame), "button_press_event",
489 	                 G_CALLBACK (pragha_toolbar_album_art_activated), toolbar);
490 	gtk_box_pack_start (GTK_BOX(hbox), album_art_frame, FALSE, FALSE, 2);
491 
492 	albumart = pragha_album_art_new ();
493 	g_object_bind_property (preferences, "album-art-size",
494 	                        albumart, "size", binding_flags);
495 	g_object_bind_property (preferences, "show-album-art",
496 	                        albumart, "visible", binding_flags);
497 	gtk_container_add(GTK_CONTAINER(album_art_frame), GTK_WIDGET(albumart));
498 	toolbar->albumart = albumart;
499 
500 	/*
501 	 * Song info vbox
502 	 */
503 	vbox_aling = gtk_alignment_new(0.5, 0.5, 1, 0);
504 
505  	vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
506 	gtk_container_add(GTK_CONTAINER(vbox_aling), GTK_WIDGET(vbox));
507 
508  	/*
509  	 * Top box: [Title][extentions]
510  	 */
511 	top_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
512 	gtk_box_pack_start(GTK_BOX(vbox), top_hbox, TRUE, TRUE, 0);
513 
514 	/* The title widget. */
515 
516 	title_event_box = gtk_event_box_new();
517 	gtk_event_box_set_visible_window(GTK_EVENT_BOX(title_event_box), FALSE);
518 
519 	g_signal_connect (G_OBJECT(title_event_box), "button-press-event",
520 	                  G_CALLBACK(pragha_toolbar_song_label_event_edit), toolbar);
521 
522 	title = gtk_label_new(NULL);
523 	gtk_label_set_ellipsize (GTK_LABEL(title), PANGO_ELLIPSIZE_END);
524 	gtk_label_set_markup(GTK_LABEL(title),_("<b>Not playing</b>"));
525 	gtk_misc_set_alignment(GTK_MISC(title), 0, 0.5);
526 
527 	gtk_container_add (GTK_CONTAINER(title_event_box), title);
528 
529 	/* The extentions box. */
530 
531 	extention_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
532 
533 	/* Pack top widgets:  */
534 
535 	gtk_box_pack_start (GTK_BOX(top_hbox),
536 	                    GTK_WIDGET(title_event_box),
537 	                    TRUE, TRUE, 0);
538 	gtk_box_pack_start (GTK_BOX(top_hbox),
539 	                    GTK_WIDGET(extention_box),
540 	                    FALSE, FALSE, 0);
541 
542 	/*
543 	 * Botton box: [Time][ProgressBar][Length]
544 	 */
545 	botton_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
546 	gtk_box_pack_start(GTK_BOX(vbox), botton_hbox, FALSE, FALSE, 0);
547 
548 	/* Time progress widget. */
549 
550 	time_align = gtk_alignment_new(1, 0.5, 0, 0);
551 
552 	time_label = gtk_label_new(NULL);
553 	gtk_label_set_markup(GTK_LABEL(time_label),"<small>00:00</small>");
554 
555 	gtk_container_add(GTK_CONTAINER(time_align), time_label);
556 
557 	/* Progress bar widget. */
558 
559 	progress_bar_event_box = gtk_event_box_new();
560 	gtk_event_box_set_visible_window(GTK_EVENT_BOX(progress_bar_event_box), FALSE);
561 
562 	g_signal_connect (G_OBJECT(progress_bar_event_box), "button-press-event",
563 	                  G_CALLBACK(pragha_toolbar_progress_bar_event_seek), toolbar);
564 
565 #if GTK_CHECK_VERSION (3, 14, 0)
566 	progress_bar = gtk_progress_bar_new ();
567 	gtk_widget_set_valign (GTK_WIDGET(progress_bar), GTK_ALIGN_CENTER);
568 #else
569 	progress_bar = GTK_WIDGET(pragha_track_progress_new ());
570 #endif
571 
572 	gtk_container_add (GTK_CONTAINER(progress_bar_event_box),
573 	                   GTK_WIDGET(progress_bar));
574 
575 	/* Length and remaining time widget. */
576 
577 	length_event_box = gtk_event_box_new();
578 	gtk_event_box_set_visible_window(GTK_EVENT_BOX(length_event_box), FALSE);
579 	g_signal_connect (G_OBJECT(length_event_box), "button-press-event",
580 	                  G_CALLBACK(pragha_toolbar_timer_label_event_change_mode), toolbar);
581 
582 	length_align = gtk_alignment_new(0, 0.5, 0, 0);
583 	gtk_container_add(GTK_CONTAINER(length_event_box), length_align);
584 
585 	length_label = gtk_label_new(NULL);
586 	gtk_label_set_markup(GTK_LABEL(length_label),"<small>--:--</small>");
587 
588 	gtk_container_add(GTK_CONTAINER(length_align), length_label);
589 
590 	/* Pack widgets. */
591 
592 	gtk_box_pack_start (GTK_BOX(botton_hbox),
593 	                    GTK_WIDGET(time_align),
594 	                    FALSE, FALSE, 3);
595 	gtk_box_pack_start (GTK_BOX(botton_hbox),
596 	                    GTK_WIDGET(progress_bar_event_box),
597 	                    TRUE, TRUE, 0);
598 	gtk_box_pack_start (GTK_BOX(botton_hbox),
599 	                    GTK_WIDGET(length_event_box),
600 	                    FALSE, FALSE, 3);
601 
602 	/* Save references. */
603 
604 	toolbar->track_progress_bar = progress_bar;
605 	toolbar->now_playing_label  = title;
606 	toolbar->track_time_label   = time_label;
607 	toolbar->track_length_label = length_label;
608 	toolbar->extention_box      = extention_box;
609 
610 	gtk_box_pack_start(GTK_BOX(hbox), vbox_aling, TRUE, TRUE, 2);
611 
612 	gtk_widget_show_all(GTK_WIDGET(vbox_aling));
613 	gtk_widget_show(GTK_WIDGET(album_art_frame));
614 	gtk_widget_show(GTK_WIDGET(hbox));
615 	gtk_widget_show(GTK_WIDGET(box));
616 
617 	g_object_unref(preferences);
618 
619 	return GTK_WIDGET(box);
620 }
621 
622 #if !GTK_CHECK_VERSION (3, 12, 0)
623 static void
gtk_tool_insert_generic_item(GtkToolbar * toolbar,GtkWidget * item)624 gtk_tool_insert_generic_item(GtkToolbar *toolbar, GtkWidget *item)
625 {
626 	GtkWidget *align_box;
627 	GtkToolItem *boxitem;
628 
629 	boxitem = gtk_tool_item_new ();
630 
631 	align_box = gtk_alignment_new(0, 0.5, 0, 0);
632 	gtk_container_add(GTK_CONTAINER(align_box), item);
633 
634 	gtk_container_add (GTK_CONTAINER(boxitem), align_box);
635 	gtk_toolbar_insert (GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(boxitem), -1);
636 }
637 #endif
638 
639 static void
vol_button_value_changed(GtkVolumeButton * button,gdouble value,PraghaToolbar * toolbar)640 vol_button_value_changed (GtkVolumeButton *button, gdouble value, PraghaToolbar *toolbar)
641 {
642 	g_object_notify_by_pspec (G_OBJECT (toolbar), properties[PROP_VOLUME]);
643 }
644 
645 static void
pragha_toolbar_set_volume(PraghaToolbar * toolbar,gdouble volume)646 pragha_toolbar_set_volume (PraghaToolbar *toolbar, gdouble volume)
647 {
648 	gtk_scale_button_set_value (GTK_SCALE_BUTTON(toolbar->vol_button), volume);
649 }
650 
651 gdouble
pragha_toolbar_get_volume(PraghaToolbar * toolbar)652 pragha_toolbar_get_volume (PraghaToolbar *toolbar)
653 {
654 	return gtk_scale_button_get_value (GTK_SCALE_BUTTON(toolbar->vol_button));
655 }
656 
657 static void
pragha_toolbar_set_remaning_mode(PraghaToolbar * toolbar,gboolean remaning_mode)658 pragha_toolbar_set_remaning_mode (PraghaToolbar *toolbar, gboolean remaning_mode)
659 {
660 	toolbar->remaning_mode = remaning_mode;
661 
662 	g_object_notify_by_pspec(G_OBJECT(toolbar), properties[PROP_REMANING_MODE]);
663 }
664 
665 gboolean
pragha_toolbar_get_remaning_mode(PraghaToolbar * toolbar)666 pragha_toolbar_get_remaning_mode (PraghaToolbar *toolbar)
667 {
668 	return toolbar->remaning_mode;
669 }
670 
671 static void
pragha_toolbar_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)672 pragha_toolbar_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
673 {
674 	PraghaToolbar *toolbar = PRAGHA_TOOLBAR (object);
675 
676 	switch (property_id)
677 	{
678 		case PROP_VOLUME:
679 			pragha_toolbar_set_volume (toolbar, g_value_get_double (value));
680 			break;
681 		case PROP_REMANING_MODE:
682 			pragha_toolbar_set_remaning_mode (toolbar, g_value_get_boolean (value));
683 			break;
684 		default:
685 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
686 			break;
687 	}
688 }
689 
690 static void
pragha_toolbar_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)691 pragha_toolbar_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
692 {
693 	PraghaToolbar *toolbar = PRAGHA_TOOLBAR (object);
694 
695 	switch (property_id)
696 	{
697 		case PROP_VOLUME:
698 			g_value_set_double (value, pragha_toolbar_get_volume (toolbar));
699 			break;
700 		case PROP_REMANING_MODE:
701 			g_value_set_boolean (value, pragha_toolbar_get_remaning_mode (toolbar));
702 			break;
703 		default:
704 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
705 			break;
706 	}
707 }
708 
709 static void
pragha_toolbar_class_init(PraghaToolbarClass * klass)710 pragha_toolbar_class_init (PraghaToolbarClass *klass)
711 {
712 	GObjectClass  *gobject_class;
713 
714 	gobject_class = G_OBJECT_CLASS (klass);
715 	gobject_class->set_property = pragha_toolbar_set_property;
716 	gobject_class->get_property = pragha_toolbar_get_property;
717 	gobject_class->finalize = pragha_toolbar_finalize;
718 
719 	/*
720 	 * Properties:
721 	 */
722 	properties[PROP_VOLUME] = g_param_spec_double ("volume", "Volume", "Volume showed on toolbar",
723 	                                               0.0, 1.0, 0.5,
724 	                                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
725 	properties[PROP_REMANING_MODE] = g_param_spec_boolean ("timer-remaining-mode", "TimerRemainingMode", "Show Remaining Time",
726 	                                                       FALSE,
727 	                                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
728 
729 	g_object_class_install_properties (gobject_class, PROP_LAST, properties);
730 
731 	/*
732 	 * Signals:
733 	 */
734 	signals[PREV_ACTIVATED] = g_signal_new ("prev",
735 	                                        G_TYPE_FROM_CLASS (gobject_class),
736 	                                        G_SIGNAL_RUN_LAST,
737 	                                        G_STRUCT_OFFSET (PraghaToolbarClass, prev),
738 	                                        NULL, NULL,
739 	                                        g_cclosure_marshal_VOID__VOID,
740 	                                        G_TYPE_NONE, 0);
741 	signals[PLAY_ACTIVATED] = g_signal_new ("play",
742 	                                        G_TYPE_FROM_CLASS (gobject_class),
743 	                                        G_SIGNAL_RUN_LAST,
744 	                                        G_STRUCT_OFFSET (PraghaToolbarClass, play),
745 	                                        NULL, NULL,
746 	                                        g_cclosure_marshal_VOID__VOID,
747 	                                        G_TYPE_NONE, 0);
748 	signals[STOP_ACTIVATED] = g_signal_new ("stop",
749 	                                        G_TYPE_FROM_CLASS (gobject_class),
750 	                                        G_SIGNAL_RUN_LAST,
751 	                                        G_STRUCT_OFFSET (PraghaToolbarClass, stop),
752 	                                        NULL, NULL,
753 	                                        g_cclosure_marshal_VOID__VOID,
754 	                                        G_TYPE_NONE, 0);
755 	signals[NEXT_ACTIVATED] = g_signal_new ("next",
756 	                                        G_TYPE_FROM_CLASS (gobject_class),
757 	                                        G_SIGNAL_RUN_LAST,
758 	                                        G_STRUCT_OFFSET (PraghaToolbarClass, next),
759 	                                        NULL, NULL,
760 	                                        g_cclosure_marshal_VOID__VOID,
761 	                                        G_TYPE_NONE, 0);
762 	signals[ALBUM_ART_ACTIVATED] = g_signal_new ("album-art-activated",
763 	                                             G_TYPE_FROM_CLASS (gobject_class),
764 	                                             G_SIGNAL_RUN_LAST,
765 	                                             G_STRUCT_OFFSET (PraghaToolbarClass, album_art_activated),
766 	                                             NULL, NULL,
767 	                                             g_cclosure_marshal_VOID__VOID,
768 	                                             G_TYPE_NONE, 0);
769 	signals[TRACK_INFO_ACTIVATED] = g_signal_new ("track-info-activated",
770 	                                              G_TYPE_FROM_CLASS (gobject_class),
771 	                                              G_SIGNAL_RUN_LAST,
772 	                                              G_STRUCT_OFFSET (PraghaToolbarClass, track_info_activated),
773 	                                              NULL, NULL,
774 	                                              g_cclosure_marshal_VOID__VOID,
775 	                                              G_TYPE_NONE, 0);
776 	signals[TRACK_PROGRESS_ACTIVATED] = g_signal_new ("track-progress-activated",
777 	                                                  G_TYPE_FROM_CLASS (gobject_class),
778 	                                                  G_SIGNAL_RUN_LAST,
779 	                                                  G_STRUCT_OFFSET (PraghaToolbarClass, track_progress_activated),
780 	                                                  NULL, NULL,
781 	                                                  g_cclosure_marshal_VOID__DOUBLE,
782 	                                                  G_TYPE_NONE, 1, G_TYPE_DOUBLE);
783 	signals[UNFULL_ACTIVATED] = g_signal_new ("unfull-activated",
784 	                                          G_TYPE_FROM_CLASS (gobject_class),
785 	                                          G_SIGNAL_RUN_LAST,
786 	                                          G_STRUCT_OFFSET (PraghaToolbarClass, unfull),
787 	                                          NULL, NULL,
788 	                                          g_cclosure_marshal_VOID__VOID,
789 	                                          G_TYPE_NONE, 0);
790 }
791 
792 static void
pragha_toolbar_init(PraghaToolbar * toolbar)793 pragha_toolbar_init (PraghaToolbar *toolbar)
794 {
795 	PraghaPreferences *preferences;
796 	PraghaToolbarButton *prev_button, *play_button, *stop_button, *next_button;
797 	PraghaToolbarButton *unfull_button;
798 	PraghaToggleButton *shuffle_button, *repeat_button;
799 	GtkWidget *vol_button;
800 
801 	const GBindingFlags binding_flags =
802 		G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL;
803 
804 	preferences = pragha_preferences_get();
805 
806 	/* Setup Left control buttons */
807 
808 	prev_button = pragha_toolbar_button_new ("media-skip-backward");
809 	gtk_widget_set_tooltip_text(GTK_WIDGET(prev_button), _("Previous Track"));
810 	toolbar->prev_button = prev_button;
811 
812 	play_button = pragha_toolbar_button_new ("media-playback-start");
813 	gtk_widget_set_tooltip_text(GTK_WIDGET(play_button), _("Play / Pause Track"));
814 	toolbar->play_button = play_button;
815 
816 	stop_button = pragha_toolbar_button_new ("media-playback-stop");
817 	gtk_widget_set_tooltip_text(GTK_WIDGET(stop_button), _("Stop playback"));
818 	toolbar->stop_button = stop_button;
819 
820 	next_button = pragha_toolbar_button_new ("media-skip-forward");
821 	gtk_widget_set_tooltip_text(GTK_WIDGET(next_button), _("Next Track"));
822 	toolbar->next_button = next_button;
823 
824 #if GTK_CHECK_VERSION (3, 12, 0)
825 	gtk_header_bar_pack_start(GTK_HEADER_BAR(toolbar), GTK_WIDGET(prev_button));
826 	gtk_header_bar_pack_start(GTK_HEADER_BAR(toolbar), GTK_WIDGET(play_button));
827 	gtk_header_bar_pack_start(GTK_HEADER_BAR(toolbar), GTK_WIDGET(stop_button));
828 	gtk_header_bar_pack_start(GTK_HEADER_BAR(toolbar), GTK_WIDGET(next_button));
829 #else
830 	gtk_tool_insert_generic_item(GTK_TOOLBAR(toolbar), GTK_WIDGET(prev_button));
831 	gtk_tool_insert_generic_item(GTK_TOOLBAR(toolbar), GTK_WIDGET(play_button));
832 	gtk_tool_insert_generic_item(GTK_TOOLBAR(toolbar), GTK_WIDGET(stop_button));
833 	gtk_tool_insert_generic_item(GTK_TOOLBAR(toolbar), GTK_WIDGET(next_button));
834 #endif
835 
836 	/* Song info Box */
837 
838 #if !GTK_CHECK_VERSION (3, 12, 0)
839 	GtkToolItem *boxitem = gtk_tool_item_new ();
840 	gtk_tool_item_set_expand (GTK_TOOL_ITEM(boxitem), TRUE);
841 	gtk_toolbar_insert (GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(boxitem), -1);
842 
843 	GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
844 	gtk_container_add (GTK_CONTAINER(boxitem), box);
845 
846 	GtkWidget *playing = pragha_toolbar_get_song_box (toolbar);
847 	gtk_box_pack_start (GTK_BOX(box), playing, TRUE, TRUE, 5);
848 #endif
849 
850 	/* Setup Right control buttons */
851 
852 	unfull_button = pragha_toolbar_button_new ("view-restore");
853 	gtk_widget_set_tooltip_text(GTK_WIDGET(unfull_button), _("Leave Fullscreen"));
854 	toolbar->unfull_button = unfull_button;
855 
856 	shuffle_button = pragha_toggle_button_new ("media-playlist-shuffle");
857 	gtk_widget_set_tooltip_text(GTK_WIDGET(shuffle_button), _("Play songs in a random order"));
858 
859 	repeat_button = pragha_toggle_button_new ("media-playlist-repeat");
860 	gtk_widget_set_tooltip_text(GTK_WIDGET(repeat_button), _("Repeat playback list at the end"));
861 
862 	vol_button = gtk_volume_button_new();
863 	g_object_set(vol_button, "use-symbolic", FALSE, NULL);
864 	gtk_button_set_relief(GTK_BUTTON(vol_button), GTK_RELIEF_NONE);
865 	g_object_set(G_OBJECT(vol_button), "size", GTK_ICON_SIZE_LARGE_TOOLBAR, NULL);
866 	toolbar->vol_button = vol_button;
867 
868 	toolbar->extra_button_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
869 
870 #if GTK_CHECK_VERSION (3, 12, 0)
871 	gtk_header_bar_pack_end(GTK_HEADER_BAR(toolbar), GTK_WIDGET(toolbar->extra_button_box));
872 	gtk_header_bar_pack_end(GTK_HEADER_BAR(toolbar), GTK_WIDGET(vol_button));
873 	gtk_header_bar_pack_end(GTK_HEADER_BAR(toolbar), GTK_WIDGET(repeat_button));
874 	gtk_header_bar_pack_end(GTK_HEADER_BAR(toolbar), GTK_WIDGET(shuffle_button));
875 	gtk_header_bar_pack_end(GTK_HEADER_BAR(toolbar), GTK_WIDGET(unfull_button));
876 #else
877 	gtk_tool_insert_generic_item(GTK_TOOLBAR(toolbar), GTK_WIDGET(unfull_button));
878 	gtk_tool_insert_generic_item(GTK_TOOLBAR(toolbar), GTK_WIDGET(shuffle_button));
879 	gtk_tool_insert_generic_item(GTK_TOOLBAR(toolbar), GTK_WIDGET(repeat_button));
880 	gtk_tool_insert_generic_item(GTK_TOOLBAR(toolbar), GTK_WIDGET(vol_button));
881 	gtk_tool_insert_generic_item(GTK_TOOLBAR(toolbar), GTK_WIDGET(toolbar->extra_button_box));
882 #endif
883 
884 	/* Connect signals */
885 
886 	g_signal_connect(G_OBJECT(prev_button), "clicked",
887 	                 G_CALLBACK(prev_button_handler), toolbar);
888 	g_signal_connect(G_OBJECT(play_button), "clicked",
889 	                 G_CALLBACK(play_button_handler), toolbar);
890 	g_signal_connect(G_OBJECT(stop_button), "clicked",
891 	                 G_CALLBACK(stop_button_handler), toolbar);
892 	g_signal_connect(G_OBJECT(next_button), "clicked",
893 	                 G_CALLBACK(next_button_handler), toolbar);
894 	g_signal_connect(G_OBJECT(unfull_button), "clicked",
895 	                 G_CALLBACK(unfull_button_handler), toolbar);
896 
897 	/*g_signal_connect(G_OBJECT (prev_button), "key-press-event",
898 	                 G_CALLBACK(panel_button_key_press), toolbar);
899 	g_signal_connect(G_OBJECT (play_button), "key-press-event",
900 	                 G_CALLBACK(panel_button_key_press), toolbar);
901 	g_signal_connect(G_OBJECT (stop_button), "key-press-event",
902 	                 G_CALLBACK(panel_button_key_press), toolbar);
903 	g_signal_connect(G_OBJECT (next_button), "key-press-event",
904 	                 G_CALLBACK(panel_button_key_press), toolbar);
905 	g_signal_connect(G_OBJECT (next_button), "key-press-event",
906 	                 G_CALLBACK(panel_button_key_press), toolbar);
907 	g_signal_connect(G_OBJECT (unfull_button), "key-press-event",
908 	                 G_CALLBACK(panel_button_key_press), toolbar);
909 	g_signal_connect(G_OBJECT (shuffle_button), "key-press-event",
910 	                 G_CALLBACK(panel_button_key_press), toolbar);
911 	g_signal_connect(G_OBJECT (repeat_button), "key-press-event",
912 	                 G_CALLBACK(panel_button_key_press), toolbar);
913 	g_signal_connect(G_OBJECT (vol_button), "key-press-event",
914 	                 G_CALLBACK(panel_button_key_press), toolbar);*/
915 
916 	g_signal_connect (G_OBJECT (vol_button), "value-changed",
917 	                  G_CALLBACK (vol_button_value_changed), toolbar);
918 
919 	g_object_bind_property(preferences, "shuffle", shuffle_button, "active", binding_flags);
920 	g_object_bind_property(preferences, "repeat", repeat_button, "active", binding_flags);
921 
922 	/* Fix styling */
923 #if GTK_CHECK_VERSION (3, 12, 0)
924 	pragha_toolbar_set_style(toolbar,
925 		pragha_preferences_get_system_titlebar (preferences));
926 #endif
927 
928 	g_object_bind_property(preferences, "toolbar-size", prev_button, "icon-size", binding_flags);
929 	g_object_bind_property(preferences, "toolbar-size", play_button, "icon-size", binding_flags);
930 	g_object_bind_property(preferences, "toolbar-size", stop_button, "icon-size", binding_flags);
931 	g_object_bind_property(preferences, "toolbar-size", next_button, "icon-size", binding_flags);
932 	g_object_bind_property(preferences, "toolbar-size", unfull_button, "icon-size", binding_flags);
933 	g_object_bind_property(preferences, "toolbar-size", shuffle_button, "icon-size", binding_flags);
934 	g_object_bind_property(preferences, "toolbar-size", repeat_button, "icon-size", binding_flags);
935 	g_object_bind_property(preferences, "toolbar-size", vol_button, "size", binding_flags);
936 
937 	gtk_widget_show(GTK_WIDGET(prev_button));
938 	gtk_widget_show(GTK_WIDGET(play_button));
939 	gtk_widget_show(GTK_WIDGET(stop_button));
940 	gtk_widget_show(GTK_WIDGET(next_button));
941 	gtk_widget_show(GTK_WIDGET(shuffle_button));
942 	gtk_widget_show(GTK_WIDGET(repeat_button));
943 	gtk_widget_show(GTK_WIDGET(vol_button));
944 	gtk_widget_show(GTK_WIDGET(toolbar->extra_button_box));
945 
946 	gtk_widget_hide(GTK_WIDGET(toolbar->unfull_button));
947 
948 	gtk_widget_show(GTK_WIDGET(toolbar));
949 
950 	g_object_unref(preferences);
951 }
952 
953 static void
pragha_toolbar_finalize(GObject * object)954 pragha_toolbar_finalize (GObject *object)
955 {
956 	(*G_OBJECT_CLASS (pragha_toolbar_parent_class)->finalize) (object);
957 }
958 
959 PraghaToolbar *
pragha_toolbar_new(void)960 pragha_toolbar_new (void)
961 {
962 	return g_object_new (PRAGHA_TYPE_TOOLBAR, NULL);
963 }
964 
965