2
## 10_vcd_hang.dpatch by Sebastien Bacher <seb128@debian.org>
4
## All lines beginning with `## DP:' are a description of the patch.
8
echo "`basename $0`: script expects -patch|-unpatch as argument" >&2
12
[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
13
patch_opts="${patch_opts:--f --no-backup-if-mismatch} ${2:+-d $2}"
16
-patch) patch -p1 ${patch_opts} < $0;;
17
-unpatch) patch -R -p1 ${patch_opts} < $0;;
19
echo "`basename $0`: script expects -patch|-unpatch as argument" >&2
26
diff -urNad /tmp/a/totem-0.99.12/src/bacon-video-widget-xine.c totem-0.99.12/src/bacon-video-widget-xine.c
27
--- /tmp/a/totem-0.99.12/src/bacon-video-widget-xine.c 2004-06-01 14:28:46.000000000 +0200
28
+++ totem-0.99.12/src/bacon-video-widget-xine.c 2004-06-08 12:22:27.000000000 +0200
29
@@ -2439,12 +2439,6 @@
30
entry.str_value = g_strdup (path);
31
xine_config_update_entry (bvw->priv->xine, &entry);
33
- /* VCD device for the new input plugin */
34
- bvw_config_helper_string (bvw->priv->xine, "vcd.default_device",
36
- entry.str_value = g_strdup (path);
37
- xine_config_update_entry (bvw->priv->xine, &entry);
40
bvw_config_helper_string (bvw->priv->xine, "input.cdda_device",
42
diff -urNad /tmp/a/totem-0.99.12/src/bacon-video-widget-xine.c.orig totem-0.99.12/src/bacon-video-widget-xine.c.orig
43
--- /tmp/a/totem-0.99.12/src/bacon-video-widget-xine.c.orig 1970-01-01 01:00:00.000000000 +0100
44
+++ totem-0.99.12/src/bacon-video-widget-xine.c.orig 2004-06-01 14:28:46.000000000 +0200
47
+ * Copyright (C) 2001-2002 the xine project
48
+ * Heavily modified by Bastien Nocera <hadess@hadess.net>
50
+ * This program is free software; you can redistribute it and/or modify
51
+ * it under the terms of the GNU General Public License as published by
52
+ * the Free Software Foundation; either version 2 of the License, or
53
+ * (at your option) any later version.
55
+ * This program is distributed in the hope that it will be useful,
56
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
57
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
58
+ * GNU General Public License for more details.
60
+ * You should have received a copy of the GNU General Public License
61
+ * along with this program; if not, write to the Free Software
62
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
64
+ * $Id: bacon-video-widget-xine.c,v 1.118 2004/05/30 12:21:10 hadess Exp $
66
+ * the xine engine in a widget - implementation
72
+#include <nvtv_simple.h>
83
+#include <X11/Xlib.h>
85
+#include <gdk/gdkx.h>
87
+#include <gconf/gconf-client.h>
92
+#include "bacon-video-widget.h"
93
+#include "baconvideowidget-marshal.h"
94
+#include "scrsaver.h"
95
+#include "video-utils.h"
96
+#include "bacon-resize.h"
99
+#define _(String) gettext (String)
101
+# define N_(String) gettext_noop (String)
103
+# define N_(String) (String)
106
+#define DEFAULT_HEIGHT 315
107
+#define DEFAULT_WIDTH 420
108
+#define CONFIG_FILE ".gnome2"G_DIR_SEPARATOR_S"totem_config"
123
+/* Enum for none-signal stuff that needs to go through the AsyncQueue */
126
+ TITLE_CHANGE_ASYNC,
128
+ CHANNELS_CHANGE_ASYNC,
131
+ SPEED_WARNING_ASYNC
147
+ PROP_STREAM_LENGTH,
155
+static int video_props[4] = {
156
+ XINE_PARAM_VO_BRIGHTNESS,
157
+ XINE_PARAM_VO_CONTRAST,
158
+ XINE_PARAM_VO_SATURATION,
161
+static char *video_props_str[4] = {
162
+ GCONF_PREFIX"/brightness",
163
+ GCONF_PREFIX"/contrast",
164
+ GCONF_PREFIX"/saturation",
168
+struct BaconVideoWidgetPrivate {
171
+ xine_stream_t *stream;
172
+ xine_video_port_t *vo_driver;
173
+ xine_audio_port_t *ao_driver;
174
+ xine_event_queue_t *ev_queue;
175
+ double display_ratio;
178
+ /* Configuration */
186
+ GdkWindow *video_window;
188
+ /* Visual effects */
191
+ gboolean using_vfx;
196
+ /* Seeking stuff */
199
+ gint64 seek_dest_time;
203
+ gboolean can_dvd, can_vcd, can_cdda;
204
+ gboolean logo_mode;
206
+ gboolean have_xrandr;
207
+ gboolean auto_resize;
210
+ guint32 video_fcc, audio_fcc;
213
+ GAsyncQueue *queue;
214
+ int video_width, video_height;
215
+ int init_width, init_height;
217
+ /* fullscreen stuff */
218
+ gboolean fullscreen_mode;
219
+ gboolean cursor_shown;
223
+static const char *mms_bandwidth_strs[] = {
224
+ "14.4 Kbps (Modem)",
225
+ "19.2 Kbps (Modem)",
226
+ "28.8 Kbps (Modem)",
227
+ "33.6 Kbps (Modem)",
228
+ "34.4 Kbps (Modem)",
229
+ "57.6 Kbps (Modem)",
230
+ "115.2 Kbps (ISDN)",
231
+ "262.2 Kbps (Cable/DSL)",
232
+ "393.2 Kbps (Cable/DSL)",
233
+ "524.3 Kbps (Cable/DSL)",
239
+static const char *audio_out_types_strs[] = {
256
+static const char *demux_strategies_str[] = {
264
+static void bacon_video_widget_class_init (BaconVideoWidgetClass *klass);
265
+static void bacon_video_widget_instance_init (BaconVideoWidget *bvw);
267
+static void setup_config (BaconVideoWidget *bvw);
269
+static void bacon_video_widget_set_property (GObject *object,
270
+ guint property_id, const GValue *value, GParamSpec *pspec);
271
+static void bacon_video_widget_get_property (GObject *object,
272
+ guint property_id, GValue *value, GParamSpec *pspec);
274
+static void bacon_video_widget_realize (GtkWidget *widget);
275
+static void bacon_video_widget_unrealize (GtkWidget *widget);
276
+static void bacon_video_widget_finalize (GObject *object);
278
+static gboolean bacon_video_widget_expose (GtkWidget *widget,
279
+ GdkEventExpose *event);
280
+static gboolean bacon_video_widget_motion_notify (GtkWidget *widget,
281
+ GdkEventMotion *event);
282
+static gboolean bacon_video_widget_button_press (GtkWidget *widget,
283
+ GdkEventButton *event);
285
+static void bacon_video_widget_size_request (GtkWidget *widget,
286
+ GtkRequisition *requisition);
287
+static void bacon_video_widget_size_allocate (GtkWidget *widget,
288
+ GtkAllocation *allocation);
289
+static xine_video_port_t * load_video_out_driver (BaconVideoWidget *bvw,
290
+ gboolean null_out);
291
+static xine_audio_port_t * load_audio_out_driver (BaconVideoWidget *bvw,
293
+static gboolean bacon_video_widget_tick_send (BaconVideoWidget *bvw);
295
+static GtkWidgetClass *parent_class = NULL;
297
+static void xine_event (void *user_data, const xine_event_t *event);
298
+static gboolean bacon_video_widget_idle_signal (BaconVideoWidget *bvw);
299
+static void show_vfx_update (BaconVideoWidget *bvw, gboolean show_visuals);
301
+static int bvw_table_signals[LAST_SIGNAL] = { 0 };
304
+bacon_video_widget_get_type (void)
306
+ static GType bacon_video_widget_type = 0;
308
+ if (!bacon_video_widget_type) {
309
+ static const GTypeInfo bacon_video_widget_info = {
310
+ sizeof (BaconVideoWidgetClass),
311
+ (GBaseInitFunc) NULL,
312
+ (GBaseFinalizeFunc) NULL,
313
+ (GClassInitFunc) bacon_video_widget_class_init,
314
+ (GClassFinalizeFunc) NULL,
315
+ NULL /* class_data */,
316
+ sizeof (BaconVideoWidget),
317
+ 0 /* n_preallocs */,
318
+ (GInstanceInitFunc) bacon_video_widget_instance_init,
321
+ bacon_video_widget_type = g_type_register_static
322
+ (GTK_TYPE_BOX, "BaconVideoWidget",
323
+ &bacon_video_widget_info, (GTypeFlags)0);
326
+ return bacon_video_widget_type;
330
+bacon_video_widget_class_init (BaconVideoWidgetClass *klass)
333
+ GObjectClass *object_class;
334
+ GtkWidgetClass *widget_class;
336
+ object_class = (GObjectClass *) klass;
337
+ widget_class = (GtkWidgetClass *) klass;
339
+ parent_class = gtk_type_class (gtk_box_get_type ());
342
+ widget_class->realize = bacon_video_widget_realize;
343
+ widget_class->unrealize = bacon_video_widget_unrealize;
344
+ widget_class->size_request = bacon_video_widget_size_request;
345
+ widget_class->size_allocate = bacon_video_widget_size_allocate;
346
+ widget_class->expose_event = bacon_video_widget_expose;
347
+ widget_class->motion_notify_event = bacon_video_widget_motion_notify;
348
+ widget_class->button_press_event = bacon_video_widget_button_press;
351
+ object_class->set_property = bacon_video_widget_set_property;
352
+ object_class->get_property = bacon_video_widget_get_property;
353
+ object_class->finalize = bacon_video_widget_finalize;
356
+ g_object_class_install_property (object_class, PROP_LOGO_MODE,
357
+ g_param_spec_boolean ("logo_mode", NULL, NULL,
358
+ FALSE, G_PARAM_READWRITE));
359
+ g_object_class_install_property (object_class, PROP_POSITION,
360
+ g_param_spec_int64 ("position", NULL, NULL,
361
+ 0, G_MAXINT64, 0, G_PARAM_READABLE));
362
+ g_object_class_install_property (object_class, PROP_STREAM_LENGTH,
363
+ g_param_spec_int64 ("stream_length", NULL, NULL,
364
+ 0, G_MAXINT64, 0, G_PARAM_READABLE));
365
+ g_object_class_install_property (object_class, PROP_PLAYING,
366
+ g_param_spec_boolean ("playing", NULL, NULL,
367
+ FALSE, G_PARAM_READABLE));
368
+ g_object_class_install_property (object_class, PROP_SEEKABLE,
369
+ g_param_spec_boolean ("seekable", NULL, NULL,
370
+ FALSE, G_PARAM_READABLE));
371
+ g_object_class_install_property (object_class, PROP_SHOWCURSOR,
372
+ g_param_spec_boolean ("showcursor", NULL, NULL,
373
+ FALSE, G_PARAM_READWRITE));
374
+ g_object_class_install_property (object_class, PROP_MEDIADEV,
375
+ g_param_spec_string ("mediadev", NULL, NULL,
376
+ FALSE, G_PARAM_WRITABLE));
377
+ g_object_class_install_property (object_class, PROP_SHOW_VISUALS,
378
+ g_param_spec_boolean ("showvisuals", NULL, NULL,
379
+ FALSE, G_PARAM_WRITABLE));
382
+ bvw_table_signals[ERROR] =
383
+ g_signal_new ("error",
384
+ G_TYPE_FROM_CLASS (object_class),
386
+ G_STRUCT_OFFSET (BaconVideoWidgetClass, error),
388
+ baconvideowidget_marshal_VOID__STRING_BOOLEAN,
389
+ G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
391
+ bvw_table_signals[EOS] =
392
+ g_signal_new ("eos",
393
+ G_TYPE_FROM_CLASS (object_class),
395
+ G_STRUCT_OFFSET (BaconVideoWidgetClass, eos),
397
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
399
+ bvw_table_signals[GOT_METADATA] =
400
+ g_signal_new ("got-metadata",
401
+ G_TYPE_FROM_CLASS (object_class),
403
+ G_STRUCT_OFFSET (BaconVideoWidgetClass, got_metadata),
405
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
407
+ bvw_table_signals[TITLE_CHANGE] =
408
+ g_signal_new ("title-change",
409
+ G_TYPE_FROM_CLASS (object_class),
411
+ G_STRUCT_OFFSET (BaconVideoWidgetClass, title_change),
413
+ g_cclosure_marshal_VOID__STRING,
414
+ G_TYPE_NONE, 1, G_TYPE_STRING);
416
+ bvw_table_signals[CHANNELS_CHANGE] =
417
+ g_signal_new ("channels-change",
418
+ G_TYPE_FROM_CLASS (object_class),
420
+ G_STRUCT_OFFSET (BaconVideoWidgetClass, channels_change),
422
+ g_cclosure_marshal_VOID__VOID,
425
+ bvw_table_signals[TICK] =
426
+ g_signal_new ("tick",
427
+ G_TYPE_FROM_CLASS (object_class),
429
+ G_STRUCT_OFFSET (BaconVideoWidgetClass, tick),
431
+ baconvideowidget_marshal_VOID__INT64_INT64_FLOAT_BOOLEAN,
432
+ G_TYPE_NONE, 4, G_TYPE_INT64, G_TYPE_INT64,
433
+ G_TYPE_FLOAT, G_TYPE_BOOLEAN);
435
+ bvw_table_signals[BUFFERING] =
436
+ g_signal_new ("buffering",
437
+ G_TYPE_FROM_CLASS (object_class),
439
+ G_STRUCT_OFFSET (BaconVideoWidgetClass, buffering),
441
+ g_cclosure_marshal_VOID__INT,
442
+ G_TYPE_NONE, 1, G_TYPE_INT);
444
+ bvw_table_signals[SPEED_WARNING] =
445
+ g_signal_new ("speed-warning",
446
+ G_TYPE_FROM_CLASS (object_class),
448
+ G_STRUCT_OFFSET (BaconVideoWidgetClass, speed_warning),
450
+ g_cclosure_marshal_VOID__VOID,
455
+bacon_video_widget_instance_init (BaconVideoWidget *bvw)
457
+ const char *const *autoplug_list;
460
+ g_return_if_fail (bvw != NULL);
461
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
463
+ GTK_WIDGET_SET_FLAGS (GTK_WIDGET (bvw), GTK_CAN_FOCUS);
464
+ /* We work around white artifacts by using a double-buffered widget */
465
+ /* FIXME, this work-around breaks exposes */
466
+ GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (bvw), GTK_DOUBLE_BUFFERED);
468
+ bvw->priv = g_new0 (BaconVideoWidgetPrivate, 1);
469
+ bvw->priv->xine = xine_new ();
470
+ bvw->priv->cursor_shown = TRUE;
471
+ bvw->priv->vis_name = g_strdup ("goom");
473
+ bvw->priv->init_width = 0;
474
+ bvw->priv->init_height = 0;
476
+ bvw->priv->queue = g_async_queue_new ();
478
+ /* init configuration */
479
+ bvw->priv->gc = gconf_client_get_default ();
480
+ setup_config (bvw);
482
+ xine_init (bvw->priv->xine);
484
+ /* Debug configuration */
485
+ if (gconf_client_get_bool (bvw->priv->gc, GCONF_PREFIX"/debug", NULL) == FALSE)
487
+ xine_engine_set_param (bvw->priv->xine,
488
+ XINE_ENGINE_PARAM_VERBOSITY,
489
+ XINE_VERBOSITY_NONE);
491
+ xine_engine_set_param (bvw->priv->xine,
492
+ XINE_ENGINE_PARAM_VERBOSITY,
493
+ XINE_VERBOSITY_DEBUG);
496
+ /* Can we play DVDs and VCDs ? */
497
+ autoplug_list = xine_get_autoplay_input_plugin_ids (bvw->priv->xine);
498
+ while (autoplug_list && autoplug_list[i])
500
+ if (g_ascii_strcasecmp (autoplug_list[i], "VCD") == 0)
501
+ bvw->priv->can_vcd = TRUE;
502
+ else if (g_ascii_strcasecmp (autoplug_list[i], "VCDO") == 0)
503
+ bvw->priv->can_vcd = TRUE;
504
+ else if (g_ascii_strcasecmp (autoplug_list[i], "DVD") == 0)
505
+ bvw->priv->can_dvd = TRUE;
506
+ else if (g_ascii_strcasecmp (autoplug_list[i], "CD") == 0)
507
+ bvw->priv->can_cdda = TRUE;
511
+ bvw->priv->tick_id = g_timeout_add (140,
512
+ (GSourceFunc) bacon_video_widget_tick_send, bvw);
516
+bacon_video_widget_finalize (GObject *object)
518
+ BaconVideoWidget *bvw = (BaconVideoWidget *) object;
520
+ if (bvw->priv->xine != NULL) {
521
+ xine_exit (bvw->priv->xine);
523
+ g_free (bvw->priv->vis_name);
524
+ g_object_unref (G_OBJECT (bvw->priv->gc));
526
+ g_list_foreach (bvw->priv->visuals, (GFunc) g_free, NULL);
527
+ g_list_free (bvw->priv->visuals);
529
+ g_idle_remove_by_data (bvw);
530
+ g_async_queue_unref (bvw->priv->queue);
531
+ G_OBJECT_CLASS (parent_class)->finalize (object);
538
+dest_size_cb (void *data,
539
+ int video_width, int video_height,
540
+ double video_pixel_aspect,
541
+ int *dest_width, int *dest_height,
542
+ double *dest_pixel_aspect)
544
+ BaconVideoWidget *bvw = (BaconVideoWidget *)data;
546
+ /* correct size with video_pixel_aspect */
547
+ if (video_pixel_aspect >= bvw->priv->display_ratio)
548
+ video_width = video_width * video_pixel_aspect
549
+ / bvw->priv->display_ratio + .5;
551
+ video_height = video_height * bvw->priv->display_ratio
552
+ / video_pixel_aspect + .5;
554
+ *dest_width = GTK_WIDGET(bvw)->allocation.width;
555
+ *dest_height = GTK_WIDGET(bvw)->allocation.height;
556
+ *dest_pixel_aspect = bvw->priv->display_ratio;
560
+frame_output_cb (void *bvw_gen,
561
+ int video_width, int video_height,
562
+ double video_pixel_aspect,
563
+ int *dest_x, int *dest_y,
564
+ int *dest_width, int *dest_height,
565
+ double *dest_pixel_aspect,
566
+ int *win_x, int *win_y)
568
+ BaconVideoWidget *bvw = (BaconVideoWidget *) bvw_gen;
570
+ if (bvw == NULL || bvw->priv == NULL)
573
+ /* correct size with video_pixel_aspect */
574
+ if (video_pixel_aspect >= bvw->priv->display_ratio)
576
+ video_width = video_width * video_pixel_aspect
577
+ / bvw->priv->display_ratio + .5;
579
+ video_height = video_height * bvw->priv->display_ratio
580
+ / video_pixel_aspect + .5;
585
+ *win_x = bvw->priv->xpos;
586
+ *win_y = bvw->priv->ypos;
588
+ *dest_width = GTK_WIDGET(bvw)->allocation.width;
589
+ *dest_height = GTK_WIDGET(bvw)->allocation.height;
592
+ if (bvw->priv->video_width != video_width
593
+ || bvw->priv->video_height != video_height)
595
+ bvw->priv->video_width = video_width;
596
+ bvw->priv->video_height = video_height;
598
+ if (bvw->priv->auto_resize != FALSE
599
+ && bvw->priv->logo_mode == FALSE
600
+ && bvw->priv->fullscreen_mode == FALSE)
604
+ data = g_new0 (signal_data, 1);
605
+ data->signal = RATIO;
606
+ g_async_queue_push (bvw->priv->queue, data);
607
+ g_idle_add ((GSourceFunc)
608
+ bacon_video_widget_idle_signal, bvw);
609
+ } else if (bvw->priv->auto_resize != FALSE
610
+ && bvw->priv->have_xrandr != FALSE
611
+ && bvw->priv->fullscreen_mode != FALSE) {
612
+ bacon_resize (video_height, video_width);
616
+ *dest_pixel_aspect = bvw->priv->display_ratio;
619
+static xine_video_port_t *
620
+load_video_out_driver (BaconVideoWidget *bvw, gboolean null_out)
622
+ double res_h, res_v;
624
+ const char *video_driver_id;
625
+ xine_video_port_t *vo_driver;
627
+ if (null_out != FALSE)
629
+ return xine_open_video_driver (bvw->priv->xine,
630
+ "none", XINE_VISUAL_TYPE_NONE, NULL);
633
+ vis.display = bvw->priv->display;
634
+ vis.screen = bvw->priv->screen;
635
+ vis.d = GDK_WINDOW_XID (bvw->priv->video_window);
636
+ res_h = (DisplayWidth (bvw->priv->display, bvw->priv->screen) * 1000 /
637
+ DisplayWidthMM (bvw->priv->display,
638
+ bvw->priv->screen));
639
+ res_v = (DisplayHeight (bvw->priv->display, bvw->priv->screen) * 1000 /
640
+ DisplayHeightMM (bvw->priv->display,
641
+ bvw->priv->screen));
642
+ bvw->priv->display_ratio = res_v / res_h;
644
+ if (fabs (bvw->priv->display_ratio - 1.0) < 0.01) {
645
+ bvw->priv->display_ratio = 1.0;
648
+ vis.dest_size_cb = dest_size_cb;
649
+ vis.frame_output_cb = frame_output_cb;
650
+ vis.user_data = bvw;
652
+ /* Try to init video with stored information */
653
+ video_driver_id = xine_config_register_string (bvw->priv->xine,
654
+ "video.driver", "auto", "video driver to use",
655
+ NULL, 10, NULL, NULL);
657
+ /* Don't try to load anything but the xshm plugin if we're not
658
+ * on a local display */
659
+ if (totem_display_is_local () == FALSE)
661
+ return xine_open_video_driver (bvw->priv->xine, "xshm",
662
+ XINE_VISUAL_TYPE_X11, (void *) &vis);
665
+ if (strcmp (video_driver_id, "auto") != 0)
667
+ vo_driver = xine_open_video_driver (bvw->priv->xine,
669
+ XINE_VISUAL_TYPE_X11,
673
+ if (strcmp (video_driver_id, "dxr3") == 0)
674
+ bvw->priv->tvout = TV_OUT_DXR3;
680
+ /* If the video driver is not dxr3, or the dxr3 failed to load
681
+ * we need to try loading the other ones, skipping dxr3 */
683
+ /* The types are hardcoded for now */
684
+ vo_driver = xine_open_video_driver (bvw->priv->xine, "xv",
685
+ XINE_VISUAL_TYPE_X11, (void *) &vis);
689
+ vo_driver = xine_open_video_driver (bvw->priv->xine, "xshm",
690
+ XINE_VISUAL_TYPE_X11, (void *) &vis);
695
+static xine_audio_port_t *
696
+load_audio_out_driver (BaconVideoWidget *bvw, GError **err)
698
+ xine_audio_port_t *ao_driver;
699
+ const char *audio_driver_id;
701
+ if (bvw->priv->null_out != FALSE)
704
+ audio_driver_id = xine_config_register_string (bvw->priv->xine,
705
+ "audio.driver", "auto", "audio driver to use",
706
+ NULL, 10, NULL, NULL);
708
+ /* No configuration, fallback to auto */
709
+ if (audio_driver_id == NULL || strcmp (audio_driver_id, "") == 0)
710
+ audio_driver_id = g_strdup ("auto");
712
+ /* We know how to handle null driver */
713
+ if (strcmp (audio_driver_id, "null") == 0)
717
+ if (strcmp (audio_driver_id, "auto") == 0)
718
+ ao_driver = xine_open_audio_driver (bvw->priv->xine,
721
+ ao_driver = xine_open_audio_driver (bvw->priv->xine,
722
+ audio_driver_id, NULL);
724
+ /* if it failed without autoprobe, probe */
725
+ if (ao_driver == NULL && strcmp (audio_driver_id, "auto") != 0)
726
+ ao_driver = xine_open_audio_driver (bvw->priv->xine,
729
+ if (ao_driver == NULL && strcmp (audio_driver_id, "auto") != 0)
731
+ g_set_error (err, 0, 0,
732
+ _("Couldn't load the '%s' audio driver\n"
733
+ "Check that the device is not busy."),
734
+ audio_driver_id ? audio_driver_id : "auto" );
742
+bvw_config_helper_string (xine_t *xine, const char *id, const char *val,
743
+ xine_cfg_entry_t *entry)
745
+ memset (entry, 0, sizeof (entry));
747
+ if (!xine_config_lookup_entry (xine, id, entry))
749
+ xine_config_register_string (xine, id, val, "", NULL, 10,
751
+ xine_config_lookup_entry (xine, id, entry);
756
+bvw_config_helper_num (xine_t *xine, const char *id, int val,
757
+ xine_cfg_entry_t *entry)
759
+ memset (entry, 0, sizeof (entry));
761
+ if (!xine_config_lookup_entry (xine, id, entry))
763
+ xine_config_register_num (xine, id, val, 0, NULL, 10,
765
+ xine_config_lookup_entry (xine, id, entry);
770
+setup_url_handlers (BaconVideoWidget *bvw, const char *protocol)
774
+ key = g_strdup_printf ("/desktop/gnome/url-handlers/%s/command",
776
+ url = gconf_client_get_string (bvw->priv->gc, key, NULL);
780
+ gconf_client_set_string (bvw->priv->gc, key,
781
+ "totem \"%s\"", NULL);
784
+ key = g_strdup_printf
785
+ ("/desktop/gnome/url-handlers/%s/need-terminal",
787
+ gconf_client_set_bool (bvw->priv->gc, key, FALSE, NULL);
790
+ key = g_strdup_printf
791
+ ("/desktop/gnome/url-handlers/%s/enabled", protocol);
792
+ gconf_client_set_bool (bvw->priv->gc, key, TRUE, NULL);
800
+setup_config (BaconVideoWidget *bvw)
803
+ xine_cfg_entry_t entry;
805
+ path = g_build_path (G_DIR_SEPARATOR_S,
806
+ g_get_home_dir (), CONFIG_FILE, NULL);
807
+ xine_config_load (bvw->priv->xine, path);
810
+ /* default demux strategy */
811
+ xine_config_register_enum (bvw->priv->xine,
812
+ "misc.demux_strategy",
814
+ (char **) demux_strategies_str,
815
+ "media format detection strategy",
816
+ NULL, 10, NULL, NULL);
818
+ xine_config_lookup_entry (bvw->priv->xine,
819
+ "misc.demux_strategy", &entry);
820
+ entry.num_value = 0;
821
+ xine_config_update_entry (bvw->priv->xine, &entry);
824
+ xine_config_register_range (bvw->priv->xine,
826
+ 50, 0, 100, "amp volume level",
827
+ NULL, 10, NULL, NULL);
828
+ bvw->priv->volume = -1;
830
+ if (bvw->priv->gc == NULL)
833
+ /* Disable CDDB, we'll use Musicbrainz instead */
834
+ bvw_config_helper_num (bvw->priv->xine,
835
+ "input.cdda_use_cddb", 1, &entry);
836
+ entry.num_value = 0;
837
+ xine_config_update_entry (bvw->priv->xine, &entry);
839
+ if (bvw->priv->gc == NULL) {
840
+ g_warning ("GConf not available, broken installation?");
844
+ /* Setup the protocol handlers for our funky stuff */
845
+ setup_url_handlers (bvw, "pnm");
846
+ setup_url_handlers (bvw, "mms");
847
+ setup_url_handlers (bvw, "rtsp");
849
+ /* Proxy configuration */
850
+ if (gconf_client_get_bool (bvw->priv->gc, "/system/http_proxy/use_http_proxy", NULL) == FALSE)
852
+ bvw_config_helper_string (bvw->priv->xine,
853
+ "input.http_proxy_host", "", &entry);
854
+ entry.str_value = "";
855
+ xine_config_update_entry (bvw->priv->xine, &entry);
860
+ bvw_config_helper_string (bvw->priv->xine,
861
+ "input.http_proxy_host", "", &entry);
862
+ entry.str_value = gconf_client_get_string (bvw->priv->gc,
863
+ "/system/http_proxy/host", NULL);
864
+ xine_config_update_entry (bvw->priv->xine, &entry);
866
+ bvw_config_helper_num (bvw->priv->xine,
867
+ "input.http_proxy_port", 8080, &entry);
868
+ entry.num_value = gconf_client_get_int (bvw->priv->gc,
869
+ "/system/http_proxy/port", NULL);
870
+ xine_config_update_entry (bvw->priv->xine, &entry);
872
+ if (gconf_client_get_bool (bvw->priv->gc, "/system/http_proxy/use_authentication", NULL) == FALSE)
874
+ bvw_config_helper_string (bvw->priv->xine,
875
+ "input.http_proxy_user", g_get_user_name(),
877
+ entry.str_value = "";
878
+ xine_config_update_entry (bvw->priv->xine, &entry);
880
+ bvw_config_helper_string (bvw->priv->xine,
881
+ "input.http_proxy_password", "",
883
+ entry.str_value = "";
884
+ xine_config_update_entry (bvw->priv->xine, &entry);
886
+ bvw_config_helper_string (bvw->priv->xine,
887
+ "input.http_proxy_user", g_get_user_name(),
889
+ entry.str_value = gconf_client_get_string (bvw->priv->gc,
890
+ "/system/http_proxy/authentication_user",
892
+ xine_config_update_entry (bvw->priv->xine, &entry);
894
+ bvw_config_helper_string (bvw->priv->xine,
895
+ "input.http_proxy_password", "",
897
+ entry.str_value = gconf_client_get_string (bvw->priv->gc,
898
+ "/system/http_proxy/authentication_password",
900
+ xine_config_update_entry (bvw->priv->xine, &entry);
905
+setup_config_video (BaconVideoWidget *bvw)
907
+ xine_cfg_entry_t entry;
909
+ /* Default xv colourkey */
910
+ bvw_config_helper_num (bvw->priv->xine, "video.xv_colorkey", 30, &entry);
911
+ entry.num_value = 30;
912
+ xine_config_update_entry (bvw->priv->xine, &entry);
914
+ /* Remove the ALSA HW mixing */
915
+ bvw_config_helper_num (bvw->priv->xine, "audio.alsa_hw_mixer", 0, &entry);
916
+ entry.num_value = 0;
917
+ xine_config_update_entry (bvw->priv->xine, &entry);
921
+setup_config_stream (BaconVideoWidget *bvw)
925
+ if (bvw->priv->gc == NULL)
928
+ /* Setup brightness and contrast */
929
+ for (i = 0; i < 4; i++)
931
+ GError *error = NULL;
934
+ value = gconf_client_get_int (bvw->priv->gc,
935
+ video_props_str[i], &error);
937
+ /* avoid black screens */
938
+ if (value == 0 && error != NULL)
941
+ tmp = xine_get_param (bvw->priv->stream, video_props[i]);
944
+ xine_set_param (bvw->priv->stream,
945
+ video_props[i], value);
949
+ g_error_free (error);
954
+video_window_translate_point (BaconVideoWidget *bvw, int gui_x, int gui_y,
955
+ int *video_x, int *video_y)
958
+ x11_rectangle_t rect;
965
+ res = xine_port_send_gui_data (bvw->priv->vo_driver,
966
+ XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO, (void*)&rect);
970
+ /* the driver implements gui->video coordinate space
971
+ * translation so we use it */
980
+/* Changes the way xine skips while playing a DVD,
985
+dvd_skip_behaviour (BaconVideoWidget *bvw, int behaviour)
987
+ if (behaviour < 1 || behaviour > 2)
990
+ xine_config_register_num (bvw->priv->xine,
991
+ "input.dvd_skip_behaviour",
993
+ "DVD Skip behaviour",
1002
+bacon_video_widget_dvd_event (BaconVideoWidget *bvw, BaconVideoWidgetDVDEvent type)
1004
+ xine_event_t event;
1006
+ g_return_if_fail (bvw != NULL);
1007
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
1008
+ g_return_if_fail (bvw->priv->xine != NULL);
1012
+ case BVW_DVD_ROOT_MENU:
1013
+ event.type = XINE_EVENT_INPUT_MENU1;
1015
+ case BVW_DVD_TITLE_MENU:
1016
+ event.type = XINE_EVENT_INPUT_MENU2;
1018
+ case BVW_DVD_SUBPICTURE_MENU:
1019
+ event.type = XINE_EVENT_INPUT_MENU4;
1021
+ case BVW_DVD_AUDIO_MENU:
1022
+ event.type = XINE_EVENT_INPUT_MENU5;
1024
+ case BVW_DVD_ANGLE_MENU:
1025
+ event.type = XINE_EVENT_INPUT_MENU6;
1027
+ case BVW_DVD_CHAPTER_MENU:
1028
+ event.type = XINE_EVENT_INPUT_MENU7;
1030
+ case BVW_DVD_NEXT_CHAPTER:
1031
+ dvd_skip_behaviour (bvw, 1);
1032
+ event.type = XINE_EVENT_INPUT_NEXT;
1034
+ case BVW_DVD_PREV_CHAPTER:
1035
+ dvd_skip_behaviour (bvw, 1);
1036
+ event.type = XINE_EVENT_INPUT_PREVIOUS;
1038
+ case BVW_DVD_NEXT_TITLE:
1039
+ dvd_skip_behaviour (bvw, 2);
1040
+ event.type = XINE_EVENT_INPUT_NEXT;
1042
+ case BVW_DVD_PREV_TITLE:
1043
+ dvd_skip_behaviour (bvw, 2);
1044
+ event.type = XINE_EVENT_INPUT_PREVIOUS;
1046
+ case BVW_DVD_NEXT_ANGLE:
1047
+ event.type = XINE_EVENT_INPUT_ANGLE_NEXT;
1049
+ case BVW_DVD_PREV_ANGLE:
1050
+ event.type = XINE_EVENT_INPUT_ANGLE_PREVIOUS;
1056
+ event.stream = bvw->priv->stream;
1057
+ event.data = NULL;
1058
+ event.data_length = 0;
1060
+ xine_event_send (bvw->priv->stream,
1061
+ (xine_event_t *) (&event));
1065
+generate_mouse_event (BaconVideoWidget *bvw, GdkEvent *event,
1066
+ gboolean is_motion)
1068
+ GdkEventMotion *mevent = (GdkEventMotion *) event;
1069
+ GdkEventButton *bevent = (GdkEventButton *) event;
1073
+ /* Don't even try to generate an event if we're dying */
1074
+ if (bvw->priv->stream == NULL)
1077
+ if (is_motion == FALSE && bevent->button != 1)
1080
+ if (is_motion != FALSE)
1081
+ retval = video_window_translate_point (bvw,
1082
+ mevent->x, mevent->y, &x, &y);
1084
+ retval = video_window_translate_point (bvw,
1085
+ bevent->x, bevent->y, &x, &y);
1087
+ if (retval != FALSE)
1089
+ xine_event_t event;
1090
+ xine_input_data_t input;
1092
+ if (is_motion != FALSE)
1094
+ event.type = XINE_EVENT_INPUT_MOUSE_MOVE;
1095
+ input.button = 0; /* Just motion. */
1097
+ event.type = XINE_EVENT_INPUT_MOUSE_BUTTON;
1103
+ event.stream = bvw->priv->stream;
1104
+ event.data = &input;
1105
+ event.data_length = sizeof(input);
1107
+ xine_event_send (bvw->priv->stream,
1108
+ (xine_event_t *) (&event));
1117
+configure_cb (GtkWidget *widget, GdkEventConfigure *event,
1118
+ BaconVideoWidget *bvw)
1120
+ bvw->priv->xpos = event->x + GTK_WIDGET (bvw)->allocation.x;
1121
+ bvw->priv->ypos = event->y + GTK_WIDGET (bvw)->allocation.y;
1127
+size_changed_cb (GdkScreen *screen, BaconVideoWidget *bvw)
1129
+ double res_h, res_v;
1131
+ XLockDisplay (bvw->priv->display);
1132
+ res_h = (DisplayWidth (bvw->priv->display, bvw->priv->screen) * 1000 /
1133
+ DisplayWidthMM (bvw->priv->display,
1134
+ bvw->priv->screen));
1135
+ res_v = (DisplayHeight (bvw->priv->display, bvw->priv->screen) * 1000 /
1136
+ DisplayHeightMM (bvw->priv->display,
1137
+ bvw->priv->screen));
1138
+ XUnlockDisplay (bvw->priv->display);
1140
+ bvw->priv->display_ratio = res_v / res_h;
1142
+ if (fabs (bvw->priv->display_ratio - 1.0) < 0.01) {
1143
+ bvw->priv->display_ratio = 1.0;
1148
+bacon_video_widget_realize (GtkWidget *widget)
1150
+ GdkWindowAttr attr;
1151
+ BaconVideoWidget *bvw;
1153
+ bvw = BACON_VIDEO_WIDGET (widget);
1155
+ if (bvw->priv->mrl != NULL) {
1156
+ bacon_video_widget_close (bvw);
1157
+ g_warning ("bvw->priv->mrl != NULL on open");
1160
+ /* set realized flag */
1161
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1163
+ /* Close the old stream */
1164
+ xine_close (bvw->priv->stream);
1165
+ xine_event_dispose_queue (bvw->priv->ev_queue);
1166
+ xine_dispose (bvw->priv->stream);
1167
+ bvw->priv->stream = NULL;
1169
+ if (bvw->priv->vo_driver != NULL) {
1170
+ xine_close_video_driver (bvw->priv->xine,
1171
+ bvw->priv->vo_driver);
1173
+ if (bvw->priv->ao_driver != NULL) {
1174
+ xine_close_audio_driver (bvw->priv->xine,
1175
+ bvw->priv->ao_driver);
1178
+ /* Create the widget's window */
1179
+ attr.x = widget->allocation.x;
1180
+ attr.y = widget->allocation.y;
1181
+ attr.width = widget->allocation.width;
1182
+ attr.height = widget->allocation.height;
1183
+ attr.window_type = GDK_WINDOW_CHILD;
1184
+ attr.wclass = GDK_INPUT_OUTPUT;
1185
+ attr.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK
1186
+ | GDK_POINTER_MOTION_MASK
1187
+ | GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS_MASK;
1188
+ widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
1189
+ &attr, GDK_WA_X | GDK_WA_Y);
1190
+ gdk_window_show (widget->window);
1192
+ /* Flush, so that the window is really shown */
1194
+ gdk_window_set_user_data (widget->window, bvw);
1196
+ bvw->priv->video_window = widget->window;
1198
+ /* Set a black background */
1199
+ gdk_draw_rectangle (widget->window, widget->style->black_gc, TRUE,
1201
+ attr.width, attr.height);
1203
+ /* track configure events of toplevel window */
1204
+ g_signal_connect (G_OBJECT (gtk_widget_get_toplevel (widget)),
1205
+ "configure-event",
1206
+ G_CALLBACK (configure_cb), bvw);
1208
+ /* get screen size changes */
1209
+ g_signal_connect (G_OBJECT (gdk_screen_get_default ()),
1210
+ "size-changed", G_CALLBACK (size_changed_cb), bvw);
1212
+ /* Now onto the video out driver */
1213
+ bvw->priv->display = XOpenDisplay (gdk_display_get_name
1214
+ (gdk_display_get_default ()));
1215
+ bvw->priv->screen = DefaultScreen (bvw->priv->display);
1217
+ bvw->priv->ao_driver = load_audio_out_driver (bvw, NULL);
1218
+ bvw->priv->vo_driver = load_video_out_driver (bvw, bvw->priv->null_out);
1220
+ if (bvw->priv->vo_driver == NULL)
1222
+ bvw->priv->vo_driver = load_video_out_driver (bvw, TRUE);
1223
+ g_signal_emit (G_OBJECT (bvw),
1224
+ bvw_table_signals[ERROR], 0,
1225
+ _("No video output is available. Make sure that the program is correctly installed."), TRUE);
1226
+ g_message ("error");
1230
+ g_assert (bvw->priv->vo_driver != NULL);
1231
+ setup_config_video (bvw);
1233
+ if (bvw->priv->null_out == FALSE && bvw->priv->ao_driver != NULL)
1235
+ bvw->priv->vis = xine_post_init (bvw->priv->xine,
1236
+ bvw->priv->vis_name, 0,
1237
+ &bvw->priv->ao_driver, &bvw->priv->vo_driver);
1240
+ bvw->priv->have_xrandr = bacon_resize_init ();
1241
+ bvw->priv->stream = xine_stream_new (bvw->priv->xine,
1242
+ bvw->priv->ao_driver, bvw->priv->vo_driver);
1243
+ setup_config_stream (bvw);
1244
+ bvw->priv->ev_queue = xine_event_new_queue (bvw->priv->stream);
1246
+ /* Setup xine events */
1247
+ xine_event_create_listener_thread (bvw->priv->ev_queue,
1248
+ xine_event, (void *) bvw);
1251
+ if (!(nvtv_simple_init() && nvtv_enable_autoresize(TRUE))) {
1252
+ nvtv_simple_enable(FALSE);
1260
+bacon_video_widget_idle_signal (BaconVideoWidget *bvw)
1263
+ signal_data *data;
1265
+ data = g_async_queue_try_pop (bvw->priv->queue);
1271
+ switch (data->signal)
1274
+ bacon_video_widget_set_scale_ratio (bvw, 1);
1276
+ case TITLE_CHANGE_ASYNC:
1277
+ g_signal_emit (G_OBJECT (bvw),
1278
+ bvw_table_signals[TITLE_CHANGE],
1282
+ g_signal_emit (G_OBJECT (bvw),
1283
+ bvw_table_signals[EOS], 0, NULL);
1285
+ case CHANNELS_CHANGE_ASYNC:
1286
+ g_signal_emit (G_OBJECT (bvw),
1287
+ bvw_table_signals[CHANNELS_CHANGE], 0, NULL);
1289
+ case BUFFERING_ASYNC:
1290
+ g_signal_emit (G_OBJECT (bvw),
1291
+ bvw_table_signals[BUFFERING],
1294
+ case MESSAGE_ASYNC:
1295
+ g_signal_emit (G_OBJECT (bvw),
1296
+ bvw_table_signals[ERROR],
1297
+ 0, data->msg, TRUE);
1299
+ case SPEED_WARNING_ASYNC:
1300
+ g_signal_emit (G_OBJECT (bvw),
1301
+ bvw_table_signals[SPEED_WARNING],
1305
+ g_assert_not_reached ();
1310
+ g_free (data->msg);
1312
+ queue_length = g_async_queue_length (bvw->priv->queue);
1314
+ return (queue_length > 0);
1318
+xine_event_message (BaconVideoWidget *bvw, xine_ui_message_data_t *data)
1321
+ signal_data *sigdata;
1325
+ switch(data->type)
1327
+ case XINE_MSG_NO_ERROR:
1329
+ case XINE_MSG_GENERAL_WARNING:
1331
+ case XINE_MSG_UNKNOWN_HOST:
1332
+ message = g_strdup_printf (_("The server you are trying to connect to is not known."));
1334
+ case XINE_MSG_UNKNOWN_DEVICE:
1335
+ message = g_strdup_printf (_("The device name you specified (%s) seems to be invalid."), (char *) data + data->parameters);
1337
+ case XINE_MSG_NETWORK_UNREACHABLE:
1338
+ message = g_strdup_printf (_("The server you are trying to connect to (%s) is unreachable."), (char *) data + data->parameters);
1340
+ case XINE_MSG_CONNECTION_REFUSED:
1341
+ message = g_strdup_printf (_("The connection to this server was refused."));
1343
+ case XINE_MSG_FILE_NOT_FOUND:
1344
+ message = g_strdup_printf (_("The specified movie '%s' could not be found."), (char *) data + data->parameters);
1346
+ case XINE_MSG_READ_ERROR:
1347
+ message = g_strdup_printf (_("The movie '%s' could not be read."), (char *) data + data->parameters);
1349
+ case XINE_MSG_LIBRARY_LOAD_ERROR:
1350
+ message = g_strdup_printf (_("A problem occured while loading a library or a decoder (%s)."), (char *) data + data->parameters);
1352
+ case XINE_MSG_ENCRYPTED_SOURCE:
1353
+ if (strncmp (bvw->priv->mrl, "dvd:", 4) == 0)
1354
+ message = g_strdup (_("The source seems encrypted, and can't be read. Are you trying to play an encrypted DVD without libdvdcss?"));
1356
+ message = g_strdup (_("This file is encrypted and cannot be played back."));
1358
+ case XINE_MSG_SECURITY:
1359
+ message = g_strdup (_("For security reasons, this movie can not be played back."));
1361
+ case XINE_MSG_AUDIO_OUT_UNAVAILABLE:
1362
+ xine_stop (bvw->priv->stream);
1363
+ message = g_strdup (_("The audio device is busy. Is another application using it?"));
1365
+ case XINE_MSG_PERMISSION_ERROR:
1366
+ if (strncmp (bvw->priv->mrl, "file:", 5) == 0)
1367
+ message = g_strdup (_("You are not allowed to open this file."));
1369
+ message = g_strdup (_("The server refused access to this file or stream."));
1373
+ if (message == NULL)
1375
+ D("xine_event_message: unhandled error\ntype: %d", data->type);
1379
+ sigdata = g_new0 (signal_data, 1);
1380
+ sigdata->signal = MESSAGE_ASYNC;
1381
+ sigdata->msg = message;
1382
+ g_async_queue_push (bvw->priv->queue, sigdata);
1383
+ g_idle_add ((GSourceFunc) bacon_video_widget_idle_signal, bvw);
1387
+xine_event (void *user_data, const xine_event_t *event)
1389
+ BaconVideoWidget *bvw = (BaconVideoWidget *) user_data;
1390
+ xine_ui_data_t *ui_data;
1391
+ xine_progress_data_t *prg;
1392
+ xine_mrl_reference_data_t *ref;
1393
+ signal_data *data;
1395
+ switch (event->type)
1397
+ case XINE_EVENT_UI_PLAYBACK_FINISHED:
1398
+ data = g_new0 (signal_data, 1);
1399
+ data->signal = EOS_ASYNC;
1400
+ g_async_queue_push (bvw->priv->queue, data);
1401
+ g_idle_add ((GSourceFunc) bacon_video_widget_idle_signal, bvw);
1403
+ case XINE_EVENT_UI_CHANNELS_CHANGED:
1404
+ data = g_new0 (signal_data, 1);
1405
+ data->signal = CHANNELS_CHANGE_ASYNC;
1406
+ g_async_queue_push (bvw->priv->queue, data);
1407
+ g_idle_add ((GSourceFunc) bacon_video_widget_idle_signal, bvw);
1409
+ case XINE_EVENT_UI_SET_TITLE:
1410
+ ui_data = event->data;
1412
+ data = g_new0 (signal_data, 1);
1413
+ data->signal = TITLE_CHANGE_ASYNC;
1414
+ data->msg = g_strdup (ui_data->str);
1415
+ g_async_queue_push (bvw->priv->queue, data);
1416
+ g_idle_add ((GSourceFunc) bacon_video_widget_idle_signal, bvw);
1418
+ case XINE_EVENT_PROGRESS:
1419
+ prg = event->data;
1421
+ data = g_new0 (signal_data, 1);
1422
+ data->signal = BUFFERING_ASYNC;
1423
+ data->num = prg->percent;
1424
+ g_async_queue_push (bvw->priv->queue, data);
1425
+ g_idle_add ((GSourceFunc) bacon_video_widget_idle_signal, bvw);
1427
+ case XINE_EVENT_MRL_REFERENCE:
1428
+ ref = event->data;
1429
+ bacon_video_widget_close (bvw);
1430
+ bacon_video_widget_open (bvw, ref->mrl, NULL);
1431
+ bacon_video_widget_play (bvw, NULL);
1433
+ case XINE_EVENT_UI_MESSAGE:
1434
+ xine_event_message (bvw, (xine_ui_message_data_t *)event->data);
1436
+ case XINE_EVENT_DROPPED_FRAMES:
1437
+ data = g_new0 (signal_data, 1);
1438
+ data->signal = SPEED_WARNING_ASYNC;
1439
+ g_async_queue_push (bvw->priv->queue, data);
1440
+ g_idle_add ((GSourceFunc) bacon_video_widget_idle_signal, bvw);
1442
+ case XINE_EVENT_AUDIO_LEVEL:
1443
+ /* Unhandled, we use the software mixer, not the hardware one */
1449
+xine_error (BaconVideoWidget *bvw, GError **error)
1451
+ signal_data *data, *save_data;
1456
+ /* Steal messages from the async queue, if there's an error,
1457
+ * to use as the error message rather than the crappy errors from
1459
+ while ((data = g_async_queue_try_pop (bvw->priv->queue)) != NULL)
1461
+ g_assert (data->signal == MESSAGE_ASYNC
1462
+ || data->signal == BUFFERING_ASYNC);
1464
+ if (data->signal != BUFFERING_ASYNC)
1466
+ if (save_data != NULL)
1468
+ g_free (save_data->msg);
1469
+ g_free (save_data);
1473
+ g_free (data->msg);
1478
+ if (save_data != NULL)
1480
+ g_set_error (error, 0, 0, save_data->msg);
1481
+ g_free (save_data->msg);
1482
+ g_free (save_data);
1487
+ err = xine_get_error (bvw->priv->stream);
1488
+ if (err == XINE_ERROR_NONE)
1493
+ case XINE_ERROR_NO_INPUT_PLUGIN:
1494
+ case XINE_ERROR_NO_DEMUX_PLUGIN:
1495
+ g_set_error (error, 0, 0, _("There is no plugin to handle this"
1498
+ case XINE_ERROR_DEMUX_FAILED:
1499
+ g_set_error (error, 0, 0, _("This movie is broken and can not "
1500
+ "be played further."));
1502
+ case XINE_ERROR_MALFORMED_MRL:
1503
+ g_set_error (error, 0, 0, _("This location is not "
1506
+ case XINE_ERROR_INPUT_FAILED:
1507
+ g_set_error (error, 0, 0, _("This movie could not be opened."));
1510
+ g_set_error (error, 0, 0, _("Generic Error."));
1516
+bacon_video_widget_unrealize (GtkWidget *widget)
1518
+ BaconVideoWidget *bvw;
1520
+ xine_cfg_entry_t entry;
1523
+ g_return_if_fail (widget != NULL);
1524
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (widget));
1526
+ bvw = BACON_VIDEO_WIDGET (widget);
1528
+ g_source_remove (bvw->priv->tick_id);
1530
+ speed = xine_get_param (bvw->priv->stream, XINE_PARAM_SPEED);
1531
+ if (speed != XINE_SPEED_PAUSE)
1532
+ show_vfx_update (bvw, FALSE);
1534
+ /* stop the playback */
1535
+ xine_stop (bvw->priv->stream);
1536
+ xine_close (bvw->priv->stream);
1538
+ /* Put the current volume in the config system */
1539
+ if (bacon_video_widget_can_set_volume (bvw) != FALSE)
1541
+ xine_config_lookup_entry (bvw->priv->xine,
1542
+ "misc.amp_level", &entry);
1543
+ entry.num_value = bvw->priv->volume;
1544
+ xine_config_update_entry (bvw->priv->xine, &entry);
1547
+ /* Kill the TV out */
1549
+ nvtv_simple_exit();
1552
+ /* Hide all windows */
1553
+ if (GTK_WIDGET_MAPPED (widget))
1554
+ gtk_widget_unmap (widget);
1555
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1557
+ /* Get rid of the rest of the stream */
1558
+ xine_dispose (bvw->priv->stream);
1559
+ xine_event_dispose_queue (bvw->priv->ev_queue);
1560
+ bvw->priv->stream = NULL;
1563
+ configfile = g_build_path (G_DIR_SEPARATOR_S,
1564
+ g_get_home_dir (), CONFIG_FILE, NULL);
1565
+ xine_config_save (bvw->priv->xine, configfile);
1566
+ g_free (configfile);
1568
+ /* Kill the drivers */
1569
+ if (bvw->priv->vo_driver != NULL)
1570
+ xine_close_video_driver (bvw->priv->xine,
1571
+ bvw->priv->vo_driver);
1572
+ if (bvw->priv->ao_driver != NULL)
1573
+ xine_close_audio_driver (bvw->priv->xine,
1574
+ bvw->priv->ao_driver);
1576
+ /* stop event thread */
1577
+ xine_exit (bvw->priv->xine);
1578
+ bvw->priv->xine = NULL;
1580
+ /* This destroys widget->window and unsets the realized flag */
1581
+ if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1582
+ (*GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1585
+static struct poptOption xine_options[] = {
1589
+struct poptOption *
1590
+bacon_video_widget_get_popt_table (void)
1592
+ /* Xine backend does not need any options */
1593
+ return (struct poptOption *) xine_options;
1597
+bacon_video_widget_new (int width, int height, gboolean null_out, GError **err)
1599
+ BaconVideoWidget *bvw;
1600
+ xine_cfg_entry_t entry;
1602
+ bvw = BACON_VIDEO_WIDGET (g_object_new
1603
+ (bacon_video_widget_get_type (), NULL));
1605
+ bvw->priv->null_out = null_out;
1607
+ /* defaults are fine if both are negative */
1608
+ if (width > 0 && height > 0)
1610
+ /* figure out the missing measure from the other one
1611
+ * with a 4:3 ratio */
1613
+ width = (int) (height * 4 / 3);
1615
+ height = (int) (width * 3 / 4);
1621
+ GTK_WIDGET(bvw)->requisition.width = width;
1622
+ GTK_WIDGET(bvw)->requisition.height = height;
1624
+ bvw->priv->init_width = width;
1625
+ bvw->priv->init_height = height;
1627
+ /* load the output drivers */
1628
+ bvw->priv->ao_driver = load_audio_out_driver (bvw, err);
1629
+ if (err != NULL && *err != NULL)
1632
+ bvw->priv->vo_driver = load_video_out_driver (bvw, TRUE);
1634
+ /* Be extra careful about exiting out nicely when a video output
1635
+ * isn't available */
1636
+ if (bvw->priv->vo_driver == NULL)
1638
+ /* Close the xine stuff */
1639
+ if (bvw->priv->ao_driver != NULL) {
1640
+ xine_close_audio_driver (bvw->priv->xine,
1641
+ bvw->priv->ao_driver);
1643
+ xine_exit (bvw->priv->xine);
1645
+ /* get rid of all our crappety crap */
1646
+ g_source_remove (bvw->priv->tick_id);
1647
+ g_idle_remove_by_data (bvw);
1648
+ g_async_queue_unref (bvw->priv->queue);
1649
+ g_free (bvw->priv->vis_name);
1650
+ g_object_unref (G_OBJECT (bvw->priv->gc));
1651
+ g_free (bvw->priv->vis_name);
1652
+ g_free (bvw->priv);
1655
+ g_set_error (err, 0, 0,
1656
+ _("No video output is available. Make sure that the program is correctly installed."));
1660
+ if (bvw->priv->null_out != FALSE)
1662
+ bvw_config_helper_num (bvw->priv->xine, "video.num_buffers",
1664
+ entry.num_value = 5;
1666
+ bvw_config_helper_num (bvw->priv->xine, "video.num_buffers",
1668
+ entry.num_value = 500;
1670
+ xine_config_update_entry (bvw->priv->xine, &entry);
1672
+ bvw->priv->stream = xine_stream_new (bvw->priv->xine,
1673
+ bvw->priv->ao_driver, bvw->priv->vo_driver);
1674
+ bvw->priv->ev_queue = xine_event_new_queue (bvw->priv->stream);
1676
+ return GTK_WIDGET (bvw);
1680
+bacon_video_widget_expose (GtkWidget *widget, GdkEventExpose *event)
1682
+ BaconVideoWidget *bvw = (BaconVideoWidget *) widget;
1683
+ XExposeEvent *expose;
1685
+ if (event->count != 0)
1688
+ expose = g_new0 (XExposeEvent, 1);
1689
+ expose->count = event->count;
1691
+ xine_port_send_gui_data (bvw->priv->vo_driver,
1692
+ XINE_GUI_SEND_EXPOSE_EVENT, expose);
1700
+bacon_video_widget_motion_notify (GtkWidget *widget, GdkEventMotion *event)
1702
+ BaconVideoWidget *bvw = (BaconVideoWidget *) widget;
1704
+ generate_mouse_event (bvw, (GdkEvent *)event, TRUE);
1706
+ if (GTK_WIDGET_CLASS (parent_class)->motion_notify_event != NULL)
1707
+ (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event) (widget, event);
1713
+bacon_video_widget_button_press (GtkWidget *widget, GdkEventButton *event)
1715
+ BaconVideoWidget *bvw = (BaconVideoWidget *) widget;
1717
+ generate_mouse_event (bvw, (GdkEvent *)event, FALSE);
1719
+ if (GTK_WIDGET_CLASS (parent_class)->button_press_event != NULL)
1720
+ (* GTK_WIDGET_CLASS (parent_class)->button_press_event) (widget, event);
1726
+bacon_video_widget_size_request (GtkWidget *widget, GtkRequisition *requisition)
1728
+ BaconVideoWidget *bvw;
1730
+ g_return_if_fail(widget != NULL);
1731
+ g_return_if_fail(BACON_IS_VIDEO_WIDGET(widget));
1733
+ bvw = BACON_VIDEO_WIDGET (widget);
1735
+ if ((bvw->priv->init_width == 0) && (bvw->priv->init_height == 0)) {
1736
+ requisition->width = DEFAULT_WIDTH;
1737
+ requisition->height = DEFAULT_HEIGHT;
1739
+ /* Requesting first allocation as a minimum */
1740
+ requisition->width = bvw->priv->init_width;
1741
+ requisition->height = bvw->priv->init_height;
1746
+bacon_video_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
1748
+ BaconVideoWidget *bvw;
1750
+ g_return_if_fail (widget != NULL);
1751
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (widget));
1753
+ bvw = BACON_VIDEO_WIDGET (widget);
1755
+ widget->allocation = *allocation;
1756
+ bvw->priv->xpos = allocation->x;
1757
+ bvw->priv->ypos = allocation->y;
1759
+ if ( (bvw->priv->init_width == 0) && (bvw->priv->init_height == 0) ) {
1760
+ /* First allocation, saving values */
1761
+ bvw->priv->init_width = allocation->width;
1762
+ bvw->priv->init_height = allocation->height;
1765
+ if (GTK_WIDGET_REALIZED (widget))
1767
+ gdk_window_move_resize (widget->window,
1770
+ allocation->width,
1771
+ allocation->height);
1776
+bacon_video_widget_tick_send (BaconVideoWidget *bvw)
1778
+ int current_time, stream_length, current_position;
1779
+ float current_position_f;
1780
+ gboolean ret = TRUE, seekable;
1782
+ if (bvw->priv->stream == NULL || bvw->priv->logo_mode != FALSE)
1785
+ if (bvw->priv->mrl == NULL)
1788
+ stream_length = 0;
1789
+ current_position = 0;
1791
+ ret = xine_get_pos_length (bvw->priv->stream,
1792
+ ¤t_position,
1800
+ if (bvw->priv->seeking == 1)
1802
+ current_position_f = bvw->priv->seek_dest;
1803
+ current_time = bvw->priv->seek_dest * stream_length;
1804
+ } else if (bvw->priv->seeking == 2) {
1805
+ current_time = bvw->priv->seek_dest_time;
1806
+ current_position_f = (float) current_time / stream_length;
1808
+ current_position_f = (float) current_position / 65535;
1811
+ if (stream_length > 0)
1812
+ bvw->priv->is_live = FALSE;
1814
+ bvw->priv->is_live = TRUE;
1816
+ if (stream_length != 0 && bvw->priv->mrl != NULL) {
1817
+ seekable = xine_get_stream_info (bvw->priv->stream,
1818
+ XINE_STREAM_INFO_SEEKABLE);
1823
+ g_signal_emit (G_OBJECT (bvw),
1824
+ bvw_table_signals[TICK], 0,
1825
+ (gint64) (current_time),
1826
+ (gint64) (stream_length),
1827
+ current_position_f,
1834
+show_vfx_update (BaconVideoWidget *bvw, gboolean show_visuals)
1836
+ xine_post_out_t *audio_source;
1837
+ gboolean has_video;
1839
+ has_video = xine_get_stream_info(bvw->priv->stream,
1840
+ XINE_STREAM_INFO_HAS_VIDEO);
1842
+ if (has_video != FALSE && show_visuals != FALSE
1843
+ && bvw->priv->using_vfx != FALSE)
1845
+ audio_source = xine_get_audio_source (bvw->priv->stream);
1846
+ if (xine_post_wire_audio_port (audio_source,
1847
+ bvw->priv->ao_driver))
1848
+ bvw->priv->using_vfx = FALSE;
1849
+ } else if (has_video == FALSE && show_visuals != FALSE
1850
+ && bvw->priv->using_vfx == FALSE
1851
+ && bvw->priv->vis != NULL)
1853
+ audio_source = xine_get_audio_source (bvw->priv->stream);
1854
+ if (xine_post_wire_audio_port (audio_source,
1855
+ bvw->priv->vis->audio_input[0]))
1856
+ bvw->priv->using_vfx = TRUE;
1857
+ } else if (has_video == FALSE && show_visuals == FALSE) {
1858
+ audio_source = xine_get_audio_source (bvw->priv->stream);
1859
+ if (xine_post_wire_audio_port (audio_source,
1860
+ bvw->priv->ao_driver))
1861
+ bvw->priv->using_vfx = FALSE;
1866
+get_fourcc_string (uint32_t f)
1870
+ memset(&fcc, 0, sizeof(fcc));
1872
+ /* Should we take care about endianess ? */
1873
+ fcc[0] = f | 0xFFFFFF00;
1874
+ fcc[1] = f>>8 | 0xFFFFFF00;
1875
+ fcc[2] = f>>16 | 0xFFFFFF00;
1876
+ fcc[3] = f>>24 | 0xFFFFFF00;
1880
+ sprintf(fcc, "0x%x", f);
1882
+ if((fcc[0] == 'm') && (fcc[1] == 's'))
1884
+ if((fcc[2] = 0x0) && (fcc[3] == 0x55))
1885
+ *(uint32_t *) fcc = 0x33706d2e; /* Force to '.mp3' */
1888
+ return g_strdup (fcc);
1892
+bacon_video_widget_get_backend_name (BaconVideoWidget *bvw)
1894
+ return g_strdup_printf ("xine-lib version %d.%d.%d",
1895
+ XINE_MAJOR_VERSION,
1896
+ XINE_MINOR_VERSION,
1897
+ XINE_SUB_VERSION);
1901
+bacon_video_widget_open (BaconVideoWidget *bvw, const char *mrl,
1906
+ g_return_val_if_fail (mrl != NULL, FALSE);
1907
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), FALSE);
1908
+ g_return_val_if_fail (bvw->priv->xine != NULL, FALSE);
1909
+ g_return_val_if_fail (bvw->priv->mrl == NULL, FALSE);
1911
+ bvw->priv->video_fcc = 0;
1912
+ bvw->priv->audio_fcc = 0;
1914
+ error = xine_open (bvw->priv->stream, mrl);
1917
+ bacon_video_widget_close (bvw);
1918
+ xine_error (bvw, gerror);
1922
+ if (xine_get_stream_info (bvw->priv->stream,
1923
+ XINE_STREAM_INFO_VIDEO_HANDLED) == FALSE
1924
+ || (xine_get_stream_info (bvw->priv->stream,
1925
+ XINE_STREAM_INFO_HAS_VIDEO) == FALSE
1926
+ && xine_get_stream_info (bvw->priv->stream,
1927
+ XINE_STREAM_INFO_AUDIO_HANDLED) == FALSE))
1929
+ char *fourcc_str, *name;
1931
+ g_signal_emit (G_OBJECT (bvw),
1932
+ bvw_table_signals[GOT_METADATA], 0, NULL);
1934
+ bvw->priv->video_fcc = xine_get_stream_info (bvw->priv->stream,
1935
+ XINE_STREAM_INFO_VIDEO_FOURCC);
1936
+ fourcc_str = get_fourcc_string (bvw->priv->video_fcc);
1937
+ name = g_strdup (xine_get_meta_info (bvw->priv->stream,
1938
+ XINE_META_INFO_VIDEOCODEC));
1940
+ /* Only change the audio_fcc if we're on x86 */
1941
+ if (xine_get_stream_info
1942
+ (bvw->priv->stream,
1943
+ XINE_STREAM_INFO_AUDIO_HANDLED) == FALSE)
1945
+ bvw->priv->audio_fcc = xine_get_stream_info
1946
+ (bvw->priv->stream,
1947
+ XINE_STREAM_INFO_AUDIO_FOURCC);
1950
+ bacon_video_widget_close (bvw);
1952
+ g_set_error (gerror, 0, 0,
1953
+ _("Video codec '%s' is not handled. You might need to install additional plugins to be able to play some types of movies"),
1954
+ name ? name : fourcc_str);
1956
+ g_free (fourcc_str);
1962
+ if (xine_get_stream_info (bvw->priv->stream,
1963
+ XINE_STREAM_INFO_HAS_VIDEO) == FALSE
1964
+ && bvw->priv->ao_driver == NULL
1965
+ && bvw->priv->null_out != FALSE)
1967
+ g_signal_emit (G_OBJECT (bvw),
1968
+ bvw_table_signals[GOT_METADATA], 0, NULL);
1970
+ bacon_video_widget_close (bvw);
1972
+ g_set_error (gerror, 0, 0,
1973
+ _("This is an audio-only file, and there is no audio output available."));
1978
+ show_vfx_update (bvw, bvw->priv->show_vfx);
1980
+ bvw->priv->mrl = g_strdup (mrl);
1982
+ g_signal_emit (G_OBJECT (bvw),
1983
+ bvw_table_signals[GOT_METADATA], 0, NULL);
1989
+bacon_video_widget_play (BaconVideoWidget *bvw, GError **gerror)
1993
+ g_return_val_if_fail (bvw != NULL, -1);
1994
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), -1);
1995
+ g_return_val_if_fail (bvw->priv->xine != NULL, -1);
1997
+ bvw->priv->started = TRUE;
2000
+ if (bvw->priv->seeking == 1)
2002
+ error = xine_play (bvw->priv->stream,
2003
+ bvw->priv->seek_dest * 65535, 0);
2004
+ bvw->priv->seeking = 0;
2005
+ } else if (bvw->priv->seeking == 2) {
2006
+ error = xine_play (bvw->priv->stream, 0,
2007
+ bvw->priv->seek_dest_time);
2008
+ bvw->priv->seeking = 0;
2010
+ int speed, status;
2012
+ speed = xine_get_param (bvw->priv->stream, XINE_PARAM_SPEED);
2013
+ status = xine_get_status (bvw->priv->stream);
2014
+ if (speed != XINE_SPEED_NORMAL && status == XINE_STATUS_PLAY)
2016
+ xine_set_param (bvw->priv->stream,
2017
+ XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
2019
+ error = xine_play (bvw->priv->stream, 0, 0);
2022
+ bvw->priv->seeking = 0;
2027
+ xine_error (bvw, gerror);
2031
+ if (bvw->priv->queued_vis != NULL)
2033
+ bacon_video_widget_set_visuals (bvw, bvw->priv->queued_vis);
2034
+ g_free (bvw->priv->queued_vis);
2035
+ bvw->priv->queued_vis = NULL;
2038
+ /* Workaround for xine-lib: don't try to use a
2039
+ * non-existent audio channel */
2043
+ cur = xine_get_param(bvw->priv->stream,
2044
+ XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
2045
+ num = xine_get_stream_info(bvw->priv->stream,
2046
+ XINE_STREAM_INFO_AUDIO_CHANNELS);
2048
+ xine_set_param(bvw->priv->stream,
2049
+ XINE_PARAM_AUDIO_CHANNEL_LOGICAL, -1);
2055
+gboolean bacon_video_widget_seek (BaconVideoWidget *bvw, float position,
2060
+ g_return_val_if_fail (bvw != NULL, -1);
2061
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), -1);
2062
+ g_return_val_if_fail (bvw->priv->xine != NULL, -1);
2064
+ speed = xine_get_param (bvw->priv->stream, XINE_PARAM_SPEED);
2065
+ if (speed == XINE_SPEED_PAUSE)
2067
+ bvw->priv->seeking = 1;
2068
+ bvw->priv->seek_dest = position;
2072
+ error = xine_play (bvw->priv->stream, position * 65535, 0);
2076
+ xine_error (bvw, gerror);
2083
+gboolean bacon_video_widget_seek_time (BaconVideoWidget *bvw, gint64 time,
2089
+ g_return_val_if_fail (bvw != NULL, -1);
2090
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), -1);
2091
+ g_return_val_if_fail (bvw->priv->xine != NULL, -1);
2093
+ length = bacon_video_widget_get_stream_length (bvw);
2095
+ speed = xine_get_param (bvw->priv->stream, XINE_PARAM_SPEED);
2096
+ if (speed == XINE_SPEED_PAUSE)
2098
+ bvw->priv->seeking = 2;
2099
+ bvw->priv->seek_dest_time = CLAMP (time, 0, length);
2103
+ length = bacon_video_widget_get_stream_length (bvw);
2105
+ error = xine_play (bvw->priv->stream, 0, CLAMP (time, 0, length));
2109
+ xine_error (bvw, gerror);
2117
+bacon_video_widget_stop (BaconVideoWidget *bvw)
2119
+ g_return_if_fail (bvw != NULL);
2120
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
2121
+ g_return_if_fail (bvw->priv->xine != NULL);
2123
+ xine_stop (bvw->priv->stream);
2127
+bacon_video_widget_close (BaconVideoWidget *bvw)
2129
+ g_return_if_fail (bvw != NULL);
2130
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
2131
+ g_return_if_fail (bvw->priv->xine != NULL);
2133
+ xine_stop (bvw->priv->stream);
2134
+ xine_close (bvw->priv->stream);
2135
+ g_free (bvw->priv->mrl);
2136
+ bvw->priv->mrl = NULL;
2138
+ if (bvw->priv->logo_mode == FALSE)
2139
+ g_signal_emit (G_OBJECT (bvw),
2140
+ bvw_table_signals[CHANNELS_CHANGE], 0, NULL);
2145
+bacon_video_widget_set_property (GObject *object, guint property_id,
2146
+ const GValue *value, GParamSpec *pspec)
2148
+ BaconVideoWidget *bvw;
2150
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (object));
2152
+ bvw = BACON_VIDEO_WIDGET (object);
2154
+ switch (property_id)
2156
+ case PROP_LOGO_MODE:
2157
+ bacon_video_widget_set_logo_mode (bvw,
2158
+ g_value_get_boolean (value));
2160
+ case PROP_SHOWCURSOR:
2161
+ bacon_video_widget_set_show_cursor (bvw,
2162
+ g_value_get_boolean (value));
2164
+ case PROP_MEDIADEV:
2165
+ bacon_video_widget_set_media_device (bvw,
2166
+ g_value_get_string (value));
2168
+ case PROP_SHOW_VISUALS:
2169
+ bacon_video_widget_set_show_visuals (bvw,
2170
+ g_value_get_boolean (value));
2173
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
2178
+bacon_video_widget_get_property (GObject *object, guint property_id,
2179
+ GValue *value, GParamSpec *pspec)
2181
+ BaconVideoWidget *bvw;
2183
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (object));
2185
+ bvw = BACON_VIDEO_WIDGET (object);
2187
+ switch (property_id)
2189
+ case PROP_LOGO_MODE:
2190
+ g_value_set_boolean (value,
2191
+ bacon_video_widget_get_logo_mode (bvw));
2193
+ case PROP_POSITION:
2194
+ g_value_set_int64 (value, bacon_video_widget_get_position (bvw));
2196
+ case PROP_STREAM_LENGTH:
2197
+ g_value_set_int64 (value,
2198
+ bacon_video_widget_get_stream_length (bvw));
2200
+ case PROP_PLAYING:
2201
+ g_value_set_boolean (value,
2202
+ bacon_video_widget_is_playing (bvw));
2204
+ case PROP_SEEKABLE:
2205
+ g_value_set_boolean (value,
2206
+ bacon_video_widget_is_seekable (bvw));
2208
+ case PROP_SHOWCURSOR:
2209
+ g_value_set_boolean (value,
2210
+ bacon_video_widget_get_show_cursor (bvw));
2213
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
2218
+bacon_video_widget_set_logo_mode (BaconVideoWidget *bvw, gboolean logo_mode)
2220
+ g_return_if_fail (bvw != NULL);
2221
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
2222
+ g_return_if_fail (bvw->priv->xine != NULL);
2224
+ bvw->priv->logo_mode = logo_mode;
2228
+bacon_video_widget_set_logo (BaconVideoWidget *bvw, char *filename)
2230
+ g_return_if_fail (bvw != NULL);
2231
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET(bvw));
2232
+ g_return_if_fail (bvw->priv->xine != NULL);
2234
+ if (bacon_video_widget_open (bvw, filename, NULL) != FALSE) {
2235
+ bacon_video_widget_play (bvw, NULL);
2240
+bacon_video_widget_get_logo_mode (BaconVideoWidget *bvw)
2242
+ g_return_val_if_fail (bvw != NULL, FALSE);
2243
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), FALSE);
2244
+ g_return_val_if_fail (bvw->priv->xine != NULL, FALSE);
2246
+ return bvw->priv->logo_mode;
2250
+bacon_video_widget_pause (BaconVideoWidget *bvw)
2252
+ g_return_if_fail (bvw != NULL);
2253
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
2254
+ g_return_if_fail (bvw->priv->xine != NULL);
2256
+ xine_set_param (bvw->priv->stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
2258
+ if (bvw->priv->is_live != FALSE)
2259
+ xine_stop (bvw->priv->stream);
2261
+ /* Close the audio device when on pause */
2262
+ xine_set_param (bvw->priv->stream,
2263
+ XINE_PARAM_AUDIO_CLOSE_DEVICE, 1);
2267
+bacon_video_widget_get_position (BaconVideoWidget *bvw)
2269
+ int pos_stream = 0, i = 0;
2270
+ int pos_time, length_time;
2273
+ g_return_val_if_fail (bvw != NULL, 0);
2274
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 0);
2275
+ g_return_val_if_fail (bvw->priv->xine != NULL, 0);
2277
+ if (bvw->priv->mrl == NULL)
2280
+ if (bacon_video_widget_is_playing (bvw) == FALSE)
2283
+ ret = xine_get_pos_length (bvw->priv->stream, &pos_stream,
2284
+ &pos_time, &length_time);
2286
+ while (ret == FALSE && i < 10)
2289
+ ret = xine_get_pos_length (bvw->priv->stream, &pos_stream,
2290
+ &pos_time, &length_time);
2294
+ if (bvw->priv->seeking == 1)
2296
+ return bvw->priv->seek_dest * length_time;
2297
+ } else if (bvw->priv->seeking == 2) {
2298
+ return bvw->priv->seek_dest_time;
2304
+ return pos_stream / 65535;
2308
+bacon_video_widget_can_set_volume (BaconVideoWidget *bvw)
2310
+ g_return_val_if_fail (bvw != NULL, 0);
2311
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 0);
2312
+ g_return_val_if_fail (bvw->priv->xine != NULL, 0);
2314
+ if (bvw->priv->ao_driver == NULL)
2317
+ if (xine_get_param (bvw->priv->stream,
2318
+ XINE_PARAM_AUDIO_CHANNEL_LOGICAL) == -2)
2325
+bacon_video_widget_set_volume (BaconVideoWidget *bvw, int volume)
2327
+ g_return_if_fail (bvw != NULL);
2328
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
2329
+ g_return_if_fail (bvw->priv->xine != NULL);
2331
+ if (bacon_video_widget_can_set_volume (bvw) != FALSE)
2333
+ volume = CLAMP (volume, 0, 100);
2334
+ xine_set_param (bvw->priv->stream,
2335
+ XINE_PARAM_AUDIO_AMP_LEVEL, volume);
2336
+ bvw->priv->volume = volume;
2341
+bacon_video_widget_get_volume (BaconVideoWidget *bvw)
2343
+ g_return_val_if_fail (bvw != NULL, 0);
2344
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 0);
2345
+ g_return_val_if_fail (bvw->priv->xine != NULL, 0);
2347
+ if (bacon_video_widget_can_set_volume (bvw) == FALSE)
2350
+ if (bvw->priv->volume == -1)
2352
+ xine_cfg_entry_t entry;
2354
+ xine_config_lookup_entry (bvw->priv->xine,
2355
+ "misc.amp_level", &entry);
2356
+ bvw->priv->volume = entry.num_value;
2358
+ xine_set_param (bvw->priv->stream,
2359
+ XINE_PARAM_AUDIO_AMP_LEVEL, bvw->priv->volume);
2362
+ return bvw->priv->volume;
2366
+bacon_video_widget_fullscreen_mode_available (BaconVideoWidget *bvw,
2371
+ /* Assume that ordinary fullscreen always works */
2373
+ case TV_OUT_NVTV_NTSC:
2374
+ case TV_OUT_NVTV_PAL:
2376
+ /* Make sure nvtv is initialized, it will not do any harm
2377
+ * if it is done twice any way */
2378
+ if (!(nvtv_simple_init() && nvtv_enable_autoresize(TRUE))) {
2379
+ nvtv_simple_enable(FALSE);
2381
+ return (nvtv_simple_is_available());
2387
+ const char * const *list;
2390
+ list = xine_list_video_output_plugins (bvw->priv->xine);
2391
+ for (i = 0; list[i] != NULL; i++) {
2392
+ if (strcmp ("dxr3", list[i]) == 0)
2398
+ g_assert_not_reached ();
2405
+bacon_video_widget_set_fullscreen (BaconVideoWidget *bvw, gboolean fullscreen)
2407
+ if (((bvw->priv->auto_resize == FALSE) || (bvw->priv->have_xrandr == FALSE)) &&
2408
+ (bvw->priv->tvout != TV_OUT_NVTV_NTSC) &&
2409
+ (bvw->priv->tvout != TV_OUT_NVTV_PAL))
2412
+ bvw->priv->fullscreen_mode = fullscreen;
2414
+ if (fullscreen == FALSE)
2417
+ /* If NVTV is used */
2418
+ if (nvtv_simple_get_state() == NVTV_SIMPLE_TV_ON) {
2419
+ nvtv_simple_switch(NVTV_SIMPLE_TV_OFF,0,0);
2421
+ /* Else if just auto resize is used */
2422
+ } else if (bvw->priv->auto_resize != FALSE) {
2424
+ bacon_restore (bvw->priv->screenid);
2427
+ /* Turn fullscreen on with NVTV if that option is on */
2428
+ } else if ((bvw->priv->tvout == TV_OUT_NVTV_NTSC) ||
2429
+ (bvw->priv->tvout == TV_OUT_NVTV_PAL)) {
2430
+ nvtv_simple_switch(NVTV_SIMPLE_TV_ON,
2431
+ bvw->priv->video_width,
2432
+ bvw->priv->video_height);
2434
+ /* Turn fullscreen on with autoresize */
2435
+ } else if (bvw->priv->auto_resize != FALSE) {
2436
+ bvw->priv->screenid = bacon_resize_get_current ();
2437
+ bacon_resize (bvw->priv->video_height,
2438
+ bvw->priv->video_width);
2443
+bacon_video_widget_set_show_cursor (BaconVideoWidget *bvw,
2444
+ gboolean show_cursor)
2446
+ g_return_if_fail (bvw != NULL);
2447
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
2448
+ g_return_if_fail (bvw->priv->xine != NULL);
2450
+ if (show_cursor == FALSE)
2452
+ eel_gdk_window_set_invisible_cursor (bvw->priv->video_window);
2454
+ gdk_window_set_cursor (bvw->priv->video_window, NULL);
2457
+ bvw->priv->cursor_shown = show_cursor;
2461
+bacon_video_widget_get_show_cursor (BaconVideoWidget *bvw)
2463
+ g_return_val_if_fail (bvw != NULL, FALSE);
2464
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), FALSE);
2465
+ g_return_val_if_fail (bvw->priv->xine != NULL, FALSE);
2467
+ return bvw->priv->cursor_shown;
2471
+bacon_video_widget_set_media_device (BaconVideoWidget *bvw, const char *path)
2473
+ xine_cfg_entry_t entry;
2476
+ bvw_config_helper_string (bvw->priv->xine, "input.dvd_device",
2478
+ entry.str_value = g_strdup (path);
2479
+ xine_config_update_entry (bvw->priv->xine, &entry);
2482
+ bvw_config_helper_string (bvw->priv->xine, "input.vcd_device",
2484
+ entry.str_value = g_strdup (path);
2485
+ xine_config_update_entry (bvw->priv->xine, &entry);
2487
+ /* VCD device for the new input plugin */
2488
+ bvw_config_helper_string (bvw->priv->xine, "vcd.default_device",
2490
+ entry.str_value = g_strdup (path);
2491
+ xine_config_update_entry (bvw->priv->xine, &entry);
2494
+ bvw_config_helper_string (bvw->priv->xine, "input.cdda_device",
2496
+ entry.str_value = g_strdup (path);
2497
+ xine_config_update_entry (bvw->priv->xine, &entry);
2501
+bacon_video_widget_set_proprietary_plugins_path (BaconVideoWidget *bvw,
2504
+ xine_cfg_entry_t entry;
2506
+ bvw_config_helper_string (bvw->priv->xine,
2507
+ "codec.win32_path", path, &entry);
2508
+ entry.str_value = g_strdup (path);
2509
+ xine_config_update_entry (bvw->priv->xine, &entry);
2511
+ bvw_config_helper_string (bvw->priv->xine,
2512
+ "codec.real_codecs_path", path, &entry);
2513
+ entry.str_value = g_strdup (path);
2514
+ xine_config_update_entry (bvw->priv->xine, &entry);
2516
+ /* And we try and create symlinks from /usr/lib/win32 to
2517
+ * the local user path */
2518
+ totem_create_symlinks ("/usr/lib/win32", path);
2519
+ totem_create_symlinks ("/usr/lib/RealPlayer9/Codecs/", path);
2520
+ totem_create_symlinks ("/usr/lib/RealPlayer9/users/Real/Codecs/", path);
2521
+ totem_create_symlinks ("/usr/lib/RealPlayer8/Codecs", path);
2525
+bacon_video_widget_set_connection_speed (BaconVideoWidget *bvw, int speed)
2527
+ xine_cfg_entry_t entry;
2529
+ g_return_if_fail (bvw != NULL);
2530
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
2531
+ g_return_if_fail (bvw->priv->xine != NULL);
2532
+ g_return_if_fail (speed > 0 || speed < 10);
2534
+ xine_config_register_enum (bvw->priv->xine,
2535
+ "input.mms_network_bandwidth",
2537
+ (char **) mms_bandwidth_strs,
2538
+ "Network bandwidth",
2539
+ NULL, 0, NULL, NULL);
2541
+ xine_config_lookup_entry (bvw->priv->xine,
2542
+ "input.mms_network_bandwidth", &entry);
2543
+ entry.num_value = speed;
2544
+ xine_config_update_entry (bvw->priv->xine, &entry);
2548
+bacon_video_widget_get_connection_speed (BaconVideoWidget *bvw)
2550
+ xine_cfg_entry_t entry;
2552
+ g_return_val_if_fail (bvw != NULL, 0);
2553
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 0);
2554
+ g_return_val_if_fail (bvw->priv->xine != NULL, 0);
2556
+ xine_config_register_enum (bvw->priv->xine,
2557
+ "input.mms_network_bandwidth",
2559
+ (char **) mms_bandwidth_strs,
2560
+ "Network bandwidth",
2561
+ NULL, 0, NULL, NULL);
2563
+ xine_config_lookup_entry (bvw->priv->xine,
2564
+ "input.mms_network_bandwidth", &entry);
2566
+ return entry.num_value;
2570
+bacon_video_widget_set_deinterlacing (BaconVideoWidget *bvw,
2571
+ gboolean deinterlace)
2573
+ g_return_if_fail (bvw != NULL);
2574
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
2575
+ g_return_if_fail (bvw->priv->xine != NULL);
2577
+ xine_set_param (bvw->priv->stream, XINE_PARAM_VO_DEINTERLACE,
2582
+bacon_video_widget_get_deinterlacing (BaconVideoWidget *bvw)
2584
+ g_return_val_if_fail (bvw != NULL, 0);
2585
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 0);
2586
+ g_return_val_if_fail (bvw->priv->xine != NULL, 0);
2588
+ return xine_get_param (bvw->priv->stream, XINE_PARAM_VO_DEINTERLACE);
2592
+bacon_video_widget_set_tv_out (BaconVideoWidget *bvw, TvOutType tvout)
2594
+ g_return_val_if_fail (bvw != NULL, FALSE);
2595
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), FALSE);
2596
+ g_return_val_if_fail (bvw->priv->xine != NULL, FALSE);
2598
+ if (tvout == TV_OUT_DXR3 || bvw->priv->tvout == TV_OUT_DXR3)
2600
+ xine_cfg_entry_t entry;
2602
+ xine_config_lookup_entry (bvw->priv->xine,
2603
+ "video.driver", &entry);
2604
+ entry.str_value = g_strdup (tvout == TV_OUT_DXR3 ?
2606
+ xine_config_update_entry (bvw->priv->xine, &entry);
2608
+ bvw->priv->tvout = tvout;
2614
+ if (tvout == TV_OUT_NVTV_PAL) {
2615
+ nvtv_simple_set_tvsystem(NVTV_SIMPLE_TVSYSTEM_PAL);
2616
+ } else if (tvout == TV_OUT_NVTV_NTSC) {
2617
+ nvtv_simple_set_tvsystem(NVTV_SIMPLE_TVSYSTEM_NTSC);
2621
+ bvw->priv->tvout = tvout;
2627
+bacon_video_widget_get_tv_out (BaconVideoWidget *bvw)
2629
+ g_return_val_if_fail (bvw != NULL, 0);
2630
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 0);
2631
+ g_return_val_if_fail (bvw->priv->xine != NULL, 0);
2633
+ return bvw->priv->tvout;
2637
+bacon_video_widget_set_show_visuals (BaconVideoWidget *bvw,
2638
+ gboolean show_visuals)
2640
+ g_return_val_if_fail (bvw != NULL, FALSE);
2641
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), FALSE);
2642
+ g_return_val_if_fail (bvw->priv->xine != NULL, FALSE);
2644
+ bvw->priv->show_vfx = show_visuals;
2645
+ show_vfx_update (bvw, show_visuals);
2651
+bacon_video_widget_get_visuals_list (BaconVideoWidget *bvw)
2653
+ const char * const* plugins;
2656
+ g_return_val_if_fail (bvw != NULL, NULL);
2657
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), NULL);
2658
+ g_return_val_if_fail (bvw->priv->xine != NULL, NULL);
2660
+ if (bvw->priv->visuals != NULL)
2661
+ return bvw->priv->visuals;
2663
+ plugins = xine_list_post_plugins_typed (bvw->priv->xine,
2664
+ XINE_POST_TYPE_AUDIO_VISUALIZATION);
2666
+ for (i = 0; plugins[i] != NULL; i++)
2668
+ bvw->priv->visuals = g_list_prepend
2669
+ (bvw->priv->visuals, g_strdup (plugins[i]));
2672
+ bvw->priv->visuals = g_list_reverse (bvw->priv->visuals);
2674
+ return bvw->priv->visuals;
2678
+bacon_video_widget_set_visuals (BaconVideoWidget *bvw, const char *name)
2680
+ xine_post_t *newvis;
2683
+ g_return_val_if_fail (bvw != NULL, FALSE);
2684
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), FALSE);
2685
+ g_return_val_if_fail (bvw->priv->xine != NULL, FALSE);
2687
+ if (bvw->priv->null_out != FALSE || bvw->priv->ao_driver == NULL)
2690
+ if (GTK_WIDGET_REALIZED (bvw) == FALSE)
2692
+ g_free (bvw->priv->vis_name);
2693
+ bvw->priv->vis_name = g_strdup (name);
2697
+ speed = xine_get_param (bvw->priv->stream, XINE_PARAM_SPEED);
2698
+ if (speed == XINE_SPEED_PAUSE && bvw->priv->using_vfx != FALSE)
2700
+ g_free (bvw->priv->queued_vis);
2701
+ if (strcmp (name, bvw->priv->vis_name) == 0)
2703
+ bvw->priv->queued_vis = NULL;
2705
+ bvw->priv->queued_vis = g_strdup (name);
2710
+ newvis = xine_post_init (bvw->priv->xine,
2712
+ &bvw->priv->ao_driver, &bvw->priv->vo_driver);
2714
+ if (newvis != NULL)
2716
+ g_free (bvw->priv->vis_name);
2717
+ bvw->priv->vis_name = g_strdup (name);
2719
+ if (bvw->priv->vis != NULL)
2721
+ xine_post_t *oldvis;
2723
+ oldvis = bvw->priv->vis;
2724
+ bvw->priv->vis = newvis;
2726
+ if (bvw->priv->using_vfx != FALSE)
2728
+ show_vfx_update (bvw, FALSE);
2729
+ show_vfx_update (bvw, TRUE);
2731
+ xine_post_dispose (bvw->priv->xine, oldvis);
2733
+ bvw->priv->vis = newvis;
2741
+bacon_video_widget_set_visuals_quality (BaconVideoWidget *bvw,
2742
+ VisualsQuality quality)
2744
+ xine_cfg_entry_t entry;
2747
+ g_return_if_fail (bvw != NULL);
2748
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
2749
+ g_return_if_fail (bvw->priv->xine != NULL);
2753
+ case VISUAL_SMALL:
2758
+ case VISUAL_NORMAL:
2763
+ case VISUAL_LARGE:
2768
+ case VISUAL_EXTRA_LARGE:
2774
+ /* shut up warnings */
2776
+ g_assert_not_reached ();
2779
+ bvw_config_helper_num (bvw->priv->xine, "post.goom_fps", fps, &entry);
2780
+ entry.num_value = fps;
2781
+ xine_config_update_entry (bvw->priv->xine, &entry);
2783
+ bvw_config_helper_num (bvw->priv->xine, "post.goom_width", w, &entry);
2784
+ entry.num_value = w;
2785
+ xine_config_update_entry (bvw->priv->xine, &entry);
2787
+ bvw_config_helper_num (bvw->priv->xine, "post.goom_height", h, &entry);
2788
+ entry.num_value = h;
2789
+ xine_config_update_entry (bvw->priv->xine, &entry);
2793
+bacon_video_widget_get_auto_resize (BaconVideoWidget *bvw)
2795
+ g_return_val_if_fail (bvw != NULL, FALSE);
2796
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), FALSE);
2797
+ g_return_val_if_fail (bvw->priv->xine != NULL, FALSE);
2799
+ return bvw->priv->auto_resize;
2803
+bacon_video_widget_set_auto_resize (BaconVideoWidget *bvw,
2804
+ gboolean auto_resize)
2806
+ g_return_if_fail (bvw != NULL);
2807
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
2808
+ g_return_if_fail (bvw->priv->xine != NULL);
2810
+ bvw->priv->auto_resize = auto_resize;
2814
+bacon_video_widget_get_current_time (BaconVideoWidget *bvw)
2816
+ int pos_time = 0, i = 0;
2817
+ int pos_stream, length_time;
2820
+ g_return_val_if_fail (bvw != NULL, 0);
2821
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 0);
2822
+ g_return_val_if_fail (bvw->priv->xine != NULL, 0);
2824
+ if (bacon_video_widget_is_playing (bvw) == FALSE)
2827
+ ret = xine_get_pos_length (bvw->priv->stream, &pos_stream,
2828
+ &pos_time, &length_time);
2830
+ while (ret == FALSE && i < 10)
2833
+ ret = xine_get_pos_length (bvw->priv->stream, &pos_stream,
2834
+ &pos_time, &length_time);
2838
+ if (bvw->priv->seeking == 1)
2840
+ return bvw->priv->seek_dest * length_time;
2841
+ } else if (bvw->priv->seeking == 2) {
2842
+ return bvw->priv->seek_dest_time;
2852
+bacon_video_widget_get_stream_length (BaconVideoWidget *bvw)
2854
+ int length_time = 0;
2855
+ int pos_stream, pos_time;
2857
+ g_return_val_if_fail (bvw != NULL, 0);
2858
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 0);
2859
+ g_return_val_if_fail (bvw->priv->xine != NULL, 0);
2861
+ if (bvw->priv->mrl == NULL)
2864
+ xine_get_pos_length (bvw->priv->stream, &pos_stream,
2865
+ &pos_time, &length_time);
2867
+ return length_time;
2871
+bacon_video_widget_is_playing (BaconVideoWidget *bvw)
2873
+ g_return_val_if_fail (bvw != NULL, 0);
2874
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 0);
2875
+ g_return_val_if_fail (bvw->priv->xine != NULL, 0);
2877
+ if (bvw->priv->stream == NULL)
2880
+ return (xine_get_status (bvw->priv->stream) == XINE_STATUS_PLAY && xine_get_param (bvw->priv->stream, XINE_PARAM_SPEED) == XINE_SPEED_NORMAL);
2884
+bacon_video_widget_is_seekable (BaconVideoWidget *bvw)
2886
+ g_return_val_if_fail (bvw != NULL, 0);
2887
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 0);
2888
+ g_return_val_if_fail (bvw->priv->xine != NULL, 0);
2890
+ if (bvw->priv->mrl == NULL)
2893
+ if (bacon_video_widget_get_stream_length (bvw) == 0)
2896
+ return xine_get_stream_info (bvw->priv->stream,
2897
+ XINE_STREAM_INFO_SEEKABLE);
2901
+bacon_video_widget_can_play (BaconVideoWidget *bvw, MediaType type)
2906
+ return bvw->priv->can_dvd;
2908
+ return bvw->priv->can_vcd;
2910
+ return bvw->priv->can_cdda;
2916
+G_CONST_RETURN char
2917
+**bacon_video_widget_get_mrls (BaconVideoWidget *bvw, MediaType type)
2922
+ g_return_val_if_fail (bvw != NULL, 0);
2923
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 0);
2924
+ g_return_val_if_fail (bvw->priv->xine != NULL, 0);
2926
+ if (type == MEDIA_DVD)
2927
+ plugin_id = "DVD";
2928
+ else if (type == MEDIA_VCD)
2929
+ plugin_id = "VCD";
2930
+ else if (type == MEDIA_CDDA)
2935
+ return (G_CONST_RETURN char **) xine_get_autoplay_mrls
2936
+ (bvw->priv->xine, plugin_id, &num_mrls);
2940
+bacon_video_widget_set_video_device (BaconVideoWidget *bvw, const char *path)
2942
+ xine_cfg_entry_t entry;
2944
+ bvw_config_helper_string (bvw->priv->xine,
2945
+ "input.v4l_video_device_path", path, &entry);
2946
+ entry.str_value = g_strdup (path);
2947
+ xine_config_update_entry (bvw->priv->xine, &entry);
2951
+bacon_video_widget_set_aspect_ratio (BaconVideoWidget *bvw,
2952
+ BaconVideoWidgetAspectRatio ratio)
2954
+ g_return_if_fail (bvw != NULL);
2955
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
2956
+ g_return_if_fail (bvw->priv->xine != NULL);
2958
+ xine_set_param (bvw->priv->stream, XINE_PARAM_VO_ASPECT_RATIO, ratio);
2962
+bacon_video_widget_get_aspect_ratio (BaconVideoWidget *bvw)
2964
+ g_return_val_if_fail (bvw != NULL, 0);
2965
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 0);
2966
+ g_return_val_if_fail (bvw->priv->xine != NULL, 0);
2968
+ return xine_get_param (bvw->priv->stream, XINE_PARAM_VO_ASPECT_RATIO);
2972
+bacon_video_widget_ratio_fits_screen (BaconVideoWidget *bvw, gfloat ratio)
2974
+ GdkRectangle fullscreen_rect;
2977
+ g_return_val_if_fail (bvw != NULL, FALSE);
2978
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), FALSE);
2979
+ g_return_val_if_fail (bvw->priv->xine != NULL, FALSE);
2981
+ new_w = bvw->priv->video_width * ratio;
2982
+ new_h = bvw->priv->video_height * ratio;
2984
+ gdk_screen_get_monitor_geometry (gdk_screen_get_default (),
2985
+ gdk_screen_get_monitor_at_window
2986
+ (gdk_screen_get_default (),
2987
+ bvw->priv->video_window),
2988
+ &fullscreen_rect);
2990
+ if (new_w > (fullscreen_rect.width - 128) ||
2991
+ new_h > (fullscreen_rect.height - 128))
3000
+bacon_video_widget_set_scale_ratio (BaconVideoWidget *bvw, gfloat ratio)
3002
+ GtkWidget *toplevel, *widget;
3003
+ int new_w, new_h, win_w, win_h;
3005
+ g_return_if_fail (bvw != NULL);
3006
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
3007
+ g_return_if_fail (bvw->priv->xine != NULL);
3008
+ g_return_if_fail (ratio >= 0);
3010
+ if (bvw->priv->fullscreen_mode != FALSE)
3013
+ /* Try best fit for the screen */
3016
+ if (bacon_video_widget_ratio_fits_screen (bvw, 2) != FALSE)
3019
+ } else if (bacon_video_widget_ratio_fits_screen (bvw, 1)
3022
+ } else if (bacon_video_widget_ratio_fits_screen (bvw, 0.5)
3029
+ /* don't scale to something bigger than the screen, and leave
3031
+ if (bacon_video_widget_ratio_fits_screen (bvw, ratio) == FALSE)
3035
+ widget = GTK_WIDGET (bvw);
3037
+ toplevel = gtk_widget_get_toplevel (widget);
3039
+ /* Get the size of the toplevel window */
3040
+ gdk_drawable_get_size (GDK_DRAWABLE (toplevel->window),
3043
+ /* Calculate the new size of the window, depending on the size of the
3044
+ * video widget, and the new size of the video */
3045
+ new_w = win_w - widget->allocation.width +
3046
+ bvw->priv->video_width * ratio;
3047
+ new_h = win_h - widget->allocation.height +
3048
+ bvw->priv->video_height * ratio;
3050
+ /* Change the minimum size of the widget
3051
+ * but only if we're getting a smaller window */
3052
+ if (new_w < widget->allocation.width
3053
+ || new_h < widget->allocation.height)
3055
+ gtk_widget_set_size_request (widget,
3056
+ bvw->priv->video_width * ratio,
3057
+ bvw->priv->video_height * ratio);
3060
+ gtk_window_resize (GTK_WINDOW (toplevel), new_w, new_h);
3064
+bacon_video_widget_get_video_property (BaconVideoWidget *bvw,
3065
+ BaconVideoWidgetVideoProperty type)
3067
+ g_return_val_if_fail (bvw != NULL, 65535 / 2);
3068
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 65535 / 2);
3069
+ g_return_val_if_fail (bvw->priv->xine != NULL, 65535 / 2);
3071
+ return xine_get_param (bvw->priv->stream, video_props[type]);
3075
+bacon_video_widget_set_video_property (BaconVideoWidget *bvw,
3076
+ BaconVideoWidgetVideoProperty type, int value)
3078
+ g_return_if_fail (bvw != NULL);
3079
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
3080
+ g_return_if_fail (bvw->priv->xine != NULL);
3082
+ if ( !(value < 65535 && value > 0) )
3085
+ xine_set_param (bvw->priv->stream, video_props[type], value);
3086
+ gconf_client_set_int (bvw->priv->gc, video_props_str[type], value, NULL);
3089
+BaconVideoWidgetAudioOutType
3090
+bacon_video_widget_get_audio_out_type (BaconVideoWidget *bvw)
3092
+ g_return_val_if_fail (bvw != NULL, BVW_AUDIO_SOUND_STEREO);
3093
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw),
3094
+ BVW_AUDIO_SOUND_STEREO);
3095
+ g_return_val_if_fail (bvw->priv->xine != NULL, BVW_AUDIO_SOUND_STEREO);
3097
+ return gconf_client_get_int (bvw->priv->gc,
3098
+ GCONF_PREFIX"/audio_output_type", NULL);
3102
+bacon_video_widget_set_audio_out_type (BaconVideoWidget *bvw,
3103
+ BaconVideoWidgetAudioOutType type)
3105
+ xine_cfg_entry_t entry;
3108
+ g_return_if_fail (bvw != NULL);
3109
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
3110
+ g_return_if_fail (bvw->priv->xine != NULL);
3112
+ xine_config_register_enum (bvw->priv->xine,
3113
+ "audio.speaker_arrangement",
3115
+ (char **) audio_out_types_strs,
3116
+ "Speaker arrangement",
3117
+ NULL, 0, NULL, NULL);
3119
+ gconf_client_set_int (bvw->priv->gc,
3120
+ GCONF_PREFIX"/audio_output_type",
3124
+ case BVW_AUDIO_SOUND_STEREO:
3127
+ case BVW_AUDIO_SOUND_4CHANNEL:
3130
+ case BVW_AUDIO_SOUND_5CHANNEL:
3133
+ case BVW_AUDIO_SOUND_51CHANNEL:
3136
+ case BVW_AUDIO_SOUND_AC3PASSTHRU:
3141
+ g_warning ("Unsupported audio type %d selected", type);
3144
+ xine_config_lookup_entry (bvw->priv->xine,
3145
+ "audio.speaker_arrangement", &entry);
3146
+ entry.num_value = value;
3147
+ xine_config_update_entry (bvw->priv->xine, &entry);
3151
+bacon_video_widget_get_metadata_string (BaconVideoWidget *bvw, BaconVideoWidgetMetadataType type,
3154
+ const char *string = NULL;
3156
+ g_value_init (value, G_TYPE_STRING);
3158
+ if (bvw->priv->stream == NULL)
3160
+ g_value_set_string (value, string);
3166
+ case BVW_INFO_TITLE:
3167
+ string = xine_get_meta_info (bvw->priv->stream,
3168
+ XINE_META_INFO_TITLE);
3170
+ case BVW_INFO_ARTIST:
3171
+ string = xine_get_meta_info (bvw->priv->stream,
3172
+ XINE_META_INFO_ARTIST);
3174
+ case BVW_INFO_YEAR:
3175
+ string = xine_get_meta_info (bvw->priv->stream,
3176
+ XINE_META_INFO_YEAR);
3178
+ case BVW_INFO_VIDEO_CODEC:
3179
+ string = xine_get_meta_info (bvw->priv->stream,
3180
+ XINE_META_INFO_VIDEOCODEC);
3182
+ case BVW_INFO_AUDIO_CODEC:
3183
+ string = xine_get_meta_info (bvw->priv->stream,
3184
+ XINE_META_INFO_AUDIOCODEC);
3186
+ case BVW_INFO_CDINDEX:
3187
+ string = xine_get_meta_info (bvw->priv->stream,
3188
+ XINE_META_INFO_CDINDEX_DISCID);
3191
+ g_assert_not_reached ();
3194
+ if (string != NULL && string[0] == '\0')
3197
+ if (string != NULL)
3199
+ if (g_utf8_validate (string, -1, NULL) == FALSE)
3203
+ utf8 = g_locale_to_utf8 (string, -1, NULL, NULL, NULL);
3204
+ g_value_set_string (value, utf8);
3210
+ g_value_set_string (value, string);
3216
+bacon_video_widget_get_metadata_int (BaconVideoWidget *bvw,
3217
+ BaconVideoWidgetMetadataType type, GValue *value)
3221
+ g_value_init (value, G_TYPE_INT);
3223
+ if (bvw->priv->stream == NULL)
3225
+ g_value_set_int (value, 0);
3231
+ case BVW_INFO_DURATION:
3232
+ integer = bacon_video_widget_get_stream_length (bvw) / 1000;
3234
+ case BVW_INFO_DIMENSION_X:
3235
+ integer = xine_get_stream_info (bvw->priv->stream,
3236
+ XINE_STREAM_INFO_VIDEO_WIDTH);
3238
+ case BVW_INFO_DIMENSION_Y:
3239
+ integer = xine_get_stream_info (bvw->priv->stream,
3240
+ XINE_STREAM_INFO_VIDEO_HEIGHT);
3242
+ case BVW_INFO_VIDEO_FOURCC:
3243
+ integer = (guint32) bvw->priv->video_fcc;
3245
+ case BVW_INFO_FPS:
3246
+ if (xine_get_stream_info (bvw->priv->stream,
3247
+ XINE_STREAM_INFO_FRAME_DURATION) != 0)
3249
+ integer = 90000 / xine_get_stream_info
3250
+ (bvw->priv->stream,
3251
+ XINE_STREAM_INFO_FRAME_DURATION);
3256
+ case BVW_INFO_BITRATE:
3257
+ integer = xine_get_stream_info (bvw->priv->stream,
3258
+ XINE_STREAM_INFO_AUDIO_BITRATE) / 1000;
3260
+ case BVW_INFO_AUDIO_FOURCC:
3261
+ integer = (guint32) bvw->priv->audio_fcc;
3264
+ g_assert_not_reached ();
3267
+ g_value_set_int (value, integer);
3273
+bacon_video_widget_get_metadata_bool (BaconVideoWidget *bvw,
3274
+ BaconVideoWidgetMetadataType type, GValue *value)
3276
+ gboolean boolean = FALSE;
3278
+ g_value_init (value, G_TYPE_BOOLEAN);
3280
+ if (bvw->priv->stream == NULL)
3282
+ g_value_set_boolean (value, FALSE);
3288
+ case BVW_INFO_HAS_VIDEO:
3289
+ boolean = xine_get_stream_info (bvw->priv->stream,
3290
+ XINE_STREAM_INFO_HAS_VIDEO);
3292
+ case BVW_INFO_HAS_AUDIO:
3293
+ boolean = xine_get_stream_info (bvw->priv->stream,
3294
+ XINE_STREAM_INFO_HAS_AUDIO);
3297
+ g_assert_not_reached ();
3300
+ g_value_set_boolean (value, boolean);
3306
+bacon_video_widget_get_metadata (BaconVideoWidget *bvw,
3307
+ BaconVideoWidgetMetadataType type, GValue *value)
3309
+ g_return_if_fail (bvw != NULL);
3310
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
3311
+ g_return_if_fail (bvw->priv->xine != NULL);
3312
+ g_return_if_fail (value != NULL);
3316
+ case BVW_INFO_TITLE:
3317
+ case BVW_INFO_ARTIST:
3318
+ case BVW_INFO_YEAR:
3319
+ case BVW_INFO_VIDEO_CODEC:
3320
+ case BVW_INFO_AUDIO_CODEC:
3321
+ bacon_video_widget_get_metadata_string (bvw, type, value);
3323
+ case BVW_INFO_DURATION:
3324
+ case BVW_INFO_DIMENSION_X:
3325
+ case BVW_INFO_DIMENSION_Y:
3326
+ case BVW_INFO_VIDEO_FOURCC:
3327
+ case BVW_INFO_FPS:
3328
+ case BVW_INFO_BITRATE:
3329
+ case BVW_INFO_AUDIO_FOURCC:
3330
+ bacon_video_widget_get_metadata_int (bvw, type, value);
3332
+ case BVW_INFO_HAS_VIDEO:
3333
+ case BVW_INFO_HAS_AUDIO:
3334
+ bacon_video_widget_get_metadata_bool (bvw, type, value);
3337
+ g_assert_not_reached ();
3344
+*bacon_video_widget_properties_get_title (BaconVideoWidget *bvw)
3346
+ const char *short_title, *artist;
3348
+ artist = xine_get_meta_info (bvw->priv->stream, XINE_META_INFO_ARTIST);
3349
+ short_title = xine_get_meta_info (bvw->priv->stream,
3350
+ XINE_META_INFO_TITLE);
3352
+ if (artist == NULL && short_title == NULL)
3355
+ if (artist == NULL && short_title != NULL)
3356
+ return g_strdup (short_title);
3358
+ if (artist != NULL && short_title != NULL)
3359
+ return g_strdup_printf ("%s - %s", artist, short_title);
3365
+*bacon_video_widget_get_languages (BaconVideoWidget *bvw)
3367
+ GList *list = NULL;
3369
+ char lang[XINE_LANG_MAX];
3371
+ for(i = 0; i < 32; i++)
3373
+ memset (&lang, 0, sizeof (lang));
3375
+ if (xine_get_audio_lang(bvw->priv->stream, i, lang) == 1)
3377
+ list = g_list_prepend (list,
3378
+ (gpointer) g_strdup (lang));
3382
+ return g_list_reverse (list);
3386
+bacon_video_widget_get_language (BaconVideoWidget *bvw)
3388
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), -1);
3389
+ g_return_val_if_fail (bvw->priv->stream != NULL, -1);
3391
+ return xine_get_param (bvw->priv->stream,
3392
+ XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
3396
+bacon_video_widget_set_language (BaconVideoWidget *bvw, int language)
3398
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
3399
+ g_return_if_fail (bvw->priv->stream != NULL);
3401
+ xine_set_param (bvw->priv->stream,
3402
+ XINE_PARAM_AUDIO_CHANNEL_LOGICAL, language);
3406
+*bacon_video_widget_get_subtitles (BaconVideoWidget *bvw)
3408
+ GList *list = NULL;
3410
+ char lang[XINE_LANG_MAX];
3412
+ for(i = 0; i < 32; i++)
3414
+ memset (&lang, 0, sizeof (lang));
3416
+ if (xine_get_spu_lang(bvw->priv->stream, i, lang) == 1)
3418
+ list = g_list_prepend (list,
3419
+ (gpointer) g_strdup (lang));
3423
+ return g_list_reverse (list);
3427
+bacon_video_widget_get_subtitle (BaconVideoWidget *bvw)
3429
+ return xine_get_param (bvw->priv->stream, XINE_PARAM_SPU_CHANNEL);
3433
+bacon_video_widget_set_subtitle (BaconVideoWidget *bvw, int subtitle)
3435
+ xine_set_param (bvw->priv->stream, XINE_PARAM_SPU_CHANNEL, subtitle);
3439
+bacon_video_widget_can_get_frames (BaconVideoWidget *bvw, GError **error)
3441
+ g_return_val_if_fail (bvw != NULL, FALSE);
3442
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), FALSE);
3443
+ g_return_val_if_fail (bvw->priv->xine != NULL, FALSE);
3445
+ if (xine_get_status (bvw->priv->stream) != XINE_STATUS_PLAY
3446
+ && bvw->priv->logo_mode == FALSE)
3448
+ g_set_error (error, 0, 0, _("Movie is not playing."));
3452
+ if (xine_get_stream_info (bvw->priv->stream,
3453
+ XINE_STREAM_INFO_HAS_VIDEO) == FALSE
3454
+ && bvw->priv->using_vfx == FALSE)
3456
+ g_set_error (error, 0, 0, _("No video to capture."));
3460
+ if (xine_get_stream_info (bvw->priv->stream,
3461
+ XINE_STREAM_INFO_VIDEO_HANDLED) == FALSE)
3463
+ g_set_error (error, 0, 0, _("Video codec is not handled."));
3471
+bacon_video_widget_get_current_frame (BaconVideoWidget *bvw)
3473
+ GdkPixbuf *pixbuf = NULL;
3474
+ uint8_t *yuv, *y, *u, *v, *rgb;
3475
+ int width, height, ratio, format;
3477
+ g_return_val_if_fail (bvw != NULL, NULL);
3478
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), NULL);
3479
+ g_return_val_if_fail (bvw->priv->xine != NULL, NULL);
3481
+ if (xine_get_current_frame (bvw->priv->stream, &width, &height,
3482
+ &ratio, &format, NULL) == 0)
3485
+ if (width == 0 || height == 0)
3488
+ yuv = malloc ((width + 8) * (height + 1) * 2);
3492
+ if (xine_get_current_frame (bvw->priv->stream, &width, &height,
3493
+ &ratio, &format, yuv) == 0)
3499
+ /* Convert to yv12 */
3501
+ case XINE_IMGFMT_YUY2:
3503
+ uint8_t *yuy2 = yuv;
3505
+ yuv = malloc (width * height * 2);
3507
+ u = yuv + width * height;
3508
+ v = yuv + width * height * 5 / 4;
3510
+ yuy2toyv12 (y, u, v, yuy2, width, height);
3515
+ case XINE_IMGFMT_YV12:
3517
+ u = yuv + width * height;
3518
+ v = yuv + width * height * 5 / 4;
3521
+ g_warning ("Format '%.4s' unsupported", (char *) &format);
3526
+ /* Convert to rgb */
3527
+ rgb = yv12torgb (y, u, v, width, height);
3529
+ pixbuf = gdk_pixbuf_new_from_data (rgb,
3530
+ GDK_COLORSPACE_RGB, FALSE,
3531
+ 8, width, height, 3 * width,
3532
+ (GdkPixbufDestroyNotify) g_free, NULL);
3534
+ /* MPEG streams have ratio information */
3535
+ ratio = xine_get_stream_info (bvw->priv->stream,
3536
+ XINE_STREAM_INFO_VIDEO_RATIO);
3538
+ if (ratio != 10000.0 && ratio != 0.0)
3542
+ if (ratio > 10000.0)
3543
+ tmp = gdk_pixbuf_scale_simple (pixbuf,
3544
+ (int) (height * ratio / 10000), height,
3545
+ GDK_INTERP_BILINEAR);
3547
+ tmp = gdk_pixbuf_scale_simple (pixbuf,
3548
+ width, (int) (width * ratio / 10000),
3549
+ GDK_INTERP_BILINEAR);
3551
+ gdk_pixbuf_unref (pixbuf);