banshee r3483 - in trunk/banshee: . build/m4/banshee libbanshee src/Backends/Banshee.GStreamer/Banshee.GStreamer src/Core/Banshee.Services/Banshee.MediaEngine src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying



Author: abock
Date: Wed Mar 19 04:54:17 2008
New Revision: 3483
URL: http://svn.gnome.org/viewvc/banshee?rev=3483&view=rev

Log:
2008-03-19  Aaron Bockover  <abock gnome org>

    * build/m4/banshee/gstreamer.m4: Link gstinterfaces and gstvideo libraries

    * libbanshee/gst-playback-0.10.c: First pass at hopefully properly
    implementing the GstXOverlay stuff; adds video rough video support
    to the pipeline/player engine

    * src/Core/Banshee.Services/Banshee.MediaEngine/NullPlayerEngine.cs:
    * src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs:
    * src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs:
    Implement a few video related features to allow setting/exposing to a
    GdkWindow for video support

    * src/Backends/Banshee.GStreamer/Banshee.GStreamer/PlayerEngine.cs:
    Send the GdkWindow/Video calls into the player engine - binds the
    pipeline XOverlay to a window in the UI

    * src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/VideoDisplay.cs:
    Managed GdkWindow and video slab display widget thingy that can be
    drawn on by an engine



Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/build/m4/banshee/gstreamer.m4
   trunk/banshee/libbanshee/gst-playback-0.10.c
   trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/PlayerEngine.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/NullPlayerEngine.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs
   trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/VideoDisplay.cs

Modified: trunk/banshee/build/m4/banshee/gstreamer.m4
==============================================================================
--- trunk/banshee/build/m4/banshee/gstreamer.m4	(original)
+++ trunk/banshee/build/m4/banshee/gstreamer.m4	Wed Mar 19 04:54:17 2008
@@ -9,7 +9,9 @@
 		gstreamer-plugins-base-0.10 >= $GSTREAMER_REQUIRED_VERSION
 		gstreamer-controller-0.10 >= $GSTREAMER_REQUIRED_VERSION
 		gstreamer-dataprotocol-0.10 >= $GSTREAMER_REQUIRED_VERSION)
-	
+
+	GST_LIBS="$GST_LIBS -lgstvideo-0.10 -lgstinterfaces-0.10"
+
 	PKG_CHECK_MODULES(GST_PBUTILS, gstreamer-plugins-base-0.10 >= 0.10.12, 
 		gst_pbutils=yes, gst_pbutils=no)
 

Modified: trunk/banshee/libbanshee/gst-playback-0.10.c
==============================================================================
--- trunk/banshee/libbanshee/gst-playback-0.10.c	(original)
+++ trunk/banshee/libbanshee/gst-playback-0.10.c	Wed Mar 19 04:54:17 2008
@@ -46,6 +46,7 @@
 #include <gdk/gdk.h>
 #ifdef GDK_WINDOWING_X11
 #include <gdk/gdkx.h>
+#include <gst/interfaces/xoverlay.h>
 #endif
 
 #include "gst-tagger.h"
@@ -71,6 +72,13 @@
     GstElement *equalizer;
     GstElement *preamp;
     
+    GMutex *mutex;
+
+    #ifdef GDK_WINDOWING_X11
+    GstXOverlay *xoverlay;
+    GdkWindow *video_window;
+    #endif
+
     guint iterate_timeout_id;
     gchar *cdda_device;
     
@@ -93,6 +101,10 @@
     #endif
 };
 
+#ifdef GDK_WINDOWING_X11
+static gboolean gst_playback_find_xoverlay (GstPlayback *engine);
+#endif
+
 // private methods
 
 static void
@@ -384,10 +396,47 @@
     return FALSE;
 }
 
+static void
+gst_playback_video_sink_element_added (GstBin *videosink, GstElement *element, GstPlayback *engine)
+{
+    g_return_if_fail (IS_GST_PLAYBACK (engine));
+
+    #ifdef GDK_WINDOWING_X11
+    g_mutex_lock (engine->mutex);
+    gst_playback_find_xoverlay (engine);
+    g_mutex_unlock (engine->mutex);    
+    #endif
+}
+
+static void
+gst_playback_bus_element_sync_message (GstBus *bus, GstMessage *message, GstPlayback *engine)
+{
+    gboolean found_xoverlay;
+    
+    g_return_if_fail (IS_GST_PLAYBACK (engine));
+
+    #ifdef GDK_WINDOWING_X11
+
+    if (message->structure == NULL || !gst_structure_has_name (message->structure, "prepare-xwindow-id")) {
+        return;
+    }
+
+    g_mutex_lock (engine->mutex);
+    found_xoverlay = gst_playback_find_xoverlay (engine);
+    g_mutex_unlock (engine->mutex);
+
+    if (found_xoverlay) {
+        gst_x_overlay_set_xwindow_id (engine->xoverlay, GDK_WINDOW_XWINDOW (engine->video_window));
+    }
+
+    #endif
+}
+
 static gboolean 
 gst_playback_construct(GstPlayback *engine)
 {
-    GstElement *fakesink;
+    GstBus *bus;
+    GstElement *videosink;
     GstElement *audiosink;
     GstElement *audiosinkqueue;
     GstElement *audioconvert;
@@ -446,23 +495,42 @@
         gst_element_link(engine->preamp, engine->equalizer);
         gst_element_link(engine->equalizer, audioconvert);
         gst_element_link(audioconvert, audiosink);
-    }
-    else
-    {
+    } else {
         // link the queue with the real audio sink
         gst_element_link(audiosinkqueue, audiosink);
     }
     
-    g_object_set(G_OBJECT(engine->playbin), "audio-sink", engine->audiobin, NULL);
+    g_object_set (G_OBJECT (engine->playbin), "audio-sink", engine->audiobin, NULL);
+    
+    videosink = gst_element_factory_make ("gconfvideosink", "videosink");
+    if (videosink == NULL) {
+        videosink = gst_element_factory_make ("ximagesink", "videosink");
+        if (videosink == NULL) {
+            videosink = gst_element_factory_make ("fakesink", "videosink");
+            if (videosink != NULL) {
+                g_object_set (G_OBJECT (videosink), "sync", TRUE, NULL);
+            }
+        }
+    }
+    
+    g_object_set (G_OBJECT (engine->playbin), "video-sink", videosink, NULL);
+
+    bus = gst_pipeline_get_bus (GST_PIPELINE (engine->playbin));
     
-    fakesink = gst_element_factory_make("fakesink", "fakesink");
-    g_object_set(G_OBJECT(engine->playbin), "video-sink", fakesink, NULL);
+    gst_bus_add_watch (bus, gst_playback_bus_callback, engine);
+    gst_bus_set_sync_handler (bus, gst_bus_sync_signal_handler, engine);
+
+    g_signal_connect (bus, "sync-message::element", 
+        G_CALLBACK (gst_playback_bus_element_sync_message), engine);
+
+    g_signal_connect (engine->playbin, "notify::source", 
+        G_CALLBACK (gst_playback_on_notify_source_cb), engine);
+    
+    if (GST_IS_BIN (videosink)) {
+        g_signal_connect (videosink, "element-added",
+            G_CALLBACK (gst_playback_video_sink_element_added), engine);
+    }
 
-    gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(engine->playbin)), 
-        gst_playback_bus_callback, engine);
-        
-    g_signal_connect(engine->playbin, "notify::source", G_CALLBACK(gst_playback_on_notify_source_cb), engine);
-        
     return TRUE;
 }
 
@@ -510,6 +578,9 @@
 gst_playback_new()
 {
     GstPlayback *engine = g_new0(GstPlayback, 1);
+    
+    engine->mutex = g_mutex_new ();
+    
     if(!gst_playback_construct(engine)) {
         g_free(engine);
         return NULL;
@@ -523,6 +594,8 @@
 {
     g_return_if_fail(IS_GST_PLAYBACK(engine));
     
+    g_mutex_free (engine->mutex);
+    
     if(GST_IS_OBJECT(engine->playbin)) {
         engine->target_state = GST_STATE_NULL;
         gst_element_set_state(engine->playbin, GST_STATE_NULL);
@@ -770,7 +843,7 @@
 }
 
 void
-gst_playback_set_gdk_window(GstPlayback *engine, GdkWindow *window)
+gst_playback_set_application_gdk_window(GstPlayback *engine, GdkWindow *window)
 {
     engine->window = window;
 }
@@ -784,10 +857,116 @@
     *stream = GST_STREAM_ERROR;
 }
 
+/* Region XOverlay */
+
+#ifdef GDK_WINDOWING_X11
+
+gboolean
+gst_playback_video_is_supported (GstPlayback *engine)
+{
+    return TRUE; // gst_playback_find_xoverlay (engine);
+}
+
+static gboolean
+gst_playback_find_xoverlay (GstPlayback *engine)
+{
+    GstElement *video_sink = NULL;
+    GstElement *xoverlay;
+    GstXOverlay *previous_xoverlay;
+
+    previous_xoverlay = engine->xoverlay;
+    
+    g_object_get (engine->playbin, "video-sink", &video_sink, NULL);
+    
+    if (video_sink == NULL) {
+        engine->xoverlay = NULL;
+        if (previous_xoverlay != NULL) {
+            gst_object_unref (previous_xoverlay);
+        }
+
+        return FALSE;
+    }
+    
+    xoverlay = GST_IS_BIN (video_sink)
+        ? gst_bin_get_by_interface (GST_BIN (video_sink), GST_TYPE_X_OVERLAY)
+        : video_sink;
+    
+    engine->xoverlay = GST_IS_X_OVERLAY (xoverlay) ? GST_X_OVERLAY (xoverlay) : NULL;
+    
+    if (previous_xoverlay != NULL) {
+        gst_object_unref (previous_xoverlay);
+    }
+        
+    if (engine->xoverlay != NULL && g_object_class_find_property (
+        G_OBJECT_GET_CLASS (engine->xoverlay), "force-aspect-ratio")) {
+        g_object_set (G_OBJECT (engine->xoverlay), "force-aspect-ratio", TRUE, NULL);
+    }
+
+    gst_object_unref (video_sink);
+
+    return engine->xoverlay != NULL;
+}
+
+void
+gst_playback_set_video_window (GstPlayback *engine, GdkWindow *window)
+{
+    engine->video_window = window;
+}
+
+void
+gst_playback_expose_video_window (GstPlayback *engine, GdkWindow *window, gboolean direct)
+{
+    XID window_id;
+    
+    if (direct && engine->xoverlay != NULL && GST_IS_X_OVERLAY (engine->xoverlay)) {
+        gst_x_overlay_expose (engine->xoverlay);
+        return;
+    }
+   
+    g_mutex_lock (engine->mutex);
+   
+    if (engine->xoverlay == NULL && !gst_playback_find_xoverlay (engine)) {
+        g_mutex_unlock (engine->mutex);
+        return;
+    }
+    
+    gst_object_ref (engine->xoverlay);
+    g_mutex_unlock (engine->mutex);
+
+    window_id = GDK_WINDOW_XWINDOW (window);
+
+    gst_x_overlay_set_xwindow_id (engine->xoverlay, window_id);
+    gst_x_overlay_expose (engine->xoverlay);
+
+    gst_object_unref (engine->xoverlay);
+}
+
+#else
+
+gboolean
+gst_playback_video_is_supported (GstPlayback *engine)
+{
+    return FALSE;
+}
+
+void
+gst_playback_set_video_window (GstPlayback *engine, GdkWindow *window)
+{
+}
+
+void
+gst_playback_expose_video_window (GstPlayback *engine, GdkWindow *window, gboolean direct)
+{
+}
+
+#endif
+
+/* Region Equalizer */
+
 gboolean
 gst_equalizer_is_supported(GstPlayback *engine)
 {
-    return (engine != NULL && engine->equalizer != NULL && engine->preamp != NULL);
+    return engine != NULL && engine->equalizer != NULL && engine->preamp != NULL;
 }
 
 void

Modified: trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/PlayerEngine.cs
==============================================================================
--- trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/PlayerEngine.cs	(original)
+++ trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/PlayerEngine.cs	Wed Mar 19 04:54:17 2008
@@ -137,7 +137,7 @@
 
             IPropertyStoreExpose service = ServiceManager.Get<IService> ("GtkElementsService") as IPropertyStoreExpose;
             if (service != null) {
-                gst_playback_set_gdk_window (handle, service.PropertyStore.Get<IntPtr> ("PrimaryWindow.RawHandle"));
+                gst_playback_set_application_gdk_window (handle, service.PropertyStore.Get<IntPtr> ("PrimaryWindow.RawHandle"));
             }
                 
             IntPtr uri_ptr = GLib.Marshaller.StringToPtrGStrdup (uri.AbsoluteUri);
@@ -156,6 +156,11 @@
             gst_playback_pause (handle);
             OnStateChanged (PlayerEngineState.Paused);
         }
+        
+        public override void VideoExpose (IntPtr window, bool direct)
+        {
+            gst_playback_expose_video_window (handle, window, direct);
+        }
 
         public override IntPtr [] GetBaseElements ()
         {
@@ -312,14 +317,35 @@
             get { return "GStreamer 0.10"; }
         }
         
+        private bool? supports_equalizer = null;
         public override bool SupportsEqualizer {
-            get { return gst_equalizer_is_supported (handle); }
+            get { 
+                if (supports_equalizer == null) {
+                    supports_equalizer = gst_equalizer_is_supported (handle); 
+                }
+                
+                return supports_equalizer.Value;
+            }
+        }
+        
+        private bool? supports_video = null;
+        public override bool SupportsVideo {
+            get { 
+                if (supports_video == null) {
+                    supports_video = gst_playback_video_is_supported (handle); 
+                }
+                
+                return supports_video.Value;
+            }
         }
-    
+        
+        public override IntPtr VideoWindow {
+            set { gst_playback_set_video_window (handle, value); }
+        }
+        
         public double AmplifierLevel {
             set {
-                double db = Math.Pow (10.0, value/20.0);
-
+                double db = Math.Pow (10.0, value / 20.0);
                 gst_equalizer_set_preamp_level (handle, db);
             }
         }
@@ -427,7 +453,16 @@
             out IntPtr audiobin, out IntPtr audiotee);
             
         [DllImport ("libbanshee")]
-        private static extern void gst_playback_set_gdk_window (HandleRef engine, IntPtr window);
+        private static extern void gst_playback_set_application_gdk_window (HandleRef engine, IntPtr window);
+        
+        [DllImport ("libbanshee")]
+        private static extern bool gst_playback_video_is_supported (HandleRef engine);
+        
+        [DllImport ("libbanshee")]
+        private static extern void gst_playback_set_video_window (HandleRef engine, IntPtr window);
+        
+        [DllImport ("libbanshee")]
+        private static extern void gst_playback_expose_video_window (HandleRef engine, IntPtr window, bool direct);
                                                                    
         [DllImport ("libbanshee")]
         private static extern void gst_playback_get_error_quarks (out uint core, out uint library, 

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/NullPlayerEngine.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/NullPlayerEngine.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/NullPlayerEngine.cs	Wed Mar 19 04:54:17 2008
@@ -62,6 +62,10 @@
             get { return false; }
         }
         
+        public override bool SupportsVideo {
+            get { return false; }
+        }
+        
         private static string [] source_capabilities = { "file", "http", "cdda" };
         public override IEnumerable SourceCapabilities {
             get { return source_capabilities; }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs	Wed Mar 19 04:54:17 2008
@@ -111,6 +111,11 @@
             OnStateChanged (PlayerEngineState.Paused);
         }
         
+        public virtual void VideoExpose (IntPtr window, bool direct)
+        {
+            throw new NotImplementedException ("Engine must implement VideoExpose since this method only gets called when SupportsVideo is true");
+        }
+        
         public virtual IntPtr [] GetBaseElements ()
         {
             return null;
@@ -273,5 +278,13 @@
         public abstract bool SupportsEqualizer {
             get;
         }
+        
+        public abstract bool SupportsVideo {
+            get;
+        }
+        
+        public virtual IntPtr VideoWindow {
+            set { }
+        }
     }
 }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs	Wed Mar 19 04:54:17 2008
@@ -354,6 +354,15 @@
             }
         }
         
+        public void VideoExpose (IntPtr window, bool direct)
+        {
+            active_engine.VideoExpose (window, direct);
+        }
+        
+        public IntPtr VideoWindow {
+            set { active_engine.VideoWindow = value; }
+        }
+        
         public void TrackInfoUpdated ()
         {
             active_engine.TrackInfoUpdated ();
@@ -435,6 +444,10 @@
             get { return ((active_engine is IEqualizer) && active_engine.SupportsEqualizer); }
         }
         
+        public bool SupportsVideo {
+            get { return active_engine.SupportsVideo; }
+        }
+        
         public uint Length {
             get { 
                 uint length = active_engine.Length;

Modified: trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/VideoDisplay.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/VideoDisplay.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/VideoDisplay.cs	Wed Mar 19 04:54:17 2008
@@ -30,37 +30,31 @@
 using Gtk;
 
 using Banshee.Gui;
+using Banshee.MediaEngine;
+using Banshee.ServiceStack;
 
 namespace Banshee.NowPlaying
 {   
     public class VideoDisplay : Gtk.Widget
     {
         private Gdk.Pixbuf idle_pixbuf;
+        private Gdk.Window video_window;
     
         public VideoDisplay ()
         {
+            CreateVideoWindow ();
         }
         
-        protected override void OnRealized ()
+        private void CreateVideoWindow ()
         {
-            WidgetFlags |= WidgetFlags.Realized;
-            
             Gdk.WindowAttr attributes = new Gdk.WindowAttr ();
             attributes.WindowType = Gdk.WindowType.Child;
-            attributes.X = Allocation.X;
-            attributes.Y = Allocation.Y;
-            attributes.Width = Allocation.Width;
-            attributes.Height = Allocation.Height;
             attributes.Visual = Visual;
             attributes.Wclass = Gdk.WindowClass.InputOutput;
             attributes.Colormap = Colormap;
             attributes.EventMask = (int)(
                 Gdk.EventMask.VisibilityNotifyMask |
-                Gdk.EventMask.ExposureMask |
-                Gdk.EventMask.PointerMotionMask |
-                Gdk.EventMask.EnterNotifyMask |
-                Gdk.EventMask.LeaveNotifyMask |
-                Events);
+                Gdk.EventMask.ExposureMask);
             
             Gdk.WindowAttributesType attributes_mask = 
                 Gdk.WindowAttributesType.X | 
@@ -68,11 +62,35 @@
                 Gdk.WindowAttributesType.Visual | 
                 Gdk.WindowAttributesType.Colormap;
                 
+            video_window = new Gdk.Window (null, attributes, attributes_mask);
+            video_window.UserData = Handle;
+            
+            video_window.SetBackPixmap (null, false);
+            Style = Style.Attach (video_window);
+            
+            ServiceManager.PlayerEngine.VideoWindow = video_window.Handle;
+        }
+        
+        protected override void OnRealized ()
+        {
+            WidgetFlags |= WidgetFlags.Realized;
+        
+            Gdk.WindowAttr attributes = new Gdk.WindowAttr ();
+            attributes.WindowType = Gdk.WindowType.Child;
+            attributes.X = Allocation.X;
+            attributes.Y = Allocation.Y;
+            attributes.Width = Allocation.Width;
+            attributes.Height = Allocation.Height;
+            attributes.Wclass = Gdk.WindowClass.InputOnly;
+            
+            Gdk.WindowAttributesType attributes_mask = 
+                Gdk.WindowAttributesType.X | 
+                Gdk.WindowAttributesType.Y;
+                
             GdkWindow = new Gdk.Window (Parent.GdkWindow, attributes, attributes_mask);
             GdkWindow.UserData = Handle;
             
-            GdkWindow.SetBackPixmap (null, false);
-            Style = Style.Attach (GdkWindow);
+            video_window.Reparent (Parent.GdkWindow, Allocation.X, Allocation.Y);
         }
         
         protected override void OnUnrealized ()
@@ -80,17 +98,20 @@
             WidgetFlags ^= WidgetFlags.Realized;
             GdkWindow.UserData = IntPtr.Zero;
             GdkWindow.Destroy ();
+            video_window.Reparent (null, 0, 0);
         }
 
         protected override void OnMapped ()
         {
             WidgetFlags |= WidgetFlags.Mapped;
+            video_window.Show ();
             GdkWindow.Show ();
         }
         
         protected override void OnUnmapped ()
         {
             WidgetFlags ^= WidgetFlags.Mapped;
+            video_window.Hide ();
             GdkWindow.Hide ();
         }
         
@@ -98,16 +119,31 @@
         {
             base.OnSizeAllocated (allocation);
             
-            if (IsRealized) {
+            if (IsRealized && IsMapped) {
+                video_window.MoveResize (allocation);
                 GdkWindow.MoveResize (allocation);
             }
             
             QueueDraw ();
         }
         
+        protected override bool OnConfigureEvent (Gdk.EventConfigure evnt)
+        {
+            if (ServiceManager.PlayerEngine.SupportsVideo) {
+                ServiceManager.PlayerEngine.VideoExpose (video_window.Handle, true);
+            }
+            
+            return false;
+        }
+
         protected override bool OnExposeEvent (Gdk.EventExpose evnt)
         {
-            if (!Visible || !IsMapped || GdkWindow == null) {
+            if (!Visible || !IsMapped || video_window == null) {
+                return true;
+            }
+            
+            if (ServiceManager.PlayerEngine.SupportsVideo) {
+                ServiceManager.PlayerEngine.VideoExpose (video_window.Handle, false);
                 return true;
             }
             
@@ -119,7 +155,7 @@
                 return true;
             }
             
-            GdkWindow.DrawPixbuf (Style.BackgroundGC (StateType.Normal), idle_pixbuf, 0, 0, 
+            video_window.DrawPixbuf (Style.BackgroundGC (StateType.Normal), idle_pixbuf, 0, 0, 
                 (Allocation.Width - idle_pixbuf.Width) / 2, (Allocation.Height - idle_pixbuf.Height) / 2, 
                 idle_pixbuf.Width, idle_pixbuf.Height, Gdk.RgbDither.Normal, 0, 0);
             



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