[chronojump] Update libcesarplayer



commit 25b00d325ac3913fd8cf6af2b313f8d5c971f4e7
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date:   Wed Jan 23 02:20:14 2013 +0100

    Update libcesarplayer

 libcesarplayer/Makefile.am                         |   63 +-
 .../{src => }/bacon-video-widget-gst-0.10.c        | 1274 ++----------
 libcesarplayer/{src => }/bacon-video-widget.h      |    4 +-
 .../{src => }/baconvideowidget-marshal.c           |  494 +++---
 .../{src => }/baconvideowidget-marshal.h           |   88 +-
 .../{src => }/baconvideowidget-marshal.list        |    0
 libcesarplayer/{src => }/common.h                  |   38 +
 libcesarplayer/gst-camera-capturer.c               | 2111 ++++++++++++++++++++
 libcesarplayer/{src => }/gst-camera-capturer.h     |   53 +-
 libcesarplayer/gst-remuxer.c                       |  538 +++++
 libcesarplayer/gst-remuxer.h                       |   72 +
 libcesarplayer/{src => }/gst-smart-video-scaler.c  |    0
 libcesarplayer/{src => }/gst-smart-video-scaler.h  |    0
 libcesarplayer/{src => }/gst-video-editor.c        |   45 +-
 libcesarplayer/{src => }/gst-video-editor.h        |    0
 libcesarplayer/{src => }/gstscreenshot.c           |    3 +-
 libcesarplayer/{src => }/gstscreenshot.h           |    0
 libcesarplayer/{src => }/gstvideowidget.c          |    0
 libcesarplayer/{src => }/gstvideowidget.h          |    0
 libcesarplayer/{src => }/macros.h                  |    0
 libcesarplayer/{src => }/main.c                    |   37 +-
 libcesarplayer/src/Makefile.am                     |   55 -
 libcesarplayer/src/bacon-resize.c                  |  338 ----
 libcesarplayer/src/bacon-resize.h                  |   55 -
 libcesarplayer/src/gst-camera-capturer.c           | 1793 -----------------
 libcesarplayer/src/video-utils.h                   |   40 -
 libcesarplayer/test-editor.c                       |  112 +
 libcesarplayer/test-remuxer.c                      |   71 +
 libcesarplayer/{src => }/video-utils.c             |   40 +-
 libcesarplayer/video-utils.h                       |   70 +
 30 files changed, 3682 insertions(+), 3712 deletions(-)
---
diff --git a/libcesarplayer/Makefile.am b/libcesarplayer/Makefile.am
index 675e822..4ab9dfd 100644
--- a/libcesarplayer/Makefile.am
+++ b/libcesarplayer/Makefile.am
@@ -1,14 +1,59 @@
 ## Process this file with automake to produce Makefile.in
-## Created by Anjuta
 
-SUBDIRS = src
 
+AM_CPPFLAGS = \
+	-DPACKAGE_SRC_DIR=\""$(srcdir)"\" \
+	-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
+	$(CESARPLAYER_CFLAGS)
 
-# Copy all the spec files. Of cource, only one is actually used.
-dist-hook:
-	for specfile in *.spec; do \
-		if test -f $$specfile; then \
-			cp -p $$specfile $(distdir); \
-		fi \
-	done
+if OSTYPE_OS_X
+AM_CPPFLAGS += \
+	-x objective-c
+endif
+
+AM_CFLAGS =\
+	 -Wall\
+	 -g
+
+BVWMARSHALFILES = baconvideowidget-marshal.c baconvideowidget-marshal.h
+GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0`
+BUILT_SOURCES = $(BVWMARSHALFILES)
+
+baconvideowidget-marshal.h: baconvideowidget-marshal.list
+	( $(GLIB_GENMARSHAL) --prefix=baconvideowidget_marshal $(srcdir)/baconvideowidget-marshal.list --header > baconvideowidget-marshal.h )
+baconvideowidget-marshal.c: baconvideowidget-marshal.h
+	( $(GLIB_GENMARSHAL) --prefix=baconvideowidget_marshal $(srcdir)/baconvideowidget-marshal.list --body --header > baconvideowidget-marshal.c )
+
+
+pkglib_LTLIBRARIES = \
+	libcesarplayer.la
+
+libcesarplayer_la_SOURCES = \
+	$(BVWMARSHALFILES) \
+	common.h\
+	bacon-video-widget.h\
+	bacon-video-widget-gst-0.10.c\
+	gstscreenshot.c \
+	gstscreenshot.h \
+	gst-camera-capturer.c\
+	gst-camera-capturer.h\
+	gst-remuxer.c\
+	gst-remuxer.h\
+	gst-video-editor.c\
+	gst-video-editor.h\
+	video-utils.c\
+	video-utils.h\
+	macros.h
+
+libcesarplayer_la_LDFLAGS = \
+	$(CESARPLAYER_LIBS)
+
+if OSTYPE_WINDOWS
+libcesarplayer_la_LDFLAGS += -no-undefined
+endif
+	
+CLEANFILES = $(BUILT_SOURCES)
+	
+EXTRA_DIST = \
+	baconvideowidget-marshal.list
 
diff --git a/libcesarplayer/src/bacon-video-widget-gst-0.10.c b/libcesarplayer/bacon-video-widget-gst-0.10.c
similarity index 79%
rename from libcesarplayer/src/bacon-video-widget-gst-0.10.c
rename to libcesarplayer/bacon-video-widget-gst-0.10.c
index e8bbe24..5782325 100644
--- a/libcesarplayer/src/bacon-video-widget-gst-0.10.c
+++ b/libcesarplayer/bacon-video-widget-gst-0.10.c
@@ -28,9 +28,6 @@
  */
 
 
-
-
-
 #include <gst/gst.h>
 
 /* GStreamer Interfaces */
@@ -70,16 +67,6 @@
 #include <gtk/gtk.h>
 
 
-#if defined(OSTYPE_WINDOWS)
-#define DEFAULT_VIDEO_SINK "autovideosink"
-#define BACKUP_VIDEO_SINK "autovideosink"
-#elif defined(OSTYPE_OS_X)
-#define DEFAULT_VIDEO_SINK "autovideosink"
-#define BACKUP_VIDEO_SINK "autovideosink"
-#elif defined(OSTYPE_LINUX)
-#define DEFAULT_VIDEO_SINK "gsettingsvideosink"
-#define BACKUP_VIDEO_SINK "autovideosink"
-#endif
 #include <gio/gio.h>
 #include <glib/gi18n.h>
 
@@ -90,7 +77,6 @@
 #include "baconvideowidget-marshal.h"
 #include "common.h"
 #include "gstscreenshot.h"
-#include "bacon-resize.h"
 #include "video-utils.h"
 
 #define DEFAULT_HEIGHT 420
@@ -182,7 +168,9 @@ struct BaconVideoWidgetPrivate
 
   gboolean got_redirect;
 
-  GdkWindow *video_window;
+  GtkWidget *video_da;
+  GtkWidget *logo_da;
+  guintptr window_handle;
   GdkCursor *cursor;
 
 
@@ -234,21 +222,14 @@ struct BaconVideoWidgetPrivate
   GList *missing_plugins;       /* GList of GstMessages */
   gboolean plugin_install_in_progress;
 
-  /* Bacon resize */
-  BaconResize *bacon_resize;
 };
 
 static void bacon_video_widget_set_property (GObject * object,
     guint property_id, const GValue * value, GParamSpec * pspec);
 static void bacon_video_widget_get_property (GObject * object,
     guint property_id, GValue * value, GParamSpec * pspec);
-static void bvw_update_interface_implementations (BaconVideoWidget * bvw);
 
 static void bacon_video_widget_finalize (GObject * object);
-static void bvw_update_interface_implementations (BaconVideoWidget * bvw);
-static gboolean bacon_video_widget_configure_event (GtkWidget * widget,
-    GdkEventConfigure * event, BaconVideoWidget * bvw);
-static void size_changed_cb (GdkScreen * screen, BaconVideoWidget * bvw);
 static void bvw_process_pending_tag_messages (BaconVideoWidget * bvw);
 static void bvw_stop_play_pipeline (BaconVideoWidget * bvw);
 static GError *bvw_error_from_gst_error (BaconVideoWidget * bvw,
@@ -262,9 +243,6 @@ static GThread *gui_thread;
 
 static int bvw_signals[LAST_SIGNAL] = { 0 };
 
-GST_DEBUG_CATEGORY (_totem_gst_debug_cat);
-#define GST_CAT_DEFAULT _totem_gst_debug_cat
-
 
 typedef gchar *(*MsgToStrFunc) (GstMessage * msg);
 
@@ -365,589 +343,186 @@ bvw_error_msg (BaconVideoWidget * bvw, GstMessage * msg)
 }
 
 static void
-get_media_size (BaconVideoWidget * bvw, gint * width, gint * height)
+bacon_video_widget_realize_event (GtkWidget * widget, BaconVideoWidget *bvw)
 {
-  if (bvw->priv->logo_mode) {
-    if (bvw->priv->logo_pixbuf) {
-      *width = gdk_pixbuf_get_width (bvw->priv->logo_pixbuf);
-      *height = gdk_pixbuf_get_height (bvw->priv->logo_pixbuf);
-    } else {
-      *width = 0;
-      *height = 0;
-    }
-  } else {
-    if (bvw->priv->media_has_video) {
-      GValue *disp_par = NULL;
-      guint movie_par_n, movie_par_d, disp_par_n, disp_par_d, num, den;
-
-      /* Create and init the fraction value */
-      disp_par = g_new0 (GValue, 1);
-      g_value_init (disp_par, GST_TYPE_FRACTION);
-
-      /* Square pixel is our default */
-      gst_value_set_fraction (disp_par, 1, 1);
-
-      /* Now try getting display's pixel aspect ratio */
-      if (bvw->priv->xoverlay) {
-        GObjectClass *klass;
-        GParamSpec *pspec;
-
-        klass = G_OBJECT_GET_CLASS (bvw->priv->xoverlay);
-        pspec = g_object_class_find_property (klass, "pixel-aspect-ratio");
-
-        if (pspec != NULL) {
-          GValue disp_par_prop = { 0, };
+  GdkWindow *window = gtk_widget_get_window (widget);
 
-          g_value_init (&disp_par_prop, pspec->value_type);
-          g_object_get_property (G_OBJECT (bvw->priv->xoverlay),
-              "pixel-aspect-ratio", &disp_par_prop);
+  if (!gdk_window_ensure_native (window))
+    g_error ("Couldn't create native window needed for GstXOverlay!");
 
-          if (!g_value_transform (&disp_par_prop, disp_par)) {
-            GST_WARNING ("Transform failed, assuming pixel-aspect-ratio = 1/1");
-            gst_value_set_fraction (disp_par, 1, 1);
-          }
-
-          g_value_unset (&disp_par_prop);
-        }
-      }
-
-      disp_par_n = gst_value_get_fraction_numerator (disp_par);
-      disp_par_d = gst_value_get_fraction_denominator (disp_par);
-
-      GST_DEBUG ("display PAR is %d/%d", disp_par_n, disp_par_d);
-
-      /* If movie pixel aspect ratio is enforced, use that */
-      if (bvw->priv->ratio_type != BVW_RATIO_AUTO) {
-        switch (bvw->priv->ratio_type) {
-          case BVW_RATIO_SQUARE:
-            movie_par_n = 1;
-            movie_par_d = 1;
-            break;
-          case BVW_RATIO_FOURBYTHREE:
-            movie_par_n = 4 * bvw->priv->video_height;
-            movie_par_d = 3 * bvw->priv->video_width;
-            break;
-          case BVW_RATIO_ANAMORPHIC:
-            movie_par_n = 16 * bvw->priv->video_height;
-            movie_par_d = 9 * bvw->priv->video_width;
-            break;
-          case BVW_RATIO_DVB:
-            movie_par_n = 20 * bvw->priv->video_height;
-            movie_par_d = 9 * bvw->priv->video_width;
-            break;
-            /* handle these to avoid compiler warnings */
-          case BVW_RATIO_AUTO:
-          default:
-            movie_par_n = 0;
-            movie_par_d = 0;
-            g_assert_not_reached ();
-        }
-      } else {
-        /* Use the movie pixel aspect ratio if any */
-        if (bvw->priv->movie_par) {
-          movie_par_n = gst_value_get_fraction_numerator (bvw->priv->movie_par);
-          movie_par_d =
-              gst_value_get_fraction_denominator (bvw->priv->movie_par);
-        } else {
-          /* Square pixels */
-          movie_par_n = 1;
-          movie_par_d = 1;
-        }
-      }
-
-      GST_DEBUG ("movie PAR is %d/%d", movie_par_n, movie_par_d);
-
-      if (bvw->priv->video_width == 0 || bvw->priv->video_height == 0) {
-        GST_DEBUG ("width and/or height 0, assuming 1/1 ratio");
-        num = 1;
-        den = 1;
-      } else if (!gst_video_calculate_display_ratio (&num, &den,
-              bvw->priv->video_width,
-              bvw->priv->video_height,
-              movie_par_n, movie_par_d, disp_par_n, disp_par_d)) {
-        GST_WARNING ("overflow calculating display aspect ratio!");
-        num = 1;                /* FIXME: what values to use here? */
-        den = 1;
-      }
-
-      GST_DEBUG ("calculated scaling ratio %d/%d for video %dx%d", num,
-          den, bvw->priv->video_width, bvw->priv->video_height);
-
-      /* now find a width x height that respects this display ratio.
-       * prefer those that have one of w/h the same as the incoming video
-       * using wd / hd = num / den */
-
-      /* start with same height, because of interlaced video */
-      /* check hd / den is an integer scale factor, and scale wd with the PAR */
-      if (bvw->priv->video_height % den == 0) {
-        GST_DEBUG ("keeping video height");
-        bvw->priv->video_width_pixels =
-            (guint) gst_util_uint64_scale (bvw->priv->video_height, num, den);
-        bvw->priv->video_height_pixels = bvw->priv->video_height;
-      } else if (bvw->priv->video_width % num == 0) {
-        GST_DEBUG ("keeping video width");
-        bvw->priv->video_width_pixels = bvw->priv->video_width;
-        bvw->priv->video_height_pixels =
-            (guint) gst_util_uint64_scale (bvw->priv->video_width, den, num);
-      } else {
-        GST_DEBUG ("approximating while keeping video height");
-        bvw->priv->video_width_pixels =
-            (guint) gst_util_uint64_scale (bvw->priv->video_height, num, den);
-        bvw->priv->video_height_pixels = bvw->priv->video_height;
-      }
-      GST_DEBUG ("scaling to %dx%d", bvw->priv->video_width_pixels,
-          bvw->priv->video_height_pixels);
-
-      *width = bvw->priv->video_width_pixels;
-      *height = bvw->priv->video_height_pixels;
-
-      /* Free the PAR fraction */
-      g_value_unset (disp_par);
-      g_free (disp_par);
-    } else {
-      *width = 0;
-      *height = 0;
-    }
-  }
-}
-
-static void
-bacon_video_widget_realize (GtkWidget * widget)
-{
-  BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget);
-  GdkWindowAttr attributes;
-  gint attributes_mask, w, h;
-  GdkColor colour;
-  GdkWindow *window;
-  GdkEventMask event_mask;
-
-  event_mask = gtk_widget_get_events (widget)
-      | GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK;
-  gtk_widget_set_events (widget, event_mask);
-
-  GTK_WIDGET_CLASS (parent_class)->realize (widget);
-
-  window = gtk_widget_get_window (widget);
-
-  /* Creating our video window */
-  attributes.window_type = GDK_WINDOW_CHILD;
-  attributes.x = 0;
-  attributes.y = 0;
-  attributes.width = widget->allocation.width;
-  attributes.height = widget->allocation.height;
-  attributes.wclass = GDK_INPUT_OUTPUT;
-  attributes.event_mask = gtk_widget_get_events (widget);
-  attributes.event_mask |= GDK_EXPOSURE_MASK |
-      GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS_MASK;
-  attributes_mask = GDK_WA_X | GDK_WA_Y;
-
-  bvw->priv->video_window = gdk_window_new (window,
-      &attributes, attributes_mask);
-  gdk_window_set_user_data (bvw->priv->video_window, widget);
-  gdk_window_ensure_native(bvw->priv->video_window);
-
-  gdk_color_parse ("black", &colour);
-  gdk_colormap_alloc_color (gtk_widget_get_colormap (widget),
-      &colour, TRUE, TRUE);
-  gdk_window_set_background (window, &colour);
-  gtk_widget_set_style (widget,
-      gtk_style_attach (gtk_widget_get_style (widget), window));
-
-  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-
-  /* Connect to configure event on the top level window */
-  g_signal_connect (G_OBJECT (gtk_widget_get_toplevel (widget)),
-      "configure-event", G_CALLBACK (bacon_video_widget_configure_event), bvw);
-
-  /* get screen size changes */
-  g_signal_connect (G_OBJECT (gtk_widget_get_screen (widget)),
-      "size-changed", G_CALLBACK (size_changed_cb), bvw);
-
-  /* nice hack to show the logo fullsize, while still being resizable */
-  get_media_size (BACON_VIDEO_WIDGET (widget), &w, &h);
-
-  /*ANDONI
-     totem_widget_set_preferred_size (widget, w, h); */
-
-  bvw->priv->bacon_resize = bacon_resize_new (widget);
-}
-
-static void
-bacon_video_widget_unrealize (GtkWidget * widget)
-{
-  BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget);
-
-  g_object_unref (bvw->priv->bacon_resize);
-  gdk_window_set_user_data (bvw->priv->video_window, NULL);
-  gdk_window_destroy (bvw->priv->video_window);
-  bvw->priv->video_window = NULL;
-
-  GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
-}
-
-static void
-bacon_video_widget_show (GtkWidget * widget)
-{
-  BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget);
-  GdkWindow *window;
-
-  window = gtk_widget_get_window (widget);
-  if (window)
-    gdk_window_show (window);
-  if (bvw->priv->video_window)
-    gdk_window_show (bvw->priv->video_window);
-
-  if (GTK_WIDGET_CLASS (parent_class)->show)
-    GTK_WIDGET_CLASS (parent_class)->show (widget);
-}
-
-static void
-bacon_video_widget_hide (GtkWidget * widget)
-{
-  BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget);
-  GdkWindow *window;
-
-  window = gtk_widget_get_window (widget);
-  if (window)
-    gdk_window_hide (window);
-  if (bvw->priv->video_window)
-    gdk_window_hide (bvw->priv->video_window);
-
-  if (GTK_WIDGET_CLASS (parent_class)->hide)
-    GTK_WIDGET_CLASS (parent_class)->hide (widget);
-}
-
-static gboolean
-bacon_video_widget_configure_event (GtkWidget * widget,
-    GdkEventConfigure * event, BaconVideoWidget * bvw)
-{
-  GstXOverlay *xoverlay = NULL;
-
-  g_return_val_if_fail (bvw != NULL, FALSE);
-  g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), FALSE);
-
-  xoverlay = bvw->priv->xoverlay;
-
-  if (xoverlay != NULL && GST_IS_X_OVERLAY (xoverlay)) {
-    gst_x_overlay_expose (xoverlay);
-  }
-
-  return FALSE;
-}
-
-static void
-size_changed_cb (GdkScreen * screen, BaconVideoWidget * bvw)
-{
-  /* FIXME:Used for visualization */
-  //setup_vis (bvw);
+  bvw->priv->window_handle = gst_get_window_handle (window);
 }
 
 static gboolean
-bacon_video_widget_expose_event (GtkWidget * widget, GdkEventExpose * event)
+bacon_video_widget_logo_expose_event (GtkWidget * widget, GdkEventExpose * event,
+    BaconVideoWidget *bvw)
 {
-  BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget);
-  GstXOverlay *xoverlay;
   gboolean draw_logo;
   GdkWindow *win;
 
   if (event && event->count > 0)
     return TRUE;
 
+  if (event == NULL)
+    return TRUE;
+
   g_mutex_lock (bvw->priv->lock);
-  xoverlay = bvw->priv->xoverlay;
-  if (xoverlay == NULL) {
-    bvw_update_interface_implementations (bvw);
-    xoverlay = bvw->priv->xoverlay;
-  }
-  if (xoverlay != NULL)
-    gst_object_ref (xoverlay);
 
-  g_mutex_unlock (bvw->priv->lock);
+  /* if there's only audio and no visualisation, draw the logo as well */
+  draw_logo = bvw->priv->media_has_audio && !bvw->priv->media_has_video;
 
+  if (!bvw->priv->logo_mode && !draw_logo)
+    goto exit;
 
-  if (xoverlay != NULL && GST_IS_X_OVERLAY (xoverlay)) {
-    gst_set_window_handle(xoverlay, bvw->priv->video_window);
-  }
+  win = gtk_widget_get_window (bvw->priv->logo_da);
 
   /* Start with a nice black canvas */
-  win = gtk_widget_get_window (widget);
   gdk_draw_rectangle (win, gtk_widget_get_style (widget)->black_gc, TRUE, 0,
       0, widget->allocation.width, widget->allocation.height);
 
-  /* if there's only audio and no visualisation, draw the logo as well */
-  draw_logo = bvw->priv->media_has_audio && !bvw->priv->media_has_video;
-
-  if (bvw->priv->logo_mode || draw_logo) {
-    if (bvw->priv->logo_pixbuf != NULL) {
-      GdkPixbuf *frame;
-      GdkPixbuf *drawing;
-      guchar *pixels;
-      int rowstride;
-      gint width, height, alloc_width, alloc_height, logo_x, logo_y;
-      gfloat ratio;
+  if (bvw->priv->logo_pixbuf != NULL) {
+    GdkPixbuf *frame;
+    GdkPixbuf *drawing;
+    guchar *pixels;
+    int rowstride;
+    gint width, height, alloc_width, alloc_height, logo_x, logo_y;
+    gfloat ratio;
 
-      /* Checking if allocated space is smaller than our logo */
+    /* Checking if allocated space is smaller than our logo */
 
 
-      width = gdk_pixbuf_get_width (bvw->priv->logo_pixbuf);
-      height = gdk_pixbuf_get_height (bvw->priv->logo_pixbuf);
-      alloc_width = widget->allocation.width;
-      alloc_height = widget->allocation.height;
+    width = gdk_pixbuf_get_width (bvw->priv->logo_pixbuf);
+    height = gdk_pixbuf_get_height (bvw->priv->logo_pixbuf);
+    alloc_width = widget->allocation.width;
+    alloc_height = widget->allocation.height;
 
-      if ((gfloat) alloc_width / width > (gfloat) alloc_height / height) {
-        ratio = (gfloat) alloc_height / height;
-      } else {
-        ratio = (gfloat) alloc_width / width;
-      }
-
-      width *= ratio;
-      height *= ratio;
+    if ((gfloat) alloc_width / width > (gfloat) alloc_height / height) {
+      ratio = (gfloat) alloc_height / height;
+    } else {
+      ratio = (gfloat) alloc_width / width;
+    }
 
-      logo_x = (alloc_width / 2) - (width / 2);
-      logo_y = (alloc_height / 2) - (height / 2);
+    width *= ratio;
+    height *= ratio;
 
+    logo_x = (alloc_width / 2) - (width / 2);
+    logo_y = (alloc_height / 2) - (height / 2);
 
-      /* Drawing our frame */
 
-      if (bvw->priv->expand_logo && !bvw->priv->drawing_mode) {
-        /* Scaling to available space */
+    /* Drawing our frame */
 
-        frame = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
-            FALSE, 8, widget->allocation.width, widget->allocation.height);
+    if (bvw->priv->expand_logo && !bvw->priv->drawing_mode) {
+      /* Scaling to available space */
 
-        gdk_pixbuf_composite (bvw->priv->logo_pixbuf,
-            frame,
-            0, 0,
-            alloc_width, alloc_height,
-            logo_x, logo_y, ratio, ratio, GDK_INTERP_BILINEAR, 255);
+      frame = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+          FALSE, 8, widget->allocation.width, widget->allocation.height);
 
-        rowstride = gdk_pixbuf_get_rowstride (frame);
+      gdk_pixbuf_composite (bvw->priv->logo_pixbuf,
+          frame,
+          0, 0,
+          alloc_width, alloc_height,
+          logo_x, logo_y, ratio, ratio, GDK_INTERP_BILINEAR, 255);
 
-        pixels = gdk_pixbuf_get_pixels (frame) +
-            rowstride * event->area.y + event->area.x * 3;
+      rowstride = gdk_pixbuf_get_rowstride (frame);
 
-        gdk_draw_rgb_image_dithalign (widget->window,
-            widget->style->black_gc,
-            event->area.x, event->area.y,
-            event->area.width,
-            event->area.height,
-            GDK_RGB_DITHER_NORMAL, pixels,
-            rowstride, event->area.x, event->area.y);
+      pixels = gdk_pixbuf_get_pixels (frame) +
+          rowstride * event->area.y + event->area.x * 3;
 
-        g_object_unref (frame);
-      } else {
-        gdk_window_clear_area (win,
-            0, 0, widget->allocation.width, widget->allocation.height);
-
-        if (width <= 1 || height <= 1) {
-          if (xoverlay != NULL)
-            gst_object_unref (xoverlay);
-          gdk_window_end_paint (win);
-          return TRUE;
-        }
+      gdk_draw_rgb_image_dithalign (widget->window,
+          widget->style->black_gc,
+          event->area.x, event->area.y,
+          event->area.width,
+          event->area.height,
+          GDK_RGB_DITHER_NORMAL, pixels,
+          rowstride, event->area.x, event->area.y);
 
-        frame = gdk_pixbuf_scale_simple (bvw->priv->logo_pixbuf,
-            width, height, GDK_INTERP_BILINEAR);
-        gdk_draw_pixbuf (win, gtk_widget_get_style (widget)->fg_gc[0],
-            frame, 0, 0, logo_x, logo_y, width, height,
-            GDK_RGB_DITHER_NONE, 0, 0);
-
-        if (bvw->priv->drawing_mode && bvw->priv->drawing_pixbuf != NULL) {
-          drawing =
-              gdk_pixbuf_scale_simple (bvw->priv->drawing_pixbuf, width,
-              height, GDK_INTERP_BILINEAR);
-          gdk_draw_pixbuf (win,
-              gtk_widget_get_style (widget)->fg_gc[0],
-              drawing, 0, 0, logo_x, logo_y, width,
-              height, GDK_RGB_DITHER_NONE, 0, 0);
-          g_object_unref (drawing);
-        }
+      g_object_unref (frame);
+    } else {
+      if (width <= 1 || height <= 1) {
+        gdk_window_end_paint (win);
+        goto exit;
+      }
 
-        g_object_unref (frame);
+      frame = gdk_pixbuf_scale_simple (bvw->priv->logo_pixbuf,
+          width, height, GDK_INTERP_BILINEAR);
+      gdk_draw_pixbuf (win, gtk_widget_get_style (widget)->fg_gc[0],
+          frame, 0, 0, logo_x, logo_y, width, height,
+          GDK_RGB_DITHER_NONE, 0, 0);
+
+      if (bvw->priv->drawing_mode && bvw->priv->drawing_pixbuf != NULL) {
+        drawing =
+            gdk_pixbuf_scale_simple (bvw->priv->drawing_pixbuf, width,
+            height, GDK_INTERP_BILINEAR);
+        gdk_draw_pixbuf (win,
+            gtk_widget_get_style (widget)->fg_gc[0],
+            drawing, 0, 0, logo_x, logo_y, width,
+            height, GDK_RGB_DITHER_NONE, 0, 0);
+        g_object_unref (drawing);
       }
-    } else if (win) {
-      /* No pixbuf, just draw a black background then */
-      gdk_window_clear_area (win,
-          0, 0, widget->allocation.width, widget->allocation.height);
-    }
-  } else {
-    /* no logo, pass the expose to gst */
-    if (xoverlay != NULL && GST_IS_X_OVERLAY (xoverlay))
-      gst_x_overlay_expose (xoverlay);
-    else {
-      /* No xoverlay to expose yet */
-      gdk_window_clear_area (win,
-          0, 0, widget->allocation.width, widget->allocation.height);
+
+      g_object_unref (frame);
     }
+  } else if (win) {
+    /* No pixbuf, just draw a black background then */
+    gdk_window_clear_area (win,
+        0, 0, widget->allocation.width, widget->allocation.height);
   }
-  if (xoverlay != NULL)
-    gst_object_unref (xoverlay);
 
-  return TRUE;
-}
-
-static GstNavigation *
-bvw_get_navigation_iface (BaconVideoWidget * bvw)
-{
-  GstNavigation *nav = NULL;
-  g_mutex_lock (bvw->priv->lock);
-  if (bvw->priv->navigation == NULL)
-    bvw_update_interface_implementations (bvw);
-  if (bvw->priv->navigation)
-    nav = gst_object_ref (GST_OBJECT (bvw->priv->navigation));
+exit:
   g_mutex_unlock (bvw->priv->lock);
-
-  return nav;
+  return TRUE;
 }
 
-/* need to use gstnavigation interface for these vmethods, to allow for the sink
-   to map screen coordinates to video coordinates in the presence of e.g.
-   hardware scaling */
-
 static gboolean
-bacon_video_widget_motion_notify (GtkWidget * widget, GdkEventMotion * event)
+bacon_video_widget_video_expose_event (GtkWidget * widget, GdkEventExpose * event,
+    BaconVideoWidget *bvw)
 {
-  gboolean res = FALSE;
-  BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget);
-
-  g_return_val_if_fail (bvw->priv->play != NULL, FALSE);
-
-  if (!bvw->priv->logo_mode) {
-    GstNavigation *nav = bvw_get_navigation_iface (bvw);
-    if (nav) {
-      gst_navigation_send_mouse_event (nav, "mouse-move", 0, event->x,
-          event->y);
-      gst_object_unref (GST_OBJECT (nav));
-    }
-  }
-
-  if (GTK_WIDGET_CLASS (parent_class)->motion_notify_event)
-    res |= GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event);
-
-  return res;
-}
+  GstXOverlay *xoverlay;
+  GdkWindow *win;
 
-static gboolean
-bacon_video_widget_button_press (GtkWidget * widget, GdkEventButton * event)
-{
-  gboolean res = FALSE;
-  BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget);
+  if (event && event->count > 0)
+    return TRUE;
 
-  g_return_val_if_fail (bvw->priv->play != NULL, FALSE);
+  if (event == NULL)
+    return TRUE;
 
-  if (!bvw->priv->logo_mode) {
-    GstNavigation *nav = bvw_get_navigation_iface (bvw);
-    if (nav) {
-      gst_navigation_send_mouse_event (nav,
-          "mouse-button-press", event->button, event->x, event->y);
-      gst_object_unref (GST_OBJECT (nav));
+  g_mutex_lock (bvw->priv->lock);
 
-      /* FIXME need to check whether the backend will have handled
-       * the button press
-       res = TRUE; */
-    }
+  xoverlay = bvw->priv->xoverlay;
+  if (xoverlay != NULL) {
+    gst_object_ref (xoverlay);
+    gst_set_window_handle (xoverlay, bvw->priv->window_handle);
   }
 
-  if (GTK_WIDGET_CLASS (parent_class)->button_press_event)
-    res |= GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event);
-
-  return res;
-}
-
-static gboolean
-bacon_video_widget_button_release (GtkWidget * widget, GdkEventButton * event)
-{
-  gboolean res = FALSE;
-  BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget);
-
-  g_return_val_if_fail (bvw->priv->play != NULL, FALSE);
-
-  if (!bvw->priv->logo_mode) {
-    GstNavigation *nav = bvw_get_navigation_iface (bvw);
-    if (nav) {
-      gst_navigation_send_mouse_event (nav,
-          "mouse-button-release", event->button, event->x, event->y);
-      gst_object_unref (GST_OBJECT (nav));
-
-      res = TRUE;
-    }
+  if (bvw->priv->logo_mode) {
+#if !defined (GDK_WINDOWING_QUARTZ)
+    g_mutex_unlock (bvw->priv->lock);
+    bacon_video_widget_logo_expose_event (widget, event, bvw);
+    g_mutex_lock (bvw->priv->lock);
+#endif
+    goto exit;
   }
 
-  if (GTK_WIDGET_CLASS (parent_class)->button_release_event)
-    res |=
-        GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event);
-
-  return res;
-}
-
-static void
-bacon_video_widget_size_request (GtkWidget * widget,
-    GtkRequisition * requisition)
-{
-  requisition->width = 240;
-  requisition->height = 180;
-}
-
-static void
-resize_video_window (BaconVideoWidget * bvw)
-{
-  const GtkAllocation *allocation;
-  gfloat width, height, ratio, x, y;
-  int w, h;
-
-  g_return_if_fail (bvw != NULL);
-  g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
-
-  allocation = &GTK_WIDGET (bvw)->allocation;
-
-  get_media_size (bvw, &w, &h);
-  if (!w || !h) {
-    w = allocation->width;
-    h = allocation->height;
+  /* no logo, pass the expose to gst */
+  if (xoverlay != NULL && GST_IS_X_OVERLAY (xoverlay)){
+    gst_x_overlay_expose (xoverlay);
   }
-  width = w;
-  height = h;
-
-  /* calculate ratio for fitting video into the available space */
-  if ((gfloat) allocation->width / width > (gfloat) allocation->height / height) {
-    ratio = (gfloat) allocation->height / height;
-  } else {
-    ratio = (gfloat) allocation->width / width;
+  else {
+    /* No xoverlay to expose yet */
+    win = gtk_widget_get_window (bvw->priv->video_da);
+    gdk_window_clear_area (win,
+      0, 0, widget->allocation.width, widget->allocation.height);
   }
 
-  /* apply zoom factor */
-  ratio = ratio * bvw->priv->zoom;
-
-  width *= ratio;
-  height *= ratio;
-  x = (allocation->width - width) / 2;
-  y = (allocation->height - height) / 2;
-
-  gdk_window_move_resize (bvw->priv->video_window, x, y, width, height);
-  gtk_widget_queue_draw (GTK_WIDGET (bvw));
-}
-
-static void
-bacon_video_widget_size_allocate (GtkWidget * widget,
-    GtkAllocation * allocation)
-{
-  BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget);
-
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (BACON_IS_VIDEO_WIDGET (widget));
+exit:
 
-  widget->allocation = *allocation;
-
-  if (GTK_WIDGET_REALIZED (widget)) {
-
-    gdk_window_move_resize (gtk_widget_get_window (widget),
-        allocation->x, allocation->y, allocation->width, allocation->height);
+  if (xoverlay != NULL)
+    gst_object_unref (xoverlay);
 
-    resize_video_window (bvw);
-  }
+  g_mutex_unlock (bvw->priv->lock);
+  return TRUE;
 }
 
-
 static gboolean
 bvw_boolean_handled_accumulator (GSignalInvocationHint * ihint,
     GValue * return_accu, const GValue * handler_return, gpointer foobar)
@@ -966,28 +541,13 @@ static void
 bacon_video_widget_class_init (BaconVideoWidgetClass * klass)
 {
   GObjectClass *object_class;
-  GtkWidgetClass *widget_class;
 
   object_class = (GObjectClass *) klass;
-  widget_class = (GtkWidgetClass *) klass;
 
   parent_class = g_type_class_peek_parent (klass);
 
   g_type_class_add_private (object_class, sizeof (BaconVideoWidgetPrivate));
 
-  /* GtkWidget */
-  widget_class->size_request = bacon_video_widget_size_request;
-  widget_class->size_allocate = bacon_video_widget_size_allocate;
-  widget_class->realize = bacon_video_widget_realize;
-  widget_class->unrealize = bacon_video_widget_unrealize;
-  widget_class->show = bacon_video_widget_show;
-  widget_class->hide = bacon_video_widget_hide;
-  widget_class->expose_event = bacon_video_widget_expose_event;
-  widget_class->motion_notify_event = bacon_video_widget_motion_notify;
-  widget_class->button_press_event = bacon_video_widget_button_press;
-  widget_class->button_release_event = bacon_video_widget_button_release;
-
-
   /* GObject */
   object_class->set_property = bacon_video_widget_set_property;
   object_class->get_property = bacon_video_widget_get_property;
@@ -1129,7 +689,6 @@ bacon_video_widget_init (BaconVideoWidget * bvw)
   BaconVideoWidgetPrivate *priv;
 
   GTK_WIDGET_SET_FLAGS (GTK_WIDGET (bvw), GTK_CAN_FOCUS);
-  GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (bvw), GTK_DOUBLE_BUFFERED);
 
   bvw->priv = priv =
       G_TYPE_INSTANCE_GET_PRIVATE (bvw, BACON_TYPE_VIDEO_WIDGET,
@@ -1144,16 +703,34 @@ bacon_video_widget_init (BaconVideoWidget * bvw)
 
   bvw->priv->missing_plugins = NULL;
   bvw->priv->plugin_install_in_progress = FALSE;
-}
 
-static void
-shrink_toplevel (BaconVideoWidget * bvw)
-{
-  GtkWidget *toplevel, *widget;
-  widget = GTK_WIDGET (bvw);
-  toplevel = gtk_widget_get_toplevel (widget);
-  if (toplevel != widget && GTK_IS_WINDOW (toplevel) != FALSE)
-    gtk_window_resize (GTK_WINDOW (toplevel), 1, 1);
+  bvw->priv->video_da = gtk_drawing_area_new ();
+  gtk_box_pack_start (GTK_BOX (bvw), bvw->priv->video_da, TRUE, TRUE, 0);
+  gtk_widget_show (bvw->priv->video_da);
+  GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (bvw->priv->video_da), GTK_DOUBLE_BUFFERED);
+
+#if defined (GDK_WINDOWING_QUARTZ)
+  bvw->priv->logo_da = gtk_drawing_area_new ();
+  gtk_box_pack_start (GTK_BOX (bvw), bvw->priv->logo_da, TRUE, TRUE, 0);
+  gtk_widget_show (bvw->priv->logo_da);
+
+  g_signal_connect (GTK_WIDGET (bvw->priv->logo_da), "expose-event",
+      G_CALLBACK (bacon_video_widget_logo_expose_event), bvw);
+#else
+  bvw->priv->logo_da = bvw->priv->video_da;
+#endif
+
+  gtk_widget_add_events (GTK_WIDGET (bvw->priv->video_da),
+      GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
+      | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
+
+  g_signal_connect (GTK_WIDGET (bvw->priv->video_da), "realize",
+      G_CALLBACK (bacon_video_widget_realize_event), bvw);
+
+  g_signal_connect (GTK_WIDGET (bvw->priv->video_da), "expose-event",
+      G_CALLBACK (bacon_video_widget_video_expose_event), bvw);
+
+  bacon_video_widget_set_logo_mode (bvw, TRUE);
 }
 
 static gboolean bvw_query_timeout (BaconVideoWidget * bvw);
@@ -1177,7 +754,6 @@ static void
 bvw_handle_application_message (BaconVideoWidget * bvw, GstMessage * msg)
 {
   const gchar *msg_name;
-  GdkWindow *window;
 
   msg_name = gst_structure_get_name (msg->structure);
   g_return_if_fail (msg_name != NULL);
@@ -1186,35 +762,8 @@ bvw_handle_application_message (BaconVideoWidget * bvw, GstMessage * msg)
 
   if (strcmp (msg_name, "stream-changed") == 0) {
     bvw_update_stream_info (bvw);
-  } else if (strcmp (msg_name, "video-size") == 0) {
-    /* if we're not interactive, we want to announce metadata
-     * only later when we can be sure we got it all */
-    if (bvw->priv->use_type == BVW_USE_TYPE_VIDEO ||
-        bvw->priv->use_type == BVW_USE_TYPE_AUDIO) {
-      g_signal_emit (bvw, bvw_signals[SIGNAL_GOT_METADATA], 0, NULL);
-    }
-
-    if (bvw->priv->auto_resize
-        && !bvw->priv->fullscreen_mode && !bvw->priv->window_resized) {
-      bacon_video_widget_set_scale_ratio (bvw, 1);
-    } else {
-      bacon_video_widget_size_allocate (GTK_WIDGET (bvw),
-          &GTK_WIDGET (bvw)->allocation);
-
-      /* Uhm, so this ugly hack here makes media loading work for
-       * weird laptops with NVIDIA graphics cards... Dunno what the
-       * bug is really, but hey, it works. :). */
-      window = gtk_widget_get_window (GTK_WIDGET (bvw));
-      if (window) {
-        gdk_window_hide (window);
-        gdk_window_show (window);
-
-        bacon_video_widget_expose_event (GTK_WIDGET (bvw), NULL);
-      }
-    }
-    bvw->priv->window_resized = TRUE;
   } else {
-    g_message ("Unhandled application message %s", msg_name);
+    GST_DEBUG ("Unhandled application message %s", msg_name);
   }
 }
 
@@ -1607,7 +1156,6 @@ bvw_bus_message_cb (GstBus * bus, GstMessage * message, gpointer data)
         g_signal_emit (bvw, bvw_signals[SIGNAL_STATE_CHANGE], 0, TRUE);
       }
 
-
       if (old_state == GST_STATE_READY && new_state == GST_STATE_PAUSED) {
         GST_DEBUG_BIN_TO_DOT_FILE (GST_BIN_CAST (bvw->priv->play),
             GST_DEBUG_GRAPH_SHOW_ALL ^
@@ -1616,7 +1164,6 @@ bvw_bus_message_cb (GstBus * bus, GstMessage * message, gpointer data)
         if (bacon_video_widget_get_stream_length (bvw) == 0) {
           GST_DEBUG ("Failed to query duration in PAUSED state?!");
         }
-        break;
         bvw_update_stream_info (bvw);
         if (!bvw_check_missing_plugins_on_preroll (bvw)) {
           /* show a non-fatal warning message if we can't decode the video */
@@ -1849,9 +1396,6 @@ parse_stream_info (BaconVideoWidget * bvw)
     gint i;
 
     bvw->priv->media_has_video = TRUE;
-    if (bvw->priv->video_window)
-      gdk_window_show (bvw->priv->video_window);
-
     for (i = 0; i < n_video && videopad == NULL; i++)
       g_signal_emit_by_name (bvw->priv->play, "get-video-pad", i, &videopad);
   }
@@ -1859,16 +1403,16 @@ parse_stream_info (BaconVideoWidget * bvw)
   bvw->priv->media_has_audio = FALSE;
   if (n_audio > 0) {
     bvw->priv->media_has_audio = TRUE;
-    if (!bvw->priv->media_has_video && bvw->priv->video_window) {
-      gint flags;
+    if (!bvw->priv->media_has_video) {
+      /*gint flags;*/
 
-      g_object_get (bvw->priv->play, "flags", &flags, NULL);
+      /*g_object_get (bvw->priv->play, "flags", &flags, NULL);*/
 
-      gdk_window_hide (bvw->priv->video_window);
-      GTK_WIDGET_SET_FLAGS (GTK_WIDGET (bvw), GTK_DOUBLE_BUFFERED);
-      flags &= ~GST_PLAY_FLAGS_VIS;
+      /*gdk_window_hide (bvw->priv->video_window);*/
+      /*GTK_WIDGET_SET_FLAGS (GTK_WIDGET (bvw), GTK_DOUBLE_BUFFERED);*/
+      /*flags &= ~GST_PLAY_FLAGS_VIS;*/
 
-      g_object_set (bvw->priv->play, "flags", flags, NULL);
+      /*g_object_set (bvw->priv->play, "flags", flags, NULL);*/
     }
   }
 
@@ -1925,10 +1469,6 @@ bacon_video_widget_finalize (GObject * object)
   g_free (bvw->priv->mrl);
   bvw->priv->mrl = NULL;
 
-
-
-
-
   if (bvw->priv->play != NULL && GST_IS_ELEMENT (bvw->priv->play)) {
     gst_element_set_state (bvw->priv->play, GST_STATE_NULL);
     gst_object_unref (bvw->priv->play);
@@ -3223,16 +2763,6 @@ bacon_video_widget_segment_seek (BaconVideoWidget * bvw, gint64 start,
   GST_LOG ("Segment seeking from %" GST_TIME_FORMAT,
       GST_TIME_ARGS (start * GST_MSECOND));
 
-
-  if (start > bvw->priv->stream_length
-      && bvw->priv->stream_length > 0
-      && !g_str_has_prefix (bvw->priv->mrl, "dvd:")
-      && !g_str_has_prefix (bvw->priv->mrl, "vcd:")) {
-    if (bvw->priv->eos_id == 0)
-      bvw->priv->eos_id = g_idle_add (bvw_signal_eos_delayed, bvw);
-    return TRUE;
-  }
-
   got_time_tick (bvw->priv->play, start * GST_MSECOND, bvw);
   gst_element_seek (bvw->priv->play, rate,
       GST_FORMAT_TIME,
@@ -3280,7 +2810,7 @@ bacon_video_widget_seek_to_previous_frame (BaconVideoWidget * bvw,
   g_return_val_if_fail (GST_IS_ELEMENT (bvw->priv->play), FALSE);
 
 
-  //Round framerate to the nearest integer        
+  //Round framerate to the nearest integer
   fps = (bvw->priv->video_fps_n + bvw->priv->video_fps_d / 2) /
       bvw->priv->video_fps_d;
   pos = bacon_video_widget_get_accurate_current_time (bvw);
@@ -3622,24 +3152,36 @@ bacon_video_widget_set_logo_mode (BaconVideoWidget * bvw, gboolean logo_mode)
 
   logo_mode = logo_mode != FALSE;
 
+  g_mutex_lock (bvw->priv->lock);
+
   if (priv->logo_mode != logo_mode) {
     priv->logo_mode = logo_mode;
 
-    if (priv->video_window) {
-      if (logo_mode) {
-        gdk_window_hide (priv->video_window);
-        GTK_WIDGET_SET_FLAGS (GTK_WIDGET (bvw), GTK_DOUBLE_BUFFERED);
-      } else {
-        gdk_window_show (priv->video_window);
-        GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (bvw), GTK_DOUBLE_BUFFERED);
-      }
+    if (logo_mode) {
+#if defined (GDK_WINDOWING_QUARTZ)
+      gtk_widget_show (priv->logo_da);
+      gtk_widget_hide (priv->video_da);
+#else
+      GTK_WIDGET_SET_FLAGS (GTK_WIDGET (bvw->priv->video_da), GTK_DOUBLE_BUFFERED);
+#endif
+    } else {
+#if defined (GDK_WINDOWING_QUARTZ)
+      gtk_widget_show (priv->video_da);
+      gtk_widget_hide (priv->logo_da);
+#else
+      GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (bvw->priv->video_da), GTK_DOUBLE_BUFFERED);
+#endif
     }
 
+    g_mutex_unlock (bvw->priv->lock);
+
     g_object_notify (G_OBJECT (bvw), "logo_mode");
     g_object_notify (G_OBJECT (bvw), "seekable");
 
     /* Queue a redraw of the widget */
     gtk_widget_queue_draw (GTK_WIDGET (bvw));
+  } else {
+    g_mutex_unlock (bvw->priv->lock);
   }
 }
 
@@ -3833,29 +3375,29 @@ bacon_video_widget_get_volume (BaconVideoWidget * bvw)
  *
  * Fullscreen rendering is done only when possible, as xvidmode is required.
  **/
-void
-bacon_video_widget_set_fullscreen (BaconVideoWidget * bvw, gboolean fullscreen)
-{
-  gboolean have_xvidmode;
+/*void*/
+/*bacon_video_widget_set_fullscreen (BaconVideoWidget * bvw, gboolean fullscreen)*/
+/*{*/
+  /*gboolean have_xvidmode;*/
 
-  g_return_if_fail (bvw != NULL);
-  g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
+  /*g_return_if_fail (bvw != NULL);*/
+  /*g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));*/
 
-  g_object_get (G_OBJECT (bvw->priv->bacon_resize),
-      "have-xvidmode", &have_xvidmode, NULL);
+  /*g_object_get (G_OBJECT (bvw->priv->bacon_resize),*/
+      /*"have-xvidmode", &have_xvidmode, NULL);*/
 
-  if (have_xvidmode == FALSE)
-    return;
+  /*if (have_xvidmode == FALSE)*/
+    /*return;*/
 
-  bvw->priv->fullscreen_mode = fullscreen;
+  /*bvw->priv->fullscreen_mode = fullscreen;*/
 
-  if (fullscreen == FALSE) {
-    bacon_resize_restore (bvw->priv->bacon_resize);
-    /* Turn fullscreen on when we have xvidmode */
-  } else if (have_xvidmode != FALSE) {
-    bacon_resize_resize (bvw->priv->bacon_resize);
-  }
-}
+  /*if (fullscreen == FALSE) {*/
+    /*bacon_resize_restore (bvw->priv->bacon_resize);*/
+    /*[> Turn fullscreen on when we have xvidmode <]*/
+  /*} else if (have_xvidmode != FALSE) {*/
+    /*bacon_resize_resize (bvw->priv->bacon_resize);*/
+  /*}*/
+/*}*/
 
 
 /**
@@ -3984,225 +3526,6 @@ bacon_video_widget_get_aspect_ratio (BaconVideoWidget * bvw)
 }
 
 /**
- * bacon_video_widget_set_scale_ratio:
- * @bvw: a #BaconVideoWidget
- * @ratio: the new scale ratio
- *
- * Sets the ratio by which the widget will scale videos when they are
- * displayed. If @ratio is set to %0, the highest ratio possible will
- * be chosen.
- **/
-void
-bacon_video_widget_set_scale_ratio (BaconVideoWidget * bvw, gfloat ratio)
-{
-  gint w, h;
-
-  g_return_if_fail (bvw != NULL);
-  g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
-  g_return_if_fail (GST_IS_ELEMENT (bvw->priv->play));
-
-  GST_DEBUG ("ratio = %.2f", ratio);
-
-  if (bvw->priv->video_window == NULL)
-    return;
-
-  get_media_size (bvw, &w, &h);
-
-
-  if (ratio == 0.0) {
-    if (totem_ratio_fits_screen (bvw->priv->video_window, w, h, 2.0))
-      ratio = 2.0;
-    else if (totem_ratio_fits_screen (bvw->priv->video_window, w, h, 1.0))
-      ratio = 1.0;
-    else if (totem_ratio_fits_screen (bvw->priv->video_window, w, h, 0.5))
-      ratio = 0.5;
-    else
-      return;
-  } else {
-    if (!totem_ratio_fits_screen (bvw->priv->video_window, w, h, ratio)) {
-      GST_DEBUG ("movie doesn't fit on screen @ %.1fx (%dx%d)", w, h, ratio);
-      return;
-    }
-  }
-  w = (gfloat) w *ratio;
-  h = (gfloat) h *ratio;
-
-  shrink_toplevel (bvw);
-
-  GST_DEBUG ("setting preferred size %dx%d", w, h);
-  totem_widget_set_preferred_size (GTK_WIDGET (bvw), w, h);
-}
-
-/**
- * bacon_video_widget_set_zoom:
- * @bvw: a #BaconVideoWidget
- * @zoom: a percentage zoom factor
- *
- * Sets the zoom factor applied to the video when it is displayed,
- * as an integeric percentage between %0 and %1
- * (e.g. set @zoom to %1 to not zoom at all).
- **/
-void
-bacon_video_widget_set_zoom (BaconVideoWidget * bvw, double zoom)
-{
-  g_return_if_fail (bvw != NULL);
-  g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
-
-  bvw->priv->zoom = zoom;
-  if (bvw->priv->video_window != NULL)
-    resize_video_window (bvw);
-}
-
-/**
- * bacon_video_widget_get_zoom:
- * @bvw: a #BaconVideoWidget
- *
- * Returns the zoom factor applied to videos displayed by the widget,
- * as an integeric percentage between %0 and %1
- * (e.g. %1 means no zooming at all).
- *
- * Return value: the zoom factor
- **/
-double
-bacon_video_widget_get_zoom (BaconVideoWidget * bvw)
-{
-  g_return_val_if_fail (bvw != NULL, 1.0);
-  g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 1.0);
-
-  return bvw->priv->zoom;
-}
-
-
-/* Search for the color balance channel corresponding to type and return it. */
-static GstColorBalanceChannel *
-bvw_get_color_balance_channel (GstColorBalance * color_balance,
-    BvwVideoProperty type)
-{
-  const GList *channels;
-
-  channels = gst_color_balance_list_channels (color_balance);
-
-  for (; channels != NULL; channels = channels->next) {
-    GstColorBalanceChannel *c = channels->data;
-
-    if (type == BVW_VIDEO_BRIGHTNESS && g_strrstr (c->label, "BRIGHTNESS"))
-      return g_object_ref (c);
-    else if (type == BVW_VIDEO_CONTRAST && g_strrstr (c->label, "CONTRAST"))
-      return g_object_ref (c);
-    else if (type == BVW_VIDEO_SATURATION && g_strrstr (c->label, "SATURATION"))
-      return g_object_ref (c);
-    else if (type == BVW_VIDEO_HUE && g_strrstr (c->label, "HUE"))
-      return g_object_ref (c);
-  }
-
-  return NULL;
-}
-
-/**
- * bacon_video_widget_get_video_property:
- * @bvw: a #BaconVideoWidget
- * @type: the type of property
- *
- * Returns the given property of the video, such as its brightness or saturation.
- *
- * It is returned as a percentage in the full range of integer values; from %0
- * to %G_MAXINT, where %G_MAXINT/2 is the default.
- *
- * Return value: the property's value, in the range %0 to %G_MAXINT
- **/
-int
-bacon_video_widget_get_video_property (BaconVideoWidget * bvw,
-    BvwVideoProperty type)
-{
-  int ret;
-
-  g_return_val_if_fail (bvw != NULL, 65535 / 2);
-  g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 65535 / 2);
-
-  g_mutex_lock (bvw->priv->lock);
-
-  ret = 0;
-
-  if (bvw->priv->balance && GST_IS_COLOR_BALANCE (bvw->priv->balance)) {
-    GstColorBalanceChannel *found_channel = NULL;
-
-    found_channel = bvw_get_color_balance_channel (bvw->priv->balance, type);
-
-    if (found_channel && GST_IS_COLOR_BALANCE_CHANNEL (found_channel)) {
-      gint cur;
-
-      cur = gst_color_balance_get_value (bvw->priv->balance, found_channel);
-
-      GST_DEBUG ("channel %s: cur=%d, min=%d, max=%d",
-          found_channel->label, cur, found_channel->min_value,
-          found_channel->max_value);
-
-      ret = floor (0.5 +
-          ((double) cur - found_channel->min_value) * 65535 /
-          ((double) found_channel->max_value - found_channel->min_value));
-
-      GST_DEBUG ("channel %s: returning value %d", found_channel->label, ret);
-      g_object_unref (found_channel);
-      goto done;
-    } else {
-      ret = -1;
-    }
-  }
-
-done:
-
-  g_mutex_unlock (bvw->priv->lock);
-  return ret;
-}
-
-/**
- * bacon_video_widget_set_video_property:
- * @bvw: a #BaconVideoWidget
- * @type: the type of property
- * @value: the property's value, in the range %0 to %G_MAXINT
- *
- * Sets the given property of the video, such as its brightness or saturation.
- *
- * It should be given as a percentage in the full range of integer values; from %0
- * to %G_MAXINT, where %G_MAXINT/2 is the default.
- **/
-void
-bacon_video_widget_set_video_property (BaconVideoWidget * bvw,
-    BvwVideoProperty type, int value)
-{
-  g_return_if_fail (bvw != NULL);
-  g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
-
-  GST_DEBUG ("set video property type %d to value %d", type, value);
-
-  if (!(value <= 65535 && value >= 0))
-    return;
-
-  if (bvw->priv->balance && GST_IS_COLOR_BALANCE (bvw->priv->balance)) {
-    GstColorBalanceChannel *found_channel = NULL;
-
-    found_channel = bvw_get_color_balance_channel (bvw->priv->balance, type);
-
-    if (found_channel && GST_IS_COLOR_BALANCE_CHANNEL (found_channel)) {
-      int i_value;
-
-      i_value = floor (0.5 + value * ((double) found_channel->max_value -
-              found_channel->min_value) / 65535 + found_channel->min_value);
-
-      GST_DEBUG ("channel %s: set to %d/65535", found_channel->label, value);
-
-      gst_color_balance_set_value (bvw->priv->balance, found_channel, i_value);
-
-      GST_DEBUG ("channel %s: val=%d, min=%d, max=%d",
-          found_channel->label, i_value, found_channel->min_value,
-          found_channel->max_value);
-
-      g_object_unref (found_channel);
-    }
-  }
-}
-
-/**
  * bacon_video_widget_get_position:
  * @bvw: a #BaconVideoWidget
  *
@@ -5138,7 +4461,7 @@ bacon_video_widget_get_current_frame (BaconVideoWidget * bvw)
 /*                                             */
 /* =========================================== */
 
-G_DEFINE_TYPE (BaconVideoWidget, bacon_video_widget, GTK_TYPE_EVENT_BOX)
+G_DEFINE_TYPE (BaconVideoWidget, bacon_video_widget, GTK_TYPE_HBOX)
 /* applications must use exactly one of bacon_video_widget_get_option_group()
  * OR bacon_video_widget_init_backend(), but not both */
 /**
@@ -5185,151 +4508,6 @@ bacon_video_widget_error_quark (void)
   return q;
 }
 
-/* fold function to pick the best colorspace element */
-static gboolean
-find_colorbalance_element (GstElement * element, GValue * ret, GstElement ** cb)
-{
-  GstColorBalanceClass *cb_class;
-
-  GST_DEBUG ("Checking element %s ...", GST_OBJECT_NAME (element));
-
-  if (!GST_IS_COLOR_BALANCE (element))
-    return TRUE;
-
-  GST_DEBUG ("Element %s is a color balance", GST_OBJECT_NAME (element));
-
-  cb_class = GST_COLOR_BALANCE_GET_CLASS (element);
-  if (GST_COLOR_BALANCE_TYPE (cb_class) == GST_COLOR_BALANCE_HARDWARE) {
-    gst_object_replace ((GstObject **) cb, (GstObject *) element);
-    /* shortcuts the fold */
-    return FALSE;
-  } else if (*cb == NULL) {
-    gst_object_replace ((GstObject **) cb, (GstObject *) element);
-    return TRUE;
-  } else {
-    return TRUE;
-  }
-}
-
-static gboolean
-bvw_update_interfaces_delayed (BaconVideoWidget * bvw)
-{
-  GST_DEBUG ("Delayed updating interface implementations");
-  g_mutex_lock (bvw->priv->lock);
-  bvw_update_interface_implementations (bvw);
-  bvw->priv->interface_update_id = 0;
-  g_mutex_unlock (bvw->priv->lock);
-
-  return FALSE;
-}
-
-/* Must be called with bvw->priv->lock held */
-static void
-bvw_update_interface_implementations (BaconVideoWidget * bvw)
-{
-  GstColorBalance *old_balance = bvw->priv->balance;
-  GstXOverlay *old_xoverlay = bvw->priv->xoverlay;
-  GstElement *video_sink = NULL;
-  GstElement *element = NULL;
-  GstIterator *iter;
-
-  if (g_thread_self () != gui_thread) {
-    if (bvw->priv->balance)
-      gst_object_unref (bvw->priv->balance);
-    bvw->priv->balance = NULL;
-    if (bvw->priv->xoverlay)
-      gst_object_unref (bvw->priv->xoverlay);
-    bvw->priv->xoverlay = NULL;
-    if (bvw->priv->navigation)
-      gst_object_unref (bvw->priv->navigation);
-    bvw->priv->navigation = NULL;
-
-    if (bvw->priv->interface_update_id)
-      g_source_remove (bvw->priv->interface_update_id);
-    bvw->priv->interface_update_id =
-        g_idle_add ((GSourceFunc) bvw_update_interfaces_delayed, bvw);
-    return;
-  }
-
-  g_object_get (bvw->priv->play, "video-sink", &video_sink, NULL);
-  g_assert (video_sink != NULL);
-
-  /* We try to get an element supporting XOverlay interface */
-  if (GST_IS_BIN (video_sink)) {
-    GST_DEBUG ("Retrieving xoverlay from bin ...");
-    element = gst_bin_get_by_interface (GST_BIN (video_sink),
-        GST_TYPE_X_OVERLAY);
-  } else {
-    element = gst_object_ref (video_sink);
-  }
-
-  if (GST_IS_X_OVERLAY (element)) {
-    GST_DEBUG ("Found xoverlay: %s", GST_OBJECT_NAME (element));
-    bvw->priv->xoverlay = GST_X_OVERLAY (element);
-  } else {
-    GST_DEBUG ("No xoverlay found");
-    if (element)
-      gst_object_unref (element);
-    bvw->priv->xoverlay = NULL;
-  }
-
-  /* Try to find the navigation interface */
-  if (GST_IS_BIN (video_sink)) {
-    GST_DEBUG ("Retrieving navigation from bin ...");
-    element = gst_bin_get_by_interface (GST_BIN (video_sink),
-        GST_TYPE_NAVIGATION);
-  } else {
-    element = gst_object_ref (video_sink);
-  }
-
-  if (GST_IS_NAVIGATION (element)) {
-    GST_DEBUG ("Found navigation: %s", GST_OBJECT_NAME (element));
-    bvw->priv->navigation = GST_NAVIGATION (element);
-  } else {
-    GST_DEBUG ("No navigation found");
-    if (element)
-      gst_object_unref (element);
-    bvw->priv->navigation = NULL;
-  }
-
-  /* Find best color balance element (using custom iterator so
-   * we can prefer hardware implementations to software ones) */
-
-  /* FIXME: this doesn't work reliably yet, most of the time
-   * the fold function doesn't even get called, while sometimes
-   * it does ... */
-  iter = gst_bin_iterate_all_by_interface (GST_BIN (bvw->priv->play),
-      GST_TYPE_COLOR_BALANCE);
-  /* naively assume no resync */
-  element = NULL;
-  gst_iterator_fold (iter, (GstIteratorFoldFunction)
-      find_colorbalance_element, NULL, &element);
-  gst_iterator_free (iter);
-
-  if (element) {
-    bvw->priv->balance = GST_COLOR_BALANCE (element);
-    GST_DEBUG ("Best colorbalance found: %s",
-        GST_OBJECT_NAME (bvw->priv->balance));
-  } else if (GST_IS_COLOR_BALANCE (bvw->priv->xoverlay)) {
-    bvw->priv->balance = GST_COLOR_BALANCE (bvw->priv->xoverlay);
-    gst_object_ref (bvw->priv->balance);
-    GST_DEBUG ("Colorbalance backup found: %s",
-        GST_OBJECT_NAME (bvw->priv->balance));
-  } else {
-    GST_DEBUG ("No colorbalance found");
-    bvw->priv->balance = NULL;
-  }
-
-  if (old_xoverlay)
-    gst_object_unref (GST_OBJECT (old_xoverlay));
-
-  if (old_balance)
-    gst_object_unref (GST_OBJECT (old_balance));
-
-  gst_object_unref (video_sink);
-}
-
-
 static void
 bvw_element_msg_sync (GstBus * bus, GstMessage * msg, gpointer data)
 {
@@ -5344,38 +4522,28 @@ bvw_element_msg_sync (GstBus * bus, GstMessage * msg, gpointer data)
   /* This only gets sent if we haven't set an ID yet. This is our last
    * chance to set it before the video sink will create its own window */
   if (gst_structure_has_name (msg->structure, "prepare-xwindow-id")) {
+    GstObject *sender = GST_MESSAGE_SRC (msg);
+
     GST_INFO ("Handling sync prepare-xwindow-id message");
 
     g_mutex_lock (bvw->priv->lock);
-    bvw_update_interface_implementations (bvw);
-    g_mutex_unlock (bvw->priv->lock);
-    
-    if (bvw->priv->xoverlay == NULL) {
-      GstObject *sender = GST_MESSAGE_SRC (msg);
-      if (sender && GST_IS_X_OVERLAY (sender))
-        bvw->priv->xoverlay = GST_X_OVERLAY (gst_object_ref (sender));
+
+    if (bvw->priv->xoverlay != NULL) {
+      gst_object_unref (bvw->priv->xoverlay);
     }
 
-    g_return_if_fail (bvw->priv->xoverlay != NULL);
-    g_return_if_fail (bvw->priv->video_window != NULL);
+    if (sender && GST_IS_X_OVERLAY (sender))
+      bvw->priv->xoverlay = GST_X_OVERLAY (gst_object_ref (sender));
 
-  gst_set_window_handle(bvw->priv->xoverlay, bvw->priv->video_window);
+    g_return_if_fail (bvw->priv->xoverlay != NULL);
+    g_return_if_fail (bvw->priv->window_handle != 0);
 
+    g_object_set (GST_ELEMENT (bvw->priv->xoverlay), "force-aspect-ratio", TRUE, NULL);
+    gst_set_window_handle(bvw->priv->xoverlay, bvw->priv->window_handle);
+    g_mutex_unlock (bvw->priv->lock);
   }
 }
 
-static void
-got_new_video_sink_bin_element (GstBin * video_sink, GstElement * element,
-    gpointer data)
-{
-  BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (data);
-
-  g_mutex_lock (bvw->priv->lock);
-  bvw_update_interface_implementations (bvw);
-  g_mutex_unlock (bvw->priv->lock);
-
-}
-
 /**
  * bacon_video_widget_new:
  * @width: initial or expected video width, in pixels, or %-1
@@ -5404,13 +4572,6 @@ bacon_video_widget_new (int width, int height, BvwUseType type, GError ** err)
   GstElement *audio_sink = NULL, *video_sink = NULL;
   gchar *version_str;
 
-#ifndef GST_DISABLE_GST_INFO
-  if (_totem_gst_debug_cat == NULL) {
-    GST_DEBUG_CATEGORY_INIT (_totem_gst_debug_cat, "totem", 0,
-        "Totem GStreamer Backend");
-  }
-#endif
-
   version_str = gst_version_string ();
   GST_INFO ("Initialised %s", version_str);
   g_free (version_str);
@@ -5419,6 +4580,11 @@ bacon_video_widget_new (int width, int height, BvwUseType type, GError ** err)
 
   bvw = g_object_new (bacon_video_widget_get_type (), NULL);
 
+  /* show the gui. */
+  gtk_widget_show_all (GTK_WIDGET(bvw));
+
+  bacon_video_widget_set_logo_mode (bvw, TRUE);
+
   bvw->priv->use_type = type;
 
   GST_INFO ("use_type = %d", type);
@@ -5435,7 +4601,6 @@ bacon_video_widget_new (int width, int height, BvwUseType type, GError ** err)
   }
 
   bvw->priv->bus = gst_element_get_bus (bvw->priv->play);
-
   gst_bus_add_signal_watch (bvw->priv->bus);
 
   bvw->priv->sig_bus_async =
@@ -5622,7 +4787,7 @@ bacon_video_widget_new (int width, int height, BvwUseType type, GError ** err)
   if (type == BVW_USE_TYPE_VIDEO) {
     GstStateChangeReturn ret;
 
-    /* wait for video sink to finish changing to READY state, 
+    /* wait for video sink to finish changing to READY state,
      * otherwise we won't be able to detect the colorbalance interface */
     ret = gst_element_get_state (video_sink, NULL, NULL, 5 * GST_SECOND);
 
@@ -5634,7 +4799,6 @@ bacon_video_widget_new (int width, int height, BvwUseType type, GError ** err)
               "Please select another video output in the Multimedia Systems Selector."));
       return NULL;
     }
-    bvw_update_interface_implementations (bvw);
 
   }
 
@@ -5645,16 +4809,6 @@ bacon_video_widget_new (int width, int height, BvwUseType type, GError ** err)
       g_signal_connect (bvw->priv->bus, "sync-message::element",
       G_CALLBACK (bvw_element_msg_sync), bvw);
 
-  if (GST_IS_BIN (video_sink)) {
-    /* video sink bins like gsettingsvideosink might remove their children and
-     * create new ones when set to NULL state, and they are currently set
-     * to NULL state whenever playbin re-creates its internal video bin
-     * (it sets all elements to NULL state before gst_bin_remove()ing them) */
-    g_signal_connect (video_sink, "element-added",
-        G_CALLBACK (got_new_video_sink_bin_element), bvw);
-  }
-
-
   return GTK_WIDGET (bvw);
 
   /* errors */
diff --git a/libcesarplayer/src/bacon-video-widget.h b/libcesarplayer/bacon-video-widget.h
similarity index 99%
rename from libcesarplayer/src/bacon-video-widget.h
rename to libcesarplayer/bacon-video-widget.h
index d2e5746..5a2753d 100644
--- a/libcesarplayer/src/bacon-video-widget.h
+++ b/libcesarplayer/bacon-video-widget.h
@@ -52,13 +52,13 @@ typedef struct BaconVideoWidgetPrivate BaconVideoWidgetPrivate;
 
 typedef struct
 {
-  GtkEventBox parent;
+  GtkHBox parent;
   BaconVideoWidgetPrivate *priv;
 } BaconVideoWidget;
 
 typedef struct
 {
-  GtkEventBoxClass parent_class;
+  GtkHBoxClass parent_class;
 
   void (*error) (BaconVideoWidget * bvw, const char *message);
   void (*eos) (BaconVideoWidget * bvw);
diff --git a/libcesarplayer/src/baconvideowidget-marshal.c b/libcesarplayer/baconvideowidget-marshal.c
similarity index 98%
rename from libcesarplayer/src/baconvideowidget-marshal.c
rename to libcesarplayer/baconvideowidget-marshal.c
index 6b34127..e914ccd 100644
--- a/libcesarplayer/src/baconvideowidget-marshal.c
+++ b/libcesarplayer/baconvideowidget-marshal.c
@@ -1,247 +1,247 @@
-
-#ifndef __baconvideowidget_marshal_MARSHAL_H__
-#define __baconvideowidget_marshal_MARSHAL_H__
-
-#include	<glib-object.h>
-
-G_BEGIN_DECLS
-
-#ifdef G_ENABLE_DEBUG
-#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
-#define g_marshal_value_peek_char(v)     g_value_get_schar (v)
-#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
-#define g_marshal_value_peek_int(v)      g_value_get_int (v)
-#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
-#define g_marshal_value_peek_long(v)     g_value_get_long (v)
-#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
-#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
-#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
-#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
-#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
-#define g_marshal_value_peek_float(v)    g_value_get_float (v)
-#define g_marshal_value_peek_double(v)   g_value_get_double (v)
-#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
-#define g_marshal_value_peek_param(v)    g_value_get_param (v)
-#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
-#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
-#define g_marshal_value_peek_object(v)   g_value_get_object (v)
-#define g_marshal_value_peek_variant(v)  g_value_get_variant (v)
-#else /* !G_ENABLE_DEBUG */
-/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
- *          Do not access GValues directly in your code. Instead, use the
- *          g_value_get_*() functions
- */
-#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
-#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
-#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
-#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
-#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
-#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
-#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
-#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
-#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
-#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
-#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
-#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
-#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
-#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
-#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
-#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
-#define g_marshal_value_peek_variant(v)  (v)->data[0].v_pointer
-#endif /* !G_ENABLE_DEBUG */
-
-
-/* VOID:INT64,INT64,DOUBLE,BOOLEAN (./baconvideowidget-marshal.list:1) */
-extern void baconvideowidget_marshal_VOID__INT64_INT64_DOUBLE_BOOLEAN (GClosure     *closure,
-                                                                       GValue       *return_value,
-                                                                       guint         n_param_values,
-                                                                       const GValue *param_values,
-                                                                       gpointer      invocation_hint,
-                                                                       gpointer      marshal_data);
-void
-baconvideowidget_marshal_VOID__INT64_INT64_DOUBLE_BOOLEAN (GClosure     *closure,
-                                                           GValue       *return_value G_GNUC_UNUSED,
-                                                           guint         n_param_values,
-                                                           const GValue *param_values,
-                                                           gpointer      invocation_hint G_GNUC_UNUSED,
-                                                           gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__INT64_INT64_DOUBLE_BOOLEAN) (gpointer     data1,
-                                                                 gint64       arg_1,
-                                                                 gint64       arg_2,
-                                                                 gdouble      arg_3,
-                                                                 gboolean     arg_4,
-                                                                 gpointer     data2);
-  register GMarshalFunc_VOID__INT64_INT64_DOUBLE_BOOLEAN callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 5);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__INT64_INT64_DOUBLE_BOOLEAN) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_int64 (param_values + 1),
-            g_marshal_value_peek_int64 (param_values + 2),
-            g_marshal_value_peek_double (param_values + 3),
-            g_marshal_value_peek_boolean (param_values + 4),
-            data2);
-}
-
-/* VOID:STRING,BOOLEAN,BOOLEAN (./baconvideowidget-marshal.list:2) */
-extern void baconvideowidget_marshal_VOID__STRING_BOOLEAN_BOOLEAN (GClosure     *closure,
-                                                                   GValue       *return_value,
-                                                                   guint         n_param_values,
-                                                                   const GValue *param_values,
-                                                                   gpointer      invocation_hint,
-                                                                   gpointer      marshal_data);
-void
-baconvideowidget_marshal_VOID__STRING_BOOLEAN_BOOLEAN (GClosure     *closure,
-                                                       GValue       *return_value G_GNUC_UNUSED,
-                                                       guint         n_param_values,
-                                                       const GValue *param_values,
-                                                       gpointer      invocation_hint G_GNUC_UNUSED,
-                                                       gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__STRING_BOOLEAN_BOOLEAN) (gpointer     data1,
-                                                             gpointer     arg_1,
-                                                             gboolean     arg_2,
-                                                             gboolean     arg_3,
-                                                             gpointer     data2);
-  register GMarshalFunc_VOID__STRING_BOOLEAN_BOOLEAN callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 4);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__STRING_BOOLEAN_BOOLEAN) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_string (param_values + 1),
-            g_marshal_value_peek_boolean (param_values + 2),
-            g_marshal_value_peek_boolean (param_values + 3),
-            data2);
-}
-
-/* BOOLEAN:BOXED,BOXED,BOOLEAN (./baconvideowidget-marshal.list:3) */
-extern void baconvideowidget_marshal_BOOLEAN__BOXED_BOXED_BOOLEAN (GClosure     *closure,
-                                                                   GValue       *return_value,
-                                                                   guint         n_param_values,
-                                                                   const GValue *param_values,
-                                                                   gpointer      invocation_hint,
-                                                                   gpointer      marshal_data);
-void
-baconvideowidget_marshal_BOOLEAN__BOXED_BOXED_BOOLEAN (GClosure     *closure,
-                                                       GValue       *return_value G_GNUC_UNUSED,
-                                                       guint         n_param_values,
-                                                       const GValue *param_values,
-                                                       gpointer      invocation_hint G_GNUC_UNUSED,
-                                                       gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__BOXED_BOXED_BOOLEAN) (gpointer     data1,
-                                                                 gpointer     arg_1,
-                                                                 gpointer     arg_2,
-                                                                 gboolean     arg_3,
-                                                                 gpointer     data2);
-  register GMarshalFunc_BOOLEAN__BOXED_BOXED_BOOLEAN callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 4);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__BOXED_BOXED_BOOLEAN) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_boxed (param_values + 1),
-                       g_marshal_value_peek_boxed (param_values + 2),
-                       g_marshal_value_peek_boolean (param_values + 3),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-/* VOID:INT64,INT64,FLOAT,BOOLEAN (./baconvideowidget-marshal.list:4) */
-extern void baconvideowidget_marshal_VOID__INT64_INT64_FLOAT_BOOLEAN (GClosure     *closure,
-                                                                      GValue       *return_value,
-                                                                      guint         n_param_values,
-                                                                      const GValue *param_values,
-                                                                      gpointer      invocation_hint,
-                                                                      gpointer      marshal_data);
-void
-baconvideowidget_marshal_VOID__INT64_INT64_FLOAT_BOOLEAN (GClosure     *closure,
-                                                          GValue       *return_value G_GNUC_UNUSED,
-                                                          guint         n_param_values,
-                                                          const GValue *param_values,
-                                                          gpointer      invocation_hint G_GNUC_UNUSED,
-                                                          gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__INT64_INT64_FLOAT_BOOLEAN) (gpointer     data1,
-                                                                gint64       arg_1,
-                                                                gint64       arg_2,
-                                                                gfloat       arg_3,
-                                                                gboolean     arg_4,
-                                                                gpointer     data2);
-  register GMarshalFunc_VOID__INT64_INT64_FLOAT_BOOLEAN callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 5);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__INT64_INT64_FLOAT_BOOLEAN) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_int64 (param_values + 1),
-            g_marshal_value_peek_int64 (param_values + 2),
-            g_marshal_value_peek_float (param_values + 3),
-            g_marshal_value_peek_boolean (param_values + 4),
-            data2);
-}
-
-G_END_DECLS
-
-#endif /* __baconvideowidget_marshal_MARSHAL_H__ */
-
+
+#ifndef __baconvideowidget_marshal_MARSHAL_H__
+#define __baconvideowidget_marshal_MARSHAL_H__
+
+#include	<glib-object.h>
+
+G_BEGIN_DECLS
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v)     g_value_get_schar (v)
+#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v)      g_value_get_int (v)
+#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
+#define g_marshal_value_peek_long(v)     g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
+#define g_marshal_value_peek_float(v)    g_value_get_float (v)
+#define g_marshal_value_peek_double(v)   g_value_get_double (v)
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v)    g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+#define g_marshal_value_peek_variant(v)  g_value_get_variant (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ *          Do not access GValues directly in your code. Instead, use the
+ *          g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
+#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
+#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_variant(v)  (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* VOID:INT64,INT64,DOUBLE,BOOLEAN (./baconvideowidget-marshal.list:1) */
+extern void baconvideowidget_marshal_VOID__INT64_INT64_DOUBLE_BOOLEAN (GClosure     *closure,
+                                                                       GValue       *return_value,
+                                                                       guint         n_param_values,
+                                                                       const GValue *param_values,
+                                                                       gpointer      invocation_hint,
+                                                                       gpointer      marshal_data);
+void
+baconvideowidget_marshal_VOID__INT64_INT64_DOUBLE_BOOLEAN (GClosure     *closure,
+                                                           GValue       *return_value G_GNUC_UNUSED,
+                                                           guint         n_param_values,
+                                                           const GValue *param_values,
+                                                           gpointer      invocation_hint G_GNUC_UNUSED,
+                                                           gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__INT64_INT64_DOUBLE_BOOLEAN) (gpointer     data1,
+                                                                 gint64       arg_1,
+                                                                 gint64       arg_2,
+                                                                 gdouble      arg_3,
+                                                                 gboolean     arg_4,
+                                                                 gpointer     data2);
+  register GMarshalFunc_VOID__INT64_INT64_DOUBLE_BOOLEAN callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 5);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__INT64_INT64_DOUBLE_BOOLEAN) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_int64 (param_values + 1),
+            g_marshal_value_peek_int64 (param_values + 2),
+            g_marshal_value_peek_double (param_values + 3),
+            g_marshal_value_peek_boolean (param_values + 4),
+            data2);
+}
+
+/* VOID:STRING,BOOLEAN,BOOLEAN (./baconvideowidget-marshal.list:2) */
+extern void baconvideowidget_marshal_VOID__STRING_BOOLEAN_BOOLEAN (GClosure     *closure,
+                                                                   GValue       *return_value,
+                                                                   guint         n_param_values,
+                                                                   const GValue *param_values,
+                                                                   gpointer      invocation_hint,
+                                                                   gpointer      marshal_data);
+void
+baconvideowidget_marshal_VOID__STRING_BOOLEAN_BOOLEAN (GClosure     *closure,
+                                                       GValue       *return_value G_GNUC_UNUSED,
+                                                       guint         n_param_values,
+                                                       const GValue *param_values,
+                                                       gpointer      invocation_hint G_GNUC_UNUSED,
+                                                       gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__STRING_BOOLEAN_BOOLEAN) (gpointer     data1,
+                                                             gpointer     arg_1,
+                                                             gboolean     arg_2,
+                                                             gboolean     arg_3,
+                                                             gpointer     data2);
+  register GMarshalFunc_VOID__STRING_BOOLEAN_BOOLEAN callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 4);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__STRING_BOOLEAN_BOOLEAN) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_string (param_values + 1),
+            g_marshal_value_peek_boolean (param_values + 2),
+            g_marshal_value_peek_boolean (param_values + 3),
+            data2);
+}
+
+/* BOOLEAN:BOXED,BOXED,BOOLEAN (./baconvideowidget-marshal.list:3) */
+extern void baconvideowidget_marshal_BOOLEAN__BOXED_BOXED_BOOLEAN (GClosure     *closure,
+                                                                   GValue       *return_value,
+                                                                   guint         n_param_values,
+                                                                   const GValue *param_values,
+                                                                   gpointer      invocation_hint,
+                                                                   gpointer      marshal_data);
+void
+baconvideowidget_marshal_BOOLEAN__BOXED_BOXED_BOOLEAN (GClosure     *closure,
+                                                       GValue       *return_value G_GNUC_UNUSED,
+                                                       guint         n_param_values,
+                                                       const GValue *param_values,
+                                                       gpointer      invocation_hint G_GNUC_UNUSED,
+                                                       gpointer      marshal_data)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__BOXED_BOXED_BOOLEAN) (gpointer     data1,
+                                                                 gpointer     arg_1,
+                                                                 gpointer     arg_2,
+                                                                 gboolean     arg_3,
+                                                                 gpointer     data2);
+  register GMarshalFunc_BOOLEAN__BOXED_BOXED_BOOLEAN callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 4);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__BOXED_BOXED_BOOLEAN) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_boxed (param_values + 1),
+                       g_marshal_value_peek_boxed (param_values + 2),
+                       g_marshal_value_peek_boolean (param_values + 3),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
+}
+
+/* VOID:INT64,INT64,FLOAT,BOOLEAN (./baconvideowidget-marshal.list:4) */
+extern void baconvideowidget_marshal_VOID__INT64_INT64_FLOAT_BOOLEAN (GClosure     *closure,
+                                                                      GValue       *return_value,
+                                                                      guint         n_param_values,
+                                                                      const GValue *param_values,
+                                                                      gpointer      invocation_hint,
+                                                                      gpointer      marshal_data);
+void
+baconvideowidget_marshal_VOID__INT64_INT64_FLOAT_BOOLEAN (GClosure     *closure,
+                                                          GValue       *return_value G_GNUC_UNUSED,
+                                                          guint         n_param_values,
+                                                          const GValue *param_values,
+                                                          gpointer      invocation_hint G_GNUC_UNUSED,
+                                                          gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__INT64_INT64_FLOAT_BOOLEAN) (gpointer     data1,
+                                                                gint64       arg_1,
+                                                                gint64       arg_2,
+                                                                gfloat       arg_3,
+                                                                gboolean     arg_4,
+                                                                gpointer     data2);
+  register GMarshalFunc_VOID__INT64_INT64_FLOAT_BOOLEAN callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 5);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__INT64_INT64_FLOAT_BOOLEAN) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_int64 (param_values + 1),
+            g_marshal_value_peek_int64 (param_values + 2),
+            g_marshal_value_peek_float (param_values + 3),
+            g_marshal_value_peek_boolean (param_values + 4),
+            data2);
+}
+
+G_END_DECLS
+
+#endif /* __baconvideowidget_marshal_MARSHAL_H__ */
+
diff --git a/libcesarplayer/src/baconvideowidget-marshal.h b/libcesarplayer/baconvideowidget-marshal.h
similarity index 98%
rename from libcesarplayer/src/baconvideowidget-marshal.h
rename to libcesarplayer/baconvideowidget-marshal.h
index 035d853..7cba5d9 100644
--- a/libcesarplayer/src/baconvideowidget-marshal.h
+++ b/libcesarplayer/baconvideowidget-marshal.h
@@ -1,44 +1,44 @@
-
-#ifndef __baconvideowidget_marshal_MARSHAL_H__
-#define __baconvideowidget_marshal_MARSHAL_H__
-
-#include	<glib-object.h>
-
-G_BEGIN_DECLS
-
-/* VOID:INT64,INT64,DOUBLE,BOOLEAN (./baconvideowidget-marshal.list:1) */
-extern void baconvideowidget_marshal_VOID__INT64_INT64_DOUBLE_BOOLEAN (GClosure     *closure,
-                                                                       GValue       *return_value,
-                                                                       guint         n_param_values,
-                                                                       const GValue *param_values,
-                                                                       gpointer      invocation_hint,
-                                                                       gpointer      marshal_data);
-
-/* VOID:STRING,BOOLEAN,BOOLEAN (./baconvideowidget-marshal.list:2) */
-extern void baconvideowidget_marshal_VOID__STRING_BOOLEAN_BOOLEAN (GClosure     *closure,
-                                                                   GValue       *return_value,
-                                                                   guint         n_param_values,
-                                                                   const GValue *param_values,
-                                                                   gpointer      invocation_hint,
-                                                                   gpointer      marshal_data);
-
-/* BOOLEAN:BOXED,BOXED,BOOLEAN (./baconvideowidget-marshal.list:3) */
-extern void baconvideowidget_marshal_BOOLEAN__BOXED_BOXED_BOOLEAN (GClosure     *closure,
-                                                                   GValue       *return_value,
-                                                                   guint         n_param_values,
-                                                                   const GValue *param_values,
-                                                                   gpointer      invocation_hint,
-                                                                   gpointer      marshal_data);
-
-/* VOID:INT64,INT64,FLOAT,BOOLEAN (./baconvideowidget-marshal.list:4) */
-extern void baconvideowidget_marshal_VOID__INT64_INT64_FLOAT_BOOLEAN (GClosure     *closure,
-                                                                      GValue       *return_value,
-                                                                      guint         n_param_values,
-                                                                      const GValue *param_values,
-                                                                      gpointer      invocation_hint,
-                                                                      gpointer      marshal_data);
-
-G_END_DECLS
-
-#endif /* __baconvideowidget_marshal_MARSHAL_H__ */
-
+
+#ifndef __baconvideowidget_marshal_MARSHAL_H__
+#define __baconvideowidget_marshal_MARSHAL_H__
+
+#include	<glib-object.h>
+
+G_BEGIN_DECLS
+
+/* VOID:INT64,INT64,DOUBLE,BOOLEAN (./baconvideowidget-marshal.list:1) */
+extern void baconvideowidget_marshal_VOID__INT64_INT64_DOUBLE_BOOLEAN (GClosure     *closure,
+                                                                       GValue       *return_value,
+                                                                       guint         n_param_values,
+                                                                       const GValue *param_values,
+                                                                       gpointer      invocation_hint,
+                                                                       gpointer      marshal_data);
+
+/* VOID:STRING,BOOLEAN,BOOLEAN (./baconvideowidget-marshal.list:2) */
+extern void baconvideowidget_marshal_VOID__STRING_BOOLEAN_BOOLEAN (GClosure     *closure,
+                                                                   GValue       *return_value,
+                                                                   guint         n_param_values,
+                                                                   const GValue *param_values,
+                                                                   gpointer      invocation_hint,
+                                                                   gpointer      marshal_data);
+
+/* BOOLEAN:BOXED,BOXED,BOOLEAN (./baconvideowidget-marshal.list:3) */
+extern void baconvideowidget_marshal_BOOLEAN__BOXED_BOXED_BOOLEAN (GClosure     *closure,
+                                                                   GValue       *return_value,
+                                                                   guint         n_param_values,
+                                                                   const GValue *param_values,
+                                                                   gpointer      invocation_hint,
+                                                                   gpointer      marshal_data);
+
+/* VOID:INT64,INT64,FLOAT,BOOLEAN (./baconvideowidget-marshal.list:4) */
+extern void baconvideowidget_marshal_VOID__INT64_INT64_FLOAT_BOOLEAN (GClosure     *closure,
+                                                                      GValue       *return_value,
+                                                                      guint         n_param_values,
+                                                                      const GValue *param_values,
+                                                                      gpointer      invocation_hint,
+                                                                      gpointer      marshal_data);
+
+G_END_DECLS
+
+#endif /* __baconvideowidget_marshal_MARSHAL_H__ */
+
diff --git a/libcesarplayer/src/baconvideowidget-marshal.list b/libcesarplayer/baconvideowidget-marshal.list
similarity index 100%
rename from libcesarplayer/src/baconvideowidget-marshal.list
rename to libcesarplayer/baconvideowidget-marshal.list
diff --git a/libcesarplayer/src/common.h b/libcesarplayer/common.h
similarity index 78%
rename from libcesarplayer/src/common.h
rename to libcesarplayer/common.h
index cb3ed97..c524ac8 100644
--- a/libcesarplayer/src/common.h
+++ b/libcesarplayer/common.h
@@ -17,6 +17,35 @@
  *
  */
 
+#ifndef __LIBCESARPLAYER_COMMON_H__
+#define __LIBCESARPLAYER_COMMON_H__
+
+/* Default video/audio sinks */
+#if defined(OSTYPE_WINDOWS)
+#define DEFAULT_VIDEO_SINK "d3dvideosink"
+#define BACKUP_VIDEO_SINK "autovideosink"
+#elif defined(OSTYPE_OS_X)
+#define DEFAULT_VIDEO_SINK "osxvideosink"
+#define BACKUP_VIDEO_SINK "autovideosink"
+#elif defined(OSTYPE_LINUX)
+#define DEFAULT_VIDEO_SINK "gsettingsvideosink"
+#define BACKUP_VIDEO_SINK "autovideosink"
+#endif
+
+/*Default video/audio source*/
+#if defined(OSTYPE_WINDOWS)
+#define DVVIDEOSRC "dshowvideosrc"
+#define SYSVIDEOSRC "dshowvideosrc"
+#define AUDIOSRC "dshowaudiosrc"
+#elif defined(OSTYPE_OS_X)
+#define DVVIDEOSRC "osxvideosrc"
+#define SYSVIDEOSRC "osxvideosrc"
+#define AUDIOSRC "osxaudiosrc"
+#elif defined(OSTYPE_LINUX)
+#define DVVIDEOSRC "dv1394src"
+#define SYSVIDEOSRC "gsettingsvideosrc"
+#define AUDIOSRC "gsettingsaudiosrc"
+#endif
 
 /**
  * Error:
@@ -104,3 +133,12 @@ typedef enum
   VIDEO_MUXER_MPEG_PS,
   VIDEO_MUXER_WEBM
 } VideoMuxerType;
+
+typedef enum
+{
+  CAPTURE_SOURCE_TYPE_NONE = 0,
+  CAPTURE_SOURCE_TYPE_DV = 1,
+  CAPTURE_SOURCE_TYPE_SYSTEM = 2,
+} CaptureSourceType;
+
+#endif
diff --git a/libcesarplayer/gst-camera-capturer.c b/libcesarplayer/gst-camera-capturer.c
new file mode 100644
index 0000000..e055d84
--- /dev/null
+++ b/libcesarplayer/gst-camera-capturer.c
@@ -0,0 +1,2111 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+* Gstreamer DV capturer
+* Copyright (C)  Andoni Morales Alastruey 2008 <ylatuya gmail com>
+* 
+* Gstreamer DV capturer is free software.
+* 
+* You may redistribute it and/or modify it under the terms of the
+* GNU General Public License, as published by the Free Software
+* Foundation; either version 2 of the License, or (at your option)
+* any later version.
+* 
+* Gstreamer DV is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU General Public License for more details.
+* 
+* You should have received a copy of the GNU General Public License
+* along with foob.  If not, write to:
+*       The Free Software Foundation, Inc.,
+*       51 Franklin Street, Fifth Floor
+*       Boston, MA  02110-1301, USA.
+*/
+
+#include <string.h>
+#include <stdio.h>
+
+#include <gst/app/gstappsrc.h>
+#include <gst/interfaces/xoverlay.h>
+#include <gst/interfaces/propertyprobe.h>
+#include <gst/gst.h>
+#include <gst/video/video.h>
+
+#include "gst-camera-capturer.h"
+#include "gstscreenshot.h"
+#include "common.h"
+#include "video-utils.h"
+
+
+/* gtk+/gnome */
+#include <gdk/gdk.h>
+#if defined (GDK_WINDOWING_X11)
+#include <gdk/gdkx.h>
+#elif defined (GDK_WINDOWING_WIN32)
+#include <gdk/gdkwin32.h>
+#elif defined (GDK_WINDOWING_QUARTZ)
+#include <gdk/gdkquartz.h>
+#endif
+#include <gtk/gtk.h>
+
+GST_DEBUG_CATEGORY (_cesarplayer_gst_debug_cat);
+#define GST_CAT_DEFAULT _cesarplayer_gst_debug_cat
+
+/* Signals */
+enum
+{
+  SIGNAL_ERROR,
+  SIGNAL_EOS,
+  SIGNAL_STATE_CHANGED,
+  SIGNAL_DEVICE_CHANGE,
+  LAST_SIGNAL
+};
+
+/* Properties */
+enum
+{
+  PROP_0,
+  PROP_OUTPUT_HEIGHT,
+  PROP_OUTPUT_WIDTH,
+  PROP_VIDEO_BITRATE,
+  PROP_AUDIO_BITRATE,
+  PROP_AUDIO_ENABLED,
+  PROP_OUTPUT_FILE,
+  PROP_DEVICE_ID,
+};
+
+struct GstCameraCapturerPrivate
+{
+
+  /*Encoding properties */
+  gchar *output_file;
+  gchar *device_id;
+  guint output_height;
+  guint output_width;
+  guint audio_bitrate;
+  guint video_bitrate;
+  gboolean audio_enabled;
+  VideoEncoderType video_encoder_type;
+  AudioEncoderType audio_encoder_type;
+  VideoMuxerType video_muxer_type;
+  CaptureSourceType source_type;
+
+  /*Video input info */
+  gint video_width;             /* Movie width */
+  gint video_height;            /* Movie height */
+  const GValue *movie_par;      /* Movie pixel aspect ratio */
+  gint video_width_pixels;      /* Scaled movie width */
+  gint video_height_pixels;     /* Scaled movie height */
+  gint video_fps_n;
+  gint video_fps_d;
+  gboolean media_has_video;
+  gboolean media_has_audio;
+
+  /* Snapshots */
+  GstBuffer *last_buffer;
+
+  /*GStreamer elements */
+  GstElement *main_pipeline;
+  GstElement *source_bin;
+  GstElement *source_decoder_bin;
+  GstElement *decoder_bin;
+  GstElement *preview_bin;
+  GstElement *encoder_bin;
+  GstElement *source;
+  GstElement *video_filter;
+  GstElement *video_enc;
+  GstElement *audio_enc;
+  GstElement *muxer;
+  GstElement *filesink;
+  GstElement* video_appsrc;
+  GstElement* audio_appsrc;
+  const gchar *source_element_name;
+
+  /* Recording */
+  gboolean is_recording;
+  gboolean closing_recording;
+  gboolean video_needs_keyframe_sync;
+  gboolean video_synced;
+  GstClockTime accum_recorded_ts;
+  GstClockTime last_accum_recorded_ts;
+  GstClockTime current_recording_start_ts;
+  GstClockTime last_video_buf_ts;
+  GstClockTime last_audio_buf_ts;
+  GMutex *recording_lock;
+
+  /*Overlay */
+  GstXOverlay *xoverlay;        /* protect with lock */
+  guintptr window_handle;
+
+  /*Videobox */
+  gboolean logo_mode;
+  GdkPixbuf *logo_pixbuf;
+  gboolean expand_logo;
+
+  /*GStreamer bus */
+  GstBus *bus;
+  gulong sig_bus_async;
+  gulong sig_bus_sync;
+};
+
+static GtkWidgetClass *parent_class = NULL;
+
+static GThread *gui_thread;
+
+static int gcc_signals[LAST_SIGNAL] = { 0 };
+
+static void gcc_error_msg (GstCameraCapturer * gcc, GstMessage * msg);
+static void gcc_bus_message_cb (GstBus * bus, GstMessage * message,
+    gpointer data);
+static void gst_camera_capturer_get_property (GObject * object,
+    guint property_id, GValue * value, GParamSpec * pspec);
+static void gst_camera_capturer_set_property (GObject * object,
+    guint property_id, const GValue * value, GParamSpec * pspec);
+static void gcc_element_msg_sync (GstBus * bus, GstMessage * msg,
+    gpointer data);
+static int gcc_get_video_stream_info (GstCameraCapturer * gcc);
+
+G_DEFINE_TYPE (GstCameraCapturer, gst_camera_capturer, GTK_TYPE_DRAWING_AREA);
+
+/***********************************
+*
+*           GTK Widget
+*
+************************************/
+
+static gboolean
+gst_camera_capturer_configure_event (GtkWidget * widget,
+    GdkEventConfigure * event, GstCameraCapturer * gcc)
+{
+  GstXOverlay *xoverlay = NULL;
+
+  g_return_val_if_fail (gcc != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_CAMERA_CAPTURER (gcc), FALSE);
+
+  xoverlay = gcc->priv->xoverlay;
+
+  if (xoverlay != NULL && GST_IS_X_OVERLAY (xoverlay)) {
+    gst_x_overlay_expose (xoverlay);
+  }
+
+  return FALSE;
+}
+
+static void
+gst_camera_capturer_realize_event (GtkWidget * widget)
+{
+  GstCameraCapturer *gcc = GST_CAMERA_CAPTURER (widget);
+  GdkWindow *window = gtk_widget_get_window (widget);
+
+  if (!gdk_window_ensure_native (window))
+    g_error ("Couldn't create native window needed for GstXOverlay!");
+
+  /* Connect to configure event on the top level window */
+  g_signal_connect (G_OBJECT (gtk_widget_get_toplevel (widget)),
+      "configure-event", G_CALLBACK (gst_camera_capturer_configure_event), gcc);
+
+  gcc->priv->window_handle = gst_get_window_handle (window);
+}
+
+static gboolean
+gst_camera_capturer_expose_event (GtkWidget * widget, GdkEventExpose * event)
+{
+  GstCameraCapturer *gcc = GST_CAMERA_CAPTURER (widget);
+  GstXOverlay *xoverlay;
+  gboolean draw_logo;
+  GdkWindow *win;
+
+  if (event && event->count > 0)
+    return TRUE;
+
+  if (event == NULL)
+    return TRUE;
+
+  xoverlay = gcc->priv->xoverlay;
+  if (xoverlay != NULL) {
+    gst_object_ref (xoverlay);
+    gst_set_window_handle (xoverlay, gcc->priv->window_handle);
+  }
+
+  win = gtk_widget_get_window (widget);
+
+  /* if there's only audio and no visualisation, draw the logo as well */
+  draw_logo = gcc->priv->media_has_audio && !gcc->priv->media_has_video;
+
+  if (gcc->priv->logo_mode || draw_logo) {
+    /* Start with a nice black canvas */
+    gdk_draw_rectangle (win, gtk_widget_get_style (widget)->black_gc, TRUE, 0,
+        0, widget->allocation.width, widget->allocation.height);
+
+    if (gcc->priv->logo_pixbuf != NULL) {
+      GdkPixbuf *frame;
+      /*GdkPixbuf *drawing;*/
+      guchar *pixels;
+      int rowstride;
+      gint width, height, alloc_width, alloc_height, logo_x, logo_y;
+      gfloat ratio;
+
+      /* Checking if allocated space is smaller than our logo */
+
+
+      width = gdk_pixbuf_get_width (gcc->priv->logo_pixbuf);
+      height = gdk_pixbuf_get_height (gcc->priv->logo_pixbuf);
+      alloc_width = widget->allocation.width;
+      alloc_height = widget->allocation.height;
+
+      if ((gfloat) alloc_width / width > (gfloat) alloc_height / height) {
+        ratio = (gfloat) alloc_height / height;
+      } else {
+        ratio = (gfloat) alloc_width / width;
+      }
+
+      width *= ratio;
+      height *= ratio;
+
+      logo_x = (alloc_width / 2) - (width / 2);
+      logo_y = (alloc_height / 2) - (height / 2);
+
+
+      /* Drawing our frame */
+
+      if (gcc->priv->expand_logo) { // && !gcc->priv->drawing_mode) {
+        /* Scaling to available space */
+
+        frame = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+            FALSE, 8, widget->allocation.width, widget->allocation.height);
+
+        gdk_pixbuf_composite (gcc->priv->logo_pixbuf,
+            frame,
+            0, 0,
+            alloc_width, alloc_height,
+            logo_x, logo_y, ratio, ratio, GDK_INTERP_BILINEAR, 255);
+
+        rowstride = gdk_pixbuf_get_rowstride (frame);
+
+        pixels = gdk_pixbuf_get_pixels (frame) +
+            rowstride * event->area.y + event->area.x * 3;
+
+        gdk_draw_rgb_image_dithalign (widget->window,
+            widget->style->black_gc,
+            event->area.x, event->area.y,
+            event->area.width,
+            event->area.height,
+            GDK_RGB_DITHER_NORMAL, pixels,
+            rowstride, event->area.x, event->area.y);
+
+        g_object_unref (frame);
+      } else {
+        if (width <= 1 || height <= 1) {
+          if (xoverlay != NULL)
+            gst_object_unref (xoverlay);
+          gdk_window_end_paint (win);
+          return TRUE;
+        }
+
+        frame = gdk_pixbuf_scale_simple (gcc->priv->logo_pixbuf,
+            width, height, GDK_INTERP_BILINEAR);
+        gdk_draw_pixbuf (win, gtk_widget_get_style (widget)->fg_gc[0],
+            frame, 0, 0, logo_x, logo_y, width, height,
+            GDK_RGB_DITHER_NONE, 0, 0);
+
+        /*if (gcc->priv->drawing_mode && bvw->priv->drawing_pixbuf != NULL) {*/
+          /*drawing =*/
+              /*gdk_pixbuf_scale_simple (gcc->priv->drawing_pixbuf, width,*/
+              /*height, GDK_INTERP_BILINEAR);*/
+          /*gdk_draw_pixbuf (win,*/
+              /*gtk_widget_get_style (widget)->fg_gc[0],*/
+              /*drawing, 0, 0, logo_x, logo_y, width,*/
+              /*height, GDK_RGB_DITHER_NONE, 0, 0);*/
+          /*g_object_unref (drawing);*/
+        /*}*/
+
+        g_object_unref (frame);
+      }
+    } else if (win) {
+      /* No pixbuf, just draw a black background then */
+      gdk_window_clear_area (win,
+          0, 0, widget->allocation.width, widget->allocation.height);
+    }
+  } else {
+    /* no logo, pass the expose to gst */
+    if (xoverlay != NULL && GST_IS_X_OVERLAY (xoverlay)){
+      gst_x_overlay_expose (xoverlay);
+    }
+    else {
+      /* No xoverlay to expose yet */
+      gdk_window_clear_area (win,
+          0, 0, widget->allocation.width, widget->allocation.height);
+    }
+  }
+  if (xoverlay != NULL)
+    gst_object_unref (xoverlay);
+
+  return TRUE;
+}
+
+/***********************************
+*
+*     Class, Object and Properties
+*
+************************************/
+
+static void
+gst_camera_capturer_init (GstCameraCapturer * object)
+{
+  GstCameraCapturerPrivate *priv;
+  object->priv = priv =
+      G_TYPE_INSTANCE_GET_PRIVATE (object, GST_TYPE_CAMERA_CAPTURER,
+      GstCameraCapturerPrivate);
+
+  GTK_WIDGET_SET_FLAGS (GTK_WIDGET (object), GTK_CAN_FOCUS);
+  GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (object), GTK_DOUBLE_BUFFERED);
+
+  priv->output_height = 480;
+  priv->output_width = 640;
+  priv->audio_bitrate = 128;
+  priv->video_bitrate = 5000;
+  priv->last_buffer = NULL;
+  priv->expand_logo = TRUE;
+  priv->current_recording_start_ts = GST_CLOCK_TIME_NONE;
+  priv->accum_recorded_ts = GST_CLOCK_TIME_NONE;
+  priv->last_accum_recorded_ts = GST_CLOCK_TIME_NONE;
+  priv->last_video_buf_ts = GST_CLOCK_TIME_NONE;
+  priv->last_audio_buf_ts = GST_CLOCK_TIME_NONE;
+  priv->is_recording = FALSE;
+  priv->recording_lock = g_mutex_new();
+
+  priv->video_encoder_type = VIDEO_ENCODER_VP8;
+  priv->audio_encoder_type = AUDIO_ENCODER_VORBIS;
+  priv->video_muxer_type = VIDEO_MUXER_WEBM;
+  priv->source_type = CAPTURE_SOURCE_TYPE_SYSTEM;
+
+  gtk_widget_add_events (GTK_WIDGET (object),
+      GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
+      | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
+
+  g_signal_connect (GTK_WIDGET (object), "realize",
+      G_CALLBACK (gst_camera_capturer_realize_event), NULL);
+}
+
+void
+gst_camera_capturer_finalize (GObject * object)
+{
+  GstCameraCapturer *gcc = (GstCameraCapturer *) object;
+
+  GST_DEBUG_OBJECT (gcc, "Finalizing.");
+  if (gcc->priv->bus) {
+    /* make bus drop all messages to make sure none of our callbacks is ever
+     * called again (main loop might be run again to display error dialog) */
+    gst_bus_set_flushing (gcc->priv->bus, TRUE);
+
+    if (gcc->priv->sig_bus_async)
+      g_signal_handler_disconnect (gcc->priv->bus, gcc->priv->sig_bus_async);
+
+    if (gcc->priv->sig_bus_sync)
+      g_signal_handler_disconnect (gcc->priv->bus, gcc->priv->sig_bus_sync);
+
+    gst_object_unref (gcc->priv->bus);
+    gcc->priv->bus = NULL;
+  }
+
+  if (gcc->priv->output_file) {
+    g_free (gcc->priv->output_file);
+    gcc->priv->output_file = NULL;
+  }
+
+  if (gcc->priv->device_id) {
+    g_free (gcc->priv->device_id);
+    gcc->priv->device_id = NULL;
+  }
+
+  if (gcc->priv->logo_pixbuf) {
+    g_object_unref (gcc->priv->logo_pixbuf);
+    gcc->priv->logo_pixbuf = NULL;
+  }
+
+  if (gcc->priv->last_buffer != NULL)
+    gst_buffer_unref (gcc->priv->last_buffer);
+
+  if (gcc->priv->main_pipeline != NULL
+      && GST_IS_ELEMENT (gcc->priv->main_pipeline)) {
+    gst_element_set_state (gcc->priv->main_pipeline, GST_STATE_NULL);
+    gst_object_unref (gcc->priv->main_pipeline);
+    gcc->priv->main_pipeline = NULL;
+  }
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_camera_capturer_set_video_bit_rate (GstCameraCapturer * gcc, gint bitrate)
+{
+  gcc->priv->video_bitrate = bitrate;
+  GST_INFO_OBJECT (gcc, "Changed video bitrate to: %d",
+      gcc->priv->video_bitrate);
+}
+
+static void
+gst_camera_capturer_set_audio_bit_rate (GstCameraCapturer * gcc, gint bitrate)
+{
+
+  gcc->priv->audio_bitrate = bitrate;
+  GST_INFO_OBJECT (gcc, "Changed audio bitrate to: %d",
+      gcc->priv->audio_bitrate);
+}
+
+static void
+gst_camera_capturer_set_audio_enabled (GstCameraCapturer * gcc,
+    gboolean enabled)
+{
+  gcc->priv->audio_enabled = enabled;
+  GST_INFO_OBJECT (gcc, "Audio is %s", enabled ? "enabled": "disabled");
+}
+
+static void
+gst_camera_capturer_set_output_file (GstCameraCapturer * gcc,
+    const gchar * file)
+{
+  gcc->priv->output_file = g_strdup (file);
+  GST_INFO_OBJECT (gcc, "Changed output filename to: %s", file);
+}
+
+static void
+gst_camera_capturer_set_device_id (GstCameraCapturer * gcc,
+    const gchar * device_id)
+{
+  gcc->priv->device_id = g_strdup (device_id);
+  GST_INFO_OBJECT (gcc, "Changed device id/name to: %s", gcc->priv->device_id);
+}
+
+static void
+gst_camera_capturer_set_property (GObject * object, guint property_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstCameraCapturer *gcc;
+
+  gcc = GST_CAMERA_CAPTURER (object);
+
+  switch (property_id) {
+    case PROP_OUTPUT_HEIGHT:
+      gcc->priv->output_height = g_value_get_uint (value);
+      break;
+    case PROP_OUTPUT_WIDTH:
+      gcc->priv->output_width = g_value_get_uint (value);
+      break;
+    case PROP_VIDEO_BITRATE:
+      gst_camera_capturer_set_video_bit_rate (gcc, g_value_get_uint (value));
+      break;
+    case PROP_AUDIO_BITRATE:
+      gst_camera_capturer_set_audio_bit_rate (gcc, g_value_get_uint (value));
+      break;
+    case PROP_AUDIO_ENABLED:
+      gst_camera_capturer_set_audio_enabled (gcc, g_value_get_boolean (value));
+      break;
+    case PROP_OUTPUT_FILE:
+      gst_camera_capturer_set_output_file (gcc, g_value_get_string (value));
+      break;
+    case PROP_DEVICE_ID:
+      gst_camera_capturer_set_device_id (gcc, g_value_get_string (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_camera_capturer_get_property (GObject * object, guint property_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstCameraCapturer *gcc;
+
+  gcc = GST_CAMERA_CAPTURER (object);
+
+  switch (property_id) {
+    case PROP_OUTPUT_HEIGHT:
+      g_value_set_uint (value, gcc->priv->output_height);
+      break;
+    case PROP_OUTPUT_WIDTH:
+      g_value_set_uint (value, gcc->priv->output_width);
+      break;
+    case PROP_AUDIO_BITRATE:
+      g_value_set_uint (value, gcc->priv->audio_bitrate);
+      break;
+    case PROP_VIDEO_BITRATE:
+      g_value_set_uint (value, gcc->priv->video_bitrate);
+      break;
+    case PROP_AUDIO_ENABLED:
+      g_value_set_boolean (value, gcc->priv->audio_enabled);
+      break;
+    case PROP_OUTPUT_FILE:
+      g_value_set_string (value, gcc->priv->output_file);
+      break;
+    case PROP_DEVICE_ID:
+      g_value_set_string (value, gcc->priv->device_id);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_camera_capturer_class_init (GstCameraCapturerClass * klass)
+{
+  GObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+
+  object_class = (GObjectClass *) klass;
+  widget_class = (GtkWidgetClass *) klass;
+  parent_class = g_type_class_peek_parent (klass);
+
+  g_type_class_add_private (object_class, sizeof (GstCameraCapturerPrivate));
+
+  /* GtkWidget */
+  widget_class->expose_event = gst_camera_capturer_expose_event;
+
+  /* GObject */
+  object_class->set_property = gst_camera_capturer_set_property;
+  object_class->get_property = gst_camera_capturer_get_property;
+  object_class->finalize = gst_camera_capturer_finalize;
+
+  /* Properties */
+  g_object_class_install_property (object_class, PROP_OUTPUT_HEIGHT,
+      g_param_spec_uint ("output_height", NULL,
+          NULL, 0, 5600, 576, G_PARAM_READWRITE));
+  g_object_class_install_property (object_class, PROP_OUTPUT_WIDTH,
+      g_param_spec_uint ("output_width", NULL,
+          NULL, 0, 5600, 720, G_PARAM_READWRITE));
+  g_object_class_install_property (object_class, PROP_VIDEO_BITRATE,
+      g_param_spec_uint ("video_bitrate", NULL,
+          NULL, 100, G_MAXUINT, 1000, G_PARAM_READWRITE));
+  g_object_class_install_property (object_class, PROP_AUDIO_BITRATE,
+      g_param_spec_uint ("audio_bitrate", NULL,
+          NULL, 12, G_MAXUINT, 128, G_PARAM_READWRITE));
+  g_object_class_install_property (object_class, PROP_AUDIO_ENABLED,
+      g_param_spec_boolean ("audio_enabled", NULL,
+          NULL, FALSE, G_PARAM_READWRITE));
+  g_object_class_install_property (object_class, PROP_OUTPUT_FILE,
+      g_param_spec_string ("output_file", NULL,
+          NULL, FALSE, G_PARAM_READWRITE));
+  g_object_class_install_property (object_class, PROP_DEVICE_ID,
+      g_param_spec_string ("device_id", NULL, NULL, FALSE, G_PARAM_READWRITE));
+
+  /* Signals */
+  gcc_signals[SIGNAL_ERROR] =
+      g_signal_new ("error",
+      G_TYPE_FROM_CLASS (object_class),
+      G_SIGNAL_RUN_LAST,
+      G_STRUCT_OFFSET (GstCameraCapturerClass, error),
+      NULL, NULL,
+      g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
+
+  gcc_signals[SIGNAL_EOS] =
+      g_signal_new ("eos",
+      G_TYPE_FROM_CLASS (object_class),
+      G_SIGNAL_RUN_LAST,
+      G_STRUCT_OFFSET (GstCameraCapturerClass, eos),
+      NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+  gcc_signals[SIGNAL_DEVICE_CHANGE] =
+      g_signal_new ("device-change",
+      G_TYPE_FROM_CLASS (object_class),
+      G_SIGNAL_RUN_LAST,
+      G_STRUCT_OFFSET (GstCameraCapturerClass, device_change),
+      NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+}
+
+/***********************************
+*
+*           GStreamer
+*
+************************************/
+
+void
+gst_camera_capturer_init_backend (int *argc, char ***argv)
+{
+  gst_init (argc, argv);
+}
+
+GQuark
+gst_camera_capturer_error_quark (void)
+{
+  static GQuark q;              /* 0 */
+
+  if (G_UNLIKELY (q == 0)) {
+    q = g_quark_from_static_string ("gcc-error-quark");
+  }
+  return q;
+}
+
+gboolean
+gst_camera_capture_videosrc_buffer_probe (GstPad * pad, GstBuffer * buf,
+    gpointer data)
+{
+  GstCameraCapturer *gcc = GST_CAMERA_CAPTURER (data);
+
+  if (gcc->priv->last_buffer) {
+    gst_buffer_unref (gcc->priv->last_buffer);
+    gcc->priv->last_buffer = NULL;
+  }
+
+  gst_buffer_ref (buf);
+  gcc->priv->last_buffer = buf;
+
+  return TRUE;
+}
+
+static void
+gst_camera_capturer_update_device_id (GstCameraCapturer *gcc)
+{
+  const gchar *prop_name;
+
+  if (!g_strcmp0 (gcc->priv->source_element_name, "dv1394src"))
+    prop_name = "guid";
+  else if (!g_strcmp0 (gcc->priv->source_element_name, "v4l2src"))
+    prop_name = "device";
+  else if (!g_strcmp0 (gcc->priv->source_element_name, "gsettingsvideosrc"))
+    prop_name = NULL;
+  else
+    prop_name = "device-name";
+
+  if (prop_name)
+    g_object_set(gcc->priv->source, prop_name, gcc->priv->device_id, NULL);
+}
+
+static void
+cb_new_pad (GstElement * element, GstPad * pad, GstCameraCapturer *gcc)
+{
+  GstCaps *caps;
+  const gchar *mime;
+  GstElement *sink = NULL;
+  GstPad *epad;
+  GstBin *bin = GST_BIN(gcc->priv->source_decoder_bin);
+
+  caps = gst_pad_get_caps_reffed (pad);
+  mime = gst_structure_get_name (gst_caps_get_structure (caps, 0));
+  if (g_strrstr (mime, "video")) {
+    sink = gst_bin_get_by_name (bin, "video-pad");
+  }
+  if (g_strrstr (mime, "audio") && gcc->priv->audio_enabled) {
+    sink = gst_bin_get_by_name (bin, "audio-pad");
+  }
+
+  if (sink != NULL) {
+    epad = gst_element_get_static_pad(sink, "sink");
+    gst_pad_link (pad, epad);
+    gst_object_unref(epad);
+    gst_object_unref (sink);
+  }
+  gst_caps_unref(caps);
+}
+
+static void
+gst_camera_capturer_create_encoder_bin (GstCameraCapturer *gcc)
+{
+  GstElement *colorspace, *videoscale;
+  GstCaps *caps;
+  GstPad *v_sink_pad;
+  gchar *caps_str;
+
+  GST_INFO_OBJECT (gcc, "Creating encoder bin");
+  gcc->priv->encoder_bin = gst_bin_new ("encoder_bin");
+
+  colorspace = gst_element_factory_make("ffmpegcolorspace", NULL);
+  videoscale = gst_element_factory_make("videoscale", NULL);
+  gcc->priv->video_filter = gst_element_factory_make("capsfilter", NULL);
+  gcc->priv->filesink = gst_element_factory_make("filesink", NULL);
+
+  /* Set caps for the encoding resolution */
+  if (gcc->priv->output_width != 0 && gcc->priv->output_height != 0) {
+    caps_str = g_strdup_printf("video/x-raw-yuv, width=%d, height=%d",
+        gcc->priv->output_width, gcc->priv->output_height);
+    caps = gst_caps_from_string(caps_str);
+    g_object_set(gcc->priv->video_filter, "caps", caps, NULL);
+    gst_caps_unref(caps);
+    g_free(caps_str);
+  }
+
+  gst_bin_add_many(GST_BIN(gcc->priv->encoder_bin), videoscale,
+      colorspace, gcc->priv->video_filter, gcc->priv->video_enc,
+      gcc->priv->muxer, gcc->priv->filesink, NULL);
+
+  gst_element_link_many(videoscale, colorspace, gcc->priv->video_filter,
+      gcc->priv->video_enc, gcc->priv->muxer, NULL);
+  gst_element_link(gcc->priv->muxer, gcc->priv->filesink);
+
+  g_object_set (gcc->priv->filesink, "location", gcc->priv->output_file, NULL);
+
+  /* Create ghost pads */
+  v_sink_pad = gst_element_get_static_pad (videoscale, "sink");
+  gst_element_add_pad (gcc->priv->encoder_bin, gst_ghost_pad_new ("video", v_sink_pad));
+  gst_object_unref (GST_OBJECT (v_sink_pad));
+
+  if (gcc->priv->audio_enabled)
+  {
+    GstElement *audioconvert, *audioresample;
+    GstPad *a_sink_pad;
+
+    audioconvert = gst_element_factory_make("audioconvert", NULL);
+    audioresample = gst_element_factory_make("audioresample", NULL);
+
+    gst_bin_add_many(GST_BIN(gcc->priv->encoder_bin), audioconvert, audioresample,
+        audioresample, gcc->priv->audio_enc, NULL);
+
+    gst_element_link_many(audioconvert, audioresample, gcc->priv->audio_enc,
+        gcc->priv->muxer, NULL);
+
+    a_sink_pad = gst_element_get_static_pad (audioconvert, "sink");
+    gst_element_add_pad (gcc->priv->encoder_bin, gst_ghost_pad_new ("audio", a_sink_pad));
+    gst_object_unref (GST_OBJECT (a_sink_pad));
+  }
+
+  GST_INFO_OBJECT (gcc, "Encoder bin created successfully");
+}
+
+static void
+gst_camera_capturer_create_remuxer_bin (GstCameraCapturer *gcc)
+{
+  GstElement *muxer;
+  GstPad *v_sink_pad;
+
+  GST_INFO_OBJECT (gcc, "Creating remuxer bin");
+  gcc->priv->encoder_bin = gst_bin_new ("encoder_bin");
+  muxer = gst_element_factory_make("qtmux", NULL);
+  gcc->priv->filesink = gst_element_factory_make("filesink", NULL);
+  g_object_set (gcc->priv->filesink, "location", gcc->priv->output_file, NULL);
+
+  gst_bin_add_many(GST_BIN(gcc->priv->encoder_bin), muxer, gcc->priv->filesink, NULL);
+  gst_element_link(muxer, gcc->priv->filesink);
+
+  /* Create ghost pads */
+  v_sink_pad = gst_element_get_request_pad (muxer, "video_%d");
+  gst_element_add_pad (gcc->priv->encoder_bin, gst_ghost_pad_new ("video", v_sink_pad));
+  gst_object_unref (v_sink_pad);
+
+  if (gcc->priv->audio_enabled) {
+    GstPad *a_sink_pad;
+
+    /* Create ghost pads */
+    a_sink_pad = gst_element_get_request_pad (muxer, "audio_%d");
+    gst_element_add_pad (gcc->priv->encoder_bin, gst_ghost_pad_new ("audio", a_sink_pad));
+    gst_object_unref (GST_OBJECT (v_sink_pad));
+  }
+}
+
+static GstElement *
+gst_camera_capturer_prepare_raw_source (GstCameraCapturer *gcc)
+{
+  GstElement *bin, *v_identity;
+  GstPad *video_pad, *src_pad;
+
+  GST_INFO_OBJECT (gcc, "Creating raw source");
+
+  gcc->priv->video_needs_keyframe_sync = FALSE;
+
+  gcc->priv->source_decoder_bin = gst_bin_new ("decoder");
+  bin = gcc->priv->source_decoder_bin;
+  v_identity = gst_element_factory_make ("identity", NULL);
+
+  gst_bin_add_many (GST_BIN (bin), v_identity, NULL);
+
+  /* add ghostpad */
+  video_pad = gst_element_get_static_pad (v_identity, "src");
+  gst_element_add_pad (bin, gst_ghost_pad_new ("video", video_pad));
+  gst_object_unref (GST_OBJECT (video_pad));
+  src_pad = gst_element_get_static_pad (v_identity, "sink");
+  gst_element_add_pad (bin, gst_ghost_pad_new ("sink", src_pad));
+  gst_object_unref (GST_OBJECT (src_pad));
+
+  gst_camera_capturer_create_encoder_bin(gcc);
+
+  return bin;
+}
+
+static GstElement *
+gst_camera_capturer_prepare_dv_source (GstCameraCapturer *gcc)
+{
+  GstElement *bin, *decodebin, *deinterlacer;
+  GstPad *video_pad, *src_pad;
+
+  GST_INFO_OBJECT (gcc, "Creating dv source");
+
+  gcc->priv->video_needs_keyframe_sync = FALSE;
+
+  gcc->priv->source_decoder_bin = gst_bin_new ("decoder");
+  bin = gcc->priv->source_decoder_bin;
+  decodebin = gst_element_factory_make ("decodebin2", NULL);
+  deinterlacer = gst_element_factory_make ("ffdeinterlace", "video-pad");
+
+  gst_bin_add_many (GST_BIN (bin), decodebin, deinterlacer, NULL);
+
+  /* add ghostpad */
+  video_pad = gst_element_get_static_pad (deinterlacer, "src");
+  gst_element_add_pad (bin, gst_ghost_pad_new ("video", video_pad));
+  gst_object_unref (GST_OBJECT (video_pad));
+  src_pad = gst_element_get_static_pad (decodebin, "sink");
+  gst_element_add_pad (bin, gst_ghost_pad_new ("sink", src_pad));
+  gst_object_unref (GST_OBJECT (src_pad));
+
+  if (gcc->priv->audio_enabled) {
+    GstElement *audio;
+    GstPad *audio_pad;
+
+    audio = gst_element_factory_make ("identity", "audio-pad");
+
+    gst_bin_add_many (GST_BIN (bin), audio, NULL);
+
+    /* add ghostpad */
+    audio_pad = gst_element_get_static_pad (audio, "src");
+    gst_element_add_pad (bin, gst_ghost_pad_new ("audio", audio_pad));
+    gst_object_unref (GST_OBJECT (audio_pad));
+  }
+
+  g_signal_connect (decodebin, "pad-added", G_CALLBACK (cb_new_pad), gcc);
+
+  gst_camera_capturer_create_encoder_bin(gcc);
+
+  return bin;
+}
+
+static GstElement *
+gst_camera_capturer_prepare_mpegts_source (GstCameraCapturer *gcc)
+{
+  GstElement *bin, *demuxer,  *video, *video_parser;
+  GstPad *video_pad, *src_pad;
+
+  GST_INFO_OBJECT (gcc, "Creating mpegts source");
+
+  gcc->priv->video_needs_keyframe_sync = TRUE;
+  gcc->priv->video_synced = FALSE;
+
+  /* We don't want to reencode, only remux */
+  gcc->priv->source_decoder_bin = gst_bin_new ("decoder");
+  bin = gcc->priv->source_decoder_bin;
+  demuxer = gst_element_factory_make ("mpegtsdemux", NULL);
+  video_parser = gst_element_factory_make ("h264parse", "video-pad");
+  video = gst_element_factory_make ("capsfilter", NULL);
+  g_object_set(video, "caps", gst_caps_from_string("video/x-h264, stream-format=avc, alignment=au"), NULL);
+
+  gst_bin_add_many (GST_BIN (bin), demuxer, video_parser, video, NULL);
+  gst_element_link(video_parser, video);
+
+  /* add ghostpad */
+  video_pad = gst_element_get_static_pad (video, "src");
+  gst_element_add_pad (bin, gst_ghost_pad_new ("video", video_pad));
+  gst_object_unref (GST_OBJECT (video_pad));
+  src_pad = gst_element_get_static_pad (demuxer, "sink");
+  gst_element_add_pad (bin, gst_ghost_pad_new ("sink", src_pad));
+  gst_object_unref (GST_OBJECT (src_pad));
+
+  if (gcc->priv->audio_enabled) {
+    GstElement *audio;
+    GstPad *audio_pad;
+
+    audio = gst_element_factory_make ("identity", "audio-pad");
+
+    gst_bin_add_many (GST_BIN (bin), audio, NULL);
+
+    /* add ghostpad */
+    audio_pad = gst_element_get_static_pad (audio, "src");
+    gst_element_add_pad (bin, gst_ghost_pad_new ("audio", audio_pad));
+    gst_object_unref (GST_OBJECT (audio_pad));
+  }
+
+  g_signal_connect (demuxer, "pad-added", G_CALLBACK (cb_new_pad), gcc);
+
+  gst_camera_capturer_create_remuxer_bin(gcc);
+
+  return bin;
+}
+
+static gboolean
+gst_camera_capturer_encoding_retimestamper (GstCameraCapturer *gcc,
+    GstBuffer *prev_buf, gboolean is_video)
+{
+  GstClockTime buf_ts, new_buf_ts, duration;
+  GstBuffer *enc_buf;
+
+  g_mutex_lock(gcc->priv->recording_lock);
+
+  if (!gcc->priv->is_recording) {
+    /* Drop buffers if we are not recording */
+    GST_LOG_OBJECT (gcc, "Dropping buffer on %s pad", is_video ? "video": "audio");
+    goto done;
+  }
+
+  /* If we are just remuxing, drop everything until we see a keyframe */
+  if (gcc->priv->video_needs_keyframe_sync && !gcc->priv->video_synced) {
+    if (is_video && !GST_BUFFER_FLAG_IS_SET(prev_buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
+      gcc->priv->video_synced = TRUE;
+    } else {
+      GST_LOG_OBJECT (gcc, "Waiting for a keyframe, "
+          "dropping buffer on %s pad", is_video ? "video": "audio");
+      goto done;
+    }
+  }
+
+  enc_buf = gst_buffer_create_sub (prev_buf, 0, GST_BUFFER_SIZE(prev_buf));
+  buf_ts = GST_BUFFER_TIMESTAMP (prev_buf);
+  duration = GST_BUFFER_DURATION (prev_buf);
+  if (duration == GST_CLOCK_TIME_NONE)
+    duration = 0;
+
+  /* Check if it's the first buffer after starting or restarting the capture
+   * and update the timestamps accordingly */
+  if (G_UNLIKELY(gcc->priv->current_recording_start_ts == GST_CLOCK_TIME_NONE)) {
+    gcc->priv->current_recording_start_ts = buf_ts;
+    gcc->priv->last_accum_recorded_ts = gcc->priv->accum_recorded_ts;
+    GST_INFO_OBJECT (gcc, "Starting recording at %" GST_TIME_FORMAT,
+        GST_TIME_ARGS(gcc->priv->last_accum_recorded_ts));
+  }
+
+  /* Clip buffers that are not in the segment */
+  if (buf_ts < gcc->priv->current_recording_start_ts) {
+    GST_WARNING_OBJECT (gcc, "Discarding buffer out of segment");
+    goto done;
+  }
+
+  if (buf_ts != GST_CLOCK_TIME_NONE) {
+    /* Get the buffer timestamp with respect of the encoding time and not
+     * the playing time for a continous stream in the encoders input */
+    new_buf_ts = buf_ts - gcc->priv->current_recording_start_ts + gcc->priv->last_accum_recorded_ts;
+
+    /* Store the last timestamp seen on this pad */
+    if (is_video)
+      gcc->priv->last_video_buf_ts = new_buf_ts;
+    else
+      gcc->priv->last_audio_buf_ts = new_buf_ts;
+
+    /* Update the highest encoded timestamp */
+    if (new_buf_ts + duration > gcc->priv->accum_recorded_ts)
+      gcc->priv->accum_recorded_ts = new_buf_ts + duration;
+  } else {
+    /* h264parse only sets the timestamp on the first buffer if a frame is
+     * split in several ones. Other parsers might do the same. We only set
+     * the last timestamp seen on the pad */
+    if (is_video)
+      new_buf_ts = gcc->priv->last_video_buf_ts;
+    else
+      new_buf_ts = gcc->priv->last_audio_buf_ts;
+  }
+
+  GST_BUFFER_TIMESTAMP (enc_buf) = new_buf_ts;
+
+  GST_LOG_OBJECT(gcc, "Pushing %s frame to the encoder in ts:% " GST_TIME_FORMAT
+      " out ts: %" GST_TIME_FORMAT, is_video ? "video": "audio",
+      GST_TIME_ARGS(buf_ts), GST_TIME_ARGS(new_buf_ts));
+
+  if (is_video)
+    gst_app_src_push_buffer(GST_APP_SRC(gcc->priv->video_appsrc), enc_buf);
+  else
+    gst_app_src_push_buffer(GST_APP_SRC(gcc->priv->audio_appsrc), enc_buf);
+
+done:
+  {
+    g_mutex_unlock(gcc->priv->recording_lock);
+    return TRUE;
+  }
+}
+
+static gboolean
+gst_camera_capturer_audio_encoding_probe (GstPad *pad, GstBuffer *buf,
+    GstCameraCapturer *gcc)
+{
+  return gst_camera_capturer_encoding_retimestamper(gcc, buf, FALSE);
+}
+
+static gboolean
+gst_camera_capturer_video_encoding_probe (GstPad *pad, GstBuffer *buf,
+    GstCameraCapturer *gcc)
+{
+  return gst_camera_capturer_encoding_retimestamper(gcc, buf, TRUE);
+}
+
+static void
+gst_camera_capturer_create_decoder_bin (GstCameraCapturer *gcc, GstElement *decoder_bin)
+{
+  /*    decoder --> video_preview_queue
+   *            |
+   *            --> audio_preview_queue
+   *
+   *            video_appsrc   --> video_queue
+   *            audio_appsrc   --> audio_queue
+   */
+
+  GstElement *v_queue, *v_prev_queue;
+  GstPad *v_dec_pad, *v_queue_pad, *v_prev_queue_pad;
+  GstPad *dec_sink_pad;
+
+  GST_INFO_OBJECT(gcc, "Creating decoder bin");
+  /* Create elements */
+  gcc->priv->decoder_bin = gst_bin_new("decoder_bin");
+  v_queue = gst_element_factory_make("queue2", "video-queue");
+  gcc->priv->video_appsrc = gst_element_factory_make("appsrc", "video-appsrc");
+  v_prev_queue = gst_element_factory_make("queue2", "video-preview-queue");
+
+  g_object_set(v_queue, "max-size-time", 1 * GST_SECOND, NULL);
+  g_object_set(v_prev_queue, "max-size-bytes", 0,  NULL);
+
+  gst_bin_add_many(GST_BIN(gcc->priv->decoder_bin), decoder_bin, v_queue,
+      gcc->priv->video_appsrc, v_prev_queue, NULL);
+
+  /* link decoder to the preview-queue */
+  v_dec_pad = gst_element_get_static_pad(decoder_bin, "video");
+  v_prev_queue_pad = gst_element_get_static_pad(v_prev_queue, "sink");
+  gst_pad_link(v_dec_pad, v_prev_queue_pad);
+  gst_object_unref(v_dec_pad);
+  gst_object_unref(v_prev_queue_pad);
+
+  /* Link appsrc */
+  gst_element_link (gcc->priv->video_appsrc, v_queue);
+
+  /* Create ghost pads */
+  v_queue_pad = gst_element_get_static_pad(v_queue, "src");
+  v_prev_queue_pad = gst_element_get_static_pad(v_prev_queue, "src");
+  dec_sink_pad = gst_element_get_static_pad(decoder_bin, "sink");
+  gst_element_add_pad (gcc->priv->decoder_bin, gst_ghost_pad_new ("video", v_queue_pad));
+  gst_element_add_pad (gcc->priv->decoder_bin, gst_ghost_pad_new ("video_preview", v_prev_queue_pad));
+  gst_element_add_pad (gcc->priv->decoder_bin, gst_ghost_pad_new ("sink", dec_sink_pad));
+  gst_object_unref(v_queue_pad);
+  gst_object_unref(v_prev_queue_pad);
+  gst_object_unref(dec_sink_pad);
+
+  /* Add pad probes for the encoding branch */
+  v_prev_queue_pad = gst_element_get_static_pad(v_prev_queue, "src");
+  gst_pad_add_buffer_probe(v_prev_queue_pad, (GCallback) gst_camera_capturer_video_encoding_probe, gcc);
+  gst_object_unref(v_prev_queue_pad);
+
+  if (gcc->priv->audio_enabled) {
+    GstElement *a_queue, *a_prev_queue;
+    GstPad *a_dec_pad, *a_queue_pad, *a_prev_queue_pad;
+
+    /* Create elements */
+    gcc->priv->audio_appsrc = gst_element_factory_make("appsrc", "video-appsrc");
+    a_queue = gst_element_factory_make("queue2", "audio-queue");
+    a_prev_queue = gst_element_factory_make("queue2", "audio-preview-queue");
+
+    g_object_set(a_queue, "max-size-time", 1 * GST_SECOND,  NULL);
+
+    gst_bin_add_many(GST_BIN(gcc->priv->decoder_bin), gcc->priv->audio_appsrc, a_queue,
+        a_prev_queue, NULL);
+
+    /* Link appsrc to the queue */
+    gst_element_link(gcc->priv->audio_appsrc, a_queue);
+
+    /* link decoder to the queue */
+    a_dec_pad = gst_element_get_static_pad(decoder_bin, "audio");
+    a_prev_queue_pad = gst_element_get_static_pad(a_prev_queue, "sink");
+    gst_pad_link(a_dec_pad, a_prev_queue_pad);
+    gst_object_unref(a_dec_pad);
+    gst_object_unref(a_prev_queue_pad);
+
+    /* Create ghost pads */
+    a_queue_pad = gst_element_get_static_pad(a_queue, "src");
+    a_prev_queue_pad = gst_element_get_static_pad(a_prev_queue, "src");
+    gst_element_add_pad (gcc->priv->decoder_bin, gst_ghost_pad_new ("audio", a_queue_pad));
+    gst_element_add_pad (gcc->priv->decoder_bin, gst_ghost_pad_new ("audio_preview", a_prev_queue_pad));
+    gst_object_unref(a_queue_pad);
+    gst_object_unref(a_prev_queue_pad);
+
+    /* Add pad probes for the encoding branch */
+    a_prev_queue_pad = gst_element_get_static_pad(a_prev_queue, "src");
+    gst_pad_add_buffer_probe(a_prev_queue_pad, (GCallback) gst_camera_capturer_audio_encoding_probe, gcc);
+    gst_object_unref(a_prev_queue_pad);
+  }
+}
+
+static void
+gst_camera_capturer_link_encoder_bin (GstCameraCapturer *gcc)
+{
+  GstPad *v_dec_pad, *v_enc_pad;
+
+  GST_INFO_OBJECT(gcc, "Linking encoder bin");
+
+  gst_bin_add(GST_BIN(gcc->priv->main_pipeline), gcc->priv->encoder_bin);
+
+  v_dec_pad = gst_element_get_static_pad(gcc->priv->decoder_bin, "video");
+  v_enc_pad = gst_element_get_static_pad(gcc->priv->encoder_bin, "video");
+  gst_pad_link(v_dec_pad, v_enc_pad);
+  gst_object_unref(v_dec_pad);
+  gst_object_unref(v_enc_pad);
+
+  if (gcc->priv->audio_enabled) {
+    GstPad *a_dec_pad, *a_enc_pad;
+
+    a_dec_pad = gst_element_get_static_pad(gcc->priv->decoder_bin, "audio");
+    a_enc_pad = gst_element_get_static_pad(gcc->priv->encoder_bin, "audio");
+    gst_pad_link(a_dec_pad, a_enc_pad);
+    gst_object_unref(a_dec_pad);
+    gst_object_unref(a_enc_pad);
+  }
+
+  gst_element_set_state(gcc->priv->encoder_bin, GST_STATE_PLAYING);
+}
+
+static void
+gst_camera_capturer_link_preview (GstCameraCapturer *gcc)
+{
+  GstPad *v_dec_prev_pad, *v_prev_pad;
+
+  GST_INFO_OBJECT(gcc, "Linking preview bin");
+
+  gst_bin_add(GST_BIN(gcc->priv->main_pipeline), gcc->priv->decoder_bin);
+
+  gst_element_link(gcc->priv->source_bin, gcc->priv->decoder_bin);
+
+  v_dec_prev_pad = gst_element_get_static_pad(gcc->priv->decoder_bin, "video_preview");
+  v_prev_pad = gst_element_get_static_pad(gcc->priv->preview_bin, "video");
+
+  gst_pad_link(v_dec_prev_pad, v_prev_pad);
+
+  gst_object_unref(v_dec_prev_pad);
+  gst_object_unref(v_prev_pad);
+
+  if (gcc->priv->audio_enabled) {
+    GstPad *a_dec_prev_pad, *a_prev_pad;
+
+    a_dec_prev_pad = gst_element_get_static_pad(gcc->priv->decoder_bin, "audio_preview");
+    a_prev_pad = gst_element_get_static_pad(gcc->priv->preview_bin, "audio");
+
+    gst_pad_link(a_dec_prev_pad, a_prev_pad);
+
+    gst_object_unref(a_dec_prev_pad);
+    gst_object_unref(a_prev_pad);
+  }
+  gst_element_set_state(gcc->priv->decoder_bin, GST_STATE_PLAYING);
+}
+
+static gboolean
+cb_last_buffer (GstPad *pad, GstBuffer *buf, GstCameraCapturer *gcc){
+  if (buf != NULL) {
+    if (gcc->priv->last_buffer != NULL)
+      gst_buffer_unref(buf);
+    gst_buffer_ref(buf);
+    gcc->priv->last_buffer = buf;
+  }
+  return TRUE;
+}
+
+static void
+cb_new_prev_pad (GstElement * element, GstPad * pad, GstElement *bin)
+{
+  GstPad *sink_pad;
+
+  sink_pad = gst_element_get_static_pad(bin, "sink");
+  gst_pad_link(pad, sink_pad);
+  gst_object_unref(sink_pad);
+}
+
+static void
+gst_camera_capturer_create_preview(GstCameraCapturer *gcc)
+{
+  GstElement *v_decoder, *video_bin;
+  GstPad *video_pad;
+
+  v_decoder = gst_element_factory_make("decodebin2", "preview-decoder");
+
+  video_bin = gst_parse_bin_from_description(
+      "videoscale ! ffmpegcolorspace ! autovideosink name=videosink", TRUE, NULL);
+
+  gcc->priv->preview_bin = gst_bin_new("preview_bin");
+  gst_bin_add_many (GST_BIN(gcc->priv->preview_bin), v_decoder, video_bin, NULL);
+
+  g_signal_connect (v_decoder, "pad-added", G_CALLBACK (cb_new_prev_pad), video_bin);
+
+  video_pad = gst_element_get_static_pad(video_bin, "sink");
+  gst_pad_add_buffer_probe (video_pad, (GCallback) cb_last_buffer, gcc);
+  gst_object_unref(video_pad);
+
+  /* Create ghost pads */
+  video_pad = gst_element_get_static_pad (v_decoder, "sink");
+  gst_element_add_pad (gcc->priv->preview_bin, gst_ghost_pad_new ("video", video_pad));
+  gst_object_unref (GST_OBJECT (video_pad));
+
+  if (gcc->priv->audio_enabled) {
+    GstElement *a_decoder, *audio_bin;
+    GstPad *audio_pad;
+
+    a_decoder = gst_element_factory_make("decodebin2", NULL);
+
+    audio_bin = gst_parse_bin_from_description(
+        "audioconvert ! audioresample ! autoaudiosink name=audiosink", TRUE, NULL);
+
+    gst_bin_add_many (GST_BIN(gcc->priv->preview_bin), a_decoder, audio_bin, NULL);
+
+    g_signal_connect (a_decoder, "pad-added", G_CALLBACK (cb_new_prev_pad), audio_bin);
+
+    /* Create ghost pads */
+    audio_pad = gst_element_get_static_pad (a_decoder, "sink");
+    gst_element_add_pad (gcc->priv->preview_bin, gst_ghost_pad_new ("audio", audio_pad));
+    gst_object_unref (GST_OBJECT (audio_pad));
+  }
+
+  gst_bin_add(GST_BIN(gcc->priv->main_pipeline), gcc->priv->preview_bin);
+  gst_element_set_state(gcc->priv->preview_bin, GST_STATE_PLAYING);
+}
+
+static gboolean
+gst_camera_capturer_have_type_cb (GstElement *typefind, guint prob,
+    GstCaps *caps, GstCameraCapturer *gcc)
+{
+  GstCaps *media_caps;
+  GstElement *decoder_bin = NULL;
+
+  GST_INFO_OBJECT (gcc, "Found type with caps %s", gst_caps_to_string(caps));
+
+  /* Check for DV streams */
+  media_caps = gst_caps_from_string("video/x-dv, systemstream=true");
+
+  if (gst_caps_can_intersect(caps, media_caps)) {
+    decoder_bin = gst_camera_capturer_prepare_dv_source(gcc);
+    gst_caps_unref(media_caps);
+  }
+
+  /* Check for MPEG-TS streams */
+  media_caps = gst_caps_from_string("video/mpegts");
+  if (gst_caps_can_intersect(caps, media_caps)) {
+    decoder_bin = gst_camera_capturer_prepare_mpegts_source(gcc);
+    gst_caps_unref(media_caps);
+  }
+
+  /* Check for Raw streams */
+  media_caps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv");
+  if (gst_caps_can_intersect(caps, media_caps)) {
+    gcc->priv->audio_enabled = FALSE;
+    decoder_bin = gst_camera_capturer_prepare_raw_source(gcc);
+    gst_caps_unref(media_caps);
+  }
+
+  if (decoder_bin != NULL) {
+    gst_camera_capturer_create_decoder_bin(gcc, decoder_bin);
+    gst_camera_capturer_create_preview(gcc);
+
+    gst_camera_capturer_link_preview(gcc);
+    gst_element_set_state(gcc->priv->main_pipeline, GST_STATE_PLAYING);
+  } else {
+    /* FIXME: post error */
+  }
+  return TRUE;
+}
+
+static gboolean
+gst_camera_capturer_create_video_source (GstCameraCapturer * gcc,
+    CaptureSourceType type, GError ** err)
+{
+  GstElement *typefind;
+  const gchar *source_desc = "";
+  gchar *source_str;
+
+  g_return_val_if_fail (gcc != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_CAMERA_CAPTURER (gcc), FALSE);
+
+  switch (type) {
+    case CAPTURE_SOURCE_TYPE_DV:
+      GST_INFO_OBJECT(gcc, "Creating dv video source");
+      source_desc = DVVIDEOSRC;
+      gcc->priv->source_element_name = source_desc;
+      break;
+    case CAPTURE_SOURCE_TYPE_SYSTEM:
+      GST_INFO_OBJECT(gcc, "Creating system video source");
+      source_desc = SYSVIDEOSRC;
+      gcc->priv->source_element_name = source_desc;
+      //source_desc = "filesrc location=/home/andoni/test.ts";
+      break;
+    default:
+      g_assert_not_reached();
+  }
+
+  /* HACK: dshowvideosrc's device must be set before linking the element
+   * since the device is set in getcaps and can't be changed later */
+  if (!g_strcmp0 (gcc->priv->source_element_name, "dshowvideosrc"))
+    source_str = g_strdup_printf("%s device-name=\"%s\" name=source ! typefind name=typefind",
+        source_desc, gcc->priv->device_id);
+  else
+    source_str = g_strdup_printf("%s name=source ! typefind name=typefind", source_desc);
+  GST_INFO_OBJECT(gcc, "Created video source %s", source_str);
+  gcc->priv->source_bin = gst_parse_bin_from_description(source_str, TRUE, NULL);
+  g_free(source_str);
+  if (!gcc->priv->source_bin) {
+    g_set_error (err,
+        GCC_ERROR,
+        GST_ERROR_PLUGIN_LOAD,
+        "Failed to create the %s element. "
+        "Please check your GStreamer installation.", source_desc);
+    return FALSE;
+  }
+
+  gcc->priv->source = gst_bin_get_by_name (GST_BIN(gcc->priv->source_bin), "source");
+  typefind = gst_bin_get_by_name (GST_BIN(gcc->priv->source_bin), "typefind");
+  g_signal_connect (typefind, "have-type",
+      G_CALLBACK (gst_camera_capturer_have_type_cb), gcc);
+
+  gst_camera_capturer_update_device_id(gcc);
+
+  GST_INFO_OBJECT(gcc, "Created video source %s", source_desc);
+
+  gst_object_unref (gcc->priv->source);
+  gst_object_unref (typefind);
+
+  return TRUE;
+}
+
+static gboolean
+gst_camera_capturer_create_video_encoder (GstCameraCapturer * gcc,
+    VideoEncoderType type, GError ** err)
+{
+  gchar *name = NULL;
+
+  g_return_val_if_fail (gcc != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_CAMERA_CAPTURER (gcc), FALSE);
+
+  switch (type) {
+    case VIDEO_ENCODER_MPEG4:
+      gcc->priv->video_enc =
+          gst_element_factory_make ("ffenc_mpeg4", "video-encoder");
+      g_object_set (gcc->priv->video_enc, "pass", 512,
+          "max-key-interval", -1, NULL);
+      name = "FFmpeg mpeg4 video encoder";
+      break;
+
+    case VIDEO_ENCODER_XVID:
+      gcc->priv->video_enc =
+          gst_element_factory_make ("xvidenc", "video-encoder");
+      g_object_set (gcc->priv->video_enc, "pass", 1,
+          "profile", 146, "max-key-interval", -1, NULL);
+      name = "Xvid video encoder";
+      break;
+
+    case VIDEO_ENCODER_H264:
+      gcc->priv->video_enc =
+          gst_element_factory_make ("x264enc", "video-encoder");
+      g_object_set (gcc->priv->video_enc, "key-int-max", 25, "pass", 17,
+          "speed-preset", 3, NULL);
+      name = "X264 video encoder";
+      break;
+
+    case VIDEO_ENCODER_THEORA:
+      gcc->priv->video_enc =
+          gst_element_factory_make ("theoraenc", "video-encoder");
+      g_object_set (gcc->priv->video_enc, "keyframe-auto", FALSE,
+          "keyframe-force", 25, NULL);
+      name = "Theora video encoder";
+      break;
+
+    case VIDEO_ENCODER_VP8:
+    default:
+      gcc->priv->video_enc =
+          gst_element_factory_make ("vp8enc", "video-encoder");
+      g_object_set (gcc->priv->video_enc, "speed", 2, "threads", 8,
+          "max-keyframe-distance", 25, NULL);
+      name = "VP8 video encoder";
+      break;
+
+  }
+  if (!gcc->priv->video_enc) {
+    g_set_error (err,
+        GCC_ERROR,
+        GST_ERROR_PLUGIN_LOAD,
+        "Failed to create the %s element. "
+        "Please check your GStreamer installation.", name);
+    return FALSE;
+  }
+
+  if (gcc->priv->video_encoder_type == VIDEO_ENCODER_MPEG4 ||
+      gcc->priv->video_encoder_type == VIDEO_ENCODER_XVID)
+    g_object_set (gcc->priv->video_enc, "bitrate", gcc->priv->video_bitrate * 1000, NULL);
+  else
+    g_object_set (gcc->priv->video_enc, "bitrate", gcc->priv->video_bitrate,
+        NULL);
+
+  GST_INFO_OBJECT(gcc, "Video encoder %s created", name);
+  gcc->priv->video_encoder_type = type;
+  return TRUE;
+}
+
+static gboolean
+gst_camera_capturer_create_audio_encoder (GstCameraCapturer * gcc,
+    AudioEncoderType type, GError ** err)
+{
+  gchar *name = NULL;
+
+  g_return_val_if_fail (gcc != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_CAMERA_CAPTURER (gcc), FALSE);
+
+  switch (type) {
+    case AUDIO_ENCODER_MP3:
+      gcc->priv->audio_enc =
+          gst_element_factory_make ("lamemp3enc", "audio-encoder");
+      g_object_set (gcc->priv->audio_enc, "target", 0, NULL);
+      name = "Mp3 audio encoder";
+      break;
+
+    case AUDIO_ENCODER_AAC:
+      gcc->priv->audio_enc = gst_element_factory_make ("faac", "audio-encoder");
+      name = "AAC audio encoder";
+      break;
+
+    case AUDIO_ENCODER_VORBIS:
+    default:
+      gcc->priv->audio_enc =
+          gst_element_factory_make ("vorbisenc", "audio-encoder");
+      name = "Vorbis audio encoder";
+      break;
+  }
+
+  if (!gcc->priv->audio_enc) {
+    g_set_error (err,
+        GCC_ERROR,
+        GST_ERROR_PLUGIN_LOAD,
+        "Failed to create the %s element. "
+        "Please check your GStreamer installation.", name);
+    return FALSE;
+  }
+
+  if (gcc->priv->audio_encoder_type == AUDIO_ENCODER_MP3)
+    g_object_set (gcc->priv->audio_enc, "bitrate", gcc->priv->audio_bitrate, NULL);
+  else
+    g_object_set (gcc->priv->audio_enc, "bitrate", 1000 * gcc->priv->audio_bitrate, NULL);
+
+  GST_INFO_OBJECT(gcc, "Audio encoder %s created", name);
+
+  gcc->priv->audio_encoder_type = type;
+  return TRUE;
+}
+
+static gboolean
+gst_camera_capturer_create_video_muxer (GstCameraCapturer * gcc,
+    VideoMuxerType type, GError ** err)
+{
+  gchar *name = NULL;
+
+  g_return_val_if_fail (gcc != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_CAMERA_CAPTURER (gcc), FALSE);
+
+  switch (type) {
+    case VIDEO_MUXER_OGG:
+      name = "OGG muxer";
+      gcc->priv->muxer = gst_element_factory_make ("oggmux", "video-muxer");
+      break;
+    case VIDEO_MUXER_AVI:
+      name = "AVI muxer";
+      gcc->priv->muxer = gst_element_factory_make ("avimux", "video-muxer");
+      break;
+    case VIDEO_MUXER_MATROSKA:
+      name = "Matroska muxer";
+      gcc->priv->muxer =
+          gst_element_factory_make ("matroskamux", "video-muxer");
+      break;
+    case VIDEO_MUXER_MP4:
+      name = "MP4 muxer";
+      gcc->priv->muxer = gst_element_factory_make ("qtmux", "video-muxer");
+      break;
+    case VIDEO_MUXER_WEBM:
+    default:
+      name = "WebM muxer";
+      gcc->priv->muxer = gst_element_factory_make ("webmmux", "video-muxer");
+      break;
+  }
+
+  if (!gcc->priv->muxer) {
+    g_set_error (err,
+        GCC_ERROR,
+        GST_ERROR_PLUGIN_LOAD,
+        "Failed to create the %s element. "
+        "Please check your GStreamer installation.", name);
+  }
+
+  GST_INFO_OBJECT(gcc, "Muxer %s created", name);
+  gcc->priv->video_muxer_type = type;
+  return TRUE;
+}
+
+static void
+gst_camera_capturer_initialize (GstCameraCapturer *gcc)
+{
+  GError *err= NULL;
+
+  GST_INFO_OBJECT (gcc, "Initializing encoders");
+  if (!gst_camera_capturer_create_video_encoder(gcc,
+        gcc->priv->video_encoder_type, &err))
+    goto missing_plugin;
+  if (!gst_camera_capturer_create_audio_encoder(gcc,
+        gcc->priv->audio_encoder_type, &err))
+    goto missing_plugin;
+  if (!gst_camera_capturer_create_video_muxer(gcc,
+        gcc->priv->video_muxer_type, &err))
+    goto missing_plugin;
+
+  GST_INFO_OBJECT (gcc, "Initializing source");
+  if (!gst_camera_capturer_create_video_source(gcc,
+        gcc->priv->source_type, &err))
+    goto missing_plugin;
+
+  /* add the source element */
+  gst_bin_add(GST_BIN(gcc->priv->main_pipeline), gcc->priv->source_bin);
+  return;
+
+missing_plugin:
+    g_signal_emit (gcc, gcc_signals[SIGNAL_ERROR], 0, err->message);
+    g_error_free (err);
+}
+
+static void
+gcc_encoder_send_event (GstCameraCapturer *gcc, GstEvent *event)
+{
+  GstPad *video_pad, *audio_pad;
+
+  if (gcc->priv->audio_enabled) {
+    gst_event_ref(event);
+    audio_pad = gst_element_get_static_pad(gcc->priv->encoder_bin, "audio");
+    gst_pad_send_event(audio_pad, event);
+    gst_object_unref(audio_pad);
+  }
+
+  video_pad = gst_element_get_static_pad(gcc->priv->encoder_bin, "video");
+  gst_pad_send_event(video_pad, event);
+  gst_object_unref(video_pad);
+
+}
+
+static void
+gcc_bus_message_cb (GstBus * bus, GstMessage * message, gpointer data)
+{
+  GstCameraCapturer *gcc = (GstCameraCapturer *) data;
+  GstMessageType msg_type;
+
+  g_return_if_fail (gcc != NULL);
+  g_return_if_fail (GST_IS_CAMERA_CAPTURER (gcc));
+
+  msg_type = GST_MESSAGE_TYPE (message);
+
+  switch (msg_type) {
+    case GST_MESSAGE_ERROR:
+    {
+      if (gcc->priv->main_pipeline) {
+        gst_camera_capturer_stop (gcc);
+        gst_camera_capturer_close (gcc);
+        gst_element_set_state (gcc->priv->main_pipeline, GST_STATE_NULL);
+      }
+      gcc_error_msg (gcc, message);
+      break;
+    }
+
+    case GST_MESSAGE_WARNING:
+    {
+      GST_WARNING ("Warning message: %" GST_PTR_FORMAT, message);
+      break;
+    }
+
+    case GST_MESSAGE_EOS:
+    {
+      GST_INFO_OBJECT (gcc, "EOS message");
+      g_signal_emit (gcc, gcc_signals[SIGNAL_EOS], 0);
+      break;
+    }
+
+    case GST_MESSAGE_STATE_CHANGED:
+    {
+      GstState old_state, new_state;
+
+      gst_message_parse_state_changed (message, &old_state, &new_state, NULL);
+
+      if (old_state == new_state)
+        break;
+
+      /* we only care about playbin (pipeline) state changes */
+      if (GST_MESSAGE_SRC (message) != GST_OBJECT (gcc->priv->main_pipeline))
+        break;
+
+      if (old_state == GST_STATE_PAUSED && new_state == GST_STATE_PLAYING) {
+        gcc_get_video_stream_info (gcc);
+      }
+    }
+
+    case GST_MESSAGE_ELEMENT:
+    {
+      const GstStructure *s;
+      gint device_change = 0;
+
+      /* We only care about messages sent by the device source */
+      if (GST_MESSAGE_SRC (message) != GST_OBJECT (gcc->priv->source))
+        break;
+
+      s = gst_message_get_structure (message);
+      /* check if it's bus reset message and it contains the
+       * 'current-device-change' field */
+      if (g_strcmp0 (gst_structure_get_name (s), "ieee1394-bus-reset"))
+        break;
+      if (!gst_structure_has_field (s, "current-device-change"))
+        break;
+
+
+      /* emit a signal if the device was connected or disconnected */
+      gst_structure_get_int (s, "current-device-change", &device_change);
+
+      if (device_change != 0)
+        g_signal_emit (gcc, gcc_signals[SIGNAL_DEVICE_CHANGE], 0,
+            device_change);
+      break;
+    }
+
+    default:
+      GST_LOG ("Unhandled message: %" GST_PTR_FORMAT, message);
+      break;
+  }
+}
+
+static void
+gcc_error_msg (GstCameraCapturer * gcc, GstMessage * msg)
+{
+  GError *err = NULL;
+  gchar *dbg = NULL;
+
+  gst_message_parse_error (msg, &err, &dbg);
+  if (err) {
+    GST_ERROR ("message = %s", GST_STR_NULL (err->message));
+    GST_ERROR ("domain  = %d (%s)", err->domain,
+        GST_STR_NULL (g_quark_to_string (err->domain)));
+    GST_ERROR ("code    = %d", err->code);
+    GST_ERROR ("debug   = %s", GST_STR_NULL (dbg));
+    GST_ERROR ("source  = %" GST_PTR_FORMAT, msg->src);
+
+
+    g_message ("Error: %s\n%s\n", GST_STR_NULL (err->message),
+        GST_STR_NULL (dbg));
+    g_signal_emit (gcc, gcc_signals[SIGNAL_ERROR], 0, err->message);
+    g_error_free (err);
+  }
+  g_free (dbg);
+}
+
+static void
+gcc_element_msg_sync (GstBus * bus, GstMessage * msg, gpointer data)
+{
+  GstCameraCapturer *gcc = GST_CAMERA_CAPTURER (data);
+
+  g_assert (msg->type == GST_MESSAGE_ELEMENT);
+
+  if (msg->structure == NULL)
+    return;
+
+  /* This only gets sent if we haven't set an ID yet. This is our last
+   * chance to set it before the video sink will create its own window */
+  if (gst_structure_has_name (msg->structure, "prepare-xwindow-id")) {
+
+    if (gcc->priv->xoverlay == NULL) {
+      GstObject *sender = GST_MESSAGE_SRC (msg);
+      if (sender && GST_IS_X_OVERLAY (sender))
+        gcc->priv->xoverlay = GST_X_OVERLAY (gst_object_ref (sender));
+    }
+
+    g_return_if_fail (gcc->priv->xoverlay != NULL);
+    g_return_if_fail (gcc->priv->window_handle != 0);
+
+    g_object_set (GST_ELEMENT (gcc->priv->xoverlay), "force-aspect-ratio", TRUE, NULL);
+    gst_set_window_handle (gcc->priv->xoverlay, gcc->priv->window_handle);
+    gtk_widget_queue_draw (GTK_WIDGET(gcc));
+  }
+}
+
+static int
+gcc_get_video_stream_info (GstCameraCapturer * gcc)
+{
+  GstPad *sourcepad;
+  GstCaps *caps;
+  GstStructure *s;
+
+  sourcepad = gst_element_get_pad (gcc->priv->source_bin, "src");
+  caps = gst_pad_get_negotiated_caps (sourcepad);
+
+  if (!(caps)) {
+    GST_WARNING_OBJECT (gcc, "Could not get stream info");
+    return -1;
+  }
+
+  /* Get the source caps */
+  s = gst_caps_get_structure (caps, 0);
+  if (s) {
+    /* We need at least width/height and framerate */
+    if (!
+        (gst_structure_get_fraction
+            (s, "framerate", &gcc->priv->video_fps_n, &gcc->priv->video_fps_d)
+            && gst_structure_get_int (s, "width", &gcc->priv->video_width)
+            && gst_structure_get_int (s, "height", &gcc->priv->video_height)))
+      return -1;
+    /* Get the source PAR if available */
+    gcc->priv->movie_par = gst_structure_get_value (s, "pixel-aspect-ratio");
+  }
+  return 1;
+}
+
+/*****************************************************
+ *
+ *             Device Probe
+ *
+ * **************************************************/
+
+GList *
+gst_camera_capturer_enum_devices (gchar * device_name)
+{
+  GstElement *device;
+  GstPropertyProbe *probe;
+  GValueArray *va;
+  gchar *prop_name;
+  GList *list = NULL;
+  guint i = 0;
+
+  device = gst_element_factory_make (device_name, "source");
+  if (!device || !GST_IS_PROPERTY_PROBE (device))
+    goto finish;
+  gst_element_set_state (device, GST_STATE_READY);
+  gst_element_get_state (device, NULL, NULL, 5 * GST_SECOND);
+  probe = GST_PROPERTY_PROBE (device);
+
+  if (!g_strcmp0 (device_name, "dv1394src"))
+    prop_name = "guid";
+  else if (!g_strcmp0 (device_name, "v4l2src") ||
+      !g_strcmp0 (device_name, "osxvideosrc"))
+    prop_name = "device";
+  else
+    prop_name = "device-name";
+
+  va = gst_property_probe_get_values_name (probe, prop_name);
+  if (!va)
+    goto finish;
+
+  for (i = 0; i < va->n_values; ++i) {
+    GValue *v = g_value_array_get_nth (va, i);
+    GValue valstr = { 0, };
+
+    g_value_init (&valstr, G_TYPE_STRING);
+    if (!g_value_transform (v, &valstr))
+      continue;
+    list = g_list_append (list, g_value_dup_string (&valstr));
+    g_value_unset (&valstr);
+  }
+  g_value_array_free (va);
+
+finish:
+  {
+    gst_element_set_state (device, GST_STATE_NULL);
+    gst_object_unref (GST_OBJECT (device));
+    return list;
+  }
+}
+
+GList *
+gst_camera_capturer_enum_video_devices (void)
+{
+  return gst_camera_capturer_enum_devices (DVVIDEOSRC);
+}
+
+GList *
+gst_camera_capturer_enum_audio_devices (void)
+{
+  return gst_camera_capturer_enum_devices (AUDIOSRC);
+}
+
+/*******************************************
+ *
+ *         Public methods
+ *
+ * ****************************************/
+
+void
+gst_camera_capturer_run (GstCameraCapturer * gcc)
+{
+  g_return_if_fail (gcc != NULL);
+  g_return_if_fail (GST_IS_CAMERA_CAPTURER (gcc));
+
+  gst_camera_capturer_initialize (gcc);
+  gst_element_set_state (gcc->priv->main_pipeline, GST_STATE_PLAYING);
+}
+
+void
+gst_camera_capturer_close (GstCameraCapturer * gcc)
+{
+  g_return_if_fail (gcc != NULL);
+  g_return_if_fail (GST_IS_CAMERA_CAPTURER (gcc));
+
+  gst_element_set_state (gcc->priv->main_pipeline, GST_STATE_NULL);
+  gst_element_get_state (gcc->priv->main_pipeline, NULL, NULL, -1);
+}
+
+void
+gst_camera_capturer_start (GstCameraCapturer * gcc)
+{
+  g_return_if_fail (gcc != NULL);
+  g_return_if_fail (GST_IS_CAMERA_CAPTURER (gcc));
+
+  GST_INFO_OBJECT(gcc, "Started capture");
+  g_mutex_lock(gcc->priv->recording_lock);
+  if (!gcc->priv->is_recording && gcc->priv->accum_recorded_ts == GST_CLOCK_TIME_NONE) {
+    gcc->priv->accum_recorded_ts = 0;
+    gcc->priv->is_recording = TRUE;
+    gst_camera_capturer_link_encoder_bin (gcc);
+  }
+  g_mutex_unlock(gcc->priv->recording_lock);
+}
+
+void
+gst_camera_capturer_toggle_pause (GstCameraCapturer * gcc)
+{
+  g_return_if_fail (gcc != NULL);
+  g_return_if_fail (GST_IS_CAMERA_CAPTURER (gcc));
+
+  g_mutex_lock(gcc->priv->recording_lock);
+  if (!gcc->priv->is_recording) {
+    gcc->priv->current_recording_start_ts = GST_CLOCK_TIME_NONE;
+    gcc->priv->is_recording = TRUE;
+  } else {
+    gcc->priv->is_recording = FALSE;
+    gcc->priv->video_synced = FALSE;
+  }
+  g_mutex_unlock(gcc->priv->recording_lock);
+
+  GST_INFO_OBJECT(gcc, "Capture state changed to %s", gcc->priv->is_recording ? "recording": "paused");
+}
+
+void
+gst_camera_capturer_set_source (GstCameraCapturer * gcc, CaptureSourceType source)
+{
+  g_return_if_fail (gcc != NULL);
+  g_return_if_fail (GST_IS_CAMERA_CAPTURER (gcc));
+
+  gcc->priv->source_type = source;
+}
+
+void
+gst_camera_capturer_set_video_encoder (GstCameraCapturer * gcc, VideoEncoderType encoder)
+{
+  g_return_if_fail (gcc != NULL);
+  g_return_if_fail (GST_IS_CAMERA_CAPTURER (gcc));
+
+  gcc->priv->video_encoder_type = encoder;
+}
+
+void
+gst_camera_capturer_set_audio_encoder (GstCameraCapturer * gcc, AudioEncoderType encoder)
+{
+  g_return_if_fail (gcc != NULL);
+  g_return_if_fail (GST_IS_CAMERA_CAPTURER (gcc));
+
+  gcc->priv->audio_encoder_type = encoder;
+}
+
+void
+gst_camera_capturer_set_video_muxer (GstCameraCapturer * gcc, VideoMuxerType muxer)
+{
+  g_return_if_fail (gcc != NULL);
+  g_return_if_fail (GST_IS_CAMERA_CAPTURER (gcc));
+
+  gcc->priv->video_muxer_type = muxer;
+}
+
+gboolean
+gst_camera_capturer_can_get_frames (GstCameraCapturer * gcc, GError ** error)
+{
+  g_return_val_if_fail (gcc != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_CAMERA_CAPTURER (gcc), FALSE);
+
+  /* check for video */
+  if (!gcc->priv->media_has_video) {
+    g_set_error_literal (error, GCC_ERROR, GST_ERROR_GENERIC,
+        "Media contains no supported video streams.");
+    return FALSE;
+  }
+  return TRUE;
+}
+
+static void
+destroy_pixbuf (guchar * pix, gpointer data)
+{
+  gst_buffer_unref (GST_BUFFER (data));
+}
+
+void
+gst_camera_capturer_unref_pixbuf (GdkPixbuf * pixbuf)
+{
+  g_object_unref (pixbuf);
+}
+
+GdkPixbuf *
+gst_camera_capturer_get_current_frame (GstCameraCapturer * gcc)
+{
+  GstStructure *s;
+  GdkPixbuf *pixbuf;
+  GstBuffer *last_buffer;
+  GstBuffer *buf;
+  GstCaps *to_caps;
+  gint outwidth = 0;
+  gint outheight = 0;
+
+  g_return_val_if_fail (gcc != NULL, NULL);
+  g_return_val_if_fail (GST_IS_CAMERA_CAPTURER (gcc), NULL);
+
+  gst_element_get_state (gcc->priv->main_pipeline, NULL, NULL, -1);
+
+  /* no video info */
+  if (!gcc->priv->video_width || !gcc->priv->video_height) {
+    GST_DEBUG_OBJECT (gcc, "Could not take screenshot: %s", "no video info");
+    g_warning ("Could not take screenshot: %s", "no video info");
+    return NULL;
+  }
+
+  /* get frame */
+  last_buffer = gcc->priv->last_buffer;
+  gst_buffer_ref (last_buffer);
+
+  if (!last_buffer) {
+    GST_DEBUG_OBJECT (gcc, "Could not take screenshot: %s",
+        "no last video frame");
+    g_warning ("Could not take screenshot: %s", "no last video frame");
+    return NULL;
+  }
+
+  if (GST_BUFFER_CAPS (last_buffer) == NULL) {
+    GST_DEBUG_OBJECT (gcc, "Could not take screenshot: %s",
+        "no caps on buffer");
+    g_warning ("Could not take screenshot: %s", "no caps on buffer");
+    return NULL;
+  }
+
+  /* convert to our desired format (RGB24) */
+  to_caps = gst_caps_new_simple ("video/x-raw-rgb",
+      "bpp", G_TYPE_INT, 24, "depth", G_TYPE_INT, 24,
+      /* Note: we don't ask for a specific width/height here, so that
+       * videoscale can adjust dimensions from a non-1/1 pixel aspect
+       * ratio to a 1/1 pixel-aspect-ratio */
+      "pixel-aspect-ratio", GST_TYPE_FRACTION, 1,
+      1, "endianness", G_TYPE_INT, G_BIG_ENDIAN,
+      "red_mask", G_TYPE_INT, 0xff0000,
+      "green_mask", G_TYPE_INT, 0x00ff00,
+      "blue_mask", G_TYPE_INT, 0x0000ff, NULL);
+
+  if (gcc->priv->video_fps_n > 0 && gcc->priv->video_fps_d > 0) {
+    gst_caps_set_simple (to_caps, "framerate", GST_TYPE_FRACTION,
+        gcc->priv->video_fps_n, gcc->priv->video_fps_d, NULL);
+  }
+
+  GST_DEBUG_OBJECT (gcc, "frame caps: %" GST_PTR_FORMAT,
+      GST_BUFFER_CAPS (gcc->priv->last_buffer));
+  GST_DEBUG_OBJECT (gcc, "pixbuf caps: %" GST_PTR_FORMAT, to_caps);
+
+  /* bvw_frame_conv_convert () takes ownership of the buffer passed */
+  buf = bvw_frame_conv_convert (last_buffer, to_caps);
+
+  gst_caps_unref (to_caps);
+  gst_buffer_unref (last_buffer);
+
+  if (!buf) {
+    GST_DEBUG_OBJECT (gcc, "Could not take screenshot: %s",
+        "conversion failed");
+    g_warning ("Could not take screenshot: %s", "conversion failed");
+    return NULL;
+  }
+
+  if (!GST_BUFFER_CAPS (buf)) {
+    GST_DEBUG_OBJECT (gcc, "Could not take screenshot: %s",
+        "no caps on output buffer");
+    g_warning ("Could not take screenshot: %s", "no caps on output buffer");
+    return NULL;
+  }
+
+  s = gst_caps_get_structure (GST_BUFFER_CAPS (buf), 0);
+  gst_structure_get_int (s, "width", &outwidth);
+  gst_structure_get_int (s, "height", &outheight);
+  g_return_val_if_fail (outwidth > 0 && outheight > 0, NULL);
+
+  /* create pixbuf from that - we don't want to use the gstreamer's buffer
+   * because the GTK# bindings won't call the destroy funtion */
+  pixbuf = gdk_pixbuf_new_from_data (GST_BUFFER_DATA (buf),
+      GDK_COLORSPACE_RGB, FALSE, 8, outwidth,
+      outheight, GST_ROUND_UP_4 (outwidth * 3), destroy_pixbuf, buf);
+
+  if (!pixbuf) {
+    GST_DEBUG_OBJECT (gcc, "Could not take screenshot: %s",
+        "could not create pixbuf");
+    g_warning ("Could not take screenshot: %s", "could not create pixbuf");
+  }
+
+  return pixbuf;
+}
+
+
+void
+gst_camera_capturer_stop (GstCameraCapturer * gcc)
+{
+  g_return_if_fail (gcc != NULL);
+  g_return_if_fail (GST_IS_CAMERA_CAPTURER (gcc));
+
+#ifdef WIN32
+  //On windows we can't handle device disconnections until dshowvideosrc
+  //supports it. When a device is disconnected, the source is locked
+  //in ::create(), blocking the streaming thread. We need to change its
+  //state to null, this way camerabin doesn't block in ::do_stop().
+  gst_element_set_state(gcc->priv->source, GST_STATE_NULL);
+#endif
+
+  GST_INFO_OBJECT(gcc, "Closing capture");
+  g_mutex_lock(gcc->priv->recording_lock);
+  gcc->priv->closing_recording = TRUE;
+  gcc->priv->is_recording = FALSE;
+  g_mutex_unlock(gcc->priv->recording_lock);
+
+  gcc_encoder_send_event(gcc, gst_event_new_eos());
+}
+
+GstCameraCapturer *
+gst_camera_capturer_new (gchar * filename, GError ** err)
+{
+  GstCameraCapturer *gcc = NULL;
+
+#ifndef GST_DISABLE_GST_INFO
+  if (_cesarplayer_gst_debug_cat == NULL) {
+    GST_DEBUG_CATEGORY_INIT (_cesarplayer_gst_debug_cat, "longomatch", 0,
+        "LongoMatch GStreamer Backend");
+  }
+#endif
+
+  gcc = g_object_new (GST_TYPE_CAMERA_CAPTURER, NULL);
+
+  gcc->priv->main_pipeline = gst_pipeline_new ("main_pipeline");
+
+  if (!gcc->priv->main_pipeline) {
+    g_set_error (err,
+        GCC_ERROR,
+        GST_ERROR_PLUGIN_LOAD,
+        "Failed to create the pipeline element. "
+        "Please check your GStreamer installation.");
+    goto missing_plugin;
+  }
+
+  /* assume we're always called from the main Gtk+ GUI thread */
+  gui_thread = g_thread_self ();
+
+  /*Connect bus signals */
+  GST_INFO_OBJECT (gcc, "Connecting bus signals");
+  gcc->priv->bus = gst_element_get_bus (GST_ELEMENT (gcc->priv->main_pipeline));
+  gst_bus_add_signal_watch (gcc->priv->bus);
+  gcc->priv->sig_bus_async =
+      g_signal_connect (gcc->priv->bus, "message",
+      G_CALLBACK (gcc_bus_message_cb), gcc);
+
+  /* we want to catch "prepare-xwindow-id" element messages synchronously */
+  gst_bus_set_sync_handler (gcc->priv->bus, gst_bus_sync_signal_handler, gcc);
+
+  gcc->priv->sig_bus_sync =
+      g_signal_connect (gcc->priv->bus, "sync-message::element",
+      G_CALLBACK (gcc_element_msg_sync), gcc);
+
+  return gcc;
+
+/* Missing plugin */
+missing_plugin:
+  {
+    g_object_ref_sink (gcc);
+    g_object_unref (gcc);
+    return NULL;
+  }
+}
diff --git a/libcesarplayer/src/gst-camera-capturer.h b/libcesarplayer/gst-camera-capturer.h
similarity index 58%
rename from libcesarplayer/src/gst-camera-capturer.h
rename to libcesarplayer/gst-camera-capturer.h
index 0e83bb5..b88982b 100644
--- a/libcesarplayer/src/gst-camera-capturer.h
+++ b/libcesarplayer/gst-camera-capturer.h
@@ -50,7 +50,7 @@ typedef struct GstCameraCapturerPrivate GstCameraCapturerPrivate;
 
 struct _GstCameraCapturerClass
 {
-  GtkHBoxClass parent_class;
+  GtkDrawingAreaClass parent_class;
 
   void (*eos) (GstCameraCapturer * gcc);
   void (*error) (GstCameraCapturer * gcc, const char *message);
@@ -60,44 +60,29 @@ struct _GstCameraCapturerClass
 
 struct _GstCameraCapturer
 {
-  GtkEventBox parent;
+  GtkDrawingArea parent;
   GstCameraCapturerPrivate *priv;
 };
 
-typedef enum
-{
-  GST_CAMERA_CAPTURE_SOURCE_TYPE_NONE = 0,
-  GST_CAMERA_CAPTURE_SOURCE_TYPE_DV = 1,
-  GST_CAMERA_CAPTURE_SOURCE_TYPE_RAW = 2,
-  GST_CAMERA_CAPTURE_SOURCE_TYPE_DSHOW = 3
-} GstCameraCaptureSourceType;
-
-EXPORT GType
-gst_camera_capturer_get_type (void)
-    G_GNUC_CONST;
+EXPORT GType gst_camera_capturer_get_type (void) G_GNUC_CONST;
 
-     EXPORT void gst_camera_capturer_init_backend (int *argc, char ***argv);
-     EXPORT GstCameraCapturer *gst_camera_capturer_new (gchar * filename,
-    GError ** err);
-     EXPORT void gst_camera_capturer_run (GstCameraCapturer * gcc);
-     EXPORT void gst_camera_capturer_close (GstCameraCapturer * gcc);
-     EXPORT void gst_camera_capturer_start (GstCameraCapturer * gcc);
-     EXPORT void gst_camera_capturer_toggle_pause (GstCameraCapturer * gcc);
-     EXPORT void gst_camera_capturer_stop (GstCameraCapturer * gcc);
-     EXPORT gboolean gst_camera_capturer_set_video_encoder (GstCameraCapturer *
-    gcc, VideoEncoderType type, GError ** err);
-     EXPORT gboolean gst_camera_capturer_set_audio_encoder (GstCameraCapturer *
-    gcc, AudioEncoderType type, GError ** err);
-     EXPORT gboolean gst_camera_capturer_set_video_muxer (GstCameraCapturer *
-    gcc, VideoMuxerType type, GError ** err);
-     EXPORT gboolean gst_camera_capturer_set_source (GstCameraCapturer * gcc,
-    GstCameraCaptureSourceType type, GError ** err);
-     EXPORT GList *gst_camera_capturer_enum_audio_devices (void);
-     EXPORT GList *gst_camera_capturer_enum_video_devices (void);
-     EXPORT GdkPixbuf *gst_camera_capturer_get_current_frame (GstCameraCapturer
+EXPORT void gst_camera_capturer_init_backend (int *argc, char ***argv);
+EXPORT GstCameraCapturer *gst_camera_capturer_new (gchar *filename, GError ** err);
+EXPORT void gst_camera_capturer_run (GstCameraCapturer * gcc);
+EXPORT void gst_camera_capturer_close (GstCameraCapturer * gcc);
+EXPORT void gst_camera_capturer_start (GstCameraCapturer * gcc);
+EXPORT void gst_camera_capturer_toggle_pause (GstCameraCapturer * gcc);
+EXPORT void gst_camera_capturer_stop (GstCameraCapturer * gcc);
+EXPORT void gst_camera_capturer_set_source (GstCameraCapturer * gcc, CaptureSourceType source);
+EXPORT void gst_camera_capturer_set_video_encoder (GstCameraCapturer * gcc, VideoEncoderType encoder);
+EXPORT void gst_camera_capturer_set_audio_encoder (GstCameraCapturer * gcc, AudioEncoderType encoder);
+EXPORT void gst_camera_capturer_set_video_muxer (GstCameraCapturer * gcc, VideoMuxerType muxer);
+EXPORT GList *gst_camera_capturer_enum_audio_devices (void);
+EXPORT GList *gst_camera_capturer_enum_video_devices (void);
+EXPORT GdkPixbuf *gst_camera_capturer_get_current_frame (GstCameraCapturer
     * gcc);
-     EXPORT void gst_camera_capturer_unref_pixbuf (GdkPixbuf * pixbuf);
-     EXPORT void gst_camera_capturer_finalize (GObject * object);
+EXPORT void gst_camera_capturer_unref_pixbuf (GdkPixbuf * pixbuf);
+EXPORT void gst_camera_capturer_finalize (GObject * object);
 
 G_END_DECLS
 #endif /* _GST_CAMERA_CAPTURER_H_ */
diff --git a/libcesarplayer/gst-remuxer.c b/libcesarplayer/gst-remuxer.c
new file mode 100644
index 0000000..166996b
--- /dev/null
+++ b/libcesarplayer/gst-remuxer.c
@@ -0,0 +1,538 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+* Gstreamer Remuxer
+* Copyright (C)  Andoni Morales Alastruey 2012 <ylatuya gmail com>
+*
+* LongoMatch is free software.
+*
+* You may redistribute it and/or modify it under the terms of the
+* GNU General Public License, as published by the Free Software
+* Foundation; either version 2 of the License, or (at your option)
+* any later version.
+*
+* LongoMatch is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with foob.  If not, write to:
+*       The Free Software Foundation, Inc.,
+*       51 Franklin Street, Fifth Floor
+*       Boston, MA  02110-1301, USA.
+*/
+
+#include <string.h>
+#include <stdio.h>
+
+#include <gst/gst.h>
+
+#include "gst-remuxer.h"
+
+GST_DEBUG_CATEGORY (_remuxer_gst_debug_cat);
+#define GST_CAT_DEFAULT _remuxer_gst_debug_cat
+
+/* Signals */
+enum
+{
+  SIGNAL_ERROR,
+  SIGNAL_PERCENT,
+  LAST_SIGNAL
+};
+
+struct GstRemuxerPrivate
+{
+
+  /*Encoding properties */
+  gchar *input_file;
+  gchar *output_file;
+  VideoMuxerType video_muxer_type;
+
+  /* Remuxer */
+  GstClockTime last_video_buf_ts;
+  GstClockTime last_audio_buf_ts;
+  gboolean audio_linked;
+  gboolean video_linked;
+
+  /*GStreamer elements */
+  GstElement *main_pipeline;
+
+  /*GStreamer bus */
+  GstBus *bus;
+  gulong sig_bus_async;
+};
+
+static GObject *parent_class = NULL;
+
+static int remuxer_signals[LAST_SIGNAL] = { 0 };
+
+static void remuxer_error_msg (GstRemuxer * remuxer, GstMessage * msg);
+static void remuxer_bus_message_cb (GstBus * bus, GstMessage * message,
+    gpointer data);
+
+G_DEFINE_TYPE (GstRemuxer, gst_remuxer, G_TYPE_OBJECT);
+
+/***********************************
+*
+*     Class, Object and Properties
+*
+************************************/
+
+static void
+gst_remuxer_init (GstRemuxer * object)
+{
+  GstRemuxerPrivate *priv;
+  object->priv = priv =
+      G_TYPE_INSTANCE_GET_PRIVATE (object, GST_TYPE_REMUXER,
+      GstRemuxerPrivate);
+
+  priv->input_file = NULL;
+  priv->output_file = NULL;
+  priv->last_video_buf_ts = GST_CLOCK_TIME_NONE;
+  priv->last_audio_buf_ts = GST_CLOCK_TIME_NONE;
+  priv->video_muxer_type = VIDEO_MUXER_WEBM;
+  priv->audio_linked = FALSE;
+  priv->video_linked = FALSE;
+}
+
+void
+gst_remuxer_finalize (GObject * object)
+{
+  GstRemuxer *remuxer = (GstRemuxer *) object;
+
+  GST_DEBUG_OBJECT (remuxer, "Finalizing.");
+  if (remuxer->priv->bus) {
+    /* make bus drop all messages to make sure none of our callbacks is ever
+     * called again (main loop might be run again to display error dialog) */
+    gst_bus_set_flushing (remuxer->priv->bus, TRUE);
+
+    if (remuxer->priv->sig_bus_async)
+      g_signal_handler_disconnect (remuxer->priv->bus, remuxer->priv->sig_bus_async);
+
+    gst_object_unref (remuxer->priv->bus);
+    remuxer->priv->bus = NULL;
+  }
+
+  if (remuxer->priv->input_file) {
+    g_free (remuxer->priv->input_file);
+    remuxer->priv->input_file = NULL;
+  }
+
+  if (remuxer->priv->output_file) {
+    g_free (remuxer->priv->output_file);
+    remuxer->priv->output_file = NULL;
+  }
+
+  if (remuxer->priv->main_pipeline != NULL
+      && GST_IS_ELEMENT (remuxer->priv->main_pipeline)) {
+    gst_element_set_state (remuxer->priv->main_pipeline,
+        GST_STATE_NULL);
+    gst_object_unref (remuxer->priv->main_pipeline);
+    remuxer->priv->main_pipeline = NULL;
+  }
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_remuxer_class_init (GstRemuxerClass * klass)
+{
+  GObjectClass *object_class;
+
+  object_class = (GObjectClass *) klass;
+  parent_class = g_type_class_peek_parent (klass);
+
+  g_type_class_add_private (object_class, sizeof (GstRemuxerPrivate));
+
+  object_class->finalize = gst_remuxer_finalize;
+
+  /* Signals */
+  remuxer_signals[SIGNAL_ERROR] =
+      g_signal_new ("error",
+        G_TYPE_FROM_CLASS (object_class),
+        G_SIGNAL_RUN_LAST,
+        G_STRUCT_OFFSET (GstRemuxerClass, error),
+        NULL, NULL,
+        g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
+
+  remuxer_signals[SIGNAL_PERCENT] =
+      g_signal_new ("percent_completed",
+        G_TYPE_FROM_CLASS (object_class),
+        G_SIGNAL_RUN_LAST,
+        G_STRUCT_OFFSET (GstRemuxerClass, percent_completed),
+        NULL, NULL, g_cclosure_marshal_VOID__FLOAT, G_TYPE_NONE, 1, G_TYPE_FLOAT);
+}
+
+/***********************************
+*
+*           GStreamer
+*
+************************************/
+
+void
+gst_remuxer_init_backend (int *argc, char ***argv)
+{
+  gst_init (argc, argv);
+}
+
+GQuark
+gst_remuxer_error_quark (void)
+{
+  static GQuark q;              /* 0 */
+
+  if (G_UNLIKELY (q == 0)) {
+    q = g_quark_from_static_string ("remuxer-error-quark");
+  }
+  return q;
+}
+
+static GstElement *
+gst_remuxer_create_video_muxer (GstRemuxer * remuxer,
+    VideoMuxerType type)
+{
+  GstElement *muxer;
+
+  g_return_val_if_fail (remuxer != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_REMUXER (remuxer), FALSE);
+
+  switch (type) {
+    case VIDEO_MUXER_OGG:
+      muxer = gst_element_factory_make ("oggmux", "muxer");
+      break;
+    case VIDEO_MUXER_AVI:
+      muxer = gst_element_factory_make ("avimux", "muxer");
+      break;
+    case VIDEO_MUXER_MATROSKA:
+      muxer = gst_element_factory_make ("matroskamux", "muxer");
+      break;
+    case VIDEO_MUXER_MP4:
+      muxer = gst_element_factory_make ("qtmux", "muxer");
+      break;
+    case VIDEO_MUXER_WEBM:
+    default:
+      muxer = gst_element_factory_make ("webmmux", "muxer");
+      break;
+  }
+
+  return muxer;
+}
+
+static gboolean
+gst_remuxer_fix_video_ts (GstPad *pad, GstBuffer *buf, GstRemuxer *remuxer)
+{
+  if (GST_BUFFER_TIMESTAMP (buf) == GST_CLOCK_TIME_NONE) {
+    GST_BUFFER_TIMESTAMP (buf) = remuxer->priv->last_video_buf_ts;
+  } else {
+    remuxer->priv->last_video_buf_ts = GST_BUFFER_TIMESTAMP (buf);
+  }
+  return TRUE;
+}
+
+static gboolean
+gst_remuxer_pad_added_cb (GstElement *demuxer, GstPad *pad,
+    GstRemuxer *remuxer)
+{
+  GstElement *muxer, *queue;
+  GstElement *parser = NULL;
+  GstPad *muxer_pad, *queue_sink_pad, *queue_src_pad;
+  GstCaps *caps, *parser_caps = NULL;
+  const GstStructure *s;
+  gchar *muxer_pad_name = NULL;
+  const gchar *mime;
+  gboolean is_video;
+
+  caps = gst_pad_get_caps_reffed (pad);
+  s = gst_caps_get_structure (caps, 0);
+  mime = gst_structure_get_name (s);
+  GST_INFO_OBJECT (remuxer, "Found mime type: %s", mime);
+
+  if (g_strrstr (mime, "video") && !remuxer->priv->video_linked) {
+    muxer_pad_name = "video_%d";
+    if (g_strrstr (mime, "video/x-h264")) {
+      GstPad *parser_pad;
+
+      parser = gst_element_factory_make("h264parse", "video-parser");
+      parser_caps = gst_caps_from_string("video/x-h264, stream-format=avc, alignment=au");
+
+      parser_pad = gst_element_get_static_pad (parser, "src");
+      gst_pad_add_buffer_probe (parser_pad, (GCallback)gst_remuxer_fix_video_ts, remuxer);
+    }
+    is_video = TRUE;
+  } else if (g_strrstr (mime, "audio") && !remuxer->priv->audio_linked) {
+    muxer_pad_name = "audio_%d";
+    if (g_strrstr (mime, "audio/mpeg")) {
+      gint version;
+      gst_structure_get_int (s, "mpegversion", &version);
+      if (version == 4) {
+        /* FIXME: aacparse doesn't seem to support adts to raw conversion */
+        //parser = gst_element_factory_make ("aacparse", NULL);
+        parser = gst_parse_bin_from_description ("faad ! faac", TRUE, NULL);
+      } else if (version == 3) {
+        parser = gst_element_factory_make("mp3parse", "audio-parser");
+      } else {
+        parser = gst_element_factory_make("mpegaudioparse", "audio-parser");
+      }
+    } else if (g_strrstr (mime, "audio/x-eac3")) {
+      parser = gst_element_factory_make ("ac3parse", NULL);
+    } else if (g_strrstr (mime, "audio/x-ac3")) {
+      parser = gst_element_factory_make ("ac3parse", NULL);
+    }
+    is_video = FALSE;
+  }
+
+  if (muxer_pad_name == NULL) {
+    gst_caps_unref (caps);
+    return TRUE;
+  }
+
+  muxer = gst_bin_get_by_name (GST_BIN(remuxer->priv->main_pipeline), "muxer");
+  if (parser != NULL) {
+    gst_bin_add (GST_BIN(remuxer->priv->main_pipeline), parser);
+    gst_element_set_state (parser, GST_STATE_PLAYING);
+    if (parser_caps) {
+      gst_element_link_filtered (parser, muxer, parser_caps);
+      gst_caps_unref (parser_caps);
+    } else {
+      gst_element_link (parser, muxer);
+    }
+    muxer_pad = gst_element_get_static_pad (parser, "sink");
+  } else {
+    muxer_pad = gst_element_get_compatible_pad (muxer, pad, caps);
+  }
+
+  if (!muxer_pad) {
+    gchar *msg;
+
+    msg = g_strdup_printf ("File with %s type %s is not supported",
+        is_video ? "video" : "audio", mime);
+    g_signal_emit (remuxer, remuxer_signals[SIGNAL_ERROR], 0, msg);
+    g_free (msg);
+    gst_remuxer_cancel (remuxer);
+    return TRUE;
+  } else {
+    if (is_video)
+      remuxer->priv->video_linked = TRUE;
+    else
+      remuxer->priv->audio_linked = TRUE;
+  }
+  queue = gst_element_factory_make ("queue2", NULL);
+  gst_bin_add (GST_BIN(remuxer->priv->main_pipeline), queue);
+  gst_element_set_state (queue, GST_STATE_PLAYING);
+  queue_sink_pad = gst_element_get_static_pad (queue, "sink");
+  queue_src_pad = gst_element_get_static_pad (queue, "src");
+
+  gst_pad_link (pad, queue_sink_pad);
+  gst_pad_link (queue_src_pad, muxer_pad);
+
+  gst_object_unref (muxer);
+  gst_object_unref (queue_sink_pad);
+  gst_object_unref (queue_src_pad);
+
+  gst_caps_unref (caps);
+  return TRUE;
+}
+
+static gboolean
+gst_remuxer_have_type_cb (GstElement *typefind, guint prob,
+    GstCaps *caps, GstRemuxer *remuxer)
+{
+  GstElement *demuxer = NULL;
+  GstElement *parser = NULL;
+  GstStructure *structure;
+  const gchar *mime;
+
+  structure = gst_caps_get_structure (caps, 0);
+  mime = gst_structure_get_name (structure);
+  GST_INFO_OBJECT (remuxer, "Found mime type: %s", mime);
+
+  if (g_strrstr (mime, "video/mpegts")) {
+    GST_INFO_OBJECT (remuxer, "Using tsdemux as demuxer");
+    demuxer = gst_element_factory_make ("tsdemux", NULL);
+  } else if (g_strrstr (mime, "video/x-ms-asf")) {
+    GST_INFO_OBJECT (remuxer, "Using asfdemux as demuxer");
+    demuxer = gst_element_factory_make ("asfdemux", NULL);
+  } else if (g_strrstr (mime, "video/mpeg")) {
+    gboolean sysstream;
+
+    if (gst_structure_get_boolean (structure, "systemstream", &sysstream) &&
+        !sysstream) {
+      GST_INFO_OBJECT (remuxer, "Using mpegvideoparse as demuxer");
+      parser = gst_element_factory_make ("mpegvideoparse", NULL);
+    } else {
+      GST_INFO_OBJECT (remuxer, "Using mpegpsdemux as demuxer");
+      demuxer = gst_element_factory_make ("mpegpsdemux", NULL);
+    }
+  }
+
+  if (demuxer) {
+    gst_bin_add (GST_BIN(remuxer->priv->main_pipeline), demuxer);
+    gst_element_link (typefind, demuxer);
+    g_signal_connect (demuxer, "pad-added",
+        G_CALLBACK (gst_remuxer_pad_added_cb), remuxer);
+  } else if (parser) {
+    GstPad *pad;
+    gst_bin_add (GST_BIN(remuxer->priv->main_pipeline), parser);
+    gst_element_link (typefind, parser);
+    pad = gst_element_get_static_pad (parser, "src");
+    gst_remuxer_pad_added_cb (parser, pad, remuxer);
+  } else {
+    gchar *msg;
+
+    msg = g_strdup_printf ("File with mime type %s is not supported", mime);
+    g_signal_emit (remuxer, remuxer_signals[SIGNAL_ERROR], 0, msg);
+    g_free (msg);
+    gst_remuxer_cancel (remuxer);
+  }
+
+  return TRUE;
+}
+
+static void
+gst_remuxer_initialize (GstRemuxer *remuxer)
+{
+  GstElement *filesrc, *typefind, *muxer, *filesink;
+
+  GST_INFO_OBJECT (remuxer, "Initializing pipeline");
+
+  /* Create elements */
+  remuxer->priv->main_pipeline = gst_pipeline_new ("pipeline");
+
+  filesrc = gst_element_factory_make("filesrc", "source");
+  typefind = gst_element_factory_make("typefind", "typefind");
+  muxer = gst_remuxer_create_video_muxer (remuxer, remuxer->priv->video_muxer_type);
+  filesink = gst_element_factory_make("filesink", "sink");
+
+  /* Set properties */
+  g_object_set (filesrc, "location", remuxer->priv->input_file, NULL);
+  g_object_set (filesink, "location", remuxer->priv->output_file, NULL);
+
+  /* Add elements to the bin */
+  gst_bin_add_many(GST_BIN(remuxer->priv->main_pipeline), filesrc, typefind,
+      muxer, filesink, NULL);
+  gst_element_link(filesrc, typefind);
+  gst_element_link(muxer, filesink);
+
+  g_signal_connect (typefind, "have-type",
+      G_CALLBACK (gst_remuxer_have_type_cb), remuxer);
+}
+
+
+static void
+remuxer_bus_message_cb (GstBus * bus, GstMessage * message, gpointer data)
+{
+  GstRemuxer *remuxer = (GstRemuxer *) data;
+  GstMessageType msg_type;
+
+  g_return_if_fail (remuxer != NULL);
+  g_return_if_fail (GST_IS_REMUXER (remuxer));
+
+  msg_type = GST_MESSAGE_TYPE (message);
+
+  switch (msg_type) {
+    case GST_MESSAGE_ERROR:
+    {
+      if (remuxer->priv->main_pipeline) {
+        gst_remuxer_cancel (remuxer);
+      }
+      remuxer_error_msg (remuxer, message);
+      break;
+    }
+
+    case GST_MESSAGE_WARNING:
+    {
+      GST_WARNING ("Warning message: %" GST_PTR_FORMAT, message);
+      break;
+    }
+
+    case GST_MESSAGE_EOS:
+    {
+      GST_INFO_OBJECT (remuxer, "EOS message");
+      g_signal_emit (remuxer, remuxer_signals[SIGNAL_PERCENT], 0, (gfloat) 1);
+      break;
+    }
+
+    default:
+      GST_LOG ("Unhandled message: %" GST_PTR_FORMAT, message);
+      break;
+  }
+}
+
+static void
+remuxer_error_msg (GstRemuxer * remuxer, GstMessage * msg)
+{
+  GError *err = NULL;
+  gchar *dbg = NULL;
+
+  gst_message_parse_error (msg, &err, &dbg);
+  if (err) {
+    GST_ERROR ("message = %s", GST_STR_NULL (err->message));
+    GST_ERROR ("domain  = %d (%s)", err->domain,
+        GST_STR_NULL (g_quark_to_string (err->domain)));
+    GST_ERROR ("code    = %d", err->code);
+    GST_ERROR ("debug   = %s", GST_STR_NULL (dbg));
+    GST_ERROR ("source  = %" GST_PTR_FORMAT, msg->src);
+
+
+    g_message ("Error: %s\n%s\n", GST_STR_NULL (err->message),
+        GST_STR_NULL (dbg));
+    g_signal_emit (remuxer, remuxer_signals[SIGNAL_ERROR], 0, err->message);
+    g_error_free (err);
+  }
+  g_free (dbg);
+}
+
+/*******************************************
+ *
+ *         Public methods
+ *
+ * ****************************************/
+
+void
+gst_remuxer_start (GstRemuxer * remuxer)
+{
+  g_return_if_fail (remuxer != NULL);
+  g_return_if_fail (GST_IS_REMUXER (remuxer));
+
+  gst_element_set_state (remuxer->priv->main_pipeline, GST_STATE_PLAYING);
+}
+
+void
+gst_remuxer_cancel (GstRemuxer * remuxer)
+{
+  g_return_if_fail (remuxer != NULL);
+  g_return_if_fail (GST_IS_REMUXER (remuxer));
+
+  gst_element_set_state (remuxer->priv->main_pipeline, GST_STATE_NULL);
+  gst_element_get_state (remuxer->priv->main_pipeline, NULL, NULL, -1);
+}
+
+GstRemuxer *
+gst_remuxer_new (gchar * input_file, gchar *output_file, GError ** err)
+{
+  GstRemuxer *remuxer = NULL;
+
+#ifndef GST_DISABLE_GST_INFO
+  if (_remuxer_gst_debug_cat == NULL) {
+    GST_DEBUG_CATEGORY_INIT (_remuxer_gst_debug_cat, "longomatch", 0,
+        "LongoMatch GStreamer Backend");
+  }
+#endif
+
+  remuxer = g_object_new (GST_TYPE_REMUXER, NULL);
+
+  remuxer->priv->input_file = input_file;
+  remuxer->priv->output_file = output_file;
+  remuxer->priv->video_muxer_type = VIDEO_MUXER_MATROSKA;
+
+  gst_remuxer_initialize (remuxer);
+
+  /*Connect bus signals */
+  GST_INFO_OBJECT (remuxer, "Connecting bus signals");
+  remuxer->priv->bus = gst_element_get_bus (remuxer->priv->main_pipeline);
+  gst_bus_add_signal_watch (remuxer->priv->bus);
+  remuxer->priv->sig_bus_async =
+      g_signal_connect (remuxer->priv->bus, "message",
+      G_CALLBACK (remuxer_bus_message_cb), remuxer);
+
+  return remuxer;
+}
diff --git a/libcesarplayer/gst-remuxer.h b/libcesarplayer/gst-remuxer.h
new file mode 100644
index 0000000..e3818bd
--- /dev/null
+++ b/libcesarplayer/gst-remuxer.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * Gstreamer DV capturer
+ * Copyright (C)  Andoni Morales Alastruey 2008 <ylatuya gmail com>
+ *
+ * Gstreamer DV capturer is free software.
+ *
+ * You may redistribute it and/or modify it under the terms of the
+ * GNU General Public License, as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * foob is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with foob.  If not, write to:
+ *      The Free Software Foundation, Inc.,
+ *      51 Franklin Street, Fifth Floor
+ *      Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _GST_REMUXER_H_
+#define _GST_REMUXER_H_
+
+#ifdef WIN32
+#define EXPORT __declspec (dllexport)
+#else
+#define EXPORT
+#endif
+
+#include <gst/gst.h>
+#include "common.h"
+
+G_BEGIN_DECLS
+#define GST_TYPE_REMUXER             (gst_remuxer_get_type ())
+#define GST_REMUXER(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_REMUXER, GstRemuxer))
+#define GST_REMUXER_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_REMUXER, GstRemuxerClass))
+#define GST_IS_REMUXER(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_REMUXER))
+#define GST_IS_REMUXER_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_REMUXER))
+#define GST_REMUXER_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_REMUXER, GstRemuxerClass))
+#define GCC_ERROR gst_remuxer_error_quark ()
+typedef struct _GstRemuxerClass GstRemuxerClass;
+typedef struct _GstRemuxer GstRemuxer;
+typedef struct GstRemuxerPrivate GstRemuxerPrivate;
+
+
+struct _GstRemuxerClass
+{
+  GObjectClass parent_class;
+
+  void (*percent_completed) (GstRemuxer * remuxer, gfloat *percent);
+  void (*error) (GstRemuxer * remuxer, const char *message);
+};
+
+struct _GstRemuxer
+{
+  GObject parent;
+  GstRemuxerPrivate *priv;
+};
+
+EXPORT GType gst_remuxer_get_type (void) G_GNUC_CONST;
+
+EXPORT void gst_remuxer_init_backend (int *argc, char ***argv);
+EXPORT GstRemuxer *gst_remuxer_new (gchar *in_filename, gchar *out_filename, GError ** err);
+EXPORT void gst_remuxer_start (GstRemuxer * remuxer);
+EXPORT void gst_remuxer_cancel (GstRemuxer * remuxer);
+
+G_END_DECLS
+#endif /* _GST_REMUXER_H_ */
diff --git a/libcesarplayer/src/gst-smart-video-scaler.c b/libcesarplayer/gst-smart-video-scaler.c
similarity index 100%
rename from libcesarplayer/src/gst-smart-video-scaler.c
rename to libcesarplayer/gst-smart-video-scaler.c
diff --git a/libcesarplayer/src/gst-smart-video-scaler.h b/libcesarplayer/gst-smart-video-scaler.h
similarity index 100%
rename from libcesarplayer/src/gst-smart-video-scaler.h
rename to libcesarplayer/gst-smart-video-scaler.h
diff --git a/libcesarplayer/src/gst-video-editor.c b/libcesarplayer/gst-video-editor.c
similarity index 98%
rename from libcesarplayer/src/gst-video-editor.c
rename to libcesarplayer/gst-video-editor.c
index 7dea513..12a9050 100644
--- a/libcesarplayer/src/gst-video-editor.c
+++ b/libcesarplayer/gst-video-editor.c
@@ -29,7 +29,6 @@
 #define DEFAULT_VIDEO_ENCODER "vp8enc"
 #define DEFAULT_AUDIO_ENCODER "vorbisenc"
 #define DEFAULT_VIDEO_MUXER "matroskamux"
-#define FONT_SIZE_FACTOR 0.05
 #define LAME_CAPS "audio/x-raw-int, rate=44100, channels=2, endianness=1234, signed=true, width=16, depth=16"
 #define VORBIS_CAPS "audio/x-raw-float, rate=44100, channels=2, endianness=1234, signed=true, width=32, depth=32"
 #define FAAC_CAPS "audio/x-raw-int, rate=44100, channels=2, endianness=1234, signed=true, width=16, depth=16"
@@ -131,7 +130,7 @@ static void gst_video_editor_set_property (GObject * object,
     guint property_id, const GValue * value, GParamSpec * pspec);
 static gboolean gve_query_timeout (GstVideoEditor * gve);
 static void gve_apply_new_caps (GstVideoEditor * gve);
-static void gve_apply_title_size (GstVideoEditor * gve);
+static void gve_apply_title_size (GstVideoEditor * gve, gint size);
 static void gve_rewrite_headers (GstVideoEditor * gve);
 G_DEFINE_TYPE (GstVideoEditor, gst_video_editor, G_TYPE_OBJECT);
 
@@ -245,7 +244,7 @@ gst_video_editor_class_init (GstVideoEditorClass * klass)
 
   g_object_class_install_property (object_class, PROP_TITLE_SIZE,
       g_param_spec_int ("title-size", NULL, NULL,
-          10, 100, 20, G_PARAM_READWRITE));
+          1, 100, 20, G_PARAM_READWRITE));
 
   g_object_class_install_property (object_class, PROP_OUTPUT_FILE,
       g_param_spec_string ("output_file", NULL, NULL, "", G_PARAM_READWRITE));
@@ -367,7 +366,7 @@ static void
 gst_video_editor_set_title_size (GstVideoEditor * gve, gint size)
 {
   gve->priv->title_size = size;
-  gve_apply_title_size (gve);
+  gve_apply_title_size (gve, size);
 }
 
 static void
@@ -502,16 +501,35 @@ gve_apply_new_caps (GstVideoEditor * gve)
 }
 
 static void
-gve_apply_title_size (GstVideoEditor * gve)
+gve_apply_title_size (GstVideoEditor * gve, gint size)
 {
   gchar *font;
 
-  font = g_strdup_printf ("sans bold %d", gve->priv->title_size);
-  g_object_set (G_OBJECT (gve->priv->textoverlay), "font-desc", font, NULL);
+  font = g_strdup_printf ("sans bold %d", size);
+  g_object_set (G_OBJECT (gve->priv->textoverlay), "font-desc", font,
+        "auto-resize", TRUE, "wrap-mode", 0, NULL);
   g_free (font);
 }
 
 static void
+gve_set_overlay_title (GstVideoEditor *gve, gchar *title)
+{
+  glong length;
+
+  if (title == NULL)
+    return;
+
+  g_object_set (G_OBJECT (gve->priv->textoverlay), "text", title, NULL);
+
+  length = g_utf8_strlen (title, -1);
+  if (length * gve->priv->title_size > gve->priv->width) {
+    gve_apply_title_size (gve, gve->priv->width / length - 1);
+  } else {
+    gve_apply_title_size (gve, gve->priv->title_size);
+  }
+}
+
+static void
 gve_create_video_encode_bin (GstVideoEditor * gve)
 {
   GstPad *sinkpad = NULL;
@@ -535,8 +553,7 @@ gve_create_video_encode_bin (GstVideoEditor * gve)
 
   g_object_set (G_OBJECT (gve->priv->identity), "single-segment", TRUE, NULL);
   g_object_set (G_OBJECT (gve->priv->textoverlay), "font-desc",
-      "sans bold 20", "shaded-background", TRUE, "valignment", 2,
-      "halignment", 2, NULL);
+      "sans bold 20", "valignment", 2, "halignment", 2, NULL);
   g_object_set (G_OBJECT (gve->priv->videoscale), "add-borders", TRUE, NULL);
   g_object_set (G_OBJECT (gve->priv->video_encoder), "bitrate",
       gve->priv->video_bitrate, NULL);
@@ -818,11 +835,12 @@ gve_query_timeout (GstVideoEditor * gve)
 
   if (gst_element_query_position (gve->priv->video_encoder, &fmt, &pos)) {
     if (stop_time - pos <= 0) {
+
       gve->priv->active_segment++;
       title =
           (gchar *) g_list_nth_data (gve->priv->titles,
           gve->priv->active_segment);
-      g_object_set (G_OBJECT (gve->priv->textoverlay), "text", title, NULL);
+      gve_set_overlay_title (gve, title);
     }
   }
 
@@ -870,7 +888,7 @@ gst_video_editor_add_segment (GstVideoEditor * gve, gchar * file,
       "start", gve->priv->duration,
       "duration", final_duration, "caps", filter, NULL);
   if (gve->priv->segments == 0) {
-    g_object_set (G_OBJECT (gve->priv->textoverlay), "text", title, NULL);
+    gve_set_overlay_title (gve, title);
   }
   gst_bin_add (GST_BIN (gve->priv->gnl_video_composition), gnl_filesource);
   gve->priv->gnl_video_filesources =
@@ -1066,12 +1084,12 @@ gst_video_editor_set_video_encoder (GstVideoEditor * gve, gchar ** err,
       g_object_set (G_OBJECT (encoder), "pass", 17, NULL);       //Variable Bitrate-Pass 1
       g_object_set (G_OBJECT (encoder), "speed-preset", 4, NULL);//"Faster" preset
       break;
-    case VIDEO_ENCODER_MPEG4:
+    case VIDEO_ENCODER_XVID:
       encoder_name = "xvidenc";
       encoder = gst_element_factory_make (encoder_name, encoder_name);
       g_object_set (G_OBJECT (encoder), "pass", 1, NULL);       //Variable Bitrate-Pass 1
       break;
-    case VIDEO_ENCODER_XVID:
+    case VIDEO_ENCODER_MPEG4:
       encoder_name = "ffenc_mpeg4";
       encoder = gst_element_factory_make (encoder_name, encoder_name);
       g_object_set (G_OBJECT (encoder), "pass", 512, NULL);     //Variable Bitrate-Pass 1
@@ -1303,6 +1321,7 @@ gst_video_editor_set_video_muxer (GstVideoEditor * gve, gchar ** err,
     case VIDEO_MUXER_MP4:
       muxer_name = "qtmux";
       muxer = gst_element_factory_make ("qtmux", muxer_name);
+      g_object_set (muxer, "faststart", TRUE, NULL);
       break;
     case VIDEO_MUXER_MPEG_PS:
       muxer_name = "ffmux_dvd";
diff --git a/libcesarplayer/src/gst-video-editor.h b/libcesarplayer/gst-video-editor.h
similarity index 100%
rename from libcesarplayer/src/gst-video-editor.h
rename to libcesarplayer/gst-video-editor.h
diff --git a/libcesarplayer/src/gstscreenshot.c b/libcesarplayer/gstscreenshot.c
similarity index 98%
rename from libcesarplayer/src/gstscreenshot.c
rename to libcesarplayer/gstscreenshot.c
index f1df208..03f67a8 100644
--- a/libcesarplayer/src/gstscreenshot.c
+++ b/libcesarplayer/gstscreenshot.c
@@ -25,9 +25,8 @@
 #include <string.h>
 
 #include "gstscreenshot.h"
+#include "video-utils.h"
 
-GST_DEBUG_CATEGORY_EXTERN (_totem_gst_debug_cat);
-#define GST_CAT_DEFAULT _totem_gst_debug_cat
 
 static void
 feed_fakesrc (GstElement * src, GstBuffer * buf, GstPad * pad, gpointer data)
diff --git a/libcesarplayer/src/gstscreenshot.h b/libcesarplayer/gstscreenshot.h
similarity index 100%
rename from libcesarplayer/src/gstscreenshot.h
rename to libcesarplayer/gstscreenshot.h
diff --git a/libcesarplayer/src/gstvideowidget.c b/libcesarplayer/gstvideowidget.c
similarity index 100%
rename from libcesarplayer/src/gstvideowidget.c
rename to libcesarplayer/gstvideowidget.c
diff --git a/libcesarplayer/src/gstvideowidget.h b/libcesarplayer/gstvideowidget.h
similarity index 100%
rename from libcesarplayer/src/gstvideowidget.h
rename to libcesarplayer/gstvideowidget.h
diff --git a/libcesarplayer/src/macros.h b/libcesarplayer/macros.h
similarity index 100%
rename from libcesarplayer/src/macros.h
rename to libcesarplayer/macros.h
diff --git a/libcesarplayer/src/main.c b/libcesarplayer/main.c
similarity index 64%
rename from libcesarplayer/src/main.c
rename to libcesarplayer/main.c
index a2726fc..ff51aab 100644
--- a/libcesarplayer/src/main.c
+++ b/libcesarplayer/main.c
@@ -17,13 +17,14 @@
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-
-
+/* Compile with:
+ * gcc -o test main.c gst-camera-capturer.c video-utils.c gstscreenshot.c `pkg-config --cflags --libs gstreamer-0.10 gstreamer-interfaces-0.10 gstreamer-video-0.10 gtk+-2.0` -DOSTYPE_LINUX -O0
+ */
 
 #include <gtk/gtk.h>
-#include "gst-video-capturer.h"
 #include <stdlib.h>
 #include <unistd.h>
+#include "gst-camera-capturer.h"
 
 
 static int i = 0;
@@ -34,22 +35,24 @@ window_state_event (GtkWidget * widget, GdkEventWindowState * event,
   i++;
   g_print ("%d\n", i);
   if (i == 3) {
-    gst_video_capturer_rec (GST_VIDEO_CAPTURER (gvc));
+    gst_camera_capturer_start (GST_CAMERA_CAPTURER (gvc));
 
   }
   if (i == 5)
-    gst_video_capturer_stop (GST_VIDEO_CAPTURER (gvc));
+    gst_camera_capturer_toggle_pause (GST_CAMERA_CAPTURER (gvc));
+  if (i == 7)
+    gst_camera_capturer_toggle_pause (GST_CAMERA_CAPTURER (gvc));
+  if (i == 9)
+    gst_camera_capturer_stop (GST_CAMERA_CAPTURER (gvc));
   return TRUE;
 }
 
 GtkWidget *
-create_window (GstVideoCapturer * gvc)
+create_window (GstCameraCapturer * gvc)
 {
   GtkWidget *window;
 
 
-
-
   /* Create a new window */
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
   gtk_window_set_title (GTK_WINDOW (window), "Capturer");
@@ -66,19 +69,21 @@ int
 main (int argc, char *argv[])
 {
   GtkWidget *window;
-  GstVideoCapturer *gvc;
+  GstCameraCapturer *gvc;
   GError *error = NULL;
 
 
   gtk_init (&argc, &argv);
 
   /*Create GstVideoCapturer */
-  gst_video_capturer_init_backend (&argc, &argv);
-  gvc = gst_video_capturer_new (GVC_USE_TYPE_DEVICE_CAPTURE, &error);
-  //gvc = gst_video_capturer_new (GVC_USE_TYPE_VIDEO_TRANSCODE, &error );
-  //g_object_set(gvc,"input_file","/home/andoni/Escritorio/RC Polo vs CD Complutense.avi",NULL);
+  gst_camera_capturer_init_backend (&argc, &argv);
+  gvc = gst_camera_capturer_new ("test", &error);
+
+  gst_camera_capturer_set_source (gvc, CAPTURE_SOURCE_TYPE_SYSTEM);
+  gst_camera_capturer_set_video_encoder (gvc, VIDEO_ENCODER_H264);
+  gst_camera_capturer_set_audio_encoder (gvc, AUDIO_ENCODER_AAC);
+  gst_camera_capturer_set_video_muxer (gvc, VIDEO_MUXER_MP4);
   g_object_set (gvc, "output_file", "/home/andoni/jander.avi", NULL);
-  //gvc = gst_video_capturer_new (GVC_USE_TYPE_TEST, &error );
 
   window = create_window (gvc);
 
@@ -86,9 +91,7 @@ main (int argc, char *argv[])
   gtk_widget_show (GTK_WIDGET (gvc));
   gtk_widget_show (window);
 
-
-
-
+  gst_camera_capturer_run(gvc);
   gtk_main ();
 
   return 0;
diff --git a/libcesarplayer/test-editor.c b/libcesarplayer/test-editor.c
new file mode 100644
index 0000000..9bfa682
--- /dev/null
+++ b/libcesarplayer/test-editor.c
@@ -0,0 +1,112 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * main.c
+ * Copyright (C) Andoni Morales Alastruey 2008 <ylatuya gmail com>
+ * 
+ * main.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * main.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Compile with:
+ * gcc -o test-editor test-editor.c gst-video-editor.c `pkg-config --cflags --libs gstreamer-0.10 gtk+-2.0` -DOSTYPE_LINUX -O0 -g
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <gst/gst.h>
+#include "gst-video-editor.h"
+
+static GMainLoop *loop;
+
+static gboolean
+percent_done_cb (GstVideoEditor *remuxer, gfloat percent, GstVideoEditor *editor)
+{
+  if (percent == 1) {
+    g_print("SUCESS!\n");
+    g_main_loop_quit (loop);
+  } else {
+    g_print("----> %f%%\n", percent);
+  }
+  return TRUE;
+}
+
+static gboolean
+error_cb (GstVideoEditor *remuxer, gchar *error, GstVideoEditor *editor)
+{
+    g_print("ERROR: %s\n", error);
+    g_main_loop_quit (loop);
+}
+
+int
+main (int argc, char *argv[])
+{
+  GstVideoEditor *editor;
+  VideoEncoderType video_encoder;
+  VideoMuxerType video_muxer;
+  AudioEncoderType audio_encoder;
+  gchar *input_file, *output_file;
+  gchar *err = NULL;
+  guint64 start, stop;
+
+  gst_video_editor_init_backend (&argc, &argv);
+
+  if (argc != 6) {
+    g_print("Usage: test-remuxer input_file output_file format start stop\n");
+    return 1;
+  }
+  input_file = argv[1];
+  output_file = argv[2];
+  start = (guint64) g_strtod (argv[3], NULL);
+  stop = (guint64) g_strtod (argv[4], NULL);
+
+  if (!g_strcmp0(argv[3], "mp4")) {
+    video_encoder = VIDEO_ENCODER_H264;
+    video_muxer = VIDEO_MUXER_MP4;
+    audio_encoder = AUDIO_ENCODER_AAC;
+  } else {
+    err = g_strdup_printf ("Invalid format %s\n", argv[3]);
+    goto error;
+  }
+
+  editor = gst_video_editor_new (NULL);
+  gst_video_editor_set_audio_encoder (editor, &err, audio_encoder);
+  if (err != NULL)
+    goto error;
+  gst_video_editor_set_video_encoder (editor, &err, video_encoder);
+  if (err != NULL)
+    goto error;
+  g_object_set (editor, "output_file", output_file,
+      "width", 320, "height", 240, "enable-audio", FALSE,
+      "enable-title", TRUE, "video-bitrate", 1000, "audio-bitrate", 200000,
+      NULL);
+  gst_video_editor_set_video_muxer (editor, &err, video_muxer);
+  if (err != NULL)
+    goto error;
+  gst_video_editor_add_segment (editor, input_file, start, stop,
+      (gdouble) 1, "Test", TRUE);
+
+  loop = g_main_loop_new (NULL, FALSE);
+  g_signal_connect (editor, "error", G_CALLBACK (error_cb), editor);
+  g_signal_connect (editor, "percent_completed", G_CALLBACK(percent_done_cb),
+      editor);
+  gst_video_editor_start (editor);
+  g_main_loop_run (loop);
+
+  return 0;
+
+error:
+  g_print ("ERROR: %s", err);
+  return 1;
+
+}
+
diff --git a/libcesarplayer/test-remuxer.c b/libcesarplayer/test-remuxer.c
new file mode 100644
index 0000000..02a18bf
--- /dev/null
+++ b/libcesarplayer/test-remuxer.c
@@ -0,0 +1,71 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * main.c
+ * Copyright (C) Andoni Morales Alastruey 2008 <ylatuya gmail com>
+ * 
+ * main.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * main.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Compile with:
+ * gcc -o test-remuxer test-remuxer.c gst-remuxer.c `pkg-config --cflags --libs gstreamer-0.10` -DOSTYPE_LINUX -O0 -g
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include "gst-remuxer.h"
+
+static gboolean
+percent_done_cb (GstRemuxer *remuxer, gfloat percent, GMainLoop *loop)
+{
+  if (percent == 1) {
+    g_print("SUCESS!\n");
+    g_main_loop_quit (loop);
+  } else {
+    g_print("----> %f%%", percent);
+  }
+}
+
+static gboolean
+error_cb (GstRemuxer *remuxer, gchar *error, GMainLoop *loop)
+{
+    g_print("ERROR: %s\n", error);
+    g_main_loop_quit (loop);
+}
+
+int
+main (int argc, char *argv[])
+{
+  GstRemuxer *remuxer;
+  GMainLoop *loop;
+
+  gst_remuxer_init_backend (&argc, &argv);
+
+  if (argc != 3) {
+    g_print("Usage: test-remuxer input_file output_file\n");
+    return 1;
+  }
+  remuxer = gst_remuxer_new (argv[1], argv[2], NULL);
+  gst_remuxer_start (remuxer);
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  g_signal_connect (remuxer, "percent_completed",
+      G_CALLBACK (percent_done_cb), loop);
+  g_signal_connect (remuxer, "error",
+      G_CALLBACK (error_cb), loop);
+
+  g_main_loop_run (loop);
+
+  return 0;
+}
diff --git a/libcesarplayer/src/video-utils.c b/libcesarplayer/video-utils.c
similarity index 79%
rename from libcesarplayer/src/video-utils.c
rename to libcesarplayer/video-utils.c
index d6fc907..6dab75d 100644
--- a/libcesarplayer/src/video-utils.c
+++ b/libcesarplayer/video-utils.c
@@ -1,4 +1,31 @@
-
+/* 
+ * Copyright (C) 2003-2007 the GStreamer project
+ *      Julien Moutte <julien moutte net>
+ *      Ronald Bultje <rbultje ronald bitfreak net>
+ * Copyright (C) 2005-2008 Tim-Philipp MÃller <tim centricular net>
+ * Copyright (C) 2009 Sebastian DrÃge <sebastian droege collabora co uk>
+ * Copyright (C) 2009  Andoni Morales Alastruey <ylatuya gmail com> 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Totem project hereby grant permission for non-gpl compatible GStreamer
+ * plugins to be used and distributed together with GStreamer and Totem. This
+ * permission is above and beyond the permissions granted by the GPL license
+ * Totem is covered by.
+ *
+ */
 
 #include "video-utils.h"
 
@@ -235,8 +262,8 @@ totem_ratio_fits_screen (GdkWindow * video_window, int video_width,
   return TRUE;
 }
 
-void
-gst_set_window_handle(GstXOverlay *xoverlay, GdkWindow *window)
+guintptr
+gst_get_window_handle(GdkWindow *window)
 {
   guintptr window_handle;
 
@@ -248,6 +275,13 @@ gst_set_window_handle(GstXOverlay *xoverlay, GdkWindow *window)
 #elif defined (GDK_WINDOWING_X11)
   window_handle = GDK_WINDOW_XID (window);
 #endif
+
+  return window_handle;
+}
+
+void
+gst_set_window_handle(GstXOverlay *xoverlay, guintptr window_handle)
+{
   gst_x_overlay_set_window_handle (xoverlay, window_handle);
 }
 
diff --git a/libcesarplayer/video-utils.h b/libcesarplayer/video-utils.h
new file mode 100644
index 0000000..4fd9704
--- /dev/null
+++ b/libcesarplayer/video-utils.h
@@ -0,0 +1,70 @@
+/* 
+ * Copyright (C) 2003-2007 the GStreamer project
+ *      Julien Moutte <julien moutte net>
+ *      Ronald Bultje <rbultje ronald bitfreak net>
+ * Copyright (C) 2005-2008 Tim-Philipp MÃller <tim centricular net>
+ * Copyright (C) 2009 Sebastian DrÃge <sebastian droege collabora co uk>
+ * Copyright (C) 2009  Andoni Morales Alastruey <ylatuya gmail com> 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Totem project hereby grant permission for non-gpl compatible GStreamer
+ * plugins to be used and distributed together with GStreamer and Totem. This
+ * permission is above and beyond the permissions granted by the GPL license
+ * Totem is covered by.
+ *
+ */
+
+#include <gst/gst.h>
+#include <gst/interfaces/xoverlay.h>
+#include <gdk/gdk.h>
+#if defined (GDK_WINDOWING_X11)
+#include <gdk/gdkx.h>
+#elif defined (GDK_WINDOWING_WIN32)
+#include <gdk/gdkwin32.h>
+#elif defined (GDK_WINDOWING_QUARTZ)
+#include <gdk/gdkquartz.h>
+#endif
+#include <gtk/gtk.h>
+
+
+#ifdef WIN32
+#define EXPORT __declspec (dllexport)
+#else
+#define EXPORT
+#endif
+
+#define TOTEM_OBJECT_HAS_SIGNAL(obj, name) (g_signal_lookup (name, g_type_from_name (G_OBJECT_TYPE_NAME (obj))) != 0)
+
+void totem_gdk_window_set_invisible_cursor (GdkWindow * window);
+void totem_gdk_window_set_waiting_cursor (GdkWindow * window);
+
+gboolean totem_display_is_local (void);
+
+char *totem_time_to_string (gint64 msecs);
+gint64 totem_string_to_time (const char *time_string);
+char *totem_time_to_string_text (gint64 msecs);
+
+void totem_widget_set_preferred_size (GtkWidget * widget, gint width,
+    gint height);
+gboolean totem_ratio_fits_screen (GdkWindow * window, int video_width,
+    int video_height, gfloat ratio);
+
+void init_backend (int argc, char **argv);
+guintptr gst_get_window_handle (GdkWindow *window);
+void gst_set_window_handle (GstXOverlay *overlay, guintptr window_handle);
+void init_debug();
+
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]