1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3 /***************************************************************************
4 * player.c
5 *
6 * lun mai 30 08:15:01 2005
7 * Copyright 2005 Philippe Rouquier
8 * brasero-app@wanadoo.fr
9 ****************************************************************************/
10
11 /*
12 * Brasero is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * Brasero is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to:
24 * The Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor
26 * Boston, MA 02110-1301, USA.
27 */
28
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif
32
33 #include <string.h>
34
35 #include <glib.h>
36 #include <glib/gi18n-lib.h>
37
38 #include <gtk/gtk.h>
39
40 #include "brasero-misc.h"
41 #include "brasero-metadata.h"
42 #include "brasero-io.h"
43
44 #include "brasero-units.h"
45
46 #include "brasero-setting.h"
47
48 #include "brasero-player.h"
49 #include "brasero-player-bacon.h"
50 #include "brasero-utils.h"
51
52
53 G_DEFINE_TYPE (BraseroPlayer, brasero_player, GTK_TYPE_ALIGNMENT);
54
55 struct BraseroPlayerPrivate {
56 GtkWidget *notebook;
57
58 GtkWidget *bacon;
59
60 GtkWidget *spinner;
61
62 GtkWidget *play_image;
63
64 gint image_width;
65 gint image_height;
66 GdkPixbuf *pixbuf;
67
68 GtkWidget *image_display;
69
70 GtkWidget *zoom_in;
71 GtkWidget *zoom_out;
72
73 gint video_width;
74 gint video_height;
75
76 BraseroPlayerBaconState state;
77
78 BraseroIOJobBase *meta_task;
79
80 gchar *uri;
81 gint64 start;
82 gint64 end;
83 gint64 length;
84
85 int is_video:1;
86 };
87
88 typedef enum {
89 READY_SIGNAL,
90 ERROR_SIGNAL,
91 EOF_SIGNAL,
92 LAST_SIGNAL
93 } BraseroPlayerSignalType;
94 static guint brasero_player_signals [LAST_SIGNAL] = { 0 };
95
96 static GObjectClass *parent_class = NULL;
97
98 static void
brasero_player_no_multimedia_stream(BraseroPlayer * player)99 brasero_player_no_multimedia_stream (BraseroPlayer *player)
100 {
101 gtk_spinner_stop (GTK_SPINNER (player->priv->spinner));
102 gtk_widget_set_has_tooltip (GTK_WIDGET (player), FALSE);
103 gtk_notebook_set_current_page (GTK_NOTEBOOK (player->priv->notebook), 2);
104
105 player->priv->length = 0;
106 player->priv->start = 0;
107 player->priv->end = 0;
108 }
109
110 static void
brasero_player_video_zoom_out(BraseroPlayer * player)111 brasero_player_video_zoom_out (BraseroPlayer *player)
112 {
113 player->priv->video_width -= PLAYER_BACON_WIDTH / 3;
114 player->priv->video_height -= PLAYER_BACON_HEIGHT / 3;
115
116 if (player->priv->video_width <= PLAYER_BACON_WIDTH ||
117 player->priv->video_height <= PLAYER_BACON_HEIGHT) {
118 player->priv->video_width = PLAYER_BACON_WIDTH;
119 player->priv->video_height = PLAYER_BACON_HEIGHT;
120 }
121
122 gtk_widget_set_size_request (GTK_WIDGET (player->priv->bacon),
123 player->priv->video_width,
124 player->priv->video_height);
125 }
126
127 static void
brasero_player_video_zoom_in(BraseroPlayer * player)128 brasero_player_video_zoom_in (BraseroPlayer *player)
129 {
130 player->priv->video_width += PLAYER_BACON_WIDTH / 3;
131 player->priv->video_height += PLAYER_BACON_HEIGHT / 3;
132
133 if (player->priv->video_width >= PLAYER_BACON_WIDTH * 3 ||
134 player->priv->video_height >= PLAYER_BACON_HEIGHT * 3) {
135 player->priv->video_width = PLAYER_BACON_WIDTH * 3;
136 player->priv->video_height = PLAYER_BACON_HEIGHT * 3;
137 }
138
139 gtk_widget_set_size_request (GTK_WIDGET (player->priv->bacon),
140 player->priv->video_width,
141 player->priv->video_height);
142 }
143
144 static gboolean
brasero_player_scale_image(BraseroPlayer * player)145 brasero_player_scale_image (BraseroPlayer *player)
146 {
147 gint height, width;
148 GdkPixbuf *scaled;
149 gdouble ratio;
150
151 height = gdk_pixbuf_get_height (player->priv->pixbuf);
152 width = gdk_pixbuf_get_width (player->priv->pixbuf);
153
154 if (player->priv->image_height == height
155 && player->priv->image_width == width) {
156 gtk_image_set_from_pixbuf (GTK_IMAGE (player->priv->image_display),
157 player->priv->pixbuf);
158 return TRUE;
159 }
160
161 if (width / (gdouble) player->priv->image_width > height / (gdouble) player->priv->image_height)
162 ratio = (gdouble) width / (gdouble) player->priv->image_width;
163 else
164 ratio = (gdouble) height / (gdouble) player->priv->image_height;
165
166 scaled = gdk_pixbuf_scale_simple (player->priv->pixbuf,
167 width / ratio,
168 height / ratio,
169 GDK_INTERP_BILINEAR);
170
171 if (!scaled)
172 return FALSE;
173
174 gtk_image_set_from_pixbuf (GTK_IMAGE (player->priv->image_display), scaled);
175 g_object_unref (scaled);
176
177 return TRUE;
178 }
179
180 static void
brasero_player_image_zoom_in(BraseroPlayer * player)181 brasero_player_image_zoom_in (BraseroPlayer *player)
182 {
183 player->priv->image_width += PLAYER_BACON_WIDTH / 3;
184 player->priv->image_height += PLAYER_BACON_HEIGHT / 3;
185
186 if (player->priv->image_width >= PLAYER_BACON_WIDTH * 3 ||
187 player->priv->image_height >= PLAYER_BACON_HEIGHT * 3) {
188 player->priv->image_width = PLAYER_BACON_WIDTH * 3;
189 player->priv->image_height = PLAYER_BACON_HEIGHT * 3;
190 }
191
192 if (player->priv->pixbuf)
193 brasero_player_scale_image (player);
194 }
195
196 static void
brasero_player_image_zoom_out(BraseroPlayer * player)197 brasero_player_image_zoom_out (BraseroPlayer *player)
198 {
199 gint min_height, min_width;
200
201 if (player->priv->pixbuf) {
202 min_width = MIN (PLAYER_BACON_WIDTH, gdk_pixbuf_get_width (player->priv->pixbuf));
203 min_height = MIN (PLAYER_BACON_HEIGHT, gdk_pixbuf_get_height (player->priv->pixbuf));
204 }
205 else {
206 min_width = PLAYER_BACON_WIDTH;
207 min_height = PLAYER_BACON_HEIGHT;
208 }
209
210 player->priv->image_width -= PLAYER_BACON_WIDTH / 3;
211 player->priv->image_height -= PLAYER_BACON_HEIGHT / 3;
212
213 /* the image itself */
214 if (player->priv->image_width <= min_width ||
215 player->priv->image_height <= min_height) {
216 player->priv->image_width = min_width;
217 player->priv->image_height = min_height;
218 }
219
220 if (player->priv->pixbuf)
221 brasero_player_scale_image (player);
222 }
223
224 static void
brasero_player_zoom_in_cb(GtkButton * button,BraseroPlayer * player)225 brasero_player_zoom_in_cb (GtkButton *button,
226 BraseroPlayer *player)
227 {
228 brasero_player_image_zoom_in (player);
229 brasero_player_video_zoom_in (player);
230 }
231
232 static void
brasero_player_zoom_out_cb(GtkButton * button,BraseroPlayer * player)233 brasero_player_zoom_out_cb (GtkButton *button,
234 BraseroPlayer *player)
235 {
236 brasero_player_image_zoom_out (player);
237 brasero_player_video_zoom_out (player);
238 }
239
240 static gboolean
brasero_bacon_scroll(BraseroPlayerBacon * bacon,GdkEventScroll * event,BraseroPlayer * player)241 brasero_bacon_scroll (BraseroPlayerBacon *bacon,
242 GdkEventScroll *event,
243 BraseroPlayer *player)
244 {
245 switch (gtk_notebook_get_current_page (GTK_NOTEBOOK (player->priv->notebook))) {
246 case 1:
247 case 4:
248 if (event->direction == GDK_SCROLL_UP)
249 brasero_player_bacon_forward (bacon, GST_SECOND);
250 else
251 brasero_player_bacon_backward (bacon, GST_SECOND);
252 break;
253
254 case 0:
255 case 2:
256 case 3:
257 default:
258 if (event->direction == GDK_SCROLL_UP) {
259 brasero_player_image_zoom_in (player);
260 brasero_player_video_zoom_in (player);
261 }
262 else {
263 brasero_player_image_zoom_out (player);
264 brasero_player_video_zoom_out (player);
265 }
266 break;
267 }
268
269 return TRUE;
270 }
271
272 static gboolean
brasero_bacon_button_release(BraseroPlayerBacon * bacon,GdkEventButton * event,BraseroPlayer * player)273 brasero_bacon_button_release (BraseroPlayerBacon *bacon,
274 GdkEventButton *event,
275 BraseroPlayer *player)
276 {
277 if (event->button != 1)
278 return FALSE;
279
280 if (player->priv->state == BACON_STATE_READY) {
281 /* This will probably never happen as we display a play button */
282 gtk_image_set_from_stock (GTK_IMAGE (player->priv->play_image), GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_DIALOG);
283 gtk_notebook_set_current_page (GTK_NOTEBOOK (player->priv->notebook), 1);
284 brasero_player_bacon_set_uri (BRASERO_PLAYER_BACON (player->priv->bacon), player->priv->uri);
285 brasero_player_bacon_play (BRASERO_PLAYER_BACON (player->priv->bacon));
286 }
287 else if (player->priv->state == BACON_STATE_PAUSED) {
288 gtk_image_set_from_stock (GTK_IMAGE (player->priv->play_image), GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_DIALOG);
289 gtk_notebook_set_current_page (GTK_NOTEBOOK (player->priv->notebook), 1);
290 brasero_player_bacon_play (BRASERO_PLAYER_BACON (player->priv->bacon));
291 }
292 else if (player->priv->state == BACON_STATE_PLAYING) {
293 gtk_image_set_from_stock (GTK_IMAGE (player->priv->play_image), GTK_STOCK_MEDIA_PAUSE, GTK_ICON_SIZE_DIALOG);
294 gtk_notebook_set_current_page (GTK_NOTEBOOK (player->priv->notebook), 4);
295 brasero_player_bacon_stop (BRASERO_PLAYER_BACON (player->priv->bacon));
296 }
297
298 return TRUE;
299 }
300
301 static gboolean
brasero_player_button_release(GtkWidget * widget,GdkEventButton * event,BraseroPlayer * player)302 brasero_player_button_release (GtkWidget *widget,
303 GdkEventButton *event,
304 BraseroPlayer *player)
305 {
306 if (event->button != 1)
307 return FALSE;
308
309 if (gtk_notebook_get_current_page (GTK_NOTEBOOK (player->priv->notebook)) == 4) {
310 if (player->priv->state == BACON_STATE_READY) {
311 gtk_image_set_from_stock (GTK_IMAGE (player->priv->play_image), GTK_STOCK_MEDIA_PAUSE, GTK_ICON_SIZE_DIALOG);
312 if (player->priv->is_video)
313 gtk_notebook_set_current_page (GTK_NOTEBOOK (player->priv->notebook), 1);
314
315 brasero_player_bacon_set_uri (BRASERO_PLAYER_BACON (player->priv->bacon), player->priv->uri);
316 brasero_player_bacon_play (BRASERO_PLAYER_BACON (player->priv->bacon));
317 }
318 else if (player->priv->state == BACON_STATE_PAUSED) {
319 gtk_image_set_from_stock (GTK_IMAGE (player->priv->play_image), GTK_STOCK_MEDIA_PAUSE, GTK_ICON_SIZE_DIALOG);
320 if (player->priv->is_video)
321 gtk_notebook_set_current_page (GTK_NOTEBOOK (player->priv->notebook), 1);
322
323 brasero_player_bacon_play (BRASERO_PLAYER_BACON (player->priv->bacon));
324 }
325 else if (player->priv->state == BACON_STATE_PLAYING) {
326 gtk_image_set_from_stock (GTK_IMAGE (player->priv->play_image), GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_DIALOG);
327 brasero_player_bacon_stop (BRASERO_PLAYER_BACON (player->priv->bacon));
328 }
329 }
330
331 return TRUE;
332 }
333
334 static gboolean
brasero_player_scroll(GtkWidget * widget,GdkEventScroll * event,BraseroPlayer * player)335 brasero_player_scroll (GtkWidget *widget,
336 GdkEventScroll *event,
337 BraseroPlayer *player)
338 {
339 switch (gtk_notebook_get_current_page (GTK_NOTEBOOK (player->priv->notebook))) {
340 case 1:
341 case 4:
342 if (event->direction == GDK_SCROLL_UP)
343 brasero_player_bacon_forward (BRASERO_PLAYER_BACON (player->priv->bacon), GST_SECOND);
344 else
345 brasero_player_bacon_backward (BRASERO_PLAYER_BACON (player->priv->bacon), GST_SECOND);
346 break;
347
348 case 0:
349 case 2:
350 case 3:
351 default:
352 if (event->direction == GDK_SCROLL_UP) {
353 brasero_player_image_zoom_in (player);
354 brasero_player_video_zoom_in (player);
355 }
356 else {
357 brasero_player_image_zoom_out (player);
358 brasero_player_video_zoom_out (player);
359 }
360 break;
361 }
362
363 return TRUE;
364 }
365
366 static void
brasero_player_image(BraseroPlayer * player)367 brasero_player_image (BraseroPlayer *player)
368 {
369 GError *error = NULL;
370 gchar *path;
371
372 if (player->priv->pixbuf) {
373 g_object_unref (player->priv->pixbuf);
374 player->priv->pixbuf = NULL;
375 }
376
377 /* image */
378 /* FIXME: this does not allow to preview remote files */
379 path = g_filename_from_uri (player->priv->uri, NULL, NULL);
380 player->priv->pixbuf = gdk_pixbuf_new_from_file (path, &error);
381
382 if (!player->priv->pixbuf) {
383 if (error) {
384 g_warning ("Couldn't load image %s\n", error->message);
385 g_error_free (error);
386 }
387
388 brasero_player_no_multimedia_stream (player);
389 g_free (path);
390 return;
391 }
392
393 brasero_player_scale_image (player);
394
395 gtk_widget_show (player->priv->notebook);
396 gtk_notebook_set_current_page (GTK_NOTEBOOK (player->priv->notebook), 0);
397 g_signal_emit (player,
398 brasero_player_signals [READY_SIGNAL],
399 0);
400 }
401
402 static void
brasero_player_update_tooltip(BraseroPlayer * player,GFileInfo * info)403 brasero_player_update_tooltip (BraseroPlayer *player,
404 GFileInfo *info)
405 {
406 gchar *string;
407 gchar *len_string;
408 const gchar *title;
409 const gchar *artist;
410
411 /* Update the tooltip */
412 len_string = brasero_units_get_time_string (g_file_info_get_attribute_uint64 (info, BRASERO_IO_LEN), TRUE, FALSE);
413 title = g_file_info_get_attribute_string (info, BRASERO_IO_TITLE);
414 artist = g_file_info_get_attribute_string (info, BRASERO_IO_ARTIST);
415 if (artist) {
416 gchar *artist_string;
417
418 /* Translators: %s is the name of the artist */
419 artist_string = g_strdup_printf (_("by %s"), artist);
420 string = g_markup_printf_escaped ("<span weight=\"bold\">%s</span>"
421 "\n<i><span size=\"smaller\">%s</span></i>"
422 "\n%s",
423 title,
424 artist_string,
425 len_string);
426 g_free (artist_string);
427 }
428 else if (title)
429 string = g_markup_printf_escaped ("<span weight=\"bold\">%s</span>"
430 "\n%s",
431 title,
432 len_string);
433 else {
434 gchar *name;
435 gchar *unescaped_uri;
436
437 unescaped_uri = g_uri_unescape_string (player->priv->uri, NULL);
438 name = g_path_get_basename (unescaped_uri);
439 g_free (unescaped_uri);
440 string = g_markup_printf_escaped ("<span weight=\"bold\">%s</span>"
441 "\n%s",
442 name,
443 len_string);
444 g_free (name);
445 }
446
447 g_free (len_string);
448
449 gtk_widget_set_tooltip_markup (GTK_WIDGET (player), string);
450 g_free (string);
451 }
452
453 static void
brasero_player_metadata_completed(GObject * obj,GError * error,const gchar * uri,GFileInfo * info,gpointer null_data)454 brasero_player_metadata_completed (GObject *obj,
455 GError *error,
456 const gchar *uri,
457 GFileInfo *info,
458 gpointer null_data)
459 {
460 BraseroPlayer *player = BRASERO_PLAYER (obj);
461 const gchar *mime;
462
463 gtk_spinner_stop (GTK_SPINNER (player->priv->spinner));
464
465 if (player->priv->pixbuf) {
466 gtk_image_set_from_pixbuf (GTK_IMAGE (player->priv->image_display), NULL);
467 g_object_unref (player->priv->pixbuf);
468 player->priv->pixbuf = NULL;
469 }
470
471 if (error) {
472 brasero_player_no_multimedia_stream (player);
473 g_signal_emit (player,
474 brasero_player_signals [ERROR_SIGNAL],
475 0);
476 return;
477 }
478
479 mime = g_file_info_get_content_type (info);
480
481 /* based on the mime type, we try to determine the type of file */
482 if (g_file_info_get_attribute_boolean (info, BRASERO_IO_HAS_VIDEO)) {
483 if (g_file_info_get_attribute_uint64 (info, BRASERO_IO_LEN) <= 0) {
484 brasero_player_no_multimedia_stream (player);
485 g_signal_emit (player,
486 brasero_player_signals [ERROR_SIGNAL],
487 0);
488 return;
489 }
490
491 /* video: display play button first */
492 player->priv->is_video = TRUE;
493 gtk_image_set_from_stock (GTK_IMAGE (player->priv->play_image), GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_DIALOG);
494 gtk_notebook_set_current_page (GTK_NOTEBOOK (player->priv->notebook), 4);
495
496 brasero_player_update_tooltip (player, info);
497 }
498 else if (g_file_info_get_attribute_boolean (info, BRASERO_IO_HAS_AUDIO)) {
499 if (g_file_info_get_attribute_uint64 (info, BRASERO_IO_LEN) <= 0) {
500 brasero_player_no_multimedia_stream (player);
501 g_signal_emit (player,
502 brasero_player_signals [ERROR_SIGNAL],
503 0);
504 return;
505 }
506
507 /* Audio */
508 player->priv->is_video = FALSE;
509 gtk_image_set_from_stock (GTK_IMAGE (player->priv->play_image), GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_DIALOG);
510 gtk_notebook_set_current_page (GTK_NOTEBOOK (player->priv->notebook), 4);
511
512 brasero_player_update_tooltip (player, info);
513 }
514 else if (mime && !strncmp ("image/", mime, 6)) {
515 gchar *size_string;
516 gchar *string;
517 gchar *path;
518 gchar *name;
519 gint height;
520 gint width;
521
522 /* Only do that if the image is < 20 M otherwise that's crap
523 * FIXME: maybe a sort of error message here? or use thumbnail? */
524 if (g_file_info_get_size (info) > 100000000LL) {
525 brasero_player_no_multimedia_stream (player);
526 g_signal_emit (player,
527 brasero_player_signals [ERROR_SIGNAL],
528 0);
529 return;
530 }
531
532 brasero_player_image (player);
533
534 path = g_filename_from_uri (player->priv->uri, NULL, NULL);
535 BRASERO_GET_BASENAME_FOR_DISPLAY (path, name);
536 g_free (path);
537
538 height = gdk_pixbuf_get_height (player->priv->pixbuf);
539 width = gdk_pixbuf_get_width (player->priv->pixbuf);
540 size_string = g_strdup_printf (_("%i \303\227 %i pixels"), width, height);
541
542 string = g_strdup_printf ("<span weight=\"bold\">%s</span>\n"
543 "<i><span size=\"smaller\">%s</span></i>",
544 name,
545 size_string);
546 g_free (name);
547 g_free (size_string);
548
549 gtk_widget_set_tooltip_markup (GTK_WIDGET (player), string);
550 g_free (string);
551 return;
552 }
553 else {
554 brasero_player_no_multimedia_stream (player);
555 g_signal_emit (player,
556 brasero_player_signals [ERROR_SIGNAL],
557 0);
558 return;
559 }
560
561 if (player->priv->end <= 0)
562 player->priv->end = g_file_info_get_attribute_uint64 (info, BRASERO_IO_LEN);
563
564 player->priv->length = g_file_info_get_attribute_uint64 (info, BRASERO_IO_LEN);
565
566 player->priv->state = BACON_STATE_READY;
567 g_signal_emit (player,
568 brasero_player_signals [READY_SIGNAL],
569 0);
570 }
571
572 static void
brasero_player_retrieve_metadata(BraseroPlayer * player)573 brasero_player_retrieve_metadata (BraseroPlayer *player)
574 {
575 if (!player->priv->meta_task)
576 player->priv->meta_task = brasero_io_register (G_OBJECT (player),
577 brasero_player_metadata_completed,
578 NULL,
579 NULL);
580
581 brasero_io_get_file_info (player->priv->uri,
582 player->priv->meta_task,
583 BRASERO_IO_INFO_METADATA|
584 BRASERO_IO_INFO_MIME,
585 NULL);
586 }
587
588 void
brasero_player_set_boundaries(BraseroPlayer * player,gint64 start,gint64 end)589 brasero_player_set_boundaries (BraseroPlayer *player,
590 gint64 start,
591 gint64 end)
592 {
593 if (start <= 0)
594 player->priv->start = 0;
595 else
596 player->priv->start = start;
597
598 if (end <= 0)
599 player->priv->end = player->priv->length;
600 else
601 player->priv->end = end;
602
603 if (player->priv->bacon)
604 brasero_player_bacon_set_boundaries (BRASERO_PLAYER_BACON (player->priv->bacon),
605 player->priv->start,
606 player->priv->end);
607 }
608
609 void
brasero_player_set_uri(BraseroPlayer * player,const gchar * uri)610 brasero_player_set_uri (BraseroPlayer *player,
611 const gchar *uri)
612 {
613 /* avoid reloading everything if it's the same uri */
614 if (!g_strcmp0 (uri, player->priv->uri)) {
615 /* if it's not loaded yet just return */
616 /* the existence of progress is the surest way to know
617 * if that uri was successfully loaded */
618 if (uri)
619 g_signal_emit (player,
620 brasero_player_signals [READY_SIGNAL],
621 0);
622 else
623 g_signal_emit (player,
624 brasero_player_signals [ERROR_SIGNAL],
625 0);
626 return;
627 }
628
629 if (player->priv->uri)
630 g_free (player->priv->uri);
631
632 player->priv->uri = g_strdup (uri);
633 player->priv->length = 0;
634 player->priv->start = 0;
635 player->priv->end = 0;
636
637 if (player->priv->meta_task)
638 brasero_io_cancel_by_base (player->priv->meta_task);
639
640 /* That stops the pipeline from playing */
641 brasero_player_bacon_set_uri (BRASERO_PLAYER_BACON (player->priv->bacon), NULL);
642 if (!uri) {
643 brasero_player_no_multimedia_stream (player);
644 return;
645 }
646
647 gtk_widget_set_has_tooltip (GTK_WIDGET (player), FALSE);
648 gtk_notebook_set_current_page (GTK_NOTEBOOK (player->priv->notebook), 3);
649 gtk_spinner_start (GTK_SPINNER (player->priv->spinner));
650
651 brasero_player_retrieve_metadata (player);
652 }
653
654 static void
brasero_player_eof_cb(BraseroPlayerBacon * bacon,BraseroPlayer * player)655 brasero_player_eof_cb (BraseroPlayerBacon *bacon, BraseroPlayer *player)
656 {
657 brasero_player_bacon_stop (BRASERO_PLAYER_BACON (player->priv->bacon));
658 brasero_player_bacon_set_pos (BRASERO_PLAYER_BACON (player->priv->bacon), player->priv->start);
659 player->priv->state = BACON_STATE_PAUSED;
660 gtk_image_set_from_stock (GTK_IMAGE (player->priv->play_image), GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_DIALOG);
661 }
662
663 static void
brasero_player_state_changed_cb(BraseroPlayerBacon * bacon,BraseroPlayerBaconState state,BraseroPlayer * player)664 brasero_player_state_changed_cb (BraseroPlayerBacon *bacon,
665 BraseroPlayerBaconState state,
666 BraseroPlayer *player)
667 {
668 if (player->priv->state == state)
669 return;
670
671 switch (state) {
672 case BACON_STATE_ERROR:
673 brasero_player_no_multimedia_stream (player);
674 break;
675
676 default:
677 break;
678 }
679
680 player->priv->state = state;
681 }
682
683 static void
brasero_player_destroy(GtkWidget * obj)684 brasero_player_destroy (GtkWidget *obj)
685 {
686 BraseroPlayer *player;
687
688 player = BRASERO_PLAYER (obj);
689
690 brasero_setting_set_value (brasero_setting_get_default (),
691 BRASERO_SETTING_IMAGE_SIZE_WIDTH,
692 GINT_TO_POINTER (player->priv->image_width));
693 brasero_setting_set_value (brasero_setting_get_default (),
694 BRASERO_SETTING_IMAGE_SIZE_HEIGHT,
695 GINT_TO_POINTER (player->priv->image_height));
696 brasero_setting_set_value (brasero_setting_get_default (),
697 BRASERO_SETTING_VIDEO_SIZE_WIDTH,
698 GINT_TO_POINTER (player->priv->video_width));
699 brasero_setting_set_value (brasero_setting_get_default (),
700 BRASERO_SETTING_VIDEO_SIZE_HEIGHT,
701 GINT_TO_POINTER (player->priv->video_height));
702
703 if (player->priv->pixbuf) {
704 g_object_unref (player->priv->pixbuf);
705 player->priv->pixbuf = NULL;
706 }
707
708 if (player->priv->uri) {
709 g_free (player->priv->uri);
710 player->priv->uri = NULL;
711 }
712
713 if (player->priv->meta_task){
714 brasero_io_cancel_by_base (player->priv->meta_task);
715 brasero_io_job_base_free (player->priv->meta_task);
716 player->priv->meta_task = 0;
717 }
718
719 if (GTK_WIDGET_CLASS (parent_class)->destroy)
720 GTK_WIDGET_CLASS (parent_class)->destroy (obj);
721 }
722
723 static void
brasero_player_finalize(GObject * object)724 brasero_player_finalize (GObject *object)
725 {
726 BraseroPlayer *cobj;
727
728 cobj = BRASERO_PLAYER (object);
729
730 g_free (cobj->priv);
731 G_OBJECT_CLASS (parent_class)->finalize (object);
732 }
733
734 static void
brasero_player_class_init(BraseroPlayerClass * klass)735 brasero_player_class_init (BraseroPlayerClass *klass)
736 {
737 GObjectClass *object_class = G_OBJECT_CLASS (klass);
738 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
739
740 parent_class = g_type_class_peek_parent (klass);
741 object_class->finalize = brasero_player_finalize;
742
743 widget_class->destroy = brasero_player_destroy;
744
745 brasero_player_signals [ERROR_SIGNAL] =
746 g_signal_new ("error",
747 G_TYPE_FROM_CLASS (klass),
748 G_SIGNAL_RUN_LAST,
749 G_STRUCT_OFFSET (BraseroPlayerClass, error),
750 NULL, NULL,
751 g_cclosure_marshal_VOID__VOID,
752 G_TYPE_NONE, 0);
753 brasero_player_signals [READY_SIGNAL] =
754 g_signal_new ("ready",
755 G_TYPE_FROM_CLASS (klass),
756 G_SIGNAL_RUN_LAST,
757 G_STRUCT_OFFSET (BraseroPlayerClass, ready),
758 NULL, NULL,
759 g_cclosure_marshal_VOID__VOID,
760 G_TYPE_NONE, 0);
761 }
762
763 static void
brasero_player_volume_changed_cb(GtkScaleButton * button,gdouble volume,BraseroPlayer * player)764 brasero_player_volume_changed_cb (GtkScaleButton *button,
765 gdouble volume,
766 BraseroPlayer *player)
767 {
768 brasero_player_bacon_set_volume (BRASERO_PLAYER_BACON (player->priv->bacon), volume);
769 }
770
771 static void
brasero_player_init(BraseroPlayer * obj)772 brasero_player_init (BraseroPlayer *obj)
773 {
774 GtkWidget *volume;
775 GtkWidget *image;
776 GtkWidget *label;
777 GtkWidget *event;
778 GtkWidget *zoom;
779 GtkWidget *hbox;
780 GtkWidget *vbox;
781 gpointer value;
782 gchar *string;
783
784 obj->priv = g_new0 (BraseroPlayerPrivate, 1);
785
786 gtk_alignment_set (GTK_ALIGNMENT (obj), 0.5, 0.5, 0.0, 0.0);
787
788 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
789 gtk_widget_show (vbox);
790 gtk_container_add (GTK_CONTAINER (obj), vbox);
791
792 /* The notebook and all views */
793 event = gtk_event_box_new ();
794 gtk_box_pack_start (GTK_BOX (vbox), event, FALSE, FALSE, 0);
795 gtk_event_box_set_above_child (GTK_EVENT_BOX (event), TRUE);
796 gtk_event_box_set_visible_window (GTK_EVENT_BOX (event), FALSE);
797 g_signal_connect (event,
798 "button-release-event",
799 G_CALLBACK (brasero_player_button_release),
800 obj);
801 g_signal_connect (event,
802 "scroll-event",
803 G_CALLBACK (brasero_player_scroll),
804 obj);
805 gtk_widget_show (event);
806
807 obj->priv->notebook = gtk_notebook_new ();
808 gtk_widget_show (obj->priv->notebook);
809 gtk_container_add (GTK_CONTAINER (event), obj->priv->notebook);
810 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (obj->priv->notebook), FALSE);
811
812 /* Images */
813 obj->priv->image_display = gtk_image_new ();
814 gtk_widget_show (obj->priv->image_display);
815 gtk_misc_set_alignment (GTK_MISC (obj->priv->image_display), 0.5, 0.5);
816 gtk_notebook_append_page (GTK_NOTEBOOK (obj->priv->notebook),
817 obj->priv->image_display,
818 NULL);
819
820 /* Video */
821 obj->priv->bacon = brasero_player_bacon_new ();
822 gtk_widget_show (obj->priv->bacon);
823 g_signal_connect (obj->priv->bacon,
824 "button-release-event",
825 G_CALLBACK (brasero_bacon_button_release),
826 obj);
827 g_signal_connect (obj->priv->bacon,
828 "scroll-event",
829 G_CALLBACK (brasero_bacon_scroll),
830 obj);
831 g_signal_connect (obj->priv->bacon,
832 "state-change",
833 G_CALLBACK (brasero_player_state_changed_cb),
834 obj);
835 g_signal_connect (obj->priv->bacon,
836 "eof",
837 G_CALLBACK (brasero_player_eof_cb),
838 obj);
839
840 gtk_notebook_append_page (GTK_NOTEBOOK (obj->priv->notebook),
841 obj->priv->bacon,
842 NULL);
843
844 /* No Preview view */
845 string = g_strdup_printf ("<span color='grey'><big><b>%s</b></big></span>", _("No preview"));
846 label = gtk_label_new (string);
847 g_free (string);
848
849 gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
850 gtk_widget_show (label);
851 gtk_notebook_append_page (GTK_NOTEBOOK (obj->priv->notebook),
852 label,
853 NULL);
854 gtk_notebook_set_current_page (GTK_NOTEBOOK (obj->priv->notebook), 2);
855
856 /* Loading view */
857 obj->priv->spinner = gtk_spinner_new ();
858 gtk_widget_show (obj->priv->spinner);
859 gtk_notebook_append_page (GTK_NOTEBOOK (obj->priv->notebook),
860 obj->priv->spinner,
861 NULL);
862
863 /* Music */
864 image = gtk_image_new_from_stock (GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_DIALOG);
865 gtk_widget_show (image);
866 gtk_notebook_append_page (GTK_NOTEBOOK (obj->priv->notebook),
867 image,
868 NULL);
869 obj->priv->play_image = image;
870
871 /* Set the saved sizes */
872 brasero_setting_get_value (brasero_setting_get_default (),
873 BRASERO_SETTING_IMAGE_SIZE_WIDTH,
874 &value);
875 obj->priv->image_width = GPOINTER_TO_INT (value);
876
877 if (obj->priv->image_width > PLAYER_BACON_WIDTH * 3
878 || obj->priv->image_width < PLAYER_BACON_WIDTH)
879 obj->priv->image_width = PLAYER_BACON_WIDTH;
880
881 brasero_setting_get_value (brasero_setting_get_default (),
882 BRASERO_SETTING_IMAGE_SIZE_HEIGHT,
883 &value);
884 obj->priv->image_height = GPOINTER_TO_INT (value);
885
886 if (obj->priv->image_height > PLAYER_BACON_HEIGHT * 3
887 || obj->priv->image_height < PLAYER_BACON_HEIGHT)
888 obj->priv->image_height = PLAYER_BACON_HEIGHT;
889
890 brasero_setting_get_value (brasero_setting_get_default (),
891 BRASERO_SETTING_VIDEO_SIZE_WIDTH,
892 &value);
893 obj->priv->video_width = GPOINTER_TO_INT (value);
894
895 if (obj->priv->video_width > PLAYER_BACON_WIDTH * 3
896 || obj->priv->video_width < PLAYER_BACON_WIDTH)
897 obj->priv->video_width = PLAYER_BACON_WIDTH;
898
899 brasero_setting_get_value (brasero_setting_get_default (),
900 BRASERO_SETTING_VIDEO_SIZE_HEIGHT,
901 &value);
902 obj->priv->video_height = GPOINTER_TO_INT (value);
903
904 if (obj->priv->video_height > PLAYER_BACON_HEIGHT * 3
905 || obj->priv->video_height < PLAYER_BACON_HEIGHT)
906 obj->priv->video_height = PLAYER_BACON_HEIGHT;
907
908 gtk_widget_set_size_request (obj->priv->bacon,
909 obj->priv->video_width,
910 obj->priv->video_height);
911
912 /* A few controls */
913 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
914 gtk_widget_show (hbox);
915 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
916
917 image = gtk_image_new_from_stock (GTK_STOCK_ZOOM_OUT, GTK_ICON_SIZE_BUTTON);
918 zoom = gtk_button_new ();
919 gtk_widget_show (zoom);
920 gtk_widget_show (image);
921 gtk_button_set_image (GTK_BUTTON (zoom), image);
922 gtk_button_set_relief (GTK_BUTTON (zoom), GTK_RELIEF_NONE);
923 gtk_button_set_focus_on_click (GTK_BUTTON (zoom), FALSE);
924 g_signal_connect (zoom,
925 "clicked",
926 G_CALLBACK (brasero_player_zoom_out_cb),
927 obj);
928 gtk_box_pack_start (GTK_BOX (hbox),
929 zoom,
930 FALSE,
931 FALSE,
932 0);
933 obj->priv->zoom_out = zoom;
934
935 image = gtk_image_new_from_stock (GTK_STOCK_ZOOM_IN, GTK_ICON_SIZE_BUTTON);
936 zoom = gtk_button_new ();
937 gtk_widget_show (zoom);
938 gtk_widget_show (image);
939 gtk_button_set_image (GTK_BUTTON (zoom), image);
940 gtk_button_set_relief (GTK_BUTTON (zoom), GTK_RELIEF_NONE);
941 gtk_button_set_focus_on_click (GTK_BUTTON (zoom), FALSE);
942 g_signal_connect (zoom,
943 "clicked",
944 G_CALLBACK (brasero_player_zoom_in_cb),
945 obj);
946 gtk_box_pack_start (GTK_BOX (hbox),
947 zoom,
948 FALSE,
949 FALSE,
950 0);
951 obj->priv->zoom_in = zoom;
952
953 volume = gtk_volume_button_new ();
954 gtk_widget_show (volume);
955 gtk_box_pack_end (GTK_BOX (hbox),
956 volume,
957 FALSE,
958 FALSE,
959 0);
960
961 gtk_scale_button_set_value (GTK_SCALE_BUTTON (volume),
962 brasero_player_bacon_get_volume (BRASERO_PLAYER_BACON (obj->priv->bacon)));
963
964 g_signal_connect (volume,
965 "value-changed",
966 G_CALLBACK (brasero_player_volume_changed_cb),
967 obj);
968 }
969
970 GtkWidget *
brasero_player_new()971 brasero_player_new ()
972 {
973 BraseroPlayer *obj;
974
975 obj = BRASERO_PLAYER (g_object_new (BRASERO_TYPE_PLAYER, NULL));
976
977 return GTK_WIDGET (obj);
978
979 }
980