[pitivi] pitivi: Start libpitivi and make use of it to handle viewer embedding



commit 64704126662533bf270839859cf5921c4dc16017
Author: Thibault Saunier <tsaunier gnome org>
Date:   Sat Feb 21 12:32:21 2015 +0100

    pitivi: Start libpitivi and make use of it to handle viewer embedding
    
    We currently need it to be able to cleanly work on mac as the GdkQuartz
    API can not easily be exposed through GI.
    
    This is currently for internal use only but in the long term that will
    be used to expose Pitivi plugin API. We might end up having to gir
    files, one called PitiviInternal and the otherone Pitivi at that point.

 .gitignore                      |    6 +++
 bin/pitivi-git-environment.sh   |    2 +
 configure.ac                    |   37 +++++++++++++++
 pitivi/Makefile.am              |    1 +
 pitivi/libpitivi/Makefile.am    |   62 +++++++++++++++++++++++++
 pitivi/libpitivi/libpitivi.c    |   20 ++++++++
 pitivi/libpitivi/pitivi.h       |   26 +++++++++++
 pitivi/libpitivi/pitiviviewer.c |   95 +++++++++++++++++++++++++++++++++++++++
 pitivi/libpitivi/pitiviviewer.h |   31 +++++++++++++
 pitivi/mediafilespreviewer.py   |    8 +---
 pitivi/utils/pipeline.py        |   10 ----
 pitivi/viewer.py                |   26 +++--------
 12 files changed, 287 insertions(+), 37 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 03cb84c..5f6b5e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,3 +55,9 @@ po/pitivi.pot
 
 # Generated when running the project
 *.pyc
+
+# libpitivi
+pitivi/libpitivi/.deps/*
+pitivi/libpitivi/.libs/*
+*.gir
+*.typelib
diff --git a/bin/pitivi-git-environment.sh b/bin/pitivi-git-environment.sh
index ebada89..b520165 100755
--- a/bin/pitivi-git-environment.sh
+++ b/bin/pitivi-git-environment.sh
@@ -65,6 +65,8 @@ else
 fi
 
 PYTHONPATH=$MYPITIVI/pitivi:$PYTHONPATH
+GI_TYPELIB_PATH=$MYPITIVI/pitivi/pitivi/libpitivi:$GI_TYPELIB_PATH
+LD_LIBRARY_PATH=$MYPITIVI/pitivi/pitivi/libpitivi/.libs:${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
 
 # The following decision has to be made before we've set any env variables,
 # otherwise the script will detect our "gst uninstalled" and think it's the
diff --git a/configure.ac b/configure.ac
index 8961df2..ed70ff3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,3 +1,8 @@
+m4_define([gi_req_version], [1.31.1])
+m4_define([glib_req_version], [2.30.0])
+m4_define([gstreamer_req_version], [1.4.0])
+m4_define([gtk_req_version], [3.10.0])
+
 AC_PREREQ(2.52)
 
 dnl Note for packagers: see pitivi/check.py for the dependencies
@@ -75,6 +80,31 @@ AC_SUBST(CONFIGURED_GI_TYPELIB_PATH)
 
 AC_CONFIG_FILES([bin/pitivi], [chmod +x bin/pitivi])
 
+dnl === GObject introspection =================================================
+
+GOBJECT_INTROSPECTION_CHECK([gi_req_version])
+
+PKG_CHECK_MODULES(GTK, [gtk+-3.0 >= gtk_req_version],
+                        [HAVE_GTK=yes],
+                        [HAVE_GTK=no])
+
+AS_IF([test "x$HAVE_GTK" = xno],
+      [AC_MSG_ERROR([GTK+ >= $gtk_req_version is required])])
+
+PKG_CHECK_MODULES(GTK_X11, gtk+-x11-3.0 >= gtk_req_version, HAVE_GTK_X11=yes, HAVE_GTK_X11=no)
+PKG_CHECK_MODULES(GTK_QUARTZ, gtk+-quartz-3.0 >= gtk_req_version, HAVE_GTK_QUARTZ=yes, HAVE_GTK_QUARTZ=no)
+AM_CONDITIONAL(HAVE_GTK_X11, test "x$HAVE_GTK_X11" = "xyes")
+AM_CONDITIONAL(HAVE_GTK_QUARTZ, test "x$HAVE_GTK_QUARTZ" = "xyes")
+
+PKG_CHECK_MODULES(GSTREAMER, [gstreamer-1.0 >= gstreamer_req_version gstreamer-video-1.0 >= 
gstreamer_req_version],
+                  [HAVE_GSTREAMER=yes],
+                  [HAVE_GSTREAMER=no])
+AC_SUBST(GTK_LIBS)
+
+
+AS_IF([test "x$HAVE_GSTREAMER" = xno],
+      [AC_MSG_ERROR([GStreamer >= $gstreamer_req_version is required])])
+
 PKG_CHECK_MODULES([cairo], [cairo])
 PKG_CHECK_MODULES([py3cairo], [py3cairo])
 
@@ -94,6 +124,12 @@ if test x$BUILD_HELP = xyes; then
   YELP_HELP_INIT
 fi
 
+PITIVI_CFLAGS="$GTK_CFLAGS $GSTREAMER_CFLAGS $GSTREAMER_VIDEO_CFLAGS"
+PITIVI_LIBS="$LIBM $GTK_LIBS $GSTREAMER_LIBS $GSTREAMER_VIDEO_CFLAGS"
+
+AC_SUBST(PITIVI_CFLAGS)
+AC_SUBST(PITIVI_LIBS)
+
 dnl output stuff
 AC_OUTPUT(
 Makefile
@@ -107,6 +143,7 @@ pitivi/dialogs/Makefile
 pitivi/undo/Makefile
 pitivi/utils/Makefile
 pitivi/timeline/Makefile
+pitivi/libpitivi/Makefile
 pitivi/coptimizations/Makefile
 po/Makefile.in
 tests/Makefile
diff --git a/pitivi/Makefile.am b/pitivi/Makefile.am
index ce2cc38..a817fa2 100644
--- a/pitivi/Makefile.am
+++ b/pitivi/Makefile.am
@@ -1,5 +1,6 @@
 SUBDIRS = \
        coptimizations \
+       libpitivi \
        dialogs \
        utils \
        timeline \
diff --git a/pitivi/libpitivi/Makefile.am b/pitivi/libpitivi/Makefile.am
new file mode 100644
index 0000000..4e2e0fd
--- /dev/null
+++ b/pitivi/libpitivi/Makefile.am
@@ -0,0 +1,62 @@
+CLEANFILES =
+
+if HAVE_GTK_QUARTZ
+  AM_CPPFLAGS = '-xobjective-c'
+endif
+
+source_h = \
+  pitiviviewer.h \
+  pitivi.h
+
+source_c = \
+  pitiviviewer.c
+
+noinst_HEADERS = $(source_h)
+
+libpitivi_1_0_la_CFLAGS = $(AM_CFLAGS) $(PITIVI_CFLAGS)
+libpitivi_1_0_la_LIBADD = $(shared_libadd) $(PITIVI_LIBS)
+libpitivi_1_0_la_LDFLAGS = -module -avoid-version $(LIBS) 
+libpitivi_1_0_la_SOURCES = $(source_c)
+
+lib_LTLIBRARIES = libpitivi-1.0.la
+
+INTROSPECTION_GIRS = Pitivi-1.0.gir
+
+introspection_source_h = $(source_h)
+introspection_source_c = $(source_c)
+Pitivi-1.0.gir: $(INTROSPECTION_SCANNER) libpitivi-1.0.la
+               $(INTROSPECTION_SCANNER) -v --namespace Pitivi \
+               --nsversion=1.0 \
+               --identifier-prefix=Pitivi \
+               --symbol-prefix=pitivi \
+               -DIN_GOBJECT_INTROSPECTION=1 \
+               --library=libpitivi-1.0.la \
+               --include=GLib-2.0 \
+               --include=GObject-2.0 \
+               --include=Gst-1.0 \
+               --include=GstVideo-1.0 \
+               --include=Gtk-3.0 \
+               --libtool="${LIBTOOL}" \
+               --pkg glib-2.0 \
+               --pkg gobject-2.0 \
+               --pkg gstreamer-1.0 \
+               --pkg gtk+-3.0 \
+               --output $@ \
+               $(introspection_source_h) \
+               $(introspection_source_c)
+
+girdir = $(datadir)/gir-1.0
+nodist_gir_DATA = $(INTROSPECTION_GIRS)
+CLEANFILES += $(nodist_gir_DATA)
+
+typelibdir = $(libdir)/girepository-1.0
+nodist_typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
+CLEANFILES += $(nodist_typelib_DATA)
+
+%.typelib: %.gir $(INTROSPECTION_COMPILER)
+       $(AM_V_GEN)$(INTROSPECTION_COMPILER) \
+       --includedir='/home/thiblahute/devel/pitivi/1.0-uninstalled/pitivi/pitivi/libpitivi' \
+       --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-1.0` \
+       --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-video-1.0` \
+       --includedir=`$(PKG_CONFIG) --variable=girdir gtk+-3.0` \
+   $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F)
diff --git a/pitivi/libpitivi/libpitivi.c b/pitivi/libpitivi/libpitivi.c
new file mode 100644
index 0000000..92f6356
--- /dev/null
+++ b/pitivi/libpitivi/libpitivi.c
@@ -0,0 +1,20 @@
+/* Pitivi
+ *
+ *
+ * Copyright (C) 2015 Thibault Saunier <tsaunier gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
diff --git a/pitivi/libpitivi/pitivi.h b/pitivi/libpitivi/pitivi.h
new file mode 100644
index 0000000..a092eed
--- /dev/null
+++ b/pitivi/libpitivi/pitivi.h
@@ -0,0 +1,26 @@
+/* Pitivi
+ *
+ * Copyright (C) 2015 Thibault Saunier <tsaunier gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __PITIVI_H__
+#define __PITIVI_H__
+
+#include "pitiviviewer.h"
+
+#endif /* __PITIVI_H__ */
diff --git a/pitivi/libpitivi/pitiviviewer.c b/pitivi/libpitivi/pitiviviewer.c
new file mode 100644
index 0000000..1e920ee
--- /dev/null
+++ b/pitivi/libpitivi/pitiviviewer.c
@@ -0,0 +1,95 @@
+/* Pitivi
+ *
+ * Copyright (C) 2015 Thibault Saunier <tsaunier gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pitiviviewer.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
+
+
+static guintptr
+get_window_handle (GtkWidget * widget)
+{
+  guintptr embed_xid;
+
+  GdkWindow *window = gtk_widget_get_window (widget);
+
+  g_return_val_if_fail (gdk_window_ensure_native (window), FALSE);
+
+#if defined (GDK_WINDOWING_WIN32)
+  embed_xid = (guintptr) GDK_WINDOW_HWND (window);
+#elif defined (GDK_WINDOWING_QUARTZ)
+  embed_xid = (guintptr) gdk_quartz_window_get_nsview (window);
+#elif defined (GDK_WINDOWING_X11)
+  embed_xid = GDK_WINDOW_XID (window);
+#endif
+
+  return embed_xid;
+}
+
+static void
+realize_cb (GtkWidget * widget, GstElement * videosink)
+{
+  gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (videosink),
+      get_window_handle (widget));
+
+  g_signal_handlers_disconnect_by_func (widget, realize_cb, videosink);
+}
+
+/**
+ * pitivi_viewer_new:
+ * @videosink: (transfer none) (allow-none): the sink
+ *
+ * Returns: (transfer full): The new GtkDrawing area ready to be used
+ */
+GtkWidget *
+pitivi_viewer_new (GstElement * videosink)
+{
+  GtkWidget *res = gtk_drawing_area_new ();
+
+  if (videosink)
+    pitivi_viewer_set_sink (res, videosink);
+
+  return res;
+}
+
+gboolean
+pitivi_viewer_set_sink (GtkWidget * widget, GstElement * videosink)
+{
+  if (gtk_widget_get_realized (widget)) {
+    gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (videosink),
+        get_window_handle (widget));
+    return TRUE;
+  }
+
+  g_signal_connect (widget, "realize", G_CALLBACK (realize_cb), videosink);
+
+  return FALSE;
+}
diff --git a/pitivi/libpitivi/pitiviviewer.h b/pitivi/libpitivi/pitiviviewer.h
new file mode 100644
index 0000000..fd9853f
--- /dev/null
+++ b/pitivi/libpitivi/pitiviviewer.h
@@ -0,0 +1,31 @@
+/* Pitivi
+ *
+ * Copyright (C) 2015 Thibault Saunier <tsaunier gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __PITIVI_VIEWER_H__
+#define __PITIVI_VIEWER_H__
+
+#include <gst/gst.h>
+#include <gst/video/videooverlay.h>
+#include <gtk/gtk.h>
+
+GtkWidget *pitivi_viewer_new (GstElement *videosink);
+gboolean pitivi_viewer_set_sink (GtkWidget * widget, GstElement * videosink);
+
+#endif /* __PITIVI_VIEWER_H__ */
diff --git a/pitivi/mediafilespreviewer.py b/pitivi/mediafilespreviewer.py
index d72c00f..b828590 100644
--- a/pitivi/mediafilespreviewer.py
+++ b/pitivi/mediafilespreviewer.py
@@ -108,9 +108,7 @@ class PreviewWidget(Gtk.Grid, Loggable):
 
         # Gui elements:
         # Drawing area for video output
-        self.preview_video = ViewerWidget(
-            realizedCb=self._on_preview_video_realize_cb)
-        self.preview_video.sink = self.player.video_sink
+        self.preview_video = ViewerWidget(sink=self.player.video_sink)
         self.preview_video.props.hexpand = minimal
         self.preview_video.props.vexpand = minimal
         self.attach(self.preview_video, 0, 0, 1, 1)
@@ -368,10 +366,6 @@ class PreviewWidget(Gtk.Grid, Loggable):
             self.pos_adj.set_value(int(curr_pos))
         return self.is_playing
 
-    def _on_preview_video_realize_cb(self, unused_drawing_area, unused_widget):
-        if self.current_preview_type == 'video':
-            self.player.connectWithViewer(self.preview_video)
-
     def _on_start_stop_clicked_cb(self, button):
         if self.is_playing:
             self.pause()
diff --git a/pitivi/utils/pipeline.py b/pitivi/utils/pipeline.py
index 9602d3b..300636a 100644
--- a/pitivi/utils/pipeline.py
+++ b/pitivi/utils/pipeline.py
@@ -194,8 +194,6 @@ class SimplePipeline(GObject.Object, Loggable):
         self._timeout_async_id = 0
         self._force_position_listener = False
 
-        # Create a cluttersink element used for display. Subclasses must connect
-        # it to self._pipeline themselves
         self.video_sink = Gst.ElementFactory.make("glimagesink", None)
         if isinstance(pipeline, GES.Pipeline):
             self._pipeline.preview_set_video_sink(self.video_sink)
@@ -574,14 +572,6 @@ class AssetPipeline(SimplePipeline):
     def setClipUri(self, uri):
         self._pipeline.set_property("uri", uri)
 
-    def connectWithViewer(self, widget):
-        if platform.system() == 'Windows':
-            handle = widget.drawing_area.get_window().get_handle()
-        else:
-            handle = widget.drawing_area.get_window().get_xid()
-
-        self.video_sink.set_window_handle(handle)
-
 
 class Pipeline(GES.Pipeline, SimplePipeline):
 
diff --git a/pitivi/viewer.py b/pitivi/viewer.py
index a285f29..ff2a40b 100644
--- a/pitivi/viewer.py
+++ b/pitivi/viewer.py
@@ -23,14 +23,10 @@ from gi.repository import Clutter
 from gi.repository import Gtk
 from gi.repository import GtkClutter
 from gi.repository import Gdk
-try:
-    from gi.repository import GdkX11
-except ImportError:
-
-    pass
 from gi.repository import Gst
 from gi.repository import GObject
 from gi.repository import GES
+from gi.repository import Pitivi
 import cairo
 
 from gettext import gettext as _
@@ -492,19 +488,9 @@ class ViewerContainer(Gtk.Box, Loggable):
         if self.pipeline is None:
             return
 
-        if self.target.get_realized():
-            self.debug("Connecting the pipeline to the viewer's texture")
-            if platform.system() == 'Windows':
-                xid = self.target.drawing_area.get_window().get_handle()
-            else:
-                xid = self.target.drawing_area.get_window().get_xid()
-
-            self.sink.set_window_handle(xid)
+        self.target.show()
+        if Pitivi.viewer_set_sink(self.target.drawing_area, self.sink):
             self.sink.expose()
-        else:
-            # Show the widget and wait for the realized callback
-            self.log("Target is not realized, showing the widget")
-            self.target.show()
 
 
 class Point():
@@ -840,14 +826,14 @@ class ViewerWidget(Gtk.AspectFrame, Loggable):
 
     __gsignals__ = {}
 
-    def __init__(self, settings=None, realizedCb=None):
+    def __init__(self, settings=None, realizedCb=None, sink=None):
         # Prevent black frames and flickering while resizing or changing focus:
         # The aspect ratio gets overridden by setDisplayAspectRatio.
         Gtk.AspectFrame.__init__(self, xalign=0.5, yalign=0.5,
                                  ratio=4.0 / 3.0, obey_child=False)
         Loggable.__init__(self)
 
-        self.drawing_area = Gtk.DrawingArea()
+        self.drawing_area = Pitivi.viewer_new(sink)
         self.drawing_area.set_double_buffered(False)
         self.drawing_area.connect("draw", self._drawCb, None)
         # We keep the ViewerWidget hidden initially, or the desktop wallpaper
@@ -864,7 +850,7 @@ class ViewerWidget(Gtk.AspectFrame, Loggable):
         self.stored = False
         self.area = None
         self.zoom = 1.0
-        self.sink = None
+        self.sink = sink
         self.pixbuf = None
         self.pipeline = None
         self.transformation_properties = None


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