1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 
3 /*
4  *  Goo
5  *
6  *  Copyright (C) 2004, 2007 Free Software Foundation, Inc.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 #include <string.h>
24 #include <glib/gi18n.h>
25 #include "goo-player-info.h"
26 #include "goo-marshal.h"
27 #include "goo-window.h"
28 #include "glib-utils.h"
29 #include "gtk-utils.h"
30 
31 #define TITLE1_FORMAT "<span size='large'>%s</span>"
32 #define TITLE2_FORMAT "%s"
33 #define TITLE3_FORMAT "%s"
34 #define TIME_FORMAT "%s"
35 #define SCALE_WIDTH 150
36 #define COVER_SIZE 100
37 #define TRAY_COVER_SIZE 80
38 #define MIN_WIDTH 500
39 #define MIN_TOOLTIP_WIDTH 300
40 #define MAX_TOOLTIP_WIDTH 400
41 #define MIN_CHARS 45
42 #define UPDATE_TIMEOUT 50
43 
44 
45 struct _GooPlayerInfoPrivate {
46 	GooWindow   *window;
47 	GtkWidget   *cover_frame;
48 	GtkWidget   *title1_label;
49 	GtkWidget   *title2_label;
50 	GtkWidget   *title3_label;
51 	GtkWidget   *time_label;
52 	GtkWidget   *cover_image;
53 	GtkWidget   *cover_button;
54 	GtkWidget   *status_button;
55 	GtkWidget   *status_image;
56 	GtkWidget   *notebook;
57 	char        *total_time;
58 	char         time[64];
59 	gint64       track_length;
60 	gboolean     dragging;
61 	guint        update_id;
62 	double       fraction;
63 	guint        update_progress_timeout;
64 	GdkPixbuf   *original_cover;
65 	char        *cover_file;
66 };
67 
68 
69 G_DEFINE_TYPE_WITH_CODE (GooPlayerInfo, goo_player_info, GTK_TYPE_BOX,
70 			 G_ADD_PRIVATE (GooPlayerInfo))
71 
72 
73 enum {
74 	COVER_CLICKED,
75 	UPDATE_STATUS,
76 	LAST_SIGNAL
77 };
78 
79 enum {
80 	TARGET_URL
81 };
82 
83 
84 static guint goo_player_info_signals[LAST_SIGNAL] = { 0 };
85 static GtkTargetEntry target_table[] = {
86 	{ "text/uri-list", 0, TARGET_URL }
87 };
88 static guint n_targets = sizeof (target_table) / sizeof (target_table[0]);
89 
90 
91 static void
goo_player_info_get_preferred_width(GtkWidget * widget,int * minimum_width,int * natural_width)92 goo_player_info_get_preferred_width (GtkWidget *widget,
93 				     int       *minimum_width,
94 				     int       *natural_width)
95 {
96 	*minimum_width = *natural_width = MIN_WIDTH;
97 }
98 
99 
100 static void
set_label(GtkWidget * label,const char * format,const char * text)101 set_label (GtkWidget  *label,
102 	  const char  *format,
103 	   const char *text)
104 {
105 	char *esc;
106 	char *markup;
107 
108 	if ((text == NULL) || (*text == '\0')) {
109 		gtk_label_set_text (GTK_LABEL (label), "");
110 		gtk_widget_hide (label);
111 		return;
112 	}
113 
114 	esc = g_markup_escape_text (text, -1);
115 	markup = g_strdup_printf (format, esc);
116 	gtk_label_set_markup (GTK_LABEL (label), markup);
117 	gtk_widget_show (label);
118 
119 	g_free (markup);
120 	g_free (esc);
121 }
122 
123 
124 static void
set_title1(GooPlayerInfo * info,const char * text)125 set_title1 (GooPlayerInfo *info,
126 	    const char    *text)
127 {
128 	set_label (info->priv->title1_label, TITLE1_FORMAT, text);
129 }
130 
131 
132 static void
set_title2(GooPlayerInfo * info,const char * text)133 set_title2 (GooPlayerInfo *info,
134 	    const char    *text)
135 {
136 	set_label (info->priv->title2_label, TITLE2_FORMAT, text);
137 }
138 
139 
140 static void
set_title3(GooPlayerInfo * info,const char * text)141 set_title3 (GooPlayerInfo *info,
142 	    const char    *text)
143 {
144 	set_label (info->priv->title3_label, TITLE3_FORMAT, text);
145 }
146 
147 
148 static void
set_total_time(GooPlayerInfo * info,const char * text)149 set_total_time (GooPlayerInfo *info,
150 		const char    *text)
151 {
152 	set_label (info->priv->time_label, TIME_FORMAT, text);
153 }
154 
155 
156 static void
cover_button_clicked_cb(GtkWidget * button,GooPlayerInfo * info)157 cover_button_clicked_cb (GtkWidget     *button,
158 			 GooPlayerInfo *info)
159 {
160 	g_signal_emit (info, goo_player_info_signals[COVER_CLICKED], 0);
161 }
162 
163 
164 static void
status_button_clicked_cb(GtkWidget * button,GooPlayerInfo * info)165 status_button_clicked_cb (GtkWidget     *button,
166 			  GooPlayerInfo *info)
167 {
168 	g_signal_emit (info, goo_player_info_signals[UPDATE_STATUS], 0);
169 }
170 
171 
172 /* -- drag and drop -- */
173 
174 
175 static void
cover_button_drag_data_received(GtkWidget * widget,GdkDragContext * context,gint x,gint y,GtkSelectionData * data,guint dnd_info,guint time,gpointer extra_data)176 cover_button_drag_data_received  (GtkWidget          *widget,
177 				  GdkDragContext     *context,
178 				  gint                x,
179 				  gint                y,
180 				  GtkSelectionData   *data,
181 				  guint               dnd_info,
182 				  guint               time,
183 				  gpointer            extra_data)
184 {
185 	GooPlayerInfo  *info = extra_data;
186 	char          **uris;
187 
188 	gtk_drag_finish (context, TRUE, FALSE, time);
189 
190 	uris = gtk_selection_data_get_uris (data);
191 	if (uris[0] != NULL) {
192 		GFile *file;
193 		char  *cover_filename;
194 
195 		file = g_file_new_for_uri (uris[0]);
196 		cover_filename = g_file_get_path (file);
197 		goo_window_set_cover_image (info->priv->window, cover_filename);
198 
199 		g_free (cover_filename);
200 		g_object_unref (file);
201 	}
202 
203 	g_strfreev (uris);
204 }
205 
206 
207 static void
goo_player_info_construct(GooPlayerInfo * info)208 goo_player_info_construct (GooPlayerInfo *info)
209 {
210 	GooPlayerInfoPrivate *priv;
211 	GtkWidget            *vbox;
212 
213 	priv = info->priv;
214 
215 	priv->dragging = FALSE;
216 	priv->total_time = NULL;
217 	priv->update_id = 0;
218 
219 	gtk_widget_set_margin_top (GTK_WIDGET (info), 10);
220 	gtk_widget_set_margin_end (GTK_WIDGET (info), 10);
221 	gtk_widget_set_margin_bottom (GTK_WIDGET (info), 10);
222 	gtk_widget_set_margin_start (GTK_WIDGET (info), 10);
223 
224 	gtk_widget_set_can_focus (GTK_WIDGET (info), FALSE);
225 	gtk_box_set_spacing (GTK_BOX (info), 12);
226 	gtk_box_set_homogeneous (GTK_BOX (info), FALSE);
227 
228 	/* Title and Artist */
229 
230 	priv->title1_label = gtk_label_new (NULL);
231 	gtk_style_context_add_class (gtk_widget_get_style_context (priv->title1_label), "goobox-info-album");
232 	gtk_label_set_xalign (GTK_LABEL (priv->title1_label), 0.0);
233 	gtk_label_set_yalign (GTK_LABEL (priv->title1_label), 0.5);
234 
235 	priv->title2_label = gtk_label_new (NULL);
236 	gtk_style_context_add_class (gtk_widget_get_style_context (priv->title2_label), "goobox-info-artist");
237 	gtk_label_set_xalign (GTK_LABEL (priv->title2_label), 0.0);
238 	gtk_label_set_yalign (GTK_LABEL (priv->title2_label), 0.5);
239 	gtk_label_set_selectable (GTK_LABEL (priv->title2_label), TRUE);
240 
241 	priv->title3_label = gtk_label_new (NULL);
242 	gtk_style_context_add_class (gtk_widget_get_style_context (priv->title3_label), "goobox-info-track");
243 	gtk_label_set_xalign (GTK_LABEL (priv->title3_label), 0.0);
244 	gtk_label_set_yalign (GTK_LABEL (priv->title3_label), 0.5);
245 	gtk_label_set_selectable (GTK_LABEL (priv->title3_label), TRUE);
246 
247 	priv->time_label = gtk_label_new (NULL);
248 	gtk_style_context_add_class (gtk_widget_get_style_context (priv->time_label), "goobox-info-time");
249 	gtk_label_set_xalign (GTK_LABEL (priv->time_label), 0.0);
250 	gtk_label_set_yalign (GTK_LABEL (priv->time_label), 0.5);
251 	gtk_label_set_selectable (GTK_LABEL (priv->time_label), TRUE);
252 
253 	gtk_label_set_ellipsize (GTK_LABEL (priv->title1_label), PANGO_ELLIPSIZE_END);
254 	gtk_label_set_width_chars (GTK_LABEL (priv->title2_label), MIN_CHARS);
255 
256 	gtk_label_set_ellipsize (GTK_LABEL (priv->title2_label), PANGO_ELLIPSIZE_END);
257 	gtk_label_set_width_chars (GTK_LABEL (priv->title2_label), MIN_CHARS);
258 
259 	gtk_label_set_ellipsize (GTK_LABEL (priv->title3_label), PANGO_ELLIPSIZE_END);
260 	gtk_label_set_width_chars (GTK_LABEL (priv->title3_label), MIN_CHARS);
261 
262 	/* Image */
263 
264 	priv->cover_button = gtk_button_new ();
265 	gtk_button_set_relief (GTK_BUTTON (priv->cover_button),
266 			       GTK_RELIEF_NONE);
267 
268 	gtk_widget_set_tooltip_text (GTK_WIDGET (priv->cover_button),
269 				     _("Click here to choose a cover for this CD"));
270 
271 	g_signal_connect (G_OBJECT (priv->cover_button),
272 			  "clicked",
273 			  G_CALLBACK (cover_button_clicked_cb),
274 			  info);
275 	gtk_drag_dest_set (priv->cover_button,
276 			   GTK_DEST_DEFAULT_ALL,
277 			   target_table, n_targets,
278 			   GDK_ACTION_COPY);
279 	g_signal_connect (G_OBJECT (priv->cover_button),
280 			  "drag_data_received",
281 			  G_CALLBACK (cover_button_drag_data_received),
282 			  info);
283 
284 	priv->cover_image = gtk_image_new_from_icon_name (GOO_ICON_NAME_NO_DISC, GTK_ICON_SIZE_DIALOG);
285 	gtk_widget_set_size_request (priv->cover_image, COVER_SIZE, COVER_SIZE);
286 	gtk_widget_show (priv->cover_image);
287 
288 	gtk_container_add (GTK_CONTAINER (priv->cover_button), priv->cover_image);
289 
290 	/* Status image */
291 
292 	priv->status_button = gtk_button_new ();
293 	gtk_button_set_relief (GTK_BUTTON (priv->status_button), GTK_RELIEF_NONE);
294 	g_signal_connect (G_OBJECT (priv->status_button),
295 			  "clicked",
296 			  G_CALLBACK (status_button_clicked_cb),
297 			  info);
298 
299 	priv->status_image = gtk_image_new_from_icon_name (GOO_ICON_NAME_NO_DISC, GTK_ICON_SIZE_DIALOG);
300 	gtk_widget_set_size_request (priv->status_image, COVER_SIZE, COVER_SIZE);
301 	gtk_widget_show (priv->cover_image);
302 	gtk_container_add (GTK_CONTAINER (priv->status_button), priv->status_image);
303 	/*gtk_container_set_border_width (GTK_CONTAINER (priv->status_image), 6);*/
304 
305 	/* Frame */
306 
307 	priv->notebook = gtk_notebook_new ();
308 	gtk_container_set_border_width (GTK_CONTAINER (priv->notebook), 0);
309 	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), FALSE);
310 	gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->notebook), FALSE);
311 	gtk_widget_show (priv->notebook);
312 
313 	gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), priv->status_button, NULL);
314 	gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), priv->cover_button, NULL);
315 
316 	priv->cover_frame = gtk_frame_new (NULL);
317 	gtk_style_context_add_class (gtk_widget_get_style_context (priv->cover_frame), "goobox-cover-frame");
318 	gtk_container_set_border_width (GTK_CONTAINER (priv->cover_frame), 0);
319 	gtk_widget_show (priv->cover_frame);
320 	gtk_container_add (GTK_CONTAINER (priv->cover_frame), priv->notebook);
321 
322 	gtk_box_pack_start (GTK_BOX (info), priv->cover_frame, FALSE, FALSE, 0);
323 
324 	/**/
325 
326 	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
327 	gtk_container_set_border_width (GTK_CONTAINER (vbox), 0);
328 	gtk_box_pack_start (GTK_BOX (vbox), priv->title1_label, TRUE, TRUE, 0);
329 	gtk_box_pack_start (GTK_BOX (vbox), priv->title2_label, FALSE, FALSE, 0);
330 	gtk_box_pack_start (GTK_BOX (vbox), priv->title3_label, FALSE, FALSE, 0);
331 	gtk_box_pack_end (GTK_BOX (vbox), priv->time_label, FALSE, FALSE, 0);
332 
333 	gtk_widget_show (vbox);
334 	gtk_box_pack_start (GTK_BOX (info), vbox, TRUE, TRUE, 0);
335 }
336 
337 
338 static void
goo_player_info_finalize(GObject * object)339 goo_player_info_finalize (GObject *object)
340 {
341         GooPlayerInfo *info;
342 
343         g_return_if_fail (object != NULL);
344         g_return_if_fail (GOO_IS_PLAYER_INFO (object));
345 
346 	info = GOO_PLAYER_INFO (object);
347 	g_free (info->priv->total_time);
348 	if (info->priv->update_id != 0) {
349 		g_free (info->priv->cover_file);
350 		g_object_unref (info->priv->original_cover);
351 		g_source_remove (info->priv->update_id);
352 		info->priv->update_id = 0;
353 	}
354 
355 	G_OBJECT_CLASS (goo_player_info_parent_class)->finalize (object);
356 }
357 
358 
359 static void
show_simple_text(GooPlayerInfo * info,const char * text)360 show_simple_text (GooPlayerInfo *info,
361 		  const char     *text)
362 {
363 	set_title1 (info, text);
364 	set_title2 (info, "");
365 	set_title3 (info, "");
366 
367 	/* center vertically the only displayed label */
368 
369 	gtk_box_set_child_packing (GTK_BOX (gtk_widget_get_parent (info->priv->title1_label)),
370 				   info->priv->title1_label,
371 				   TRUE,
372 				   TRUE,
373 				   0,
374 				   GTK_PACK_START);
375 }
376 
377 
378 static void
show_all_labels(GooPlayerInfo * info)379 show_all_labels (GooPlayerInfo *info)
380 {
381 	gtk_widget_show (info->priv->title1_label);
382 	gtk_widget_show (info->priv->title2_label);
383 	gtk_widget_show (info->priv->title3_label);
384 
385 	gtk_box_set_child_packing (GTK_BOX (gtk_widget_get_parent (info->priv->title1_label)),
386 				   info->priv->title1_label,
387 				   FALSE,
388 				   FALSE,
389 				   0,
390 				   GTK_PACK_START);
391 }
392 
393 
394 static void
goo_player_info_update_state(GooPlayerInfo * info)395 goo_player_info_update_state (GooPlayerInfo *info)
396 {
397 	GooPlayerInfoPrivate *priv = info->priv;
398 	GooPlayerState        state;
399 	AlbumInfo            *album;
400 	GooPlayer            *player;
401 
402 	if (info->priv->window == NULL)
403 		return;
404 
405 	player = goo_window_get_player (info->priv->window);
406 	if (player == NULL)
407 		return;
408 
409 	state = goo_player_get_state (player);
410 	album = goo_window_get_album (info->priv->window);
411 
412 	gtk_label_set_selectable (GTK_LABEL (priv->title1_label), FALSE);
413 	gtk_label_set_selectable (GTK_LABEL (priv->title2_label), FALSE);
414 	gtk_label_set_selectable (GTK_LABEL (priv->title3_label), FALSE);
415 
416 	set_total_time (info, priv->total_time);
417 
418 	if ((state == GOO_PLAYER_STATE_ERROR) || (state == GOO_PLAYER_STATE_NO_DISC))
419 	{
420 		show_simple_text (info, _("No disc"));
421 	}
422 	else if (state == GOO_PLAYER_STATE_DATA_DISC) {
423 		show_simple_text (info, _("Data disc"));
424 	}
425 	else {
426 		if (state == GOO_PLAYER_STATE_EJECTING) {
427 			show_simple_text (info, _("Ejecting CD"));
428 		}
429 		else if (state == GOO_PLAYER_STATE_UPDATING) {
430 			show_simple_text (info, _("Checking CD drive"));
431 		}
432 		else if (state == GOO_PLAYER_STATE_SEEKING) {
433 			show_simple_text (info, _("Reading CD"));
434 		}
435 		else if (state == GOO_PLAYER_STATE_LISTING) {
436 			show_simple_text (info, _("Reading CD"));
437 		}
438 		else if (album->title == NULL) {
439 			show_simple_text (info, _("Audio CD"));
440 		}
441 		else {
442 			char year[128];
443 
444 			show_all_labels (info);
445 
446 			if (g_date_valid (album->release_date) != 0)
447 				sprintf (year, "%u", g_date_get_year (album->release_date));
448 			else
449 				year[0] = '\0';
450 
451 			set_title1 (info, album->title);
452 			gtk_label_set_selectable (GTK_LABEL (priv->title1_label), TRUE);
453 
454 			if (album->artist != NULL) {
455 				set_title2 (info, album->artist);
456 				set_title3 (info, year);
457 				gtk_label_set_selectable (GTK_LABEL (priv->title2_label), TRUE);
458 			}
459 			else {
460 				set_title2 (info, year);
461 				set_title3 (info, "");
462 			}
463 		}
464 	}
465 }
466 
467 
468 static void
goo_player_info_set_sensitive(GooPlayerInfo * info,gboolean value)469 goo_player_info_set_sensitive (GooPlayerInfo  *info,
470 			       gboolean        value)
471 {
472 	gtk_widget_set_sensitive (info->priv->cover_button, value);
473 }
474 
475 
476 static void
player_state_changed_cb(GooPlayer * player,GooPlayerInfo * info)477 player_state_changed_cb (GooPlayer     *player,
478 			 GooPlayerInfo *info)
479 {
480 	goo_player_info_update_state (info);
481 	goo_player_info_set_sensitive (info, (goo_player_get_state (player) != GOO_PLAYER_STATE_ERROR) && (goo_player_get_discid (player) != NULL));
482 }
483 
484 
485 static void
player_start_cb(GooPlayer * player,GooPlayerAction action,GooPlayerInfo * info)486 player_start_cb (GooPlayer       *player,
487 		 GooPlayerAction  action,
488 		 GooPlayerInfo   *info)
489 {
490 	goo_player_info_update_state (info);
491 }
492 
493 
494 static void
goo_player_info_set_total_time(GooPlayerInfo * info,gint64 total_time)495 goo_player_info_set_total_time (GooPlayerInfo  *info,
496 				gint64          total_time)
497 {
498 	g_free (info->priv->total_time);
499 	info->priv->total_time = (total_time > 0) ? _g_format_duration_for_display (total_time * 1000) : NULL;
500 	goo_player_info_update_state (info);
501 }
502 
503 
504 static void
player_done_cb(GooPlayer * player,GooPlayerAction action,GError * error,GooPlayerInfo * info)505 player_done_cb (GooPlayer       *player,
506 		GooPlayerAction  action,
507 		GError          *error,
508 		GooPlayerInfo   *info)
509 {
510 	AlbumInfo *album;
511 
512 	switch (action) {
513 	case GOO_PLAYER_ACTION_LIST:
514 		goo_player_info_update_state (info);
515 		album = goo_player_get_album (player);
516 		goo_player_info_set_total_time (info, album->total_length);
517 		break;
518 	case GOO_PLAYER_ACTION_METADATA:
519 	case GOO_PLAYER_ACTION_SEEK_SONG:
520 		goo_player_info_update_state (info);
521 		break;
522 	default:
523 		break;
524 	}
525 }
526 
527 
528 static void
goo_player_info_set_cover(GooPlayerInfo * info,const char * cover)529 goo_player_info_set_cover (GooPlayerInfo *info,
530 			   const char    *cover)
531 {
532 	if (cover == NULL)
533 		return;
534 
535 	g_clear_object (&info->priv->original_cover);
536 	if (info->priv->cover_file != NULL) {
537 		g_free (info->priv->cover_file);
538 		info->priv->cover_file = NULL;
539 	}
540 
541 	if (strcmp (cover, "no-disc") == 0) {
542 		gtk_notebook_set_current_page (GTK_NOTEBOOK (info->priv->notebook), 0);
543 		gtk_image_set_from_icon_name (GTK_IMAGE (info->priv->status_image),
544 					      GOO_ICON_NAME_NO_DISC,
545 					      GTK_ICON_SIZE_DIALOG);
546 	}
547 	else if (strcmp (cover, "data-disc") == 0) {
548 		gtk_notebook_set_current_page (GTK_NOTEBOOK (info->priv->notebook), 0);
549 		gtk_image_set_from_icon_name (GTK_IMAGE (info->priv->status_image),
550 					      GOO_ICON_NAME_DATA_DISC,
551 					      GTK_ICON_SIZE_DIALOG);
552 	}
553 	else if (strcmp (cover, "audio-cd") == 0) {
554 		gtk_notebook_set_current_page (GTK_NOTEBOOK (info->priv->notebook), 1);
555 		gtk_image_set_from_icon_name (GTK_IMAGE (info->priv->cover_image),
556 					      GOO_ICON_NAME_NO_DISC,
557 					      GTK_ICON_SIZE_DIALOG);
558 	}
559 	else {
560 		info->priv->cover_file = g_strdup (cover);
561 		info->priv->original_cover = gdk_pixbuf_new_from_file (cover, NULL);
562 		if (info->priv->original_cover != NULL) {
563 			GdkPixbuf *image;
564 
565 			image = gdk_pixbuf_scale_simple (info->priv->original_cover, COVER_SIZE, COVER_SIZE, GDK_INTERP_BILINEAR);
566 			gtk_notebook_set_current_page (GTK_NOTEBOOK (info->priv->notebook), 1);
567 			gtk_image_set_from_pixbuf (GTK_IMAGE (info->priv->cover_image), image);
568 
569 			g_object_unref (image);
570 		}
571 		else
572 			goo_player_info_set_cover (info, "audio-cd");
573 	}
574 }
575 
576 
577 static void
window_update_cover_cb(GooWindow * window,GooPlayerInfo * info)578 window_update_cover_cb (GooWindow     *window,
579 			GooPlayerInfo *info)
580 {
581 	GooPlayerState  state;
582 	char           *filename;
583 
584 	state = goo_player_get_state (goo_window_get_player (window));
585 
586 	if ((state == GOO_PLAYER_STATE_ERROR) || (state == GOO_PLAYER_STATE_NO_DISC)) {
587 	    	goo_player_info_set_cover (info, "no-disc");
588 	    	return;
589 	}
590 
591 	if (state == GOO_PLAYER_STATE_DATA_DISC) {
592 	    	goo_player_info_set_cover (info, "data-disc");
593 	    	return;
594 	}
595 
596 	filename = goo_window_get_cover_filename (window);
597 	if (filename == NULL) {
598 		goo_player_info_set_cover (info, "audio-cd");
599 		return;
600 	}
601 
602 	goo_player_info_set_cover (info, filename);
603 	g_free (filename);
604 }
605 
606 
607 static void
goo_player_info_class_init(GooPlayerInfoClass * class)608 goo_player_info_class_init (GooPlayerInfoClass *class)
609 {
610         GObjectClass   *gobject_class;
611 	GtkWidgetClass *widget_class;
612 
613 	gobject_class = G_OBJECT_CLASS (class);
614         gobject_class->finalize = goo_player_info_finalize;
615 
616 	widget_class = GTK_WIDGET_CLASS (class);
617 	widget_class->get_preferred_width = goo_player_info_get_preferred_width;
618 
619 	goo_player_info_signals[COVER_CLICKED] =
620 		g_signal_new ("cover_clicked",
621 			      G_TYPE_FROM_CLASS (class),
622 			      G_SIGNAL_RUN_LAST,
623 			      G_STRUCT_OFFSET (GooPlayerInfoClass, cover_clicked),
624 			      NULL, NULL,
625 			      goo_marshal_VOID__VOID,
626 			      G_TYPE_NONE,
627 			      0);
628 	goo_player_info_signals[UPDATE_STATUS] =
629 		g_signal_new ("update-status",
630 			      G_TYPE_FROM_CLASS (class),
631 			      G_SIGNAL_RUN_LAST,
632 			      G_STRUCT_OFFSET (GooPlayerInfoClass, update_status),
633 			      NULL, NULL,
634 			      goo_marshal_VOID__VOID,
635 			      G_TYPE_NONE,
636 			      0);
637 }
638 
639 
640 static void
goo_player_info_init(GooPlayerInfo * info)641 goo_player_info_init (GooPlayerInfo *info)
642 {
643 	gtk_orientable_set_orientation (GTK_ORIENTABLE (info), GTK_ORIENTATION_HORIZONTAL);
644 	info->priv = goo_player_info_get_instance_private (info);
645 }
646 
647 
648 GtkWidget *
goo_player_info_new(GooWindow * window)649 goo_player_info_new (GooWindow *window)
650 {
651 	GooPlayerInfo *info;
652 	GooPlayer     *player;
653 
654 	g_return_val_if_fail (window != NULL, NULL);
655 
656 	player = goo_window_get_player (window);
657 	g_return_val_if_fail (player != NULL, NULL);
658 
659 	info = GOO_PLAYER_INFO (g_object_new (GOO_TYPE_PLAYER_INFO, NULL));
660 
661 	info->priv->window = window;
662 	goo_player_info_construct (info);
663 
664 	g_signal_connect (window,
665 			  "update_cover",
666 			  G_CALLBACK (window_update_cover_cb),
667 			  info);
668 	g_signal_connect (player,
669 			  "start",
670 			  G_CALLBACK (player_start_cb),
671 			  info);
672 	g_signal_connect (player,
673 			  "done",
674 			  G_CALLBACK (player_done_cb),
675 			  info);
676 	g_signal_connect (player,
677 			  "state_changed",
678 			  G_CALLBACK (player_state_changed_cb),
679 			  info);
680 
681 	return GTK_WIDGET (info);
682 }
683 
684 
685 GdkPixbuf *
goo_player_info_get_cover(GooPlayerInfo * info)686 goo_player_info_get_cover (GooPlayerInfo *info)
687 {
688 	return info->priv->original_cover;
689 }
690 
691 
692 const char *
goo_player_info_get_cover_file(GooPlayerInfo * info)693 goo_player_info_get_cover_file (GooPlayerInfo *info)
694 {
695 	return info->priv->cover_file;
696 }
697