1 /*
2 * Copyright (C) 2005 Marc Pavot <marc.pavot@gmail.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 */
19
20 #include "widgets/ario-header.h"
21 #include <gtk/gtk.h>
22 #include <config.h>
23 #include <string.h>
24 #include <glib/gi18n.h>
25
26 #include "ario-util.h"
27 #include "ario-debug.h"
28 #include "covers/ario-cover.h"
29 #include "covers/ario-cover-handler.h"
30 #include "covers/ario-cover-handler.h"
31 #include "shell/ario-shell-coverselect.h"
32 #include "widgets/ario-volume.h"
33
34 static GObject* ario_header_constructor (GType type, guint n_construct_properties,
35 GObjectConstructParam *construct_properties);
36 static gboolean ario_header_image_press_cb (GtkWidget *widget,
37 GdkEventButton *event,
38 ArioHeader *header);
39 static gboolean ario_header_slider_press_cb (GtkWidget *widget,
40 GdkEventButton *event,
41 ArioHeader *header);
42 static gboolean ario_header_slider_release_cb (GtkWidget *widget,
43 GdkEventButton *event,
44 ArioHeader *header);
45 static void ario_header_slider_value_changed_cb (GtkWidget *widget,
46 ArioHeader *header);
47 static void ario_header_song_changed_cb (ArioServer *server,
48 ArioHeader *header);
49 static void ario_header_album_changed_cb (ArioServer *server,
50 ArioHeader *header);
51 static void ario_header_state_changed_cb (ArioServer *server,
52 ArioHeader *header);
53 static void ario_header_cover_changed_cb (ArioCoverHandler *cover_handler,
54 ArioHeader *header);
55 static void ario_header_elapsed_changed_cb (ArioServer *server,
56 int elapsed,
57 ArioHeader *header);
58 static void ario_header_consume_changed_cb (ArioServer *server,
59 ArioHeader *header);
60 static void ario_header_random_changed_cb (ArioServer *server,
61 ArioHeader *header);
62 static void ario_header_repeat_changed_cb (ArioServer *server,
63 ArioHeader *header);
64 static void ario_header_do_consume (ArioHeader *header);
65 static void ario_header_do_random (ArioHeader *header);
66 static void ario_header_do_repeat (ArioHeader *header);
67
68 #define SONG_MARKUP(xSONG) g_markup_printf_escaped ("<big><b>%s</b></big>", xSONG);
69 #define FROM_MARKUP(xALBUM, xARTIST) g_markup_printf_escaped (_("<i>from</i> %s <i>by</i> %s"), xALBUM, xARTIST);
70
71 struct ArioHeaderPrivate
72 {
73 GtkWidget *prev_button;
74 GtkWidget *play_pause_button;
75 GtkWidget *consume_button;
76 GtkWidget *random_button;
77 GtkWidget *repeat_button;
78
79 GtkWidget *stop_button;
80 GtkWidget *next_button;
81
82 GtkWidget *play_image;
83 GtkWidget *pause_image;
84
85 GtkWidget *image;
86
87 GtkWidget *song;
88 GtkWidget *artist_album;
89
90 GtkWidget *scale;
91 GtkAdjustment *adjustment;
92
93 GtkWidget *elapsed;
94 GtkWidget *of;
95 GtkWidget *total;
96
97 GtkWidget *volume_button;
98
99 gboolean slider_dragging;
100
101 gint image_width;
102 gint image_height;
103 };
104
105 #define ARIO_HEADER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_ARIO_HEADER, ArioHeaderPrivate))
G_DEFINE_TYPE(ArioHeader,ario_header,GTK_TYPE_BOX)106 G_DEFINE_TYPE (ArioHeader, ario_header, GTK_TYPE_BOX)
107
108 static void
109 ario_header_class_init (ArioHeaderClass *klass)
110 {
111 ARIO_LOG_FUNCTION_START;
112 GObjectClass *object_class = G_OBJECT_CLASS (klass);
113
114 /* Virtual methods */
115 object_class->constructor = ario_header_constructor;
116
117 /* Private attributes */
118 g_type_class_add_private (klass, sizeof (ArioHeaderPrivate));
119 }
120
121 static void
ario_header_init(ArioHeader * header)122 ario_header_init (ArioHeader *header)
123 {
124 ARIO_LOG_FUNCTION_START;
125 header->priv = ARIO_HEADER_GET_PRIVATE (header);
126 }
127
128 static void
ario_header_drag_leave_cb(GtkWidget * widget,GdkDragContext * context,gint x,gint y,GtkSelectionData * data,guint info,guint time,ArioHeader * header)129 ario_header_drag_leave_cb (GtkWidget *widget,
130 GdkDragContext *context,
131 gint x,
132 gint y,
133 GtkSelectionData *data,
134 guint info,
135 guint time,
136 ArioHeader *header)
137 {
138 ARIO_LOG_FUNCTION_START;
139 gchar *url;
140 gchar *contents;
141 gsize length;
142
143 if (info == 1) {
144 /* Image dropped */
145 ARIO_LOG_INFO ("image DND : TODO\n");
146 } else if (info == 2) {
147 const guchar *udata = gtk_selection_data_get_data (data);
148 /* URL dropped */
149 url = g_strndup ((gchar *) udata + 7, gtk_selection_data_get_length (data) - 2 - 7);
150 if (ario_util_uri_exists (url)) {
151 /* Get file content and save it as the cover */
152 if (ario_file_get_contents (url,
153 &contents,
154 &length,
155 NULL)) {
156 ario_cover_save_cover (ario_server_get_current_artist (),
157 ario_server_get_current_album (),
158 contents, length,
159 OVERWRITE_MODE_REPLACE);
160 g_free (contents);
161 ario_cover_handler_force_reload ();
162 }
163 }
164 g_free (url);
165 }
166
167 /* finish the drag */
168 gtk_drag_finish (context, TRUE, FALSE, time);
169 }
170
171 static GObject *
ario_header_constructor(GType type,guint n_construct_properties,GObjectConstructParam * construct_properties)172 ario_header_constructor (GType type, guint n_construct_properties,
173 GObjectConstructParam *construct_properties)
174 {
175 ARIO_LOG_FUNCTION_START;
176 ArioHeader *header;
177 ArioHeaderClass *klass;
178 GObjectClass *parent_class;
179 GtkWidget *cover_event_box;
180 GtkTargetList *targets;
181 GtkTargetEntry *target_entry;
182 gint n_elem;
183 GtkWidget *image, *hbox, *right_hbox, *vbox;
184 GList *focus = NULL;
185
186 klass = ARIO_HEADER_CLASS (g_type_class_peek (TYPE_ARIO_HEADER));
187
188 parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
189 header = ARIO_HEADER (parent_class->constructor (type, n_construct_properties,
190 construct_properties));
191 gtk_orientable_set_orientation (GTK_ORIENTABLE (header), GTK_ORIENTATION_HORIZONTAL);
192
193 /* Construct previous button */
194 image = gtk_image_new_from_icon_name ("media-skip-backward",
195 GTK_ICON_SIZE_LARGE_TOOLBAR);
196
197 header->priv->prev_button = gtk_button_new ();
198 gtk_container_add (GTK_CONTAINER (header->priv->prev_button), image);
199 g_signal_connect_swapped (header->priv->prev_button,
200 "clicked",
201 G_CALLBACK (ario_header_do_previous),
202 header);
203 gtk_widget_set_tooltip_text (GTK_WIDGET (header->priv->prev_button),
204 _("Play previous song"));
205
206 /* Construct button images */
207 header->priv->play_image = gtk_image_new_from_icon_name ("media-playback-start",
208 GTK_ICON_SIZE_LARGE_TOOLBAR);
209 g_object_ref (header->priv->play_image);
210 gtk_widget_show (header->priv->play_image);
211 header->priv->pause_image = gtk_image_new_from_icon_name ("media-playback-pause",
212 GTK_ICON_SIZE_LARGE_TOOLBAR);
213 g_object_ref (header->priv->pause_image);
214 gtk_widget_show (header->priv->pause_image);
215 header->priv->play_pause_button = gtk_button_new ();
216 gtk_container_add (GTK_CONTAINER (header->priv->play_pause_button), header->priv->pause_image);
217 g_signal_connect_swapped (header->priv->play_pause_button,
218 "clicked",
219 G_CALLBACK (ario_header_playpause),
220 header);
221 gtk_widget_set_tooltip_text (GTK_WIDGET (header->priv->play_pause_button),
222 _("Play/Pause the music"));
223
224 /* Construct stop button */
225 image = gtk_image_new_from_icon_name ("media-playback-stop",
226 GTK_ICON_SIZE_LARGE_TOOLBAR);
227 header->priv->stop_button = gtk_button_new ();
228 gtk_container_add (GTK_CONTAINER (header->priv->stop_button), image);
229 g_signal_connect_swapped (header->priv->stop_button,
230 "clicked",
231 G_CALLBACK (ario_header_stop),
232 header);
233 gtk_widget_set_tooltip_text (GTK_WIDGET (header->priv->stop_button),
234 _("Stop the music"));
235
236 /* Construct next button */
237 image = gtk_image_new_from_icon_name ("media-skip-forward",
238 GTK_ICON_SIZE_LARGE_TOOLBAR);
239 header->priv->next_button = gtk_button_new ();
240 gtk_container_add (GTK_CONTAINER (header->priv->next_button), image);
241 g_signal_connect_swapped (header->priv->next_button,
242 "clicked",
243 G_CALLBACK (ario_header_do_next),
244 header);
245 gtk_widget_set_tooltip_text (GTK_WIDGET (header->priv->next_button),
246 _("Play next song"));
247
248 /* Construct cover display */
249 cover_event_box = gtk_event_box_new ();
250 header->priv->image = gtk_image_new ();
251 gtk_icon_size_lookup (GTK_ICON_SIZE_LARGE_TOOLBAR,
252 &header->priv->image_width,
253 &header->priv->image_height);
254 header->priv->image_width += 18;
255 header->priv->image_height += 18;
256 gtk_container_add (GTK_CONTAINER (cover_event_box), header->priv->image);
257 g_signal_connect (cover_event_box,
258 "button_press_event",
259 G_CALLBACK (ario_header_image_press_cb),
260 header);
261 targets = gtk_target_list_new (NULL, 0);
262 gtk_target_list_add_image_targets (targets, 1, TRUE);
263 gtk_target_list_add_uri_targets (targets, 2);
264 target_entry = gtk_target_table_new_from_list (targets, &n_elem);
265 gtk_target_list_unref (targets);
266
267 gtk_drag_dest_set (cover_event_box,
268 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP,
269 target_entry, n_elem,
270 GDK_ACTION_COPY);
271 gtk_target_table_free (target_entry, n_elem);
272
273 g_signal_connect (cover_event_box,
274 "drag_data_received",
275 G_CALLBACK (ario_header_drag_leave_cb),
276 header);
277
278 g_signal_connect_object (ario_cover_handler_get_instance (),
279 "cover_changed", G_CALLBACK (ario_header_cover_changed_cb),
280 header, 0);
281
282 /* Construct Song/Artist/Album display */
283 header->priv->song = gtk_label_new ("");
284 gtk_label_set_ellipsize (GTK_LABEL (header->priv->song), PANGO_ELLIPSIZE_END);
285 gtk_label_set_use_markup (GTK_LABEL (header->priv->song), TRUE);
286
287 header->priv->artist_album = gtk_label_new ("");
288 gtk_label_set_ellipsize (GTK_LABEL (header->priv->artist_album), PANGO_ELLIPSIZE_END);
289
290 /* Construct time slider */
291 header->priv->adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 10.0, 1.0, 10.0, 0.0));
292 header->priv->scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, header->priv->adjustment);
293
294 g_signal_connect (header->priv->scale,
295 "button_press_event",
296 G_CALLBACK (ario_header_slider_press_cb),
297 header);
298 g_signal_connect (header->priv->scale,
299 "button_release_event",
300 G_CALLBACK (ario_header_slider_release_cb),
301 header);
302 g_signal_connect (header->priv->scale,
303 "value-changed",
304 G_CALLBACK (ario_header_slider_value_changed_cb),
305 header);
306
307 gtk_scale_set_draw_value (GTK_SCALE (header->priv->scale), FALSE);
308 gtk_widget_set_size_request (header->priv->scale, 150, -1);
309
310 header->priv->elapsed = gtk_label_new ("0:00");
311 /* Translators - This " of " is used to count the elapsed time
312 of a song like in "00:59 of 03:24" */
313 header->priv->of = gtk_label_new (_(" of "));
314 header->priv->total = gtk_label_new ("0:00");
315
316 /* Construct consume button */
317 image = gtk_image_new_from_icon_name ("consume",
318 GTK_ICON_SIZE_LARGE_TOOLBAR);
319 header->priv->consume_button = gtk_toggle_button_new ();
320 gtk_container_add (GTK_CONTAINER (header->priv->consume_button), image);
321 g_signal_connect_swapped (header->priv->consume_button,
322 "clicked",
323 G_CALLBACK (ario_header_do_consume),
324 header);
325 gtk_widget_set_tooltip_text (GTK_WIDGET (header->priv->consume_button),
326 _("Toggle 'consume' (remove played song from playlist) on/off"));
327
328 /* Construct random button */
329 image = gtk_image_new_from_icon_name ("shuffle",
330 GTK_ICON_SIZE_LARGE_TOOLBAR);
331 header->priv->random_button = gtk_toggle_button_new ();
332 gtk_container_add (GTK_CONTAINER (header->priv->random_button), image);
333 g_signal_connect_swapped (header->priv->random_button,
334 "clicked",
335 G_CALLBACK (ario_header_do_random),
336 header);
337 gtk_widget_set_tooltip_text (GTK_WIDGET (header->priv->random_button),
338 _("Toggle random on/off"));
339
340 /* Construct repeat button */
341 image = gtk_image_new_from_icon_name ("repeat",
342 GTK_ICON_SIZE_LARGE_TOOLBAR);
343 header->priv->repeat_button = gtk_toggle_button_new ();
344 gtk_container_add (GTK_CONTAINER (header->priv->repeat_button), image);
345 g_signal_connect_swapped (header->priv->repeat_button,
346 "clicked",
347 G_CALLBACK (ario_header_do_repeat),
348 header);
349 gtk_widget_set_tooltip_text (GTK_WIDGET (header->priv->repeat_button),
350 _("Toggle repeat on/off"));
351
352 /* Construct volume button */
353 header->priv->volume_button = GTK_WIDGET (ario_volume_new ());
354 gtk_widget_set_tooltip_text (header->priv->volume_button,
355 _("Change the music volume"));
356
357 /* Add everything in header Hbox */
358 gtk_box_set_spacing (GTK_BOX (header), 12);
359
360 /* Add command Buttons */
361 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
362 gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
363
364 gtk_box_pack_start (GTK_BOX (hbox), header->priv->prev_button, FALSE, TRUE, 0);
365 gtk_box_pack_start (GTK_BOX (hbox), header->priv->play_pause_button, FALSE, TRUE, 0);
366 gtk_box_pack_start (GTK_BOX (hbox), header->priv->stop_button, FALSE, TRUE, 0);
367 gtk_box_pack_start (GTK_BOX (hbox), header->priv->next_button, FALSE, TRUE, 0);
368
369 gtk_box_pack_start (GTK_BOX (header), hbox, FALSE, TRUE, 0);
370
371 /* Add cover */
372 gtk_box_pack_start (GTK_BOX (header), cover_event_box, FALSE, TRUE, 0);
373
374 /* Add song labels */
375 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
376 gtk_box_pack_start (GTK_BOX (vbox), header->priv->song, TRUE, TRUE, 0);
377 gtk_box_pack_start (GTK_BOX (vbox), header->priv->artist_album, TRUE, TRUE, 0);
378
379 gtk_box_pack_start (GTK_BOX (header), vbox, TRUE, TRUE, 0);
380
381 /* Add time slider */
382 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
383 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
384 right_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
385
386 gtk_box_pack_start (GTK_BOX (hbox), header->priv->elapsed, FALSE, TRUE, 0);
387 gtk_box_pack_start (GTK_BOX (hbox), header->priv->of, FALSE, TRUE, 0);
388 gtk_box_pack_start (GTK_BOX (hbox), header->priv->total, FALSE, TRUE, 0);
389
390 gtk_box_pack_start (GTK_BOX (vbox), header->priv->scale, FALSE, TRUE, 0);
391 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
392 gtk_box_pack_start (GTK_BOX (right_hbox), vbox, FALSE, TRUE, 0);
393
394 /* Add consume/random/repeat buttons */
395 gtk_box_pack_start (GTK_BOX (right_hbox), header->priv->consume_button, FALSE, TRUE, 0);
396 gtk_box_pack_start (GTK_BOX (right_hbox), header->priv->random_button, FALSE, TRUE, 0);
397 gtk_box_pack_start (GTK_BOX (right_hbox), header->priv->repeat_button, FALSE, TRUE, 0);
398
399 /* Add volume button */
400 gtk_box_pack_start (GTK_BOX (right_hbox), header->priv->volume_button, FALSE, TRUE, 5);
401
402 gtk_box_pack_end (GTK_BOX (header), right_hbox, FALSE, TRUE, 0);
403
404 /* Set focus chain */
405 focus = g_list_append (focus, header->priv->scale);
406 gtk_container_set_focus_chain (GTK_CONTAINER (header), focus);
407
408 return G_OBJECT (header);
409 }
410
411 GtkWidget *
ario_header_new(void)412 ario_header_new (void)
413 {
414 ARIO_LOG_FUNCTION_START;
415 ArioHeader *header;
416 ArioServer *server = ario_server_get_instance ();
417
418 header = ARIO_HEADER (g_object_new (TYPE_ARIO_HEADER,
419 NULL));
420
421 g_return_val_if_fail (header->priv != NULL, NULL);
422
423 /* Signals to synchronize the header with server */
424 g_signal_connect_object (server,
425 "song_changed", G_CALLBACK (ario_header_song_changed_cb),
426 header, 0);
427 g_signal_connect_object (server,
428 "album_changed", G_CALLBACK (ario_header_album_changed_cb),
429 header, 0);
430 g_signal_connect_object (server,
431 "state_changed", G_CALLBACK (ario_header_state_changed_cb),
432 header, 0);
433 g_signal_connect_object (server,
434 "elapsed_changed", G_CALLBACK (ario_header_elapsed_changed_cb),
435 header, 0);
436 g_signal_connect_object (server,
437 "consume_changed", G_CALLBACK (ario_header_consume_changed_cb),
438 header, 0);
439 g_signal_connect_object (server,
440 "random_changed", G_CALLBACK (ario_header_random_changed_cb),
441 header, 0);
442 g_signal_connect_object (server,
443 "repeat_changed", G_CALLBACK (ario_header_repeat_changed_cb),
444 header, 0);
445
446 return GTK_WIDGET (header);
447 }
448
449 static void
ario_header_change_total_time(ArioHeader * header)450 ario_header_change_total_time (ArioHeader *header)
451 {
452 ARIO_LOG_FUNCTION_START;
453 char *tmp;
454 int total_time;
455
456 /* Get total song time from server */
457 if (!ario_server_is_connected ()) {
458 total_time = 0;
459 } else {
460 switch (ario_server_get_current_state ()) {
461 case ARIO_STATE_PLAY:
462 case ARIO_STATE_PAUSE:
463 total_time = ario_server_get_current_total_time ();
464 break;
465 case ARIO_STATE_UNKNOWN:
466 case ARIO_STATE_STOP:
467 default:
468 total_time = 0;
469 break;
470 }
471
472 }
473
474 /* Change label value with total time */
475 if (total_time > 0) {
476 tmp = ario_util_format_time (total_time);
477 gtk_label_set_text (GTK_LABEL (header->priv->total), tmp);
478 g_free (tmp);
479 gtk_widget_show (header->priv->total);
480 gtk_widget_show (header->priv->of);
481 } else {
482 gtk_widget_hide (header->priv->total);
483 gtk_widget_hide (header->priv->of);
484 }
485
486 /* Change slider higher value */
487 gtk_adjustment_set_upper (header->priv->adjustment, total_time);
488 }
489
490 static void
ario_header_change_song_label(ArioHeader * header)491 ario_header_change_song_label (ArioHeader *header)
492 {
493 ARIO_LOG_FUNCTION_START;
494 char *title;
495 char *tmp;
496
497 switch (ario_server_get_current_state ()) {
498 case ARIO_STATE_PLAY:
499 case ARIO_STATE_PAUSE:
500 /* Set the label with formated title from server */
501 title = ario_util_format_title (ario_server_get_current_song ());
502
503 tmp = SONG_MARKUP (title);
504 gtk_label_set_markup (GTK_LABEL (header->priv->song), tmp);
505 g_free (tmp);
506 break;
507 case ARIO_STATE_UNKNOWN:
508 case ARIO_STATE_STOP:
509 default:
510 /* Set default label value */
511 gtk_label_set_label (GTK_LABEL (header->priv->song), "");
512 break;
513 }
514 }
515
516 static void
ario_header_change_artist_album_label(ArioHeader * header)517 ario_header_change_artist_album_label (ArioHeader *header)
518 {
519 ARIO_LOG_FUNCTION_START;
520 char *artist;
521 char *album;
522 char *tmp;
523
524 switch (ario_server_get_current_state ()) {
525 case ARIO_STATE_PLAY:
526 case ARIO_STATE_PAUSE:
527 /* Set label value with server values */
528 artist = ario_server_get_current_artist ();
529 album = ario_server_get_current_album ();
530
531 if (!album)
532 album = ARIO_SERVER_UNKNOWN;
533
534 if (!artist)
535 artist = ARIO_SERVER_UNKNOWN;
536
537 tmp = FROM_MARKUP (album, artist);
538 gtk_label_set_markup (GTK_LABEL (header->priv->artist_album), tmp);
539 g_free (tmp);
540 break;
541 case ARIO_STATE_UNKNOWN:
542 case ARIO_STATE_STOP:
543 default:
544 /* Set default label value */
545 gtk_label_set_label (GTK_LABEL (header->priv->artist_album), "");
546 break;
547 }
548 }
549
550 static void
ario_header_change_cover(ArioHeader * header)551 ario_header_change_cover (ArioHeader *header)
552 {
553 ARIO_LOG_FUNCTION_START;
554 GdkPixbuf *cover;
555 GdkPixbuf *small_cover = NULL;
556
557 switch (ario_server_get_current_state ()) {
558 case ARIO_STATE_PLAY:
559 case ARIO_STATE_PAUSE:
560 /* Get cover from cover handler and display it */
561 cover = ario_cover_handler_get_cover ();
562 if (cover) {
563 small_cover = gdk_pixbuf_scale_simple (cover,
564 header->priv->image_width,
565 header->priv->image_height,
566 GDK_INTERP_BILINEAR);
567 }
568
569 gtk_image_set_from_pixbuf (GTK_IMAGE (header->priv->image), small_cover);
570
571 if (small_cover)
572 g_object_unref (small_cover);
573 break;
574 case ARIO_STATE_UNKNOWN:
575 case ARIO_STATE_STOP:
576 default:
577 /* Set default cover (empty) */
578 gtk_image_set_from_pixbuf (GTK_IMAGE (header->priv->image), NULL);
579 break;
580 }
581 }
582
583 static void
ario_header_song_changed_cb(ArioServer * server,ArioHeader * header)584 ario_header_song_changed_cb (ArioServer *server,
585 ArioHeader *header)
586 {
587 ARIO_LOG_FUNCTION_START;
588 /* Synchronize song label */
589 ario_header_change_song_label (header);
590
591 /* Synchronize total time label */
592 ario_header_change_total_time (header);
593 }
594
595 static void
ario_header_album_changed_cb(ArioServer * server,ArioHeader * header)596 ario_header_album_changed_cb (ArioServer *server,
597 ArioHeader *header)
598 {
599 ARIO_LOG_FUNCTION_START;
600 /* Synchronize Artist-Album label */
601 ario_header_change_artist_album_label (header);
602 }
603
604 static void
ario_header_cover_changed_cb(ArioCoverHandler * cover_handler,ArioHeader * header)605 ario_header_cover_changed_cb (ArioCoverHandler *cover_handler,
606 ArioHeader *header)
607 {
608 ARIO_LOG_FUNCTION_START;
609 /* Synchronize cover art */
610 ario_header_change_cover (header);
611 }
612
613 static void
ario_header_state_changed_cb(ArioServer * server,ArioHeader * header)614 ario_header_state_changed_cb (ArioServer *server,
615 ArioHeader *header)
616 {
617 ARIO_LOG_FUNCTION_START;
618
619 /* Synchronize song label */
620 ario_header_change_song_label (header);
621
622 /* Synchronize Artist-Album label */
623 ario_header_change_artist_album_label (header);
624
625 /* Synchronize total time label */
626 ario_header_change_total_time (header);
627
628 /* Remove icon from play/pause button */
629 gtk_container_remove (GTK_CONTAINER (header->priv->play_pause_button),
630 gtk_bin_get_child (GTK_BIN (header->priv->play_pause_button)));
631
632 /* Set the appropriate icon in play/pause button */
633 if (ario_server_is_paused ())
634 gtk_container_add (GTK_CONTAINER (header->priv->play_pause_button),
635 header->priv->play_image);
636 else
637 gtk_container_add (GTK_CONTAINER (header->priv->play_pause_button),
638 header->priv->pause_image);
639
640 if (!ario_server_is_connected ()) {
641 /* Set button insensitive if Ario is not connected to a server */
642 gtk_widget_set_sensitive (header->priv->prev_button, FALSE);
643 gtk_widget_set_sensitive (header->priv->play_pause_button, FALSE);
644
645 gtk_widget_set_sensitive (header->priv->consume_button, FALSE);
646 gtk_widget_set_sensitive (header->priv->random_button, FALSE);
647 gtk_widget_set_sensitive (header->priv->repeat_button, FALSE);
648
649 gtk_widget_set_sensitive (header->priv->stop_button, FALSE);
650 gtk_widget_set_sensitive (header->priv->next_button, FALSE);
651
652 gtk_widget_set_sensitive (header->priv->scale, FALSE);
653
654 gtk_widget_set_sensitive (header->priv->volume_button, FALSE);
655 } else {
656 /* Set button sensitive if Ario is connected to a server */
657 gtk_widget_set_sensitive (header->priv->prev_button, TRUE);
658 gtk_widget_set_sensitive (header->priv->play_pause_button, TRUE);
659
660 gtk_widget_set_sensitive (header->priv->consume_button, TRUE);
661 gtk_widget_set_sensitive (header->priv->random_button, TRUE);
662 gtk_widget_set_sensitive (header->priv->repeat_button, TRUE);
663
664 gtk_widget_set_sensitive (header->priv->stop_button, TRUE);
665 gtk_widget_set_sensitive (header->priv->next_button, TRUE);
666
667 gtk_widget_set_sensitive (header->priv->scale, TRUE);
668
669 gtk_widget_set_sensitive (header->priv->volume_button, TRUE);
670 }
671 }
672
673 static void
ario_header_elapsed_changed_cb(ArioServer * server,int elapsed,ArioHeader * header)674 ario_header_elapsed_changed_cb (ArioServer *server,
675 int elapsed,
676 ArioHeader *header)
677 {
678 ARIO_LOG_FUNCTION_START;
679 gchar time[ARIO_MAX_TIME_SIZE];
680
681 if (header->priv->slider_dragging)
682 return;
683
684 /* Update elapsed time label */
685 ario_util_format_time_buf (elapsed, time, ARIO_MAX_TIME_SIZE);
686 gtk_label_set_text (GTK_LABEL (header->priv->elapsed), time);
687
688 /* Update slider value */
689 gtk_adjustment_set_value (header->priv->adjustment, (gdouble) elapsed);
690 }
691
692 static void
ario_header_consume_changed_cb(ArioServer * server,ArioHeader * header)693 ario_header_consume_changed_cb (ArioServer *server,
694 ArioHeader *header)
695 {
696 ARIO_LOG_FUNCTION_START;
697 gboolean consume;
698
699 /* Get consume state on server */
700 consume = ario_server_get_current_consume ();
701
702 /* Block consume button signal */
703 g_signal_handlers_block_by_func (G_OBJECT (header->priv->consume_button),
704 G_CALLBACK (ario_header_do_consume),
705 header);
706
707 /* Change button state depending on consume value */
708 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (header->priv->consume_button),
709 consume);
710
711 /* Unblock consume button signal */
712 g_signal_handlers_unblock_by_func (G_OBJECT (header->priv->consume_button),
713 G_CALLBACK (ario_header_do_consume),
714 header);
715 }
716
717 static void
ario_header_random_changed_cb(ArioServer * server,ArioHeader * header)718 ario_header_random_changed_cb (ArioServer *server,
719 ArioHeader *header)
720 {
721 ARIO_LOG_FUNCTION_START;
722 gboolean random;
723
724 /* Get random state on server */
725 random = ario_server_get_current_random ();
726
727 /* Block random button signal */
728 g_signal_handlers_block_by_func (G_OBJECT (header->priv->random_button),
729 G_CALLBACK (ario_header_do_random),
730 header);
731
732 /* Change button state depending on random value */
733 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (header->priv->random_button),
734 random);
735
736 /* Unblock random button signal */
737 g_signal_handlers_unblock_by_func (G_OBJECT (header->priv->random_button),
738 G_CALLBACK (ario_header_do_random),
739 header);
740 }
741
742 static void
ario_header_repeat_changed_cb(ArioServer * server,ArioHeader * header)743 ario_header_repeat_changed_cb (ArioServer *server,
744 ArioHeader *header)
745 {
746 ARIO_LOG_FUNCTION_START;
747 gboolean repeat;
748
749 /* Get repeat state on server */
750 repeat = ario_server_get_current_repeat ();
751
752 /* Block repeat button signal */
753 g_signal_handlers_block_by_func (G_OBJECT (header->priv->repeat_button),
754 G_CALLBACK (ario_header_do_repeat),
755 header);
756
757 /* Change button state depending on repeat value */
758 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (header->priv->repeat_button),
759 repeat);
760
761 /* Unblock repeat button signal */
762 g_signal_handlers_unblock_by_func (G_OBJECT (header->priv->repeat_button),
763 G_CALLBACK (ario_header_do_repeat),
764 header);
765 }
766
767 static gboolean
ario_header_image_press_cb(GtkWidget * widget,GdkEventButton * event,ArioHeader * header)768 ario_header_image_press_cb (GtkWidget *widget,
769 GdkEventButton *event,
770 ArioHeader *header)
771 {
772 GtkWidget *coverselect;
773 ArioServerAlbum server_album;
774
775 /* Double click on cover art launches the cover selection dialog */
776 if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) {
777 server_album.artist = ario_server_get_current_artist ();
778 server_album.album = ario_server_get_current_album ();
779 server_album.path = g_path_get_dirname ((ario_server_get_current_song ())->file);
780
781 if (!server_album.album)
782 server_album.album = ARIO_SERVER_UNKNOWN;
783
784 if (!server_album.artist)
785 server_album.artist = ARIO_SERVER_UNKNOWN;
786
787 coverselect = ario_shell_coverselect_new (&server_album);
788 gtk_dialog_run (GTK_DIALOG (coverselect));
789 gtk_widget_destroy (coverselect);
790 g_free (server_album.path);
791 }
792
793 return FALSE;
794 }
795
796 static gboolean
ario_header_slider_press_cb(GtkWidget * widget,GdkEventButton * event,ArioHeader * header)797 ario_header_slider_press_cb (GtkWidget *widget,
798 GdkEventButton *event,
799 ArioHeader *header)
800 {
801 ARIO_LOG_FUNCTION_START;
802 header->priv->slider_dragging = TRUE;
803 return FALSE;
804 }
805
806 static gboolean
ario_header_slider_release_cb(GtkWidget * widget,GdkEventButton * event,ArioHeader * header)807 ario_header_slider_release_cb (GtkWidget *widget,
808 GdkEventButton *event,
809 ArioHeader *header)
810 {
811 ARIO_LOG_FUNCTION_START;
812 gdouble scale;
813
814 header->priv->slider_dragging = FALSE;
815 /* Change elapsed time on server */
816 scale = gtk_range_get_value (GTK_RANGE (header->priv->scale));
817 ario_server_set_current_elapsed ((int) scale);
818 return FALSE;
819 }
820
ario_header_slider_value_changed_cb(GtkWidget * widget,ArioHeader * header)821 static void ario_header_slider_value_changed_cb (GtkWidget *widget,
822 ArioHeader *header)
823 {
824 ARIO_LOG_FUNCTION_START;
825 gchar time[ARIO_MAX_TIME_SIZE];
826 int elapsed;
827 gdouble scale;
828
829 if (header->priv->slider_dragging) {
830 /* If user is dragging the slider, we update displayed value */
831 scale = gtk_range_get_value (GTK_RANGE (header->priv->scale));
832 elapsed = (int) scale;
833 ario_util_format_time_buf (elapsed, time, ARIO_MAX_TIME_SIZE);
834 gtk_label_set_text (GTK_LABEL (header->priv->elapsed), time);
835 }
836 }
837
838 void
ario_header_do_next(ArioHeader * header)839 ario_header_do_next (ArioHeader *header)
840 {
841 ARIO_LOG_FUNCTION_START;
842 g_return_if_fail (IS_ARIO_HEADER (header));
843 /* Change to next song */
844 ario_server_do_next ();
845 }
846
847 void
ario_header_do_previous(ArioHeader * header)848 ario_header_do_previous (ArioHeader *header)
849 {
850 ARIO_LOG_FUNCTION_START;
851 g_return_if_fail (IS_ARIO_HEADER (header));
852 /* Change to previous song */
853 ario_server_do_prev ();
854 }
855
856 void
ario_header_playpause(ArioHeader * header)857 ario_header_playpause (ArioHeader *header)
858 {
859 ARIO_LOG_FUNCTION_START;
860 g_return_if_fail (IS_ARIO_HEADER (header));
861 /* Play/pause on server */
862 if (ario_server_is_paused ())
863 ario_server_do_play ();
864 else
865 ario_server_do_pause ();
866 }
867
868 void
ario_header_stop(ArioHeader * header)869 ario_header_stop (ArioHeader *header)
870 {
871 ARIO_LOG_FUNCTION_START;
872 g_return_if_fail (IS_ARIO_HEADER (header));
873 /* Stop music */
874 ario_server_do_stop ();
875 }
876
877 static void
ario_header_do_consume(ArioHeader * header)878 ario_header_do_consume (ArioHeader *header)
879 {
880 ARIO_LOG_FUNCTION_START;
881 g_return_if_fail (IS_ARIO_HEADER (header));
882 /* Change consume on server */
883 ario_server_set_current_consume (!ario_server_get_current_consume ());
884 }
885
886 static void
ario_header_do_random(ArioHeader * header)887 ario_header_do_random (ArioHeader *header)
888 {
889 ARIO_LOG_FUNCTION_START;
890 g_return_if_fail (IS_ARIO_HEADER (header));
891 /* Change random on server */
892 ario_server_set_current_random (!ario_server_get_current_random ());
893 }
894
895 static void
ario_header_do_repeat(ArioHeader * header)896 ario_header_do_repeat (ArioHeader *header)
897 {
898 ARIO_LOG_FUNCTION_START;
899 g_return_if_fail (IS_ARIO_HEADER (header));
900 /* Change repeat on server */
901 ario_server_set_current_repeat (!ario_server_get_current_repeat ());
902 }
903