~ubuntu-branches/ubuntu/saucy/totem/saucy-proposed

« back to all changes in this revision

Viewing changes to debian/patches/10_vcd_hang.dpatch

  • Committer: Bazaar Package Importer
  • Author(s): Loic Minier, Sebastien Bacher, Loic Minier
  • Date: 2007-03-08 14:51:55 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070308145155-cnu1r0s1z4ffcxza
Tags: 2.16.5-3
[ Sebastien Bacher ]
* debian/patches/30_dlopen_noremove_dbus_glib.dpatch:
  - fix "crash because NPPVpluginKeepLibraryInMemory is broken in gecko",
    patch from Alexander Sack (GNOME bug #415389)

[ Loic Minier ]
* Urgency medium.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#! /bin/sh -e
2
 
## 10_vcd_hang.dpatch by Sebastien Bacher <seb128@debian.org>
3
 
##
4
 
## All lines beginning with `## DP:' are a description of the patch.
5
 
## DP: No description.
6
 
 
7
 
if [ $# -lt 1 ]; then
8
 
    echo "`basename $0`: script expects -patch|-unpatch as argument" >&2
9
 
    exit 1
10
 
fi
11
 
 
12
 
[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
13
 
patch_opts="${patch_opts:--f --no-backup-if-mismatch} ${2:+-d $2}"
14
 
 
15
 
case "$1" in
16
 
    -patch) patch -p1 ${patch_opts} < $0;;
17
 
    -unpatch) patch -R -p1 ${patch_opts} < $0;;
18
 
    *)
19
 
        echo "`basename $0`: script expects -patch|-unpatch as argument" >&2
20
 
        exit 1;;
21
 
esac
22
 
 
23
 
exit 0
24
 
 
25
 
@DPATCH@
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);
32
 
 
33
 
-       /* VCD device for the new input plugin */
34
 
-       bvw_config_helper_string (bvw->priv->xine, "vcd.default_device",
35
 
-                       path, &entry);
36
 
-       entry.str_value = g_strdup (path);
37
 
-       xine_config_update_entry (bvw->priv->xine, &entry);
38
 
-
39
 
        /* CDDA device */
40
 
        bvw_config_helper_string (bvw->priv->xine, "input.cdda_device",
41
 
                        path, &entry);
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
45
 
@@ -0,0 +1,3512 @@
46
 
+/* 
47
 
+ * Copyright (C) 2001-2002 the xine project
48
 
+ *     Heavily modified by Bastien Nocera <hadess@hadess.net>
49
 
+ *
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.
54
 
+ *
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.
59
 
+ *
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.
63
 
+ *
64
 
+ * $Id: bacon-video-widget-xine.c,v 1.118 2004/05/30 12:21:10 hadess Exp $
65
 
+ *
66
 
+ * the xine engine in a widget - implementation
67
 
+ */
68
 
+
69
 
+#include <config.h>
70
 
+
71
 
+#ifdef HAVE_NVTV
72
 
+#include <nvtv_simple.h>
73
 
+#endif 
74
 
+
75
 
+
76
 
+/* system */
77
 
+#include <math.h>
78
 
+#include <string.h>
79
 
+#include <stdio.h>
80
 
+#include <stdlib.h>
81
 
+/* X11 */
82
 
+#include <X11/X.h>
83
 
+#include <X11/Xlib.h>
84
 
+/* gtk+/gnome */
85
 
+#include <gdk/gdkx.h>
86
 
+#include <gtk/gtk.h>
87
 
+#include <gconf/gconf-client.h>
88
 
+/* xine */
89
 
+#include <xine.h>
90
 
+
91
 
+#include "debug.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"
97
 
+
98
 
+#include <libintl.h>
99
 
+#define _(String) gettext (String)
100
 
+#ifdef gettext_noop
101
 
+#   define N_(String) gettext_noop (String)
102
 
+#else
103
 
+#   define N_(String) (String)
104
 
+#endif
105
 
+
106
 
+#define DEFAULT_HEIGHT 315
107
 
+#define DEFAULT_WIDTH 420
108
 
+#define CONFIG_FILE ".gnome2"G_DIR_SEPARATOR_S"totem_config"
109
 
+
110
 
+/* Signals */
111
 
+enum {
112
 
+       ERROR,
113
 
+       EOS,
114
 
+       TITLE_CHANGE,
115
 
+       CHANNELS_CHANGE,
116
 
+       TICK,
117
 
+       GOT_METADATA,
118
 
+       BUFFERING,
119
 
+       SPEED_WARNING,
120
 
+       LAST_SIGNAL
121
 
+};
122
 
+
123
 
+/* Enum for none-signal stuff that needs to go through the AsyncQueue */
124
 
+enum {
125
 
+       RATIO,
126
 
+       TITLE_CHANGE_ASYNC,
127
 
+       EOS_ASYNC,
128
 
+       CHANNELS_CHANGE_ASYNC,
129
 
+       BUFFERING_ASYNC,
130
 
+       MESSAGE_ASYNC,
131
 
+       SPEED_WARNING_ASYNC
132
 
+};
133
 
+
134
 
+typedef struct {
135
 
+       int signal;
136
 
+       char *msg;
137
 
+       int num;
138
 
+} signal_data;
139
 
+
140
 
+/* Arguments */
141
 
+enum {
142
 
+       PROP_0,
143
 
+       PROP_LOGO_MODE,
144
 
+       PROP_SPEED,
145
 
+       PROP_POSITION,
146
 
+       PROP_CURRENT_TIME,
147
 
+       PROP_STREAM_LENGTH,
148
 
+       PROP_PLAYING,
149
 
+       PROP_SEEKABLE,
150
 
+       PROP_SHOWCURSOR,
151
 
+       PROP_MEDIADEV,
152
 
+       PROP_SHOW_VISUALS
153
 
+};
154
 
+
155
 
+static int video_props[4] = {
156
 
+       XINE_PARAM_VO_BRIGHTNESS,
157
 
+       XINE_PARAM_VO_CONTRAST,
158
 
+       XINE_PARAM_VO_SATURATION,
159
 
+       XINE_PARAM_VO_HUE
160
 
+};
161
 
+static char *video_props_str[4] = {
162
 
+       GCONF_PREFIX"/brightness",
163
 
+       GCONF_PREFIX"/contrast",
164
 
+       GCONF_PREFIX"/saturation",
165
 
+       GCONF_PREFIX"/hue"
166
 
+};
167
 
+
168
 
+struct BaconVideoWidgetPrivate {
169
 
+       /* Xine stuff */
170
 
+       xine_t *xine;
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;
176
 
+       gboolean started;
177
 
+
178
 
+       /* Configuration */
179
 
+       GConfClient *gc;
180
 
+       gboolean null_out;
181
 
+       char *mrl;
182
 
+
183
 
+       /* X stuff */
184
 
+       Display *display;
185
 
+       int screen;
186
 
+       GdkWindow *video_window;
187
 
+
188
 
+       /* Visual effects */
189
 
+       char *vis_name;
190
 
+       gboolean show_vfx;
191
 
+       gboolean using_vfx;
192
 
+       xine_post_t *vis;
193
 
+       GList *visuals;
194
 
+       char *queued_vis;
195
 
+
196
 
+       /* Seeking stuff */
197
 
+       int seeking;
198
 
+       float seek_dest;
199
 
+       gint64 seek_dest_time;
200
 
+
201
 
+       /* Other stuff */
202
 
+       int xpos, ypos;
203
 
+       gboolean can_dvd, can_vcd, can_cdda;
204
 
+       gboolean logo_mode;
205
 
+       guint tick_id;
206
 
+       gboolean have_xrandr;
207
 
+       gboolean auto_resize;
208
 
+       int volume;
209
 
+       TvOutType tvout;
210
 
+       guint32 video_fcc, audio_fcc;
211
 
+       gboolean is_live;
212
 
+
213
 
+       GAsyncQueue *queue;
214
 
+       int video_width, video_height;
215
 
+       int init_width, init_height;
216
 
+
217
 
+       /* fullscreen stuff */
218
 
+       gboolean fullscreen_mode;
219
 
+       gboolean cursor_shown;
220
 
+       int screenid;
221
 
+};
222
 
+
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)",
234
 
+       "1.5 Mbps (T1)",
235
 
+       "10.5 Mbps (LAN)",
236
 
+       NULL
237
 
+};
238
 
+
239
 
+static const char *audio_out_types_strs[] = {
240
 
+       "Mono",
241
 
+       "Stereo",
242
 
+       "Headphones",
243
 
+       "A52_Passthru",
244
 
+       "Surround21",
245
 
+       "Surround3",
246
 
+       "Surround4",
247
 
+       "Surround41",
248
 
+       "Surround5",
249
 
+       "Surround51",
250
 
+       "Surround6",
251
 
+       "Surround61",
252
 
+       "Surround71",
253
 
+       NULL
254
 
+};
255
 
+
256
 
+static const char *demux_strategies_str[] = {
257
 
+       "default",
258
 
+       "reverse",
259
 
+       "content",
260
 
+       "extension",
261
 
+       NULL
262
 
+};
263
 
+
264
 
+static void bacon_video_widget_class_init (BaconVideoWidgetClass *klass);
265
 
+static void bacon_video_widget_instance_init (BaconVideoWidget *bvw);
266
 
+
267
 
+static void setup_config (BaconVideoWidget *bvw);
268
 
+
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);
273
 
+
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);
277
 
+
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);
284
 
+
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,
292
 
+               GError **error);
293
 
+static gboolean bacon_video_widget_tick_send (BaconVideoWidget *bvw);
294
 
+
295
 
+static GtkWidgetClass *parent_class = NULL;
296
 
+
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);
300
 
+
301
 
+static int bvw_table_signals[LAST_SIGNAL] = { 0 };
302
 
+
303
 
+GType
304
 
+bacon_video_widget_get_type (void)
305
 
+{
306
 
+       static GType bacon_video_widget_type = 0;
307
 
+
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,
319
 
+               };
320
 
+
321
 
+               bacon_video_widget_type = g_type_register_static
322
 
+                       (GTK_TYPE_BOX, "BaconVideoWidget",
323
 
+                        &bacon_video_widget_info, (GTypeFlags)0);
324
 
+       }
325
 
+
326
 
+       return bacon_video_widget_type;
327
 
+}
328
 
+
329
 
+static void
330
 
+bacon_video_widget_class_init (BaconVideoWidgetClass *klass)
331
 
+{
332
 
+
333
 
+       GObjectClass *object_class;
334
 
+       GtkWidgetClass *widget_class;
335
 
+
336
 
+       object_class = (GObjectClass *) klass;
337
 
+       widget_class = (GtkWidgetClass *) klass;
338
 
+
339
 
+       parent_class = gtk_type_class (gtk_box_get_type ());
340
 
+
341
 
+       /* GtkWidget */
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;
349
 
+
350
 
+       /* GObject */
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;
354
 
+
355
 
+       /* Properties */
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));
380
 
+
381
 
+       /* Signals */
382
 
+       bvw_table_signals[ERROR] =
383
 
+               g_signal_new ("error",
384
 
+                               G_TYPE_FROM_CLASS (object_class),
385
 
+                               G_SIGNAL_RUN_LAST,
386
 
+                               G_STRUCT_OFFSET (BaconVideoWidgetClass, error),
387
 
+                               NULL, NULL,
388
 
+                               baconvideowidget_marshal_VOID__STRING_BOOLEAN,
389
 
+                               G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
390
 
+
391
 
+       bvw_table_signals[EOS] =
392
 
+               g_signal_new ("eos",
393
 
+                               G_TYPE_FROM_CLASS (object_class),
394
 
+                               G_SIGNAL_RUN_LAST,
395
 
+                               G_STRUCT_OFFSET (BaconVideoWidgetClass, eos),
396
 
+                               NULL, NULL,
397
 
+                               g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
398
 
+                               
399
 
+       bvw_table_signals[GOT_METADATA] =
400
 
+               g_signal_new ("got-metadata",
401
 
+                               G_TYPE_FROM_CLASS (object_class),
402
 
+                               G_SIGNAL_RUN_LAST,
403
 
+                               G_STRUCT_OFFSET (BaconVideoWidgetClass, got_metadata),
404
 
+                               NULL, NULL,
405
 
+                               g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
406
 
+
407
 
+       bvw_table_signals[TITLE_CHANGE] =
408
 
+               g_signal_new ("title-change",
409
 
+                               G_TYPE_FROM_CLASS (object_class),
410
 
+                               G_SIGNAL_RUN_LAST,
411
 
+                               G_STRUCT_OFFSET (BaconVideoWidgetClass, title_change),
412
 
+                               NULL, NULL,
413
 
+                               g_cclosure_marshal_VOID__STRING,
414
 
+                               G_TYPE_NONE, 1, G_TYPE_STRING);
415
 
+
416
 
+       bvw_table_signals[CHANNELS_CHANGE] =
417
 
+               g_signal_new ("channels-change",
418
 
+                               G_TYPE_FROM_CLASS (object_class),
419
 
+                               G_SIGNAL_RUN_LAST,
420
 
+                               G_STRUCT_OFFSET (BaconVideoWidgetClass, channels_change),
421
 
+                               NULL, NULL,
422
 
+                               g_cclosure_marshal_VOID__VOID,
423
 
+                               G_TYPE_NONE, 0);
424
 
+
425
 
+       bvw_table_signals[TICK] =
426
 
+               g_signal_new ("tick",
427
 
+                               G_TYPE_FROM_CLASS (object_class),
428
 
+                               G_SIGNAL_RUN_LAST,
429
 
+                               G_STRUCT_OFFSET (BaconVideoWidgetClass, tick),
430
 
+                               NULL, NULL,
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);
434
 
+
435
 
+       bvw_table_signals[BUFFERING] =
436
 
+               g_signal_new ("buffering",
437
 
+                               G_TYPE_FROM_CLASS (object_class),
438
 
+                               G_SIGNAL_RUN_LAST,
439
 
+                               G_STRUCT_OFFSET (BaconVideoWidgetClass, buffering),
440
 
+                               NULL, NULL,
441
 
+                               g_cclosure_marshal_VOID__INT,
442
 
+                               G_TYPE_NONE, 1, G_TYPE_INT);
443
 
+
444
 
+       bvw_table_signals[SPEED_WARNING] =
445
 
+               g_signal_new ("speed-warning",
446
 
+                               G_TYPE_FROM_CLASS (object_class),
447
 
+                               G_SIGNAL_RUN_LAST,
448
 
+                               G_STRUCT_OFFSET (BaconVideoWidgetClass, speed_warning),
449
 
+                               NULL, NULL,
450
 
+                               g_cclosure_marshal_VOID__VOID,
451
 
+                               G_TYPE_NONE, 0);
452
 
+}
453
 
+
454
 
+static void
455
 
+bacon_video_widget_instance_init (BaconVideoWidget *bvw)
456
 
+{
457
 
+       const char *const *autoplug_list;
458
 
+       int i = 0;
459
 
+
460
 
+       g_return_if_fail (bvw != NULL);
461
 
+       g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
462
 
+
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);
467
 
+
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");
472
 
+
473
 
+       bvw->priv->init_width = 0;
474
 
+       bvw->priv->init_height = 0;
475
 
+
476
 
+       bvw->priv->queue = g_async_queue_new ();
477
 
+
478
 
+       /* init configuration  */
479
 
+       bvw->priv->gc = gconf_client_get_default ();
480
 
+       setup_config (bvw);
481
 
+
482
 
+       xine_init (bvw->priv->xine);
483
 
+
484
 
+       /* Debug configuration */
485
 
+       if (gconf_client_get_bool (bvw->priv->gc, GCONF_PREFIX"/debug", NULL) == FALSE)
486
 
+       {
487
 
+               xine_engine_set_param (bvw->priv->xine,
488
 
+                               XINE_ENGINE_PARAM_VERBOSITY,
489
 
+                               XINE_VERBOSITY_NONE);
490
 
+       } else {
491
 
+               xine_engine_set_param (bvw->priv->xine,
492
 
+                               XINE_ENGINE_PARAM_VERBOSITY,
493
 
+                               XINE_VERBOSITY_DEBUG);
494
 
+       }
495
 
+
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])
499
 
+       {
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;
508
 
+               i++;
509
 
+       }
510
 
+
511
 
+       bvw->priv->tick_id = g_timeout_add (140,
512
 
+                       (GSourceFunc) bacon_video_widget_tick_send, bvw);
513
 
+}
514
 
+
515
 
+static void
516
 
+bacon_video_widget_finalize (GObject *object)
517
 
+{
518
 
+       BaconVideoWidget *bvw = (BaconVideoWidget *) object;
519
 
+
520
 
+       if (bvw->priv->xine != NULL) {
521
 
+               xine_exit (bvw->priv->xine);
522
 
+       }
523
 
+       g_free (bvw->priv->vis_name);
524
 
+       g_object_unref (G_OBJECT (bvw->priv->gc));
525
 
+
526
 
+       g_list_foreach (bvw->priv->visuals, (GFunc) g_free, NULL);
527
 
+       g_list_free (bvw->priv->visuals);
528
 
+
529
 
+       g_idle_remove_by_data (bvw);
530
 
+       g_async_queue_unref (bvw->priv->queue);
531
 
+       G_OBJECT_CLASS (parent_class)->finalize (object);
532
 
+
533
 
+       bvw->priv = NULL;
534
 
+       bvw = NULL;
535
 
+}
536
 
+
537
 
+static void
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)
543
 
+{
544
 
+       BaconVideoWidget *bvw = (BaconVideoWidget *)data;
545
 
+
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;
550
 
+       else
551
 
+               video_height = video_height * bvw->priv->display_ratio
552
 
+                       / video_pixel_aspect + .5;
553
 
+
554
 
+       *dest_width = GTK_WIDGET(bvw)->allocation.width;
555
 
+       *dest_height = GTK_WIDGET(bvw)->allocation.height;
556
 
+       *dest_pixel_aspect = bvw->priv->display_ratio;
557
 
+}
558
 
+
559
 
+static void
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)
567
 
+{
568
 
+       BaconVideoWidget *bvw = (BaconVideoWidget *) bvw_gen;
569
 
+
570
 
+       if (bvw == NULL || bvw->priv == NULL)
571
 
+               return;
572
 
+
573
 
+       /* correct size with video_pixel_aspect */
574
 
+       if (video_pixel_aspect >= bvw->priv->display_ratio)
575
 
+       {
576
 
+               video_width = video_width * video_pixel_aspect
577
 
+                       / bvw->priv->display_ratio + .5;
578
 
+       } else {
579
 
+               video_height = video_height * bvw->priv->display_ratio
580
 
+                       / video_pixel_aspect + .5;
581
 
+       }
582
 
+
583
 
+       *dest_x = 0;
584
 
+       *dest_y = 0;
585
 
+       *win_x = bvw->priv->xpos;
586
 
+       *win_y = bvw->priv->ypos;
587
 
+
588
 
+       *dest_width = GTK_WIDGET(bvw)->allocation.width;
589
 
+       *dest_height = GTK_WIDGET(bvw)->allocation.height;
590
 
+
591
 
+       /* Size changed */
592
 
+       if (bvw->priv->video_width != video_width
593
 
+                       || bvw->priv->video_height != video_height)
594
 
+       {
595
 
+               bvw->priv->video_width = video_width;
596
 
+               bvw->priv->video_height = video_height;
597
 
+
598
 
+               if (bvw->priv->auto_resize != FALSE
599
 
+                               && bvw->priv->logo_mode == FALSE
600
 
+                               && bvw->priv->fullscreen_mode == FALSE)
601
 
+               {
602
 
+                       signal_data *data;
603
 
+
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);
613
 
+               }
614
 
+       }
615
 
+
616
 
+       *dest_pixel_aspect = bvw->priv->display_ratio;
617
 
+}
618
 
+
619
 
+static xine_video_port_t *
620
 
+load_video_out_driver (BaconVideoWidget *bvw, gboolean null_out)
621
 
+{
622
 
+       double res_h, res_v;
623
 
+       x11_visual_t vis;
624
 
+       const char *video_driver_id;
625
 
+       xine_video_port_t *vo_driver;
626
 
+
627
 
+       if (null_out != FALSE)
628
 
+       {
629
 
+               return xine_open_video_driver (bvw->priv->xine,
630
 
+                               "none", XINE_VISUAL_TYPE_NONE, NULL);
631
 
+       }
632
 
+
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;
643
 
+
644
 
+       if (fabs (bvw->priv->display_ratio - 1.0) < 0.01) {
645
 
+               bvw->priv->display_ratio = 1.0;
646
 
+       }
647
 
+
648
 
+       vis.dest_size_cb = dest_size_cb;
649
 
+       vis.frame_output_cb = frame_output_cb;
650
 
+       vis.user_data = bvw;
651
 
+
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);
656
 
+
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)
660
 
+       {
661
 
+               return xine_open_video_driver (bvw->priv->xine, "xshm",
662
 
+                               XINE_VISUAL_TYPE_X11, (void *) &vis); 
663
 
+       }
664
 
+
665
 
+       if (strcmp (video_driver_id, "auto") != 0)
666
 
+       {
667
 
+               vo_driver = xine_open_video_driver (bvw->priv->xine,
668
 
+                                                  video_driver_id,
669
 
+                                                  XINE_VISUAL_TYPE_X11,
670
 
+                                                  (void *) &vis);
671
 
+               if (vo_driver)
672
 
+               {
673
 
+                       if (strcmp (video_driver_id, "dxr3") == 0)
674
 
+                               bvw->priv->tvout = TV_OUT_DXR3;
675
 
+
676
 
+                       return vo_driver;
677
 
+               }
678
 
+       }
679
 
+
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 */
682
 
+
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);
686
 
+       if (vo_driver)
687
 
+               return vo_driver;
688
 
+
689
 
+       vo_driver = xine_open_video_driver (bvw->priv->xine, "xshm",
690
 
+                       XINE_VISUAL_TYPE_X11, (void *) &vis);
691
 
+
692
 
+       return vo_driver;
693
 
+}
694
 
+
695
 
+static xine_audio_port_t *
696
 
+load_audio_out_driver (BaconVideoWidget *bvw, GError **err)
697
 
+{
698
 
+       xine_audio_port_t *ao_driver;
699
 
+       const char *audio_driver_id;
700
 
+
701
 
+       if (bvw->priv->null_out != FALSE)
702
 
+               return NULL;
703
 
+
704
 
+       audio_driver_id = xine_config_register_string (bvw->priv->xine,
705
 
+                       "audio.driver", "auto", "audio driver to use",
706
 
+                       NULL, 10, NULL, NULL);
707
 
+
708
 
+       /* No configuration, fallback to auto */
709
 
+       if (audio_driver_id == NULL || strcmp (audio_driver_id, "") == 0)
710
 
+               audio_driver_id = g_strdup ("auto");
711
 
+
712
 
+       /* We know how to handle null driver */
713
 
+       if (strcmp (audio_driver_id, "null") == 0)
714
 
+               return NULL;
715
 
+
716
 
+       /* auto probe */
717
 
+       if (strcmp (audio_driver_id, "auto") == 0)
718
 
+               ao_driver = xine_open_audio_driver (bvw->priv->xine,
719
 
+                               NULL, NULL);
720
 
+       else
721
 
+               ao_driver = xine_open_audio_driver (bvw->priv->xine,
722
 
+                               audio_driver_id, NULL);
723
 
+
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,
727
 
+                               NULL, NULL);
728
 
+
729
 
+       if (ao_driver == NULL && strcmp (audio_driver_id, "auto") != 0)
730
 
+       {
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" );
735
 
+               return NULL;
736
 
+       }
737
 
+
738
 
+       return ao_driver;
739
 
+}
740
 
+
741
 
+static void
742
 
+bvw_config_helper_string (xine_t *xine, const char *id, const char *val,
743
 
+               xine_cfg_entry_t *entry)
744
 
+{
745
 
+       memset (entry, 0, sizeof (entry));
746
 
+
747
 
+       if (!xine_config_lookup_entry (xine, id, entry))
748
 
+       {
749
 
+               xine_config_register_string (xine, id, val, "", NULL, 10,
750
 
+                               NULL, NULL);
751
 
+               xine_config_lookup_entry (xine, id, entry);
752
 
+       }
753
 
+}
754
 
+
755
 
+static void
756
 
+bvw_config_helper_num (xine_t *xine, const char *id, int val,
757
 
+               xine_cfg_entry_t *entry)
758
 
+{
759
 
+       memset (entry, 0, sizeof (entry));
760
 
+
761
 
+       if (!xine_config_lookup_entry (xine, id, entry))
762
 
+       {
763
 
+               xine_config_register_num (xine, id, val, 0, NULL, 10,
764
 
+                               NULL, NULL);
765
 
+               xine_config_lookup_entry (xine, id, entry);
766
 
+       }
767
 
+}
768
 
+
769
 
+static void
770
 
+setup_url_handlers (BaconVideoWidget *bvw, const char *protocol)
771
 
+{
772
 
+       char *key, *url;
773
 
+
774
 
+       key = g_strdup_printf ("/desktop/gnome/url-handlers/%s/command",
775
 
+                       protocol);
776
 
+       url = gconf_client_get_string (bvw->priv->gc, key, NULL);
777
 
+
778
 
+       if (url == NULL)
779
 
+       {
780
 
+               gconf_client_set_string (bvw->priv->gc, key,
781
 
+                               "totem \"%s\"", NULL);
782
 
+               g_free (key);
783
 
+
784
 
+               key = g_strdup_printf
785
 
+                       ("/desktop/gnome/url-handlers/%s/need-terminal",
786
 
+                        protocol);
787
 
+               gconf_client_set_bool (bvw->priv->gc, key, FALSE, NULL);
788
 
+               g_free (key);
789
 
+
790
 
+               key =  g_strdup_printf
791
 
+                       ("/desktop/gnome/url-handlers/%s/enabled", protocol);
792
 
+               gconf_client_set_bool (bvw->priv->gc, key, TRUE, NULL);
793
 
+               g_free (key);
794
 
+       }
795
 
+
796
 
+       g_free (url);
797
 
+}
798
 
+
799
 
+static void
800
 
+setup_config (BaconVideoWidget *bvw)
801
 
+{
802
 
+       char *path;
803
 
+       xine_cfg_entry_t entry;
804
 
+
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);
808
 
+       g_free (path);
809
 
+
810
 
+       /* default demux strategy */
811
 
+       xine_config_register_enum (bvw->priv->xine,
812
 
+                       "misc.demux_strategy",
813
 
+                       0,
814
 
+                       (char **) demux_strategies_str,
815
 
+                        "media format detection strategy",
816
 
+                        NULL, 10, NULL, NULL);
817
 
+
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);
822
 
+
823
 
+       /* The volume */
824
 
+       xine_config_register_range (bvw->priv->xine,
825
 
+                       "misc.amp_level",
826
 
+                       50, 0, 100, "amp volume level",
827
 
+                       NULL, 10, NULL, NULL);
828
 
+       bvw->priv->volume = -1;
829
 
+
830
 
+       if (bvw->priv->gc == NULL)
831
 
+               return;
832
 
+
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);
838
 
+
839
 
+       if (bvw->priv->gc == NULL) {
840
 
+               g_warning ("GConf not available, broken installation?");
841
 
+               return;
842
 
+       }
843
 
+
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");
848
 
+
849
 
+       /* Proxy configuration */
850
 
+       if (gconf_client_get_bool (bvw->priv->gc, "/system/http_proxy/use_http_proxy", NULL) == FALSE)
851
 
+       {
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);
856
 
+
857
 
+               return;
858
 
+       }
859
 
+
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);
865
 
+
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);
871
 
+
872
 
+       if (gconf_client_get_bool (bvw->priv->gc, "/system/http_proxy/use_authentication", NULL) == FALSE)
873
 
+       {
874
 
+               bvw_config_helper_string (bvw->priv->xine,
875
 
+                               "input.http_proxy_user", g_get_user_name(),
876
 
+                               &entry);
877
 
+               entry.str_value = "";
878
 
+               xine_config_update_entry (bvw->priv->xine, &entry);
879
 
+
880
 
+               bvw_config_helper_string (bvw->priv->xine,
881
 
+                               "input.http_proxy_password", "",
882
 
+                               &entry);
883
 
+               entry.str_value = "";
884
 
+               xine_config_update_entry (bvw->priv->xine, &entry);
885
 
+       } else {
886
 
+               bvw_config_helper_string (bvw->priv->xine,
887
 
+                               "input.http_proxy_user", g_get_user_name(),
888
 
+                               &entry);
889
 
+               entry.str_value = gconf_client_get_string (bvw->priv->gc,
890
 
+                               "/system/http_proxy/authentication_user",
891
 
+                               NULL);
892
 
+               xine_config_update_entry (bvw->priv->xine, &entry);
893
 
+
894
 
+               bvw_config_helper_string (bvw->priv->xine,
895
 
+                               "input.http_proxy_password", "",
896
 
+                               &entry);
897
 
+               entry.str_value = gconf_client_get_string (bvw->priv->gc,
898
 
+                               "/system/http_proxy/authentication_password",
899
 
+                               NULL);
900
 
+               xine_config_update_entry (bvw->priv->xine, &entry);
901
 
+       }
902
 
+}
903
 
+
904
 
+static void
905
 
+setup_config_video (BaconVideoWidget *bvw)
906
 
+{
907
 
+       xine_cfg_entry_t entry;
908
 
+
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);
913
 
+
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);
918
 
+}
919
 
+
920
 
+static void
921
 
+setup_config_stream (BaconVideoWidget *bvw)
922
 
+{
923
 
+       int value, i;
924
 
+
925
 
+       if (bvw->priv->gc == NULL)
926
 
+               return;
927
 
+
928
 
+       /* Setup brightness and contrast */
929
 
+       for (i = 0; i < 4; i++)
930
 
+       {
931
 
+               GError *error = NULL;
932
 
+               int tmp;
933
 
+
934
 
+               value = gconf_client_get_int (bvw->priv->gc,
935
 
+                               video_props_str[i], &error);
936
 
+
937
 
+               /* avoid black screens */
938
 
+               if (value == 0 && error != NULL)
939
 
+                       value = 65535 / 2;
940
 
+
941
 
+               tmp = xine_get_param (bvw->priv->stream, video_props[i]);
942
 
+               if (value != tmp)
943
 
+               {
944
 
+                       xine_set_param (bvw->priv->stream,
945
 
+                                       video_props[i], value);
946
 
+               }
947
 
+
948
 
+               if (error != NULL)
949
 
+                       g_error_free (error);
950
 
+       }
951
 
+}
952
 
+
953
 
+static gboolean
954
 
+video_window_translate_point (BaconVideoWidget *bvw, int gui_x, int gui_y,
955
 
+               int *video_x, int *video_y)
956
 
+{
957
 
+       int res;
958
 
+       x11_rectangle_t rect;
959
 
+
960
 
+       rect.x = gui_x;
961
 
+       rect.y = gui_y;
962
 
+       rect.w = 0;
963
 
+       rect.h = 0;
964
 
+
965
 
+       res = xine_port_send_gui_data (bvw->priv->vo_driver,
966
 
+                       XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO, (void*)&rect);
967
 
+
968
 
+       if (res != -1)
969
 
+       {
970
 
+               /* the driver implements gui->video coordinate space
971
 
+                * translation so we use it */
972
 
+               *video_x = rect.x;
973
 
+               *video_y = rect.y;
974
 
+               return TRUE;
975
 
+       }
976
 
+
977
 
+       return FALSE;
978
 
+}
979
 
+
980
 
+/* Changes the way xine skips while playing a DVD,
981
 
+ * 1 == CHAPTER
982
 
+ * 2 == TITLE
983
 
+ */
984
 
+static void 
985
 
+dvd_skip_behaviour (BaconVideoWidget *bvw, int behaviour)
986
 
+{
987
 
+        if (behaviour < 1 || behaviour > 2)
988
 
+                return;
989
 
+
990
 
+        xine_config_register_num (bvw->priv->xine,
991
 
+                        "input.dvd_skip_behaviour",
992
 
+                        behaviour,
993
 
+                        "DVD Skip behaviour",
994
 
+                        NULL,
995
 
+                        10,
996
 
+                        NULL, NULL);
997
 
+
998
 
+        return;
999
 
+}
1000
 
+
1001
 
+void
1002
 
+bacon_video_widget_dvd_event (BaconVideoWidget *bvw, BaconVideoWidgetDVDEvent type)
1003
 
+{
1004
 
+        xine_event_t event;
1005
 
+
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);
1009
 
+
1010
 
+        switch (type)
1011
 
+        {
1012
 
+        case BVW_DVD_ROOT_MENU:
1013
 
+                event.type = XINE_EVENT_INPUT_MENU1;
1014
 
+                break;
1015
 
+        case BVW_DVD_TITLE_MENU:
1016
 
+                event.type = XINE_EVENT_INPUT_MENU2;
1017
 
+                break;
1018
 
+        case BVW_DVD_SUBPICTURE_MENU:
1019
 
+                event.type = XINE_EVENT_INPUT_MENU4;
1020
 
+                break;
1021
 
+        case BVW_DVD_AUDIO_MENU:
1022
 
+                event.type = XINE_EVENT_INPUT_MENU5;
1023
 
+                break;
1024
 
+        case BVW_DVD_ANGLE_MENU:
1025
 
+                event.type = XINE_EVENT_INPUT_MENU6;
1026
 
+                break;
1027
 
+        case BVW_DVD_CHAPTER_MENU:
1028
 
+                event.type = XINE_EVENT_INPUT_MENU7;
1029
 
+                break;
1030
 
+        case BVW_DVD_NEXT_CHAPTER:
1031
 
+                dvd_skip_behaviour (bvw, 1);
1032
 
+                event.type = XINE_EVENT_INPUT_NEXT;
1033
 
+                break;
1034
 
+        case BVW_DVD_PREV_CHAPTER:
1035
 
+                dvd_skip_behaviour (bvw, 1);
1036
 
+                event.type = XINE_EVENT_INPUT_PREVIOUS;
1037
 
+                break;
1038
 
+        case BVW_DVD_NEXT_TITLE:
1039
 
+                dvd_skip_behaviour (bvw, 2);
1040
 
+                event.type = XINE_EVENT_INPUT_NEXT;
1041
 
+                break;
1042
 
+        case BVW_DVD_PREV_TITLE:
1043
 
+                dvd_skip_behaviour (bvw, 2);
1044
 
+                event.type = XINE_EVENT_INPUT_PREVIOUS;
1045
 
+                break;
1046
 
+        case BVW_DVD_NEXT_ANGLE:
1047
 
+                event.type = XINE_EVENT_INPUT_ANGLE_NEXT;
1048
 
+                break;
1049
 
+        case BVW_DVD_PREV_ANGLE:
1050
 
+                event.type = XINE_EVENT_INPUT_ANGLE_PREVIOUS;
1051
 
+                break;
1052
 
+        default:
1053
 
+                return;
1054
 
+        }
1055
 
+
1056
 
+        event.stream = bvw->priv->stream;
1057
 
+        event.data = NULL;
1058
 
+        event.data_length = 0;
1059
 
+
1060
 
+        xine_event_send (bvw->priv->stream,
1061
 
+                        (xine_event_t *) (&event));
1062
 
+}
1063
 
+
1064
 
+static gboolean
1065
 
+generate_mouse_event (BaconVideoWidget *bvw, GdkEvent *event,
1066
 
+               gboolean is_motion)
1067
 
+{
1068
 
+       GdkEventMotion *mevent = (GdkEventMotion *) event;
1069
 
+       GdkEventButton *bevent = (GdkEventButton *) event;
1070
 
+       int x, y;
1071
 
+       gboolean retval;
1072
 
+
1073
 
+       /* Don't even try to generate an event if we're dying */
1074
 
+       if (bvw->priv->stream == NULL)
1075
 
+               return FALSE;
1076
 
+
1077
 
+       if (is_motion == FALSE && bevent->button != 1)
1078
 
+               return FALSE;
1079
 
+
1080
 
+       if (is_motion != FALSE)
1081
 
+               retval = video_window_translate_point (bvw,
1082
 
+                               mevent->x, mevent->y, &x, &y);
1083
 
+       else
1084
 
+               retval = video_window_translate_point (bvw,
1085
 
+                               bevent->x, bevent->y, &x, &y);
1086
 
+
1087
 
+       if (retval != FALSE)
1088
 
+       {
1089
 
+               xine_event_t event;
1090
 
+               xine_input_data_t input;
1091
 
+
1092
 
+               if (is_motion != FALSE)
1093
 
+               {
1094
 
+                       event.type = XINE_EVENT_INPUT_MOUSE_MOVE;
1095
 
+                       input.button = 0; /* Just motion. */
1096
 
+               } else {
1097
 
+                       event.type = XINE_EVENT_INPUT_MOUSE_BUTTON;
1098
 
+                       input.button = 1;
1099
 
+               }
1100
 
+
1101
 
+               input.x = x;
1102
 
+               input.y = y;
1103
 
+               event.stream = bvw->priv->stream;
1104
 
+               event.data = &input;
1105
 
+               event.data_length = sizeof(input);
1106
 
+
1107
 
+               xine_event_send (bvw->priv->stream,
1108
 
+                               (xine_event_t *) (&event));
1109
 
+
1110
 
+               return TRUE;
1111
 
+       }
1112
 
+
1113
 
+       return FALSE;
1114
 
+}
1115
 
+
1116
 
+static gboolean
1117
 
+configure_cb (GtkWidget *widget, GdkEventConfigure *event,
1118
 
+               BaconVideoWidget *bvw)
1119
 
+{
1120
 
+       bvw->priv->xpos = event->x + GTK_WIDGET (bvw)->allocation.x;
1121
 
+       bvw->priv->ypos = event->y + GTK_WIDGET (bvw)->allocation.y;
1122
 
+
1123
 
+       return FALSE;
1124
 
+}
1125
 
+
1126
 
+static void
1127
 
+size_changed_cb (GdkScreen *screen, BaconVideoWidget *bvw)
1128
 
+{
1129
 
+       double res_h, res_v;
1130
 
+
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);
1139
 
+
1140
 
+       bvw->priv->display_ratio = res_v / res_h;
1141
 
+
1142
 
+       if (fabs (bvw->priv->display_ratio - 1.0) < 0.01) {
1143
 
+               bvw->priv->display_ratio = 1.0;
1144
 
+       }
1145
 
+}
1146
 
+
1147
 
+static void
1148
 
+bacon_video_widget_realize (GtkWidget *widget)
1149
 
+{
1150
 
+       GdkWindowAttr attr;
1151
 
+       BaconVideoWidget *bvw;
1152
 
+
1153
 
+       bvw = BACON_VIDEO_WIDGET (widget);
1154
 
+
1155
 
+       if (bvw->priv->mrl != NULL) {
1156
 
+               bacon_video_widget_close (bvw);
1157
 
+               g_warning ("bvw->priv->mrl != NULL on open");
1158
 
+       }
1159
 
+
1160
 
+       /* set realized flag */
1161
 
+       GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1162
 
+
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;
1168
 
+
1169
 
+       if (bvw->priv->vo_driver != NULL) {
1170
 
+               xine_close_video_driver (bvw->priv->xine,
1171
 
+                               bvw->priv->vo_driver);
1172
 
+       }
1173
 
+       if (bvw->priv->ao_driver != NULL) {
1174
 
+               xine_close_audio_driver (bvw->priv->xine,
1175
 
+                               bvw->priv->ao_driver);
1176
 
+       }
1177
 
+
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);
1191
 
+
1192
 
+       /* Flush, so that the window is really shown */
1193
 
+       gdk_flush ();
1194
 
+       gdk_window_set_user_data (widget->window, bvw);
1195
 
+
1196
 
+       bvw->priv->video_window = widget->window;
1197
 
+
1198
 
+       /* Set a black background */
1199
 
+       gdk_draw_rectangle (widget->window, widget->style->black_gc, TRUE,
1200
 
+                       attr.x, attr.y,
1201
 
+                       attr.width, attr.height);
1202
 
+
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);
1207
 
+
1208
 
+       /* get screen size changes */
1209
 
+       g_signal_connect (G_OBJECT (gdk_screen_get_default ()),
1210
 
+                       "size-changed", G_CALLBACK (size_changed_cb), bvw);
1211
 
+
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);
1216
 
+
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);
1219
 
+
1220
 
+       if (bvw->priv->vo_driver == NULL)
1221
 
+       {
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");
1227
 
+       }
1228
 
+       //FIXME
1229
 
+
1230
 
+       g_assert (bvw->priv->vo_driver != NULL);
1231
 
+       setup_config_video (bvw);
1232
 
+
1233
 
+       if (bvw->priv->null_out == FALSE && bvw->priv->ao_driver != NULL)
1234
 
+       {
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);
1238
 
+       }
1239
 
+
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);
1245
 
+
1246
 
+       /* Setup xine events */
1247
 
+       xine_event_create_listener_thread (bvw->priv->ev_queue,
1248
 
+                       xine_event, (void *) bvw);
1249
 
+
1250
 
+#ifdef HAVE_NVTV
1251
 
+       if (!(nvtv_simple_init() && nvtv_enable_autoresize(TRUE))) {
1252
 
+               nvtv_simple_enable(FALSE);
1253
 
+       } 
1254
 
+#endif
1255
 
+
1256
 
+       return;
1257
 
+}
1258
 
+
1259
 
+static gboolean
1260
 
+bacon_video_widget_idle_signal (BaconVideoWidget *bvw)
1261
 
+{
1262
 
+       int queue_length;
1263
 
+       signal_data *data;
1264
 
+
1265
 
+       data = g_async_queue_try_pop (bvw->priv->queue);
1266
 
+       if (data == NULL)
1267
 
+               return FALSE;
1268
 
+
1269
 
+       TE ();
1270
 
+
1271
 
+       switch (data->signal)
1272
 
+       {
1273
 
+       case RATIO:
1274
 
+               bacon_video_widget_set_scale_ratio (bvw, 1);
1275
 
+               break;
1276
 
+       case TITLE_CHANGE_ASYNC:
1277
 
+               g_signal_emit (G_OBJECT (bvw),
1278
 
+                               bvw_table_signals[TITLE_CHANGE],
1279
 
+                               0, data->msg);
1280
 
+               break;
1281
 
+       case EOS_ASYNC:
1282
 
+               g_signal_emit (G_OBJECT (bvw),
1283
 
+                               bvw_table_signals[EOS], 0, NULL);
1284
 
+               break;
1285
 
+       case CHANNELS_CHANGE_ASYNC:
1286
 
+               g_signal_emit (G_OBJECT (bvw),
1287
 
+                               bvw_table_signals[CHANNELS_CHANGE], 0, NULL);
1288
 
+               break;
1289
 
+       case BUFFERING_ASYNC:
1290
 
+               g_signal_emit (G_OBJECT (bvw),
1291
 
+                               bvw_table_signals[BUFFERING],
1292
 
+                               0, data->num);
1293
 
+               break;
1294
 
+       case MESSAGE_ASYNC:
1295
 
+               g_signal_emit (G_OBJECT (bvw),
1296
 
+                               bvw_table_signals[ERROR],
1297
 
+                               0, data->msg, TRUE);
1298
 
+               break;
1299
 
+       case SPEED_WARNING_ASYNC:
1300
 
+               g_signal_emit (G_OBJECT (bvw),
1301
 
+                               bvw_table_signals[SPEED_WARNING],
1302
 
+                               0, NULL);
1303
 
+               break;
1304
 
+       default:
1305
 
+               g_assert_not_reached ();
1306
 
+       }
1307
 
+
1308
 
+       TL ();
1309
 
+
1310
 
+       g_free (data->msg);
1311
 
+       g_free (data);
1312
 
+       queue_length = g_async_queue_length (bvw->priv->queue);
1313
 
+
1314
 
+       return (queue_length > 0);
1315
 
+}
1316
 
+
1317
 
+static void
1318
 
+xine_event_message (BaconVideoWidget *bvw, xine_ui_message_data_t *data)
1319
 
+{
1320
 
+       char *message;
1321
 
+       signal_data *sigdata;
1322
 
+
1323
 
+       message = NULL;
1324
 
+
1325
 
+       switch(data->type)
1326
 
+       {
1327
 
+       case XINE_MSG_NO_ERROR:
1328
 
+               break;
1329
 
+       case XINE_MSG_GENERAL_WARNING:
1330
 
+               break;
1331
 
+       case XINE_MSG_UNKNOWN_HOST:
1332
 
+               message = g_strdup_printf (_("The server you are trying to connect to is not known."));
1333
 
+               break;
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);
1336
 
+               break;
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);
1339
 
+               break;
1340
 
+       case XINE_MSG_CONNECTION_REFUSED:
1341
 
+               message = g_strdup_printf (_("The connection to this server was refused."));
1342
 
+               break;
1343
 
+       case XINE_MSG_FILE_NOT_FOUND:
1344
 
+               message = g_strdup_printf (_("The specified movie '%s' could not be found."), (char *) data + data->parameters);
1345
 
+               break;
1346
 
+       case XINE_MSG_READ_ERROR:
1347
 
+               message = g_strdup_printf (_("The movie '%s' could not be read."), (char *) data + data->parameters);
1348
 
+               break;
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);
1351
 
+               break;
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?"));
1355
 
+               else
1356
 
+                       message = g_strdup (_("This file is encrypted and cannot be played back."));
1357
 
+               break;
1358
 
+       case XINE_MSG_SECURITY:
1359
 
+               message = g_strdup (_("For security reasons, this movie can not be played back."));
1360
 
+               break;
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?"));
1364
 
+               break;
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."));
1368
 
+               else
1369
 
+                       message = g_strdup (_("The server refused access to this file or stream."));
1370
 
+               break;
1371
 
+       }
1372
 
+
1373
 
+       if (message == NULL)
1374
 
+       {
1375
 
+               D("xine_event_message: unhandled error\ntype: %d", data->type);
1376
 
+               return;
1377
 
+       }
1378
 
+
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);
1384
 
+}
1385
 
+
1386
 
+static void
1387
 
+xine_event (void *user_data, const xine_event_t *event)
1388
 
+{
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;
1394
 
+
1395
 
+       switch (event->type)
1396
 
+       {
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);
1402
 
+               break;
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);
1408
 
+               break;
1409
 
+       case XINE_EVENT_UI_SET_TITLE:
1410
 
+               ui_data = event->data;
1411
 
+
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);
1417
 
+               break;
1418
 
+       case XINE_EVENT_PROGRESS:
1419
 
+               prg = event->data;
1420
 
+
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);
1426
 
+               break;
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);
1432
 
+               break;
1433
 
+       case XINE_EVENT_UI_MESSAGE:
1434
 
+               xine_event_message (bvw, (xine_ui_message_data_t *)event->data);
1435
 
+               break;
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);
1441
 
+               break;
1442
 
+       case XINE_EVENT_AUDIO_LEVEL:
1443
 
+               /* Unhandled, we use the software mixer, not the hardware one */
1444
 
+               break;
1445
 
+       }
1446
 
+}
1447
 
+
1448
 
+static void
1449
 
+xine_error (BaconVideoWidget *bvw, GError **error)
1450
 
+{
1451
 
+       signal_data *data, *save_data;
1452
 
+       int err;
1453
 
+
1454
 
+       save_data = NULL;
1455
 
+
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
1458
 
+        * xine_open() */
1459
 
+       while ((data = g_async_queue_try_pop (bvw->priv->queue)) != NULL)
1460
 
+       {
1461
 
+               g_assert (data->signal == MESSAGE_ASYNC
1462
 
+                               || data->signal == BUFFERING_ASYNC);
1463
 
+
1464
 
+               if (data->signal != BUFFERING_ASYNC)
1465
 
+               {
1466
 
+                       if (save_data != NULL)
1467
 
+                       {
1468
 
+                               g_free (save_data->msg);
1469
 
+                               g_free (save_data);
1470
 
+                       }
1471
 
+                       save_data = data;
1472
 
+               } else {
1473
 
+                       g_free (data->msg);
1474
 
+                       g_free (data);
1475
 
+               }
1476
 
+       }
1477
 
+
1478
 
+       if (save_data != NULL)
1479
 
+       {
1480
 
+               g_set_error (error, 0, 0, save_data->msg);
1481
 
+               g_free (save_data->msg);
1482
 
+               g_free (save_data);
1483
 
+
1484
 
+               return;
1485
 
+       }
1486
 
+
1487
 
+       err = xine_get_error (bvw->priv->stream);
1488
 
+       if (err == XINE_ERROR_NONE)
1489
 
+               return;
1490
 
+
1491
 
+       switch (err)
1492
 
+       {
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"
1496
 
+                                       " movie."));
1497
 
+               break;
1498
 
+       case XINE_ERROR_DEMUX_FAILED:
1499
 
+               g_set_error (error, 0, 0, _("This movie is broken and can not "
1500
 
+                                       "be played further."));
1501
 
+               break;
1502
 
+       case XINE_ERROR_MALFORMED_MRL:
1503
 
+               g_set_error (error, 0, 0, _("This location is not "
1504
 
+                                       "a valid one."));
1505
 
+               break;
1506
 
+       case XINE_ERROR_INPUT_FAILED:
1507
 
+               g_set_error (error, 0, 0, _("This movie could not be opened."));
1508
 
+               break;
1509
 
+       default:
1510
 
+               g_set_error (error, 0, 0, _("Generic Error."));
1511
 
+               break;
1512
 
+       }
1513
 
+}
1514
 
+
1515
 
+static void
1516
 
+bacon_video_widget_unrealize (GtkWidget *widget)
1517
 
+{
1518
 
+       BaconVideoWidget *bvw;
1519
 
+       char *configfile;
1520
 
+       xine_cfg_entry_t entry;
1521
 
+       int speed;
1522
 
+
1523
 
+       g_return_if_fail (widget != NULL);
1524
 
+       g_return_if_fail (BACON_IS_VIDEO_WIDGET (widget));
1525
 
+
1526
 
+       bvw = BACON_VIDEO_WIDGET (widget);
1527
 
+
1528
 
+       g_source_remove (bvw->priv->tick_id);
1529
 
+
1530
 
+       speed = xine_get_param (bvw->priv->stream, XINE_PARAM_SPEED);
1531
 
+       if (speed != XINE_SPEED_PAUSE)
1532
 
+               show_vfx_update (bvw, FALSE);
1533
 
+
1534
 
+       /* stop the playback */
1535
 
+       xine_stop (bvw->priv->stream);
1536
 
+       xine_close (bvw->priv->stream);
1537
 
+
1538
 
+       /* Put the current volume in the config system */
1539
 
+       if (bacon_video_widget_can_set_volume (bvw) != FALSE)
1540
 
+       {
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);
1545
 
+       }
1546
 
+
1547
 
+       /* Kill the TV out */
1548
 
+#ifdef HAVE_NVTV
1549
 
+        nvtv_simple_exit();
1550
 
+#endif
1551
 
+
1552
 
+       /* Hide all windows */
1553
 
+       if (GTK_WIDGET_MAPPED (widget))
1554
 
+               gtk_widget_unmap (widget);
1555
 
+       GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1556
 
+
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;
1561
 
+
1562
 
+       /* save config */
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);
1567
 
+
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);
1575
 
+
1576
 
+       /* stop event thread */
1577
 
+       xine_exit (bvw->priv->xine);
1578
 
+       bvw->priv->xine = NULL;
1579
 
+
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);
1583
 
+}
1584
 
+
1585
 
+static struct poptOption xine_options[] = {
1586
 
+       POPT_TABLEEND
1587
 
+};
1588
 
+
1589
 
+struct poptOption *
1590
 
+bacon_video_widget_get_popt_table (void)
1591
 
+{
1592
 
+       /* Xine backend does not need any options */
1593
 
+       return (struct poptOption *) xine_options;
1594
 
+}
1595
 
+
1596
 
+GtkWidget *
1597
 
+bacon_video_widget_new (int width, int height, gboolean null_out, GError **err)
1598
 
+{
1599
 
+       BaconVideoWidget *bvw;
1600
 
+       xine_cfg_entry_t entry;
1601
 
+
1602
 
+       bvw = BACON_VIDEO_WIDGET (g_object_new
1603
 
+                       (bacon_video_widget_get_type (), NULL));
1604
 
+
1605
 
+       bvw->priv->null_out = null_out;
1606
 
+
1607
 
+       /* defaults are fine if both are negative */
1608
 
+       if (width > 0 && height > 0)
1609
 
+       {
1610
 
+               /* figure out the missing measure from the other one
1611
 
+                * with a 4:3 ratio */
1612
 
+               if (width <= 0)
1613
 
+                       width = (int) (height * 4 / 3);
1614
 
+               if (height <= 0)
1615
 
+                       height = (int) (width * 3 / 4);
1616
 
+       } else {
1617
 
+               width = 0;
1618
 
+               height = 0;
1619
 
+       }
1620
 
+
1621
 
+       GTK_WIDGET(bvw)->requisition.width = width;
1622
 
+       GTK_WIDGET(bvw)->requisition.height = height;
1623
 
+
1624
 
+       bvw->priv->init_width = width;
1625
 
+       bvw->priv->init_height = height;
1626
 
+
1627
 
+       /* load the output drivers */
1628
 
+       bvw->priv->ao_driver = load_audio_out_driver (bvw, err);
1629
 
+       if (err != NULL && *err != NULL)
1630
 
+               return NULL;
1631
 
+
1632
 
+       bvw->priv->vo_driver = load_video_out_driver (bvw, TRUE);
1633
 
+
1634
 
+       /* Be extra careful about exiting out nicely when a video output
1635
 
+        * isn't available */
1636
 
+       if (bvw->priv->vo_driver == NULL)
1637
 
+       {
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);
1642
 
+               }
1643
 
+               xine_exit (bvw->priv->xine);
1644
 
+
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);
1653
 
+               g_free (bvw);
1654
 
+
1655
 
+               g_set_error (err, 0, 0,
1656
 
+                               _("No video output is available. Make sure that the program is correctly installed."));
1657
 
+               return NULL;
1658
 
+       }
1659
 
+
1660
 
+       if (bvw->priv->null_out != FALSE)
1661
 
+       {
1662
 
+               bvw_config_helper_num (bvw->priv->xine, "video.num_buffers",
1663
 
+                               5, &entry);
1664
 
+               entry.num_value = 5;
1665
 
+       } else {
1666
 
+               bvw_config_helper_num (bvw->priv->xine, "video.num_buffers",
1667
 
+                               500, &entry);
1668
 
+               entry.num_value = 500;
1669
 
+       }
1670
 
+       xine_config_update_entry (bvw->priv->xine, &entry);
1671
 
+
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);
1675
 
+
1676
 
+       return GTK_WIDGET (bvw);
1677
 
+}
1678
 
+
1679
 
+static gboolean
1680
 
+bacon_video_widget_expose (GtkWidget *widget, GdkEventExpose *event)
1681
 
+{
1682
 
+       BaconVideoWidget *bvw = (BaconVideoWidget *) widget;
1683
 
+       XExposeEvent *expose;
1684
 
+
1685
 
+       if (event->count != 0)
1686
 
+               return FALSE;
1687
 
+
1688
 
+       expose = g_new0 (XExposeEvent, 1);
1689
 
+       expose->count = event->count;
1690
 
+
1691
 
+       xine_port_send_gui_data (bvw->priv->vo_driver,
1692
 
+                       XINE_GUI_SEND_EXPOSE_EVENT, expose);
1693
 
+
1694
 
+       g_free (expose);
1695
 
+
1696
 
+       return FALSE;
1697
 
+}
1698
 
+
1699
 
+static gboolean
1700
 
+bacon_video_widget_motion_notify (GtkWidget *widget, GdkEventMotion *event)
1701
 
+{
1702
 
+       BaconVideoWidget *bvw = (BaconVideoWidget *) widget;
1703
 
+
1704
 
+       generate_mouse_event (bvw, (GdkEvent *)event, TRUE);
1705
 
+
1706
 
+       if (GTK_WIDGET_CLASS (parent_class)->motion_notify_event != NULL)
1707
 
+               (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event) (widget, event);
1708
 
+
1709
 
+       return FALSE;
1710
 
+}
1711
 
+
1712
 
+static gboolean
1713
 
+bacon_video_widget_button_press (GtkWidget *widget, GdkEventButton *event)
1714
 
+{
1715
 
+       BaconVideoWidget *bvw = (BaconVideoWidget *) widget;
1716
 
+
1717
 
+       generate_mouse_event (bvw, (GdkEvent *)event, FALSE);
1718
 
+
1719
 
+       if (GTK_WIDGET_CLASS (parent_class)->button_press_event != NULL)
1720
 
+                               (* GTK_WIDGET_CLASS (parent_class)->button_press_event) (widget, event);
1721
 
+
1722
 
+       return FALSE;
1723
 
+}
1724
 
+
1725
 
+static void
1726
 
+bacon_video_widget_size_request (GtkWidget *widget, GtkRequisition *requisition)
1727
 
+{
1728
 
+       BaconVideoWidget *bvw;
1729
 
+
1730
 
+       g_return_if_fail(widget != NULL);
1731
 
+       g_return_if_fail(BACON_IS_VIDEO_WIDGET(widget));
1732
 
+
1733
 
+       bvw = BACON_VIDEO_WIDGET (widget);
1734
 
+       
1735
 
+       if ((bvw->priv->init_width == 0) && (bvw->priv->init_height == 0)) {
1736
 
+               requisition->width = DEFAULT_WIDTH;
1737
 
+               requisition->height = DEFAULT_HEIGHT;
1738
 
+       } else {
1739
 
+               /* Requesting first allocation as a minimum */
1740
 
+               requisition->width = bvw->priv->init_width;
1741
 
+               requisition->height = bvw->priv->init_height;
1742
 
+       }
1743
 
+}
1744
 
+
1745
 
+static void
1746
 
+bacon_video_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
1747
 
+{
1748
 
+       BaconVideoWidget *bvw;
1749
 
+
1750
 
+       g_return_if_fail (widget != NULL);
1751
 
+       g_return_if_fail (BACON_IS_VIDEO_WIDGET (widget));
1752
 
+
1753
 
+       bvw = BACON_VIDEO_WIDGET (widget);
1754
 
+
1755
 
+       widget->allocation = *allocation;
1756
 
+       bvw->priv->xpos = allocation->x;
1757
 
+       bvw->priv->ypos = allocation->y;
1758
 
+
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;
1763
 
+       }
1764
 
+
1765
 
+       if (GTK_WIDGET_REALIZED (widget))
1766
 
+       {
1767
 
+               gdk_window_move_resize (widget->window,
1768
 
+                                       allocation->x,
1769
 
+                                       allocation->y,
1770
 
+                                       allocation->width,
1771
 
+                                       allocation->height);
1772
 
+       }
1773
 
+}
1774
 
+
1775
 
+static gboolean
1776
 
+bacon_video_widget_tick_send (BaconVideoWidget *bvw)
1777
 
+{
1778
 
+       int current_time, stream_length, current_position;
1779
 
+       float current_position_f;
1780
 
+       gboolean ret = TRUE, seekable;
1781
 
+
1782
 
+       if (bvw->priv->stream == NULL || bvw->priv->logo_mode != FALSE)
1783
 
+               return TRUE;
1784
 
+
1785
 
+       if (bvw->priv->mrl == NULL)
1786
 
+       {
1787
 
+               current_time = 0;
1788
 
+               stream_length = 0;
1789
 
+               current_position = 0;
1790
 
+       } else {
1791
 
+               ret = xine_get_pos_length (bvw->priv->stream,
1792
 
+                               &current_position,
1793
 
+                               &current_time,
1794
 
+                               &stream_length);
1795
 
+       }
1796
 
+
1797
 
+       if (ret == FALSE)
1798
 
+               return TRUE;
1799
 
+
1800
 
+       if (bvw->priv->seeking == 1)
1801
 
+       {
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;
1807
 
+       } else {
1808
 
+               current_position_f = (float) current_position / 65535;
1809
 
+       }
1810
 
+
1811
 
+       if (stream_length > 0)
1812
 
+               bvw->priv->is_live = FALSE;
1813
 
+       else
1814
 
+               bvw->priv->is_live = TRUE;
1815
 
+
1816
 
+       if (stream_length != 0 && bvw->priv->mrl != NULL) {
1817
 
+               seekable = xine_get_stream_info (bvw->priv->stream,
1818
 
+                               XINE_STREAM_INFO_SEEKABLE);
1819
 
+       } else {
1820
 
+               seekable = FALSE;
1821
 
+       }
1822
 
+
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,
1828
 
+                       seekable);
1829
 
+
1830
 
+       return TRUE;
1831
 
+}
1832
 
+
1833
 
+static void
1834
 
+show_vfx_update (BaconVideoWidget *bvw, gboolean show_visuals)
1835
 
+{
1836
 
+       xine_post_out_t *audio_source;
1837
 
+       gboolean has_video;
1838
 
+
1839
 
+       has_video = xine_get_stream_info(bvw->priv->stream,
1840
 
+                       XINE_STREAM_INFO_HAS_VIDEO);
1841
 
+
1842
 
+       if (has_video != FALSE && show_visuals != FALSE
1843
 
+                       && bvw->priv->using_vfx != FALSE)
1844
 
+       {
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)
1852
 
+       {
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;
1862
 
+       }
1863
 
+}
1864
 
+
1865
 
+static char *
1866
 
+get_fourcc_string (uint32_t f)
1867
 
+{
1868
 
+       char fcc[5];
1869
 
+
1870
 
+       memset(&fcc, 0, sizeof(fcc));
1871
 
+
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;
1877
 
+       fcc[4] = 0;
1878
 
+
1879
 
+       if(f <= 0xFFFF)
1880
 
+               sprintf(fcc, "0x%x", f);
1881
 
+
1882
 
+       if((fcc[0] == 'm') && (fcc[1] == 's'))
1883
 
+       {
1884
 
+               if((fcc[2] = 0x0) && (fcc[3] == 0x55))
1885
 
+                       *(uint32_t *) fcc = 0x33706d2e; /* Force to '.mp3' */
1886
 
+       }
1887
 
+
1888
 
+       return g_strdup (fcc);
1889
 
+}
1890
 
+
1891
 
+char *
1892
 
+bacon_video_widget_get_backend_name (BaconVideoWidget *bvw)
1893
 
+{      
1894
 
+       return g_strdup_printf ("xine-lib version %d.%d.%d",
1895
 
+                       XINE_MAJOR_VERSION,
1896
 
+                       XINE_MINOR_VERSION,
1897
 
+                       XINE_SUB_VERSION);
1898
 
+}
1899
 
+
1900
 
+gboolean
1901
 
+bacon_video_widget_open (BaconVideoWidget *bvw, const char *mrl,
1902
 
+               GError **gerror)
1903
 
+{
1904
 
+       int error;
1905
 
+
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);
1910
 
+
1911
 
+       bvw->priv->video_fcc = 0;
1912
 
+       bvw->priv->audio_fcc = 0;
1913
 
+
1914
 
+       error = xine_open (bvw->priv->stream, mrl);
1915
 
+       if (error == 0)
1916
 
+       {
1917
 
+               bacon_video_widget_close (bvw);
1918
 
+               xine_error (bvw, gerror);
1919
 
+               return FALSE;
1920
 
+       }
1921
 
+
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))
1928
 
+       {
1929
 
+               char *fourcc_str, *name;
1930
 
+
1931
 
+               g_signal_emit (G_OBJECT (bvw),
1932
 
+                               bvw_table_signals[GOT_METADATA], 0, NULL);
1933
 
+
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));
1939
 
+
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)
1944
 
+               {
1945
 
+                       bvw->priv->audio_fcc = xine_get_stream_info
1946
 
+                               (bvw->priv->stream,
1947
 
+                                XINE_STREAM_INFO_AUDIO_FOURCC);
1948
 
+               }
1949
 
+
1950
 
+               bacon_video_widget_close (bvw);
1951
 
+
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);
1955
 
+
1956
 
+               g_free (fourcc_str);
1957
 
+               g_free (name);
1958
 
+
1959
 
+               return FALSE;
1960
 
+       }
1961
 
+
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)
1966
 
+       {
1967
 
+               g_signal_emit (G_OBJECT (bvw),
1968
 
+                               bvw_table_signals[GOT_METADATA], 0, NULL);
1969
 
+
1970
 
+               bacon_video_widget_close (bvw);
1971
 
+
1972
 
+               g_set_error (gerror, 0, 0,
1973
 
+                               _("This is an audio-only file, and there is no audio output available."));
1974
 
+
1975
 
+               return FALSE;
1976
 
+       }
1977
 
+
1978
 
+       show_vfx_update (bvw, bvw->priv->show_vfx);
1979
 
+
1980
 
+       bvw->priv->mrl = g_strdup (mrl);
1981
 
+
1982
 
+       g_signal_emit (G_OBJECT (bvw),
1983
 
+                       bvw_table_signals[GOT_METADATA], 0, NULL);
1984
 
+
1985
 
+       return TRUE;
1986
 
+}
1987
 
+
1988
 
+gboolean
1989
 
+bacon_video_widget_play (BaconVideoWidget *bvw, GError **gerror)
1990
 
+{
1991
 
+       int error;
1992
 
+
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);
1996
 
+
1997
 
+       bvw->priv->started = TRUE;
1998
 
+       error = 1;
1999
 
+
2000
 
+       if (bvw->priv->seeking == 1)
2001
 
+       {
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;
2009
 
+       } else {
2010
 
+               int speed, status;
2011
 
+
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)
2015
 
+               {
2016
 
+                       xine_set_param (bvw->priv->stream,
2017
 
+                                       XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
2018
 
+               } else {
2019
 
+                       error = xine_play (bvw->priv->stream, 0, 0);
2020
 
+               }
2021
 
+
2022
 
+               bvw->priv->seeking = 0;
2023
 
+       }
2024
 
+
2025
 
+       if (error == 0)
2026
 
+       {
2027
 
+               xine_error (bvw, gerror);
2028
 
+               return FALSE;
2029
 
+       }
2030
 
+
2031
 
+       if (bvw->priv->queued_vis != NULL)
2032
 
+       {
2033
 
+               bacon_video_widget_set_visuals (bvw, bvw->priv->queued_vis);
2034
 
+               g_free (bvw->priv->queued_vis);
2035
 
+               bvw->priv->queued_vis = NULL;
2036
 
+       }
2037
 
+
2038
 
+       /* Workaround for xine-lib: don't try to use a
2039
 
+        * non-existent audio channel */
2040
 
+       {
2041
 
+               int cur, num;
2042
 
+
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);
2047
 
+               if (cur > num)
2048
 
+                       xine_set_param(bvw->priv->stream,
2049
 
+                                       XINE_PARAM_AUDIO_CHANNEL_LOGICAL, -1);
2050
 
+       }
2051
 
+
2052
 
+       return TRUE;
2053
 
+}
2054
 
+
2055
 
+gboolean bacon_video_widget_seek (BaconVideoWidget *bvw, float position,
2056
 
+               GError **gerror)
2057
 
+{
2058
 
+       int error, speed;
2059
 
+
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);
2063
 
+
2064
 
+       speed = xine_get_param (bvw->priv->stream, XINE_PARAM_SPEED);
2065
 
+       if (speed == XINE_SPEED_PAUSE)
2066
 
+       {
2067
 
+               bvw->priv->seeking = 1;
2068
 
+               bvw->priv->seek_dest = position;
2069
 
+               return TRUE;
2070
 
+       }
2071
 
+
2072
 
+       error = xine_play (bvw->priv->stream, position * 65535, 0);
2073
 
+
2074
 
+       if (error == 0)
2075
 
+       {
2076
 
+               xine_error (bvw, gerror);
2077
 
+               return FALSE;
2078
 
+       }
2079
 
+
2080
 
+       return TRUE;
2081
 
+}
2082
 
+
2083
 
+gboolean bacon_video_widget_seek_time (BaconVideoWidget *bvw, gint64 time,
2084
 
+               GError **gerror)
2085
 
+{
2086
 
+       int error, speed;
2087
 
+       gint64 length;
2088
 
+
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);
2092
 
+
2093
 
+       length = bacon_video_widget_get_stream_length (bvw);
2094
 
+
2095
 
+       speed = xine_get_param (bvw->priv->stream, XINE_PARAM_SPEED);
2096
 
+       if (speed == XINE_SPEED_PAUSE)
2097
 
+       {
2098
 
+               bvw->priv->seeking = 2;
2099
 
+               bvw->priv->seek_dest_time = CLAMP (time, 0, length);
2100
 
+               return TRUE;
2101
 
+       }
2102
 
+
2103
 
+       length = bacon_video_widget_get_stream_length (bvw);
2104
 
+
2105
 
+       error = xine_play (bvw->priv->stream, 0, CLAMP (time, 0, length));
2106
 
+
2107
 
+       if (error == 0)
2108
 
+       {
2109
 
+               xine_error (bvw, gerror);
2110
 
+               return FALSE;
2111
 
+       }
2112
 
+
2113
 
+       return TRUE;
2114
 
+}
2115
 
+
2116
 
+void
2117
 
+bacon_video_widget_stop (BaconVideoWidget *bvw)
2118
 
+{
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);
2122
 
+
2123
 
+       xine_stop (bvw->priv->stream);
2124
 
+}
2125
 
+
2126
 
+void
2127
 
+bacon_video_widget_close (BaconVideoWidget *bvw)
2128
 
+{
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);
2132
 
+
2133
 
+       xine_stop (bvw->priv->stream);
2134
 
+       xine_close (bvw->priv->stream);
2135
 
+       g_free (bvw->priv->mrl);
2136
 
+       bvw->priv->mrl = NULL;
2137
 
+
2138
 
+       if (bvw->priv->logo_mode == FALSE)
2139
 
+               g_signal_emit (G_OBJECT (bvw),
2140
 
+                               bvw_table_signals[CHANNELS_CHANGE], 0, NULL);
2141
 
+}
2142
 
+
2143
 
+/* Properties */
2144
 
+static void
2145
 
+bacon_video_widget_set_property (GObject *object, guint property_id,
2146
 
+               const GValue *value, GParamSpec *pspec)
2147
 
+{
2148
 
+       BaconVideoWidget *bvw;
2149
 
+
2150
 
+       g_return_if_fail (BACON_IS_VIDEO_WIDGET (object));
2151
 
+
2152
 
+       bvw = BACON_VIDEO_WIDGET (object);
2153
 
+
2154
 
+       switch (property_id)
2155
 
+       {
2156
 
+       case PROP_LOGO_MODE:
2157
 
+               bacon_video_widget_set_logo_mode (bvw,
2158
 
+                               g_value_get_boolean (value));
2159
 
+               break;
2160
 
+       case PROP_SHOWCURSOR:
2161
 
+               bacon_video_widget_set_show_cursor (bvw,
2162
 
+                               g_value_get_boolean (value));
2163
 
+               break;
2164
 
+       case PROP_MEDIADEV:
2165
 
+               bacon_video_widget_set_media_device (bvw,
2166
 
+                               g_value_get_string (value));
2167
 
+               break;
2168
 
+       case PROP_SHOW_VISUALS:
2169
 
+               bacon_video_widget_set_show_visuals (bvw,
2170
 
+                               g_value_get_boolean (value));
2171
 
+               break;
2172
 
+       default:
2173
 
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
2174
 
+       }
2175
 
+}
2176
 
+
2177
 
+static void
2178
 
+bacon_video_widget_get_property (GObject *object, guint property_id,
2179
 
+               GValue *value, GParamSpec *pspec)
2180
 
+{
2181
 
+       BaconVideoWidget *bvw;
2182
 
+
2183
 
+       g_return_if_fail (BACON_IS_VIDEO_WIDGET (object));
2184
 
+
2185
 
+       bvw = BACON_VIDEO_WIDGET (object);
2186
 
+
2187
 
+       switch (property_id)
2188
 
+       {
2189
 
+       case PROP_LOGO_MODE:
2190
 
+               g_value_set_boolean (value,
2191
 
+                               bacon_video_widget_get_logo_mode (bvw));
2192
 
+               break;
2193
 
+       case PROP_POSITION:
2194
 
+               g_value_set_int64 (value, bacon_video_widget_get_position (bvw));
2195
 
+               break;
2196
 
+       case PROP_STREAM_LENGTH:
2197
 
+               g_value_set_int64 (value,
2198
 
+                               bacon_video_widget_get_stream_length (bvw));
2199
 
+               break;
2200
 
+       case PROP_PLAYING:
2201
 
+               g_value_set_boolean (value,
2202
 
+                               bacon_video_widget_is_playing (bvw));
2203
 
+               break;
2204
 
+       case PROP_SEEKABLE:
2205
 
+               g_value_set_boolean (value,
2206
 
+                               bacon_video_widget_is_seekable (bvw));
2207
 
+               break;
2208
 
+       case PROP_SHOWCURSOR:
2209
 
+               g_value_set_boolean (value,
2210
 
+                               bacon_video_widget_get_show_cursor (bvw));
2211
 
+               break;
2212
 
+       default:
2213
 
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
2214
 
+       }
2215
 
+}
2216
 
+
2217
 
+void
2218
 
+bacon_video_widget_set_logo_mode (BaconVideoWidget *bvw, gboolean logo_mode)
2219
 
+{
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);
2223
 
+
2224
 
+       bvw->priv->logo_mode = logo_mode;
2225
 
+}
2226
 
+
2227
 
+void
2228
 
+bacon_video_widget_set_logo (BaconVideoWidget *bvw, char *filename)
2229
 
+{
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);
2233
 
+
2234
 
+       if (bacon_video_widget_open (bvw, filename, NULL) != FALSE) {
2235
 
+               bacon_video_widget_play (bvw, NULL);
2236
 
+       }
2237
 
+}
2238
 
+
2239
 
+gboolean
2240
 
+bacon_video_widget_get_logo_mode (BaconVideoWidget *bvw)
2241
 
+{
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);
2245
 
+
2246
 
+       return bvw->priv->logo_mode;
2247
 
+}
2248
 
+
2249
 
+void
2250
 
+bacon_video_widget_pause (BaconVideoWidget *bvw)
2251
 
+{
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);
2255
 
+
2256
 
+       xine_set_param (bvw->priv->stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
2257
 
+
2258
 
+       if (bvw->priv->is_live != FALSE)
2259
 
+               xine_stop (bvw->priv->stream);
2260
 
+
2261
 
+       /* Close the audio device when on pause */
2262
 
+       xine_set_param (bvw->priv->stream,
2263
 
+                       XINE_PARAM_AUDIO_CLOSE_DEVICE, 1);
2264
 
+}
2265
 
+
2266
 
+float
2267
 
+bacon_video_widget_get_position (BaconVideoWidget *bvw)
2268
 
+{
2269
 
+       int pos_stream = 0, i = 0;
2270
 
+       int pos_time, length_time;
2271
 
+       gboolean ret;
2272
 
+
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);
2276
 
+
2277
 
+       if (bvw->priv->mrl == NULL)
2278
 
+               return 0;
2279
 
+
2280
 
+       if (bacon_video_widget_is_playing (bvw) == FALSE)
2281
 
+               return 0;
2282
 
+
2283
 
+       ret = xine_get_pos_length (bvw->priv->stream, &pos_stream,
2284
 
+                       &pos_time, &length_time);
2285
 
+
2286
 
+       while (ret == FALSE && i < 10)
2287
 
+       {
2288
 
+               usleep (100000);
2289
 
+               ret = xine_get_pos_length (bvw->priv->stream, &pos_stream,
2290
 
+                               &pos_time, &length_time);
2291
 
+               i++;
2292
 
+       }
2293
 
+
2294
 
+       if (bvw->priv->seeking == 1)
2295
 
+       {
2296
 
+               return bvw->priv->seek_dest * length_time;
2297
 
+       } else if (bvw->priv->seeking == 2) {
2298
 
+               return bvw->priv->seek_dest_time;
2299
 
+       }
2300
 
+
2301
 
+       if (ret == FALSE)
2302
 
+               return -1;
2303
 
+
2304
 
+       return pos_stream / 65535;
2305
 
+}
2306
 
+
2307
 
+gboolean
2308
 
+bacon_video_widget_can_set_volume (BaconVideoWidget *bvw)
2309
 
+{
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);
2313
 
+
2314
 
+       if (bvw->priv->ao_driver == NULL)
2315
 
+               return FALSE;
2316
 
+
2317
 
+       if (xine_get_param (bvw->priv->stream,
2318
 
+                               XINE_PARAM_AUDIO_CHANNEL_LOGICAL) == -2)
2319
 
+               return FALSE;
2320
 
+
2321
 
+       return TRUE;
2322
 
+}
2323
 
+
2324
 
+void
2325
 
+bacon_video_widget_set_volume (BaconVideoWidget *bvw, int volume)
2326
 
+{
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);
2330
 
+
2331
 
+       if (bacon_video_widget_can_set_volume (bvw) != FALSE)
2332
 
+       {
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;
2337
 
+       }
2338
 
+}
2339
 
+
2340
 
+int
2341
 
+bacon_video_widget_get_volume (BaconVideoWidget *bvw)
2342
 
+{
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);
2346
 
+
2347
 
+       if (bacon_video_widget_can_set_volume (bvw) == FALSE)
2348
 
+               return 0;
2349
 
+
2350
 
+       if (bvw->priv->volume == -1)
2351
 
+       {
2352
 
+               xine_cfg_entry_t entry;
2353
 
+
2354
 
+               xine_config_lookup_entry (bvw->priv->xine,
2355
 
+                               "misc.amp_level", &entry);
2356
 
+               bvw->priv->volume = entry.num_value;
2357
 
+
2358
 
+               xine_set_param (bvw->priv->stream,
2359
 
+                               XINE_PARAM_AUDIO_AMP_LEVEL, bvw->priv->volume);
2360
 
+       }
2361
 
+
2362
 
+       return bvw->priv->volume;
2363
 
+}
2364
 
+
2365
 
+gboolean
2366
 
+bacon_video_widget_fullscreen_mode_available (BaconVideoWidget *bvw,
2367
 
+               TvOutType tvout) 
2368
 
+{
2369
 
+       switch(tvout) {
2370
 
+       case TV_OUT_NONE:
2371
 
+               /* Assume that ordinary fullscreen always works */
2372
 
+               return TRUE;
2373
 
+       case TV_OUT_NVTV_NTSC:
2374
 
+       case TV_OUT_NVTV_PAL:
2375
 
+#ifdef HAVE_NVTV
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);
2380
 
+               }
2381
 
+               return (nvtv_simple_is_available());
2382
 
+#else
2383
 
+               return FALSE;
2384
 
+#endif
2385
 
+       case TV_OUT_DXR3:
2386
 
+               {
2387
 
+                       const char * const *list;
2388
 
+                       int i;
2389
 
+
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)
2393
 
+                                       return TRUE;
2394
 
+                       }
2395
 
+                       return FALSE;
2396
 
+               }
2397
 
+       default:
2398
 
+               g_assert_not_reached ();
2399
 
+       }
2400
 
+
2401
 
+       return FALSE;
2402
 
+}
2403
 
+
2404
 
+void
2405
 
+bacon_video_widget_set_fullscreen (BaconVideoWidget *bvw, gboolean fullscreen)
2406
 
+{
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))
2410
 
+               return;
2411
 
+
2412
 
+       bvw->priv->fullscreen_mode = fullscreen;
2413
 
+
2414
 
+       if (fullscreen == FALSE)
2415
 
+       {
2416
 
+#ifdef HAVE_NVTV
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);
2420
 
+        
2421
 
+               /* Else if just auto resize is used */
2422
 
+        } else if (bvw->priv->auto_resize != FALSE) {
2423
 
+#endif
2424
 
+               bacon_restore (bvw->priv->screenid);
2425
 
+#ifdef HAVE_NVTV
2426
 
+       }
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);
2433
 
+#endif
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);
2439
 
+       } 
2440
 
+}
2441
 
+
2442
 
+void
2443
 
+bacon_video_widget_set_show_cursor (BaconVideoWidget *bvw,
2444
 
+               gboolean show_cursor)
2445
 
+{
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);
2449
 
+
2450
 
+       if (show_cursor == FALSE)
2451
 
+       {
2452
 
+               eel_gdk_window_set_invisible_cursor (bvw->priv->video_window);
2453
 
+       } else {
2454
 
+               gdk_window_set_cursor (bvw->priv->video_window, NULL);
2455
 
+       }
2456
 
+
2457
 
+       bvw->priv->cursor_shown = show_cursor;
2458
 
+}
2459
 
+
2460
 
+gboolean
2461
 
+bacon_video_widget_get_show_cursor (BaconVideoWidget *bvw)
2462
 
+{
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);
2466
 
+
2467
 
+       return bvw->priv->cursor_shown;
2468
 
+}
2469
 
+
2470
 
+void
2471
 
+bacon_video_widget_set_media_device (BaconVideoWidget *bvw, const char *path)
2472
 
+{
2473
 
+       xine_cfg_entry_t entry;
2474
 
+
2475
 
+       /* DVD device */
2476
 
+       bvw_config_helper_string (bvw->priv->xine, "input.dvd_device",
2477
 
+                       path, &entry);
2478
 
+       entry.str_value = g_strdup (path);
2479
 
+       xine_config_update_entry (bvw->priv->xine, &entry);
2480
 
+
2481
 
+       /* VCD device */
2482
 
+       bvw_config_helper_string (bvw->priv->xine, "input.vcd_device",
2483
 
+                       path, &entry);
2484
 
+       entry.str_value = g_strdup (path);
2485
 
+       xine_config_update_entry (bvw->priv->xine, &entry);
2486
 
+
2487
 
+       /* VCD device for the new input plugin */
2488
 
+       bvw_config_helper_string (bvw->priv->xine, "vcd.default_device",
2489
 
+                       path, &entry);
2490
 
+       entry.str_value = g_strdup (path);
2491
 
+       xine_config_update_entry (bvw->priv->xine, &entry);
2492
 
+
2493
 
+       /* CDDA device */
2494
 
+       bvw_config_helper_string (bvw->priv->xine, "input.cdda_device",
2495
 
+                       path, &entry);
2496
 
+       entry.str_value = g_strdup (path);
2497
 
+       xine_config_update_entry (bvw->priv->xine, &entry);
2498
 
+}
2499
 
+
2500
 
+void
2501
 
+bacon_video_widget_set_proprietary_plugins_path (BaconVideoWidget *bvw,
2502
 
+               const char *path)
2503
 
+{
2504
 
+       xine_cfg_entry_t entry;
2505
 
+
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);
2510
 
+
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);
2515
 
+
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);
2522
 
+}
2523
 
+
2524
 
+void
2525
 
+bacon_video_widget_set_connection_speed (BaconVideoWidget *bvw, int speed)
2526
 
+{
2527
 
+       xine_cfg_entry_t entry;
2528
 
+
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);
2533
 
+
2534
 
+       xine_config_register_enum (bvw->priv->xine,
2535
 
+                       "input.mms_network_bandwidth",
2536
 
+                       6,
2537
 
+                       (char **) mms_bandwidth_strs,
2538
 
+                       "Network bandwidth",
2539
 
+                       NULL, 0, NULL, NULL);
2540
 
+
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);
2545
 
+}
2546
 
+
2547
 
+int
2548
 
+bacon_video_widget_get_connection_speed (BaconVideoWidget *bvw)
2549
 
+{
2550
 
+       xine_cfg_entry_t entry;
2551
 
+
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);
2555
 
+
2556
 
+       xine_config_register_enum (bvw->priv->xine,
2557
 
+                       "input.mms_network_bandwidth",
2558
 
+                       6,
2559
 
+                       (char **) mms_bandwidth_strs,
2560
 
+                       "Network bandwidth",
2561
 
+                       NULL, 0, NULL, NULL);
2562
 
+
2563
 
+       xine_config_lookup_entry (bvw->priv->xine,
2564
 
+                       "input.mms_network_bandwidth", &entry);
2565
 
+
2566
 
+       return entry.num_value;
2567
 
+}
2568
 
+
2569
 
+void
2570
 
+bacon_video_widget_set_deinterlacing (BaconVideoWidget *bvw,
2571
 
+               gboolean deinterlace)
2572
 
+{
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);
2576
 
+
2577
 
+       xine_set_param (bvw->priv->stream, XINE_PARAM_VO_DEINTERLACE,
2578
 
+                       deinterlace);
2579
 
+}
2580
 
+
2581
 
+gboolean
2582
 
+bacon_video_widget_get_deinterlacing (BaconVideoWidget *bvw)
2583
 
+{
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);
2587
 
+
2588
 
+       return xine_get_param (bvw->priv->stream, XINE_PARAM_VO_DEINTERLACE);
2589
 
+}
2590
 
+
2591
 
+gboolean
2592
 
+bacon_video_widget_set_tv_out (BaconVideoWidget *bvw, TvOutType tvout)
2593
 
+{
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);
2597
 
+
2598
 
+       if (tvout == TV_OUT_DXR3 || bvw->priv->tvout == TV_OUT_DXR3)
2599
 
+       {
2600
 
+               xine_cfg_entry_t entry;
2601
 
+
2602
 
+               xine_config_lookup_entry (bvw->priv->xine,
2603
 
+                               "video.driver", &entry);
2604
 
+               entry.str_value = g_strdup (tvout == TV_OUT_DXR3 ?
2605
 
+                               "dxr3" : "auto");
2606
 
+               xine_config_update_entry (bvw->priv->xine, &entry);
2607
 
+
2608
 
+               bvw->priv->tvout = tvout;
2609
 
+
2610
 
+               return TRUE;
2611
 
+       }
2612
 
+
2613
 
+#ifdef HAVE_NVTV
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);
2618
 
+       }
2619
 
+#endif
2620
 
+
2621
 
+       bvw->priv->tvout = tvout;
2622
 
+
2623
 
+       return FALSE;
2624
 
+}
2625
 
+
2626
 
+TvOutType
2627
 
+bacon_video_widget_get_tv_out (BaconVideoWidget *bvw)
2628
 
+{
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);
2632
 
+
2633
 
+       return bvw->priv->tvout;
2634
 
+}
2635
 
+
2636
 
+gboolean
2637
 
+bacon_video_widget_set_show_visuals (BaconVideoWidget *bvw,
2638
 
+               gboolean show_visuals)
2639
 
+{
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);
2643
 
+
2644
 
+       bvw->priv->show_vfx = show_visuals;
2645
 
+       show_vfx_update (bvw, show_visuals);
2646
 
+
2647
 
+       return TRUE;
2648
 
+}
2649
 
+
2650
 
+GList *
2651
 
+bacon_video_widget_get_visuals_list (BaconVideoWidget *bvw)
2652
 
+{
2653
 
+       const char * const* plugins;
2654
 
+       int i;
2655
 
+
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);
2659
 
+
2660
 
+       if (bvw->priv->visuals != NULL)
2661
 
+               return bvw->priv->visuals;
2662
 
+
2663
 
+       plugins = xine_list_post_plugins_typed (bvw->priv->xine,
2664
 
+                       XINE_POST_TYPE_AUDIO_VISUALIZATION);
2665
 
+
2666
 
+       for (i = 0; plugins[i] != NULL; i++)
2667
 
+       {
2668
 
+               bvw->priv->visuals = g_list_prepend
2669
 
+                       (bvw->priv->visuals, g_strdup (plugins[i]));
2670
 
+       }
2671
 
+
2672
 
+       bvw->priv->visuals = g_list_reverse (bvw->priv->visuals);
2673
 
+
2674
 
+       return bvw->priv->visuals;
2675
 
+}
2676
 
+
2677
 
+gboolean
2678
 
+bacon_video_widget_set_visuals (BaconVideoWidget *bvw, const char *name)
2679
 
+{
2680
 
+       xine_post_t *newvis;
2681
 
+       int speed;
2682
 
+
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);
2686
 
+
2687
 
+       if (bvw->priv->null_out != FALSE || bvw->priv->ao_driver == NULL)
2688
 
+               return FALSE;
2689
 
+
2690
 
+       if (GTK_WIDGET_REALIZED (bvw) == FALSE)
2691
 
+       {
2692
 
+               g_free (bvw->priv->vis_name);
2693
 
+               bvw->priv->vis_name = g_strdup (name);
2694
 
+               return FALSE;
2695
 
+       }
2696
 
+
2697
 
+       speed = xine_get_param (bvw->priv->stream, XINE_PARAM_SPEED);
2698
 
+       if (speed == XINE_SPEED_PAUSE && bvw->priv->using_vfx != FALSE)
2699
 
+       {
2700
 
+               g_free (bvw->priv->queued_vis);
2701
 
+               if (strcmp (name, bvw->priv->vis_name) == 0)
2702
 
+               {
2703
 
+                       bvw->priv->queued_vis = NULL;
2704
 
+               } else {
2705
 
+                       bvw->priv->queued_vis = g_strdup (name);
2706
 
+               }
2707
 
+               return FALSE;
2708
 
+       }
2709
 
+
2710
 
+       newvis = xine_post_init (bvw->priv->xine,
2711
 
+                       name, 0,
2712
 
+                       &bvw->priv->ao_driver, &bvw->priv->vo_driver);
2713
 
+
2714
 
+       if (newvis != NULL)
2715
 
+       {
2716
 
+               g_free (bvw->priv->vis_name);
2717
 
+               bvw->priv->vis_name = g_strdup (name);
2718
 
+
2719
 
+               if (bvw->priv->vis != NULL)
2720
 
+               {
2721
 
+                       xine_post_t *oldvis;
2722
 
+
2723
 
+                       oldvis = bvw->priv->vis;
2724
 
+                       bvw->priv->vis = newvis;
2725
 
+
2726
 
+                       if (bvw->priv->using_vfx != FALSE)
2727
 
+                       {
2728
 
+                               show_vfx_update (bvw, FALSE);
2729
 
+                               show_vfx_update (bvw, TRUE);
2730
 
+                       }
2731
 
+                       xine_post_dispose (bvw->priv->xine, oldvis);
2732
 
+               } else {
2733
 
+                       bvw->priv->vis = newvis;
2734
 
+               }
2735
 
+       }
2736
 
+
2737
 
+       return FALSE;
2738
 
+}
2739
 
+
2740
 
+void
2741
 
+bacon_video_widget_set_visuals_quality (BaconVideoWidget *bvw,
2742
 
+               VisualsQuality quality)
2743
 
+{
2744
 
+       xine_cfg_entry_t entry;
2745
 
+       int fps, w, h;
2746
 
+
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);
2750
 
+
2751
 
+       switch (quality)
2752
 
+       {
2753
 
+       case VISUAL_SMALL:
2754
 
+               fps = 15;
2755
 
+               w = 320;
2756
 
+               h = 240;
2757
 
+               break;
2758
 
+       case VISUAL_NORMAL:
2759
 
+               fps = 25;
2760
 
+               w = 320;
2761
 
+               h = 240;
2762
 
+               break;
2763
 
+       case VISUAL_LARGE:
2764
 
+               fps = 25;
2765
 
+               w = 640;
2766
 
+               h = 480;
2767
 
+               break;
2768
 
+       case VISUAL_EXTRA_LARGE:
2769
 
+               fps = 30;
2770
 
+               w = 800;
2771
 
+               h = 600;
2772
 
+               break;
2773
 
+       default:
2774
 
+               /* shut up warnings */
2775
 
+               fps = w = h = 0;
2776
 
+               g_assert_not_reached ();
2777
 
+       }
2778
 
+
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);
2782
 
+
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);
2786
 
+
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);
2790
 
+}
2791
 
+
2792
 
+gboolean
2793
 
+bacon_video_widget_get_auto_resize (BaconVideoWidget *bvw)
2794
 
+{
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);
2798
 
+
2799
 
+       return bvw->priv->auto_resize;
2800
 
+}
2801
 
+
2802
 
+void
2803
 
+bacon_video_widget_set_auto_resize (BaconVideoWidget *bvw,
2804
 
+               gboolean auto_resize)
2805
 
+{
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);
2809
 
+
2810
 
+       bvw->priv->auto_resize = auto_resize;
2811
 
+}
2812
 
+
2813
 
+gint64
2814
 
+bacon_video_widget_get_current_time (BaconVideoWidget *bvw)
2815
 
+{
2816
 
+       int pos_time = 0, i = 0;
2817
 
+       int pos_stream, length_time;
2818
 
+       gboolean ret;
2819
 
+
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);
2823
 
+
2824
 
+       if (bacon_video_widget_is_playing (bvw) == FALSE)
2825
 
+               return 0;
2826
 
+
2827
 
+       ret = xine_get_pos_length (bvw->priv->stream, &pos_stream,
2828
 
+                       &pos_time, &length_time);
2829
 
+
2830
 
+       while (ret == FALSE && i < 10)
2831
 
+       {
2832
 
+               usleep (100000);
2833
 
+               ret = xine_get_pos_length (bvw->priv->stream, &pos_stream,
2834
 
+                               &pos_time, &length_time);
2835
 
+               i++;
2836
 
+       }
2837
 
+
2838
 
+       if (bvw->priv->seeking == 1)
2839
 
+       {
2840
 
+               return bvw->priv->seek_dest * length_time;
2841
 
+       } else if (bvw->priv->seeking == 2) {
2842
 
+               return bvw->priv->seek_dest_time;
2843
 
+       }
2844
 
+
2845
 
+       if (ret == FALSE)
2846
 
+               return -1;
2847
 
+
2848
 
+       return pos_time;
2849
 
+}
2850
 
+
2851
 
+gint64
2852
 
+bacon_video_widget_get_stream_length (BaconVideoWidget *bvw)
2853
 
+{
2854
 
+       int length_time = 0;
2855
 
+       int pos_stream, pos_time;
2856
 
+
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);
2860
 
+
2861
 
+       if (bvw->priv->mrl == NULL)
2862
 
+               return 0;
2863
 
+
2864
 
+       xine_get_pos_length (bvw->priv->stream, &pos_stream,
2865
 
+                       &pos_time, &length_time);
2866
 
+
2867
 
+       return length_time;
2868
 
+}
2869
 
+
2870
 
+gboolean
2871
 
+bacon_video_widget_is_playing (BaconVideoWidget *bvw)
2872
 
+{
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);
2876
 
+
2877
 
+       if (bvw->priv->stream == NULL)
2878
 
+               return FALSE;
2879
 
+
2880
 
+       return (xine_get_status (bvw->priv->stream) == XINE_STATUS_PLAY && xine_get_param (bvw->priv->stream, XINE_PARAM_SPEED) == XINE_SPEED_NORMAL);
2881
 
+}
2882
 
+
2883
 
+gboolean
2884
 
+bacon_video_widget_is_seekable (BaconVideoWidget *bvw)
2885
 
+{
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);
2889
 
+
2890
 
+       if (bvw->priv->mrl == NULL)
2891
 
+               return FALSE;
2892
 
+
2893
 
+       if (bacon_video_widget_get_stream_length (bvw) == 0)
2894
 
+               return FALSE;
2895
 
+
2896
 
+       return xine_get_stream_info (bvw->priv->stream,
2897
 
+                       XINE_STREAM_INFO_SEEKABLE);
2898
 
+}
2899
 
+
2900
 
+gboolean
2901
 
+bacon_video_widget_can_play (BaconVideoWidget *bvw, MediaType type)
2902
 
+{
2903
 
+       switch (type)
2904
 
+       {
2905
 
+       case MEDIA_DVD:
2906
 
+               return bvw->priv->can_dvd;
2907
 
+       case MEDIA_VCD:
2908
 
+               return bvw->priv->can_vcd;
2909
 
+       case MEDIA_CDDA:
2910
 
+               return bvw->priv->can_cdda;
2911
 
+       default:
2912
 
+               return FALSE;
2913
 
+       }
2914
 
+}
2915
 
+
2916
 
+G_CONST_RETURN char
2917
 
+**bacon_video_widget_get_mrls (BaconVideoWidget *bvw, MediaType type)
2918
 
+{
2919
 
+       char *plugin_id;
2920
 
+       int num_mrls;
2921
 
+
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);
2925
 
+
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)
2931
 
+               plugin_id = "CD";
2932
 
+       else
2933
 
+               return NULL;
2934
 
+
2935
 
+       return (G_CONST_RETURN char **) xine_get_autoplay_mrls
2936
 
+               (bvw->priv->xine, plugin_id, &num_mrls);
2937
 
+}
2938
 
+
2939
 
+void
2940
 
+bacon_video_widget_set_video_device (BaconVideoWidget *bvw, const char *path)
2941
 
+{
2942
 
+       xine_cfg_entry_t entry;
2943
 
+
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);
2948
 
+}
2949
 
+
2950
 
+void
2951
 
+bacon_video_widget_set_aspect_ratio (BaconVideoWidget *bvw,
2952
 
+               BaconVideoWidgetAspectRatio ratio)
2953
 
+{
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);
2957
 
+
2958
 
+       xine_set_param (bvw->priv->stream, XINE_PARAM_VO_ASPECT_RATIO, ratio);
2959
 
+}
2960
 
+
2961
 
+int
2962
 
+bacon_video_widget_get_aspect_ratio (BaconVideoWidget *bvw)
2963
 
+{
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);
2967
 
+
2968
 
+       return xine_get_param (bvw->priv->stream, XINE_PARAM_VO_ASPECT_RATIO);
2969
 
+}
2970
 
+
2971
 
+static gboolean
2972
 
+bacon_video_widget_ratio_fits_screen (BaconVideoWidget *bvw, gfloat ratio)
2973
 
+{
2974
 
+       GdkRectangle fullscreen_rect;
2975
 
+       int new_w, new_h;
2976
 
+
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);
2980
 
+
2981
 
+       new_w = bvw->priv->video_width * ratio;
2982
 
+       new_h = bvw->priv->video_height * ratio;
2983
 
+
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);
2989
 
+
2990
 
+       if (new_w > (fullscreen_rect.width - 128) ||
2991
 
+                       new_h > (fullscreen_rect.height - 128))
2992
 
+       {
2993
 
+               return FALSE;
2994
 
+       }
2995
 
+
2996
 
+       return TRUE;
2997
 
+}
2998
 
+
2999
 
+void
3000
 
+bacon_video_widget_set_scale_ratio (BaconVideoWidget *bvw, gfloat ratio)
3001
 
+{
3002
 
+       GtkWidget *toplevel, *widget;
3003
 
+       int new_w, new_h, win_w, win_h;
3004
 
+
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);
3009
 
+
3010
 
+       if (bvw->priv->fullscreen_mode != FALSE)
3011
 
+               return;
3012
 
+
3013
 
+       /* Try best fit for the screen */
3014
 
+       if (ratio == 0)
3015
 
+       {
3016
 
+               if (bacon_video_widget_ratio_fits_screen (bvw, 2) != FALSE)
3017
 
+               {
3018
 
+                       ratio = 2;
3019
 
+               } else if (bacon_video_widget_ratio_fits_screen (bvw, 1)
3020
 
+                               != FALSE) {
3021
 
+                       ratio = 1;
3022
 
+               } else if (bacon_video_widget_ratio_fits_screen (bvw, 0.5)
3023
 
+                               != FALSE) {
3024
 
+                       ratio = 0.5;
3025
 
+               } else {
3026
 
+                       return;
3027
 
+               }
3028
 
+       } else {
3029
 
+               /* don't scale to something bigger than the screen, and leave
3030
 
+                * us some room */
3031
 
+               if (bacon_video_widget_ratio_fits_screen (bvw, ratio) == FALSE)
3032
 
+                       return;
3033
 
+       }
3034
 
+
3035
 
+       widget = GTK_WIDGET (bvw);
3036
 
+
3037
 
+       toplevel = gtk_widget_get_toplevel (widget);
3038
 
+
3039
 
+       /* Get the size of the toplevel window */
3040
 
+       gdk_drawable_get_size (GDK_DRAWABLE (toplevel->window),
3041
 
+                       &win_w, &win_h);
3042
 
+
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;
3049
 
+
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)
3054
 
+       {
3055
 
+               gtk_widget_set_size_request (widget,
3056
 
+                               bvw->priv->video_width * ratio,
3057
 
+                               bvw->priv->video_height * ratio);
3058
 
+       }
3059
 
+
3060
 
+       gtk_window_resize (GTK_WINDOW (toplevel), new_w, new_h);
3061
 
+}
3062
 
+
3063
 
+int
3064
 
+bacon_video_widget_get_video_property (BaconVideoWidget *bvw,
3065
 
+               BaconVideoWidgetVideoProperty type)
3066
 
+{
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);
3070
 
+
3071
 
+       return xine_get_param (bvw->priv->stream, video_props[type]);
3072
 
+}
3073
 
+
3074
 
+void
3075
 
+bacon_video_widget_set_video_property (BaconVideoWidget *bvw,
3076
 
+               BaconVideoWidgetVideoProperty type, int value)
3077
 
+{
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);
3081
 
+
3082
 
+       if ( !(value < 65535 && value > 0) )
3083
 
+               return;
3084
 
+
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);
3087
 
+}
3088
 
+
3089
 
+BaconVideoWidgetAudioOutType
3090
 
+bacon_video_widget_get_audio_out_type (BaconVideoWidget *bvw)
3091
 
+{
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);
3096
 
+
3097
 
+       return gconf_client_get_int (bvw->priv->gc,
3098
 
+                       GCONF_PREFIX"/audio_output_type", NULL);
3099
 
+}
3100
 
+
3101
 
+void
3102
 
+bacon_video_widget_set_audio_out_type (BaconVideoWidget *bvw,
3103
 
+               BaconVideoWidgetAudioOutType type)
3104
 
+{
3105
 
+       xine_cfg_entry_t entry;
3106
 
+       int value;
3107
 
+
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);
3111
 
+
3112
 
+       xine_config_register_enum (bvw->priv->xine,
3113
 
+                       "audio.speaker_arrangement",
3114
 
+                       1,
3115
 
+                       (char **) audio_out_types_strs,
3116
 
+                       "Speaker arrangement",
3117
 
+                       NULL, 0, NULL, NULL); 
3118
 
+
3119
 
+       gconf_client_set_int (bvw->priv->gc,
3120
 
+                       GCONF_PREFIX"/audio_output_type",
3121
 
+                       type, NULL);
3122
 
+
3123
 
+       switch (type) {
3124
 
+       case BVW_AUDIO_SOUND_STEREO:
3125
 
+               value = 1;
3126
 
+               break;
3127
 
+       case BVW_AUDIO_SOUND_4CHANNEL:
3128
 
+               value = 6;
3129
 
+               break;
3130
 
+       case BVW_AUDIO_SOUND_5CHANNEL:
3131
 
+               value = 8;
3132
 
+               break;
3133
 
+       case BVW_AUDIO_SOUND_51CHANNEL:
3134
 
+               value = 9;
3135
 
+               break;
3136
 
+       case BVW_AUDIO_SOUND_AC3PASSTHRU:
3137
 
+               value = 3;
3138
 
+               break;
3139
 
+       default:
3140
 
+               value = 2;
3141
 
+               g_warning ("Unsupported audio type %d selected", type);
3142
 
+       }
3143
 
+
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);
3148
 
+}
3149
 
+
3150
 
+static void
3151
 
+bacon_video_widget_get_metadata_string (BaconVideoWidget *bvw, BaconVideoWidgetMetadataType type,
3152
 
+               GValue *value)
3153
 
+{
3154
 
+       const char *string = NULL;
3155
 
+
3156
 
+       g_value_init (value, G_TYPE_STRING);
3157
 
+
3158
 
+       if (bvw->priv->stream == NULL)
3159
 
+       {
3160
 
+               g_value_set_string (value, string);
3161
 
+               return;
3162
 
+       }
3163
 
+
3164
 
+       switch (type)
3165
 
+       {
3166
 
+       case BVW_INFO_TITLE:
3167
 
+               string = xine_get_meta_info (bvw->priv->stream,
3168
 
+                               XINE_META_INFO_TITLE);
3169
 
+               break;
3170
 
+       case BVW_INFO_ARTIST:
3171
 
+               string = xine_get_meta_info (bvw->priv->stream,
3172
 
+                               XINE_META_INFO_ARTIST);
3173
 
+               break;
3174
 
+       case BVW_INFO_YEAR:
3175
 
+               string = xine_get_meta_info (bvw->priv->stream,
3176
 
+                               XINE_META_INFO_YEAR);
3177
 
+               break;
3178
 
+       case BVW_INFO_VIDEO_CODEC:
3179
 
+               string = xine_get_meta_info (bvw->priv->stream,
3180
 
+                               XINE_META_INFO_VIDEOCODEC);
3181
 
+               break;
3182
 
+       case BVW_INFO_AUDIO_CODEC:
3183
 
+               string = xine_get_meta_info (bvw->priv->stream,
3184
 
+                               XINE_META_INFO_AUDIOCODEC);
3185
 
+               break;
3186
 
+       case BVW_INFO_CDINDEX:
3187
 
+               string = xine_get_meta_info (bvw->priv->stream,
3188
 
+                               XINE_META_INFO_CDINDEX_DISCID);
3189
 
+               break;
3190
 
+       default:
3191
 
+               g_assert_not_reached ();
3192
 
+       }
3193
 
+
3194
 
+       if (string != NULL && string[0] == '\0')
3195
 
+               string = NULL;
3196
 
+
3197
 
+       if (string != NULL)
3198
 
+       {
3199
 
+               if (g_utf8_validate (string, -1, NULL) == FALSE)
3200
 
+               {
3201
 
+                       char *utf8;
3202
 
+
3203
 
+                       utf8 = g_locale_to_utf8 (string, -1, NULL, NULL, NULL);
3204
 
+                       g_value_set_string (value, utf8);
3205
 
+                       g_free (utf8);
3206
 
+                       return;
3207
 
+               }
3208
 
+       }
3209
 
+
3210
 
+       g_value_set_string (value, string);
3211
 
+
3212
 
+       return;
3213
 
+}
3214
 
+
3215
 
+static void
3216
 
+bacon_video_widget_get_metadata_int (BaconVideoWidget *bvw,
3217
 
+               BaconVideoWidgetMetadataType type, GValue *value)
3218
 
+{
3219
 
+       int integer = 0;
3220
 
+
3221
 
+       g_value_init (value, G_TYPE_INT);
3222
 
+
3223
 
+       if (bvw->priv->stream == NULL)
3224
 
+       {
3225
 
+               g_value_set_int (value, 0);
3226
 
+               return;
3227
 
+       }
3228
 
+
3229
 
+       switch (type)
3230
 
+       {
3231
 
+       case BVW_INFO_DURATION:
3232
 
+               integer = bacon_video_widget_get_stream_length (bvw) / 1000;
3233
 
+               break;
3234
 
+       case BVW_INFO_DIMENSION_X:
3235
 
+               integer = xine_get_stream_info (bvw->priv->stream,
3236
 
+                               XINE_STREAM_INFO_VIDEO_WIDTH);
3237
 
+               break;
3238
 
+       case BVW_INFO_DIMENSION_Y:
3239
 
+               integer = xine_get_stream_info (bvw->priv->stream,
3240
 
+                               XINE_STREAM_INFO_VIDEO_HEIGHT);
3241
 
+               break;
3242
 
+       case BVW_INFO_VIDEO_FOURCC:
3243
 
+               integer = (guint32) bvw->priv->video_fcc;
3244
 
+               break;
3245
 
+       case BVW_INFO_FPS:
3246
 
+               if (xine_get_stream_info (bvw->priv->stream,
3247
 
+                                       XINE_STREAM_INFO_FRAME_DURATION) != 0)
3248
 
+               {
3249
 
+                       integer = 90000 / xine_get_stream_info
3250
 
+                               (bvw->priv->stream,
3251
 
+                                XINE_STREAM_INFO_FRAME_DURATION);
3252
 
+               } else {
3253
 
+                       integer = 0;
3254
 
+               }
3255
 
+               break;
3256
 
+        case BVW_INFO_BITRATE:
3257
 
+               integer = xine_get_stream_info (bvw->priv->stream,
3258
 
+                               XINE_STREAM_INFO_AUDIO_BITRATE) / 1000;
3259
 
+               break;
3260
 
+        case BVW_INFO_AUDIO_FOURCC:
3261
 
+               integer = (guint32) bvw->priv->audio_fcc;
3262
 
+               break;
3263
 
+        default:
3264
 
+               g_assert_not_reached ();
3265
 
+        }
3266
 
+
3267
 
+        g_value_set_int (value, integer);
3268
 
+
3269
 
+        return;
3270
 
+}
3271
 
+
3272
 
+static void
3273
 
+bacon_video_widget_get_metadata_bool (BaconVideoWidget *bvw,
3274
 
+               BaconVideoWidgetMetadataType type, GValue *value)
3275
 
+{
3276
 
+       gboolean boolean = FALSE;
3277
 
+
3278
 
+       g_value_init (value, G_TYPE_BOOLEAN);
3279
 
+
3280
 
+       if (bvw->priv->stream == NULL)
3281
 
+       {
3282
 
+               g_value_set_boolean (value, FALSE);
3283
 
+               return;
3284
 
+       }
3285
 
+
3286
 
+       switch (type)
3287
 
+       {
3288
 
+       case BVW_INFO_HAS_VIDEO:
3289
 
+               boolean = xine_get_stream_info (bvw->priv->stream,
3290
 
+                               XINE_STREAM_INFO_HAS_VIDEO);
3291
 
+               break;
3292
 
+       case BVW_INFO_HAS_AUDIO:
3293
 
+               boolean = xine_get_stream_info (bvw->priv->stream,
3294
 
+                               XINE_STREAM_INFO_HAS_AUDIO);
3295
 
+               break;
3296
 
+       default:
3297
 
+               g_assert_not_reached ();
3298
 
+       }
3299
 
+
3300
 
+       g_value_set_boolean (value, boolean);
3301
 
+
3302
 
+       return;
3303
 
+}
3304
 
+
3305
 
+void
3306
 
+bacon_video_widget_get_metadata (BaconVideoWidget *bvw,
3307
 
+               BaconVideoWidgetMetadataType type, GValue *value)
3308
 
+{
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);
3313
 
+
3314
 
+       switch (type)
3315
 
+       {
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);
3322
 
+               break;
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);
3331
 
+               break;
3332
 
+       case BVW_INFO_HAS_VIDEO:
3333
 
+       case BVW_INFO_HAS_AUDIO:
3334
 
+               bacon_video_widget_get_metadata_bool (bvw, type, value);
3335
 
+               break;
3336
 
+       default:
3337
 
+               g_assert_not_reached ();
3338
 
+       }
3339
 
+
3340
 
+       return;
3341
 
+}
3342
 
+
3343
 
+char
3344
 
+*bacon_video_widget_properties_get_title (BaconVideoWidget *bvw)
3345
 
+{
3346
 
+       const char *short_title, *artist;
3347
 
+
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);
3351
 
+
3352
 
+       if (artist == NULL && short_title == NULL)
3353
 
+               return NULL;
3354
 
+
3355
 
+       if (artist == NULL && short_title != NULL)
3356
 
+               return g_strdup (short_title);
3357
 
+
3358
 
+       if (artist != NULL && short_title != NULL)
3359
 
+               return g_strdup_printf ("%s - %s", artist, short_title);
3360
 
+
3361
 
+       return NULL;
3362
 
+}
3363
 
+
3364
 
+GList
3365
 
+*bacon_video_widget_get_languages (BaconVideoWidget *bvw)
3366
 
+{
3367
 
+       GList *list = NULL;
3368
 
+       int i;
3369
 
+       char lang[XINE_LANG_MAX];
3370
 
+
3371
 
+       for(i = 0; i < 32; i++)
3372
 
+       {
3373
 
+               memset (&lang, 0, sizeof (lang));
3374
 
+
3375
 
+               if (xine_get_audio_lang(bvw->priv->stream, i, lang) == 1)
3376
 
+               {
3377
 
+                       list = g_list_prepend (list,
3378
 
+                                       (gpointer) g_strdup (lang));
3379
 
+               }
3380
 
+       }
3381
 
+
3382
 
+       return g_list_reverse (list);
3383
 
+}
3384
 
+
3385
 
+int
3386
 
+bacon_video_widget_get_language (BaconVideoWidget *bvw)
3387
 
+{
3388
 
+       g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), -1);
3389
 
+       g_return_val_if_fail (bvw->priv->stream != NULL, -1);
3390
 
+
3391
 
+       return xine_get_param (bvw->priv->stream,
3392
 
+                       XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
3393
 
+}
3394
 
+
3395
 
+void
3396
 
+bacon_video_widget_set_language (BaconVideoWidget *bvw, int language)
3397
 
+{
3398
 
+       g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
3399
 
+       g_return_if_fail (bvw->priv->stream != NULL);
3400
 
+
3401
 
+       xine_set_param (bvw->priv->stream,
3402
 
+                       XINE_PARAM_AUDIO_CHANNEL_LOGICAL, language);
3403
 
+}
3404
 
+
3405
 
+GList
3406
 
+*bacon_video_widget_get_subtitles (BaconVideoWidget *bvw)
3407
 
+{
3408
 
+       GList *list = NULL;
3409
 
+       int i;
3410
 
+       char lang[XINE_LANG_MAX];
3411
 
+
3412
 
+       for(i = 0; i < 32; i++)
3413
 
+       {
3414
 
+               memset (&lang, 0, sizeof (lang));
3415
 
+
3416
 
+               if (xine_get_spu_lang(bvw->priv->stream, i, lang) == 1)
3417
 
+               {
3418
 
+                       list = g_list_prepend (list,
3419
 
+                                       (gpointer) g_strdup (lang));
3420
 
+               }
3421
 
+       }
3422
 
+
3423
 
+       return g_list_reverse (list);
3424
 
+}
3425
 
+
3426
 
+int
3427
 
+bacon_video_widget_get_subtitle (BaconVideoWidget *bvw)
3428
 
+{
3429
 
+       return xine_get_param (bvw->priv->stream, XINE_PARAM_SPU_CHANNEL);
3430
 
+}
3431
 
+
3432
 
+void
3433
 
+bacon_video_widget_set_subtitle (BaconVideoWidget *bvw, int subtitle)
3434
 
+{
3435
 
+       xine_set_param (bvw->priv->stream, XINE_PARAM_SPU_CHANNEL, subtitle);
3436
 
+}
3437
 
+
3438
 
+gboolean
3439
 
+bacon_video_widget_can_get_frames (BaconVideoWidget *bvw, GError **error)
3440
 
+{
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);
3444
 
+
3445
 
+       if (xine_get_status (bvw->priv->stream) != XINE_STATUS_PLAY
3446
 
+                       && bvw->priv->logo_mode == FALSE)
3447
 
+       {
3448
 
+               g_set_error (error, 0, 0, _("Movie is not playing."));
3449
 
+               return FALSE;
3450
 
+       }
3451
 
+
3452
 
+       if (xine_get_stream_info (bvw->priv->stream,
3453
 
+                               XINE_STREAM_INFO_HAS_VIDEO) == FALSE
3454
 
+                       && bvw->priv->using_vfx == FALSE)
3455
 
+       {
3456
 
+               g_set_error (error, 0, 0, _("No video to capture."));
3457
 
+               return FALSE;
3458
 
+       }
3459
 
+
3460
 
+       if (xine_get_stream_info (bvw->priv->stream,
3461
 
+                               XINE_STREAM_INFO_VIDEO_HANDLED) == FALSE)
3462
 
+       {
3463
 
+               g_set_error (error, 0, 0, _("Video codec is not handled."));
3464
 
+               return FALSE;
3465
 
+       }
3466
 
+
3467
 
+       return TRUE;
3468
 
+}
3469
 
+
3470
 
+GdkPixbuf *
3471
 
+bacon_video_widget_get_current_frame (BaconVideoWidget *bvw)
3472
 
+{
3473
 
+       GdkPixbuf *pixbuf = NULL;
3474
 
+       uint8_t *yuv, *y, *u, *v, *rgb;
3475
 
+       int width, height, ratio, format;
3476
 
+
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);
3480
 
+
3481
 
+       if (xine_get_current_frame (bvw->priv->stream, &width, &height,
3482
 
+                       &ratio, &format, NULL) == 0)
3483
 
+               return NULL;
3484
 
+
3485
 
+       if (width == 0 || height == 0)
3486
 
+               return NULL;
3487
 
+
3488
 
+       yuv = malloc ((width + 8) * (height + 1) * 2);
3489
 
+       if (yuv == NULL)
3490
 
+               return NULL;
3491
 
+
3492
 
+       if (xine_get_current_frame (bvw->priv->stream, &width, &height,
3493
 
+                       &ratio, &format, yuv) == 0)
3494
 
+       {
3495
 
+               g_free (yuv);
3496
 
+               return NULL;
3497
 
+       }
3498
 
+
3499
 
+       /* Convert to yv12 */
3500
 
+       switch (format) {
3501
 
+       case XINE_IMGFMT_YUY2:
3502
 
+               {
3503
 
+                       uint8_t *yuy2 = yuv;
3504
 
+
3505
 
+                       yuv = malloc (width * height * 2);
3506
 
+                       y = yuv;
3507
 
+                       u = yuv + width * height;
3508
 
+                       v = yuv + width * height * 5 / 4;
3509
 
+
3510
 
+                       yuy2toyv12 (y, u, v, yuy2, width, height);
3511
 
+
3512
 
+                       g_free (yuy2);
3513
 
+               }
3514
 
+               break;
3515
 
+       case XINE_IMGFMT_YV12:
3516
 
+               y = yuv;
3517
 
+               u = yuv + width * height;
3518
 
+               v = yuv + width * height * 5 / 4;
3519
 
+               break;
3520
 
+       default:
3521
 
+               g_warning ("Format '%.4s' unsupported", (char *) &format);
3522
 
+               g_free (yuv);
3523
 
+               return NULL;
3524
 
+       }
3525
 
+
3526
 
+       /* Convert to rgb */
3527
 
+       rgb = yv12torgb (y, u, v, width, height);
3528
 
+
3529
 
+       pixbuf = gdk_pixbuf_new_from_data (rgb,
3530
 
+                       GDK_COLORSPACE_RGB, FALSE,
3531
 
+                       8, width, height, 3 * width,
3532
 
+                       (GdkPixbufDestroyNotify) g_free, NULL);
3533
 
+
3534
 
+       /* MPEG streams have ratio information */
3535
 
+       ratio = xine_get_stream_info (bvw->priv->stream,
3536
 
+                       XINE_STREAM_INFO_VIDEO_RATIO);
3537
 
+
3538
 
+       if (ratio != 10000.0 && ratio != 0.0)
3539
 
+       {
3540
 
+               GdkPixbuf *tmp;
3541
 
+
3542
 
+               if (ratio > 10000.0)
3543
 
+                       tmp = gdk_pixbuf_scale_simple (pixbuf,
3544
 
+                                       (int) (height * ratio / 10000), height,
3545
 
+                                       GDK_INTERP_BILINEAR);
3546
 
+               else
3547
 
+                       tmp = gdk_pixbuf_scale_simple (pixbuf,
3548
 
+                                       width, (int) (width * ratio / 10000),
3549
 
+                                       GDK_INTERP_BILINEAR);
3550
 
+
3551
 
+               gdk_pixbuf_unref (pixbuf);
3552
 
+
3553
 
+               return tmp;
3554
 
+       }
3555
 
+
3556
 
+       return pixbuf;
3557
 
+}