[banshee] [XOverlay] fix video embed bnc#585817, bgo#548635



commit 074a32f7a180350aff599a0e90a178c5667403ac
Author: Aaron Bockover <abockover novell com>
Date:   Sat May 1 16:19:34 2010 -0400

    [XOverlay] fix video embed bnc#585817, bgo#548635
    
    GStreamer requires an X11 window handle to be set on the XOverlay
    interface of the video sink in order to render video. If one is not set
    in time, GStreamer will create its own X window. Closing this window
    will result in a crash, since it becomes unrealized, after which
    GStreamer will continue to try to render to it.
    
    Before, the X11 video window was created when the Now Playing UI
    was realized. The window is now created when the pipeline is created, by
    raising the new PrepareVideoWindow event. Technically, this event should
    be raised when the prepare-xwindow-id message is pushed onto the
    pipeline bus, but this is raised out of the main thread.

 libbanshee/banshee-player-private.h                |    2 +
 libbanshee/banshee-player-video.c                  |   10 ++++++
 .../Banshee.GStreamer/PlayerEngine.cs              |   14 ++++++++
 .../Banshee.MediaEngine/PlayerEngine.cs            |    1 +
 .../Banshee.MediaEngine/PlayerEngineService.cs     |    3 +-
 .../Banshee.MediaEngine/PlayerEvent.cs             |    3 +-
 .../Banshee.NowPlaying/NowPlayingContents.cs       |   12 ++++++-
 .../Banshee.NowPlaying/NowPlayingSource.cs         |    7 ++++
 .../Banshee.NowPlaying/XOverlayVideoDisplay.cs     |   35 +++++++++++--------
 9 files changed, 68 insertions(+), 19 deletions(-)
---
diff --git a/libbanshee/banshee-player-private.h b/libbanshee/banshee-player-private.h
index 3e0ad26..66ee2a7 100644
--- a/libbanshee/banshee-player-private.h
+++ b/libbanshee/banshee-player-private.h
@@ -98,6 +98,7 @@ typedef void (* BansheePlayerVisDataCallback)      (BansheePlayer *player, gint
 typedef void (* BansheePlayerNextTrackStartingCallback)     (BansheePlayer *player);
 typedef void (* BansheePlayerAboutToFinishCallback)         (BansheePlayer *player);
 typedef GstElement * (* BansheePlayerVideoPipelineSetupCallback) (BansheePlayer *player, GstBus *bus);
+typedef void (* BansheePlayerVideoPrepareWindowCallback) (BansheePlayer *player);
 typedef void (* BansheePlayerVolumeChangedCallback) (BansheePlayer *player, gdouble new_volume);
 typedef void (* BansheePlayerVideoGeometryNotifyCallback) (BansheePlayer *player, gint width, gint height, gint fps_n, gint fps_d, gint par_n, gint par_d);
 
@@ -119,6 +120,7 @@ struct BansheePlayer {
     BansheePlayerNextTrackStartingCallback next_track_starting_cb;
     BansheePlayerAboutToFinishCallback about_to_finish_cb;
     BansheePlayerVideoPipelineSetupCallback video_pipeline_setup_cb;
+    BansheePlayerVideoPrepareWindowCallback video_prepare_window_cb;
     BansheePlayerVolumeChangedCallback volume_changed_cb;
     BansheePlayerVideoGeometryNotifyCallback video_geometry_notify_cb;
 
diff --git a/libbanshee/banshee-player-video.c b/libbanshee/banshee-player-video.c
index e757a99..e092095 100644
--- a/libbanshee/banshee-player-video.c
+++ b/libbanshee/banshee-player-video.c
@@ -251,6 +251,10 @@ _bp_video_pipeline_setup (BansheePlayer *player, GstBus *bus)
     #endif
     
     #endif
+
+    if (player->video_prepare_window_cb != NULL) {
+        player->video_prepare_window_cb (player);
+    }
 }
 
 P_INVOKE void
@@ -265,6 +269,12 @@ bp_set_video_geometry_notify_callback (BansheePlayer *player, BansheePlayerVideo
     SET_CALLBACK (video_geometry_notify_cb);
 }
 
+P_INVOKE void
+bp_set_video_prepare_window_callback (BansheePlayer *player, BansheePlayerVideoPrepareWindowCallback cb)
+{
+    SET_CALLBACK (video_prepare_window_cb);
+}
+
 // ---------------------------------------------------------------------------
 // Public Functions
 // ---------------------------------------------------------------------------
diff --git a/src/Backends/Banshee.GStreamer/Banshee.GStreamer/PlayerEngine.cs b/src/Backends/Banshee.GStreamer/Banshee.GStreamer/PlayerEngine.cs
index 499a913..0ae25b3 100644
--- a/src/Backends/Banshee.GStreamer/Banshee.GStreamer/PlayerEngine.cs
+++ b/src/Backends/Banshee.GStreamer/Banshee.GStreamer/PlayerEngine.cs
@@ -69,6 +69,8 @@ namespace Banshee.GStreamer
     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
     internal delegate IntPtr VideoPipelineSetupHandler (IntPtr player, IntPtr bus);
     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    internal delegate void VideoPrepareWindowHandler (IntPtr player);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
     internal delegate void BansheePlayerVolumeChangedCallback (IntPtr player, double newVolume);
 
     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
@@ -93,6 +95,7 @@ namespace Banshee.GStreamer
         private BansheePlayerBufferingCallback buffering_callback;
         private BansheePlayerVisDataCallback vis_data_callback;
         private VideoPipelineSetupHandler video_pipeline_setup_callback;
+        private VideoPrepareWindowHandler video_prepare_window_callback;
         private GstTaggerTagFoundCallback tag_found_callback;
         private BansheePlayerNextTrackStartingCallback next_track_starting_callback;
         private BansheePlayerAboutToFinishCallback about_to_finish_callback;
@@ -157,6 +160,7 @@ namespace Banshee.GStreamer
             buffering_callback = new BansheePlayerBufferingCallback (OnBuffering);
             vis_data_callback = new BansheePlayerVisDataCallback (OnVisualizationData);
             video_pipeline_setup_callback = new VideoPipelineSetupHandler (OnVideoPipelineSetup);
+            video_prepare_window_callback = new VideoPrepareWindowHandler (OnVideoPrepareWindow);
             tag_found_callback = new GstTaggerTagFoundCallback (OnTagFound);
             next_track_starting_callback = new BansheePlayerNextTrackStartingCallback (OnNextTrackStarting);
             about_to_finish_callback = new BansheePlayerAboutToFinishCallback (OnAboutToFinish);
@@ -168,6 +172,7 @@ namespace Banshee.GStreamer
             bp_set_tag_found_callback (handle, tag_found_callback);
             bp_set_next_track_starting_callback (handle, next_track_starting_callback);
             bp_set_video_pipeline_setup_callback (handle, video_pipeline_setup_callback);
+            bp_set_video_prepare_window_callback (handle, video_prepare_window_callback);
             bp_set_volume_changed_callback (handle, volume_changed_callback);
 
             next_track_set = new EventWaitHandle (false, EventResetMode.ManualReset);
@@ -714,6 +719,11 @@ namespace Banshee.GStreamer
             return clutter_video_sink;
         }
 
+        private void OnVideoPrepareWindow (IntPtr player)
+        {
+            OnEventChanged (PlayerEvent.PrepareVideoWindow);
+        }
+
 #endregion
 
 #region Preferences
@@ -809,6 +819,10 @@ namespace Banshee.GStreamer
             GstTaggerTagFoundCallback cb);
 
         [DllImport ("libbanshee.dll")]
+        private static extern void bp_set_video_prepare_window_callback (HandleRef player,
+           VideoPrepareWindowHandler cb);
+
+        [DllImport ("libbanshee.dll")]
         private static extern void bp_set_next_track_starting_callback (HandleRef player,
             BansheePlayerNextTrackStartingCallback cb);
 
diff --git a/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs b/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs
index d5006cb..2c1fd80 100644
--- a/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs
+++ b/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs
@@ -220,6 +220,7 @@ namespace Banshee.MediaEngine
                 pending_track = null;
                 pending_uri = null;
             }
+
             if (ThreadAssist.InMainThread) {
                 RaiseEventChanged (args);
             } else {
diff --git a/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs b/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs
index 79ec1f8..48652af 100644
--- a/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs
+++ b/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs
@@ -691,7 +691,8 @@ namespace Banshee.MediaEngine
             | PlayerEvent.Volume
             | PlayerEvent.Metadata
             | PlayerEvent.TrackInfoUpdated
-            | PlayerEvent.RequestNextTrack;
+            | PlayerEvent.RequestNextTrack
+            | PlayerEvent.PrepareVideoWindow;
 
         private const PlayerEvent event_default_mask = event_all_mask & ~PlayerEvent.Iterate;
 
diff --git a/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEvent.cs b/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEvent.cs
index a5c714f..92f09da 100644
--- a/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEvent.cs
+++ b/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEvent.cs
@@ -109,7 +109,8 @@ namespace Banshee.MediaEngine
         Volume = 128,
         Metadata = 256,
         TrackInfoUpdated = 512,
-        RequestNextTrack = 1024
+        RequestNextTrack = 1024,
+        PrepareVideoWindow = 2048
     }
 
     public enum PlayerState
diff --git a/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingContents.cs b/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingContents.cs
index f411eaf..04721af 100644
--- a/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingContents.cs
+++ b/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingContents.cs
@@ -35,8 +35,16 @@ namespace Banshee.NowPlaying
 {
     public class NowPlayingContents : EventBox, IDisposable
     {
+        private static Widget video_display;
+
+        public static void CreateVideoDisplay ()
+        {
+            if (video_display == null) {
+                video_display = new XOverlayVideoDisplay ();
+            }
+        }
+
         private Table table;
-        private Widget video_display;
         private Widget substitute_audio_display;
         private bool video_display_initial_shown = false;
 
@@ -49,7 +57,7 @@ namespace Banshee.NowPlaying
 
             table.NoShowAll = true;
 
-            video_display = new XOverlayVideoDisplay ();
+            CreateVideoDisplay ();
 
             IVideoDisplay ivideo_display = video_display as IVideoDisplay;
             if (ivideo_display != null) {
diff --git a/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingSource.cs b/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingSource.cs
index 04ee475..c4d15bb 100644
--- a/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingSource.cs
+++ b/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingSource.cs
@@ -58,6 +58,13 @@ namespace Banshee.NowPlaying
             ServiceManager.PlaybackController.Transition += OnPlaybackControllerTransition;
             ServiceManager.PlaybackController.TrackStarted += OnPlaybackControllerTrackStarted;
             ServiceManager.PlayerEngine.ConnectEvent (OnTrackInfoUpdated, PlayerEvent.TrackInfoUpdated);
+            ServiceManager.PlayerEngine.ConnectEvent (OnCreateVideoWindow, PlayerEvent.PrepareVideoWindow);
+        }
+
+        private void OnCreateVideoWindow (PlayerEventArgs args)
+        {
+            ServiceManager.PlayerEngine.DisconnectEvent (OnCreateVideoWindow);
+            NowPlayingContents.CreateVideoDisplay ();
         }
 
         public void Dispose ()
diff --git a/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/XOverlayVideoDisplay.cs b/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/XOverlayVideoDisplay.cs
index c365db5..de924f5 100644
--- a/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/XOverlayVideoDisplay.cs
+++ b/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/XOverlayVideoDisplay.cs
@@ -44,31 +44,36 @@ namespace Banshee.NowPlaying
         public XOverlayVideoDisplay () : base ()
         {
             WidgetFlags = WidgetFlags.NoWindow;
+            CreateVideoWindow ();
         }
 
         protected override void OnRealized ()
         {
             WidgetFlags |= WidgetFlags.Realized;
-
+            CreateVideoWindow ();
             GdkWindow = Parent.GdkWindow;
+            video_window.Reparent (GdkWindow, 0, 0);
+            video_window.MoveResize (Allocation.X, Allocation.Y, Allocation.Width, Allocation.Height);
+            video_window.ShowUnraised ();
+        }
 
+        private void CreateVideoWindow ()
+        {
             if (video_window != null) {
-                video_window.Reparent (GdkWindow, 0, 0);
-                video_window.MoveResize (Allocation.X, Allocation.Y, Allocation.Width, Allocation.Height);
-                video_window.ShowUnraised ();
                 return;
             }
 
-            Gdk.WindowAttr attributes = new Gdk.WindowAttr ();
-            attributes.WindowType = Gdk.WindowType.Child;
-            attributes.X = 0;
-            attributes.Y = 0;
-            attributes.Width = Allocation.Width;
-            attributes.Height = Allocation.Height;
-            attributes.Visual = Visual;
-            attributes.Wclass = Gdk.WindowClass.InputOutput;
-            attributes.Colormap = Colormap;
-            attributes.EventMask = (int)(Gdk.EventMask.ExposureMask | Gdk.EventMask.VisibilityNotifyMask);
+            var attributes = new Gdk.WindowAttr () {
+                WindowType = Gdk.WindowType.Child,
+                X = 0,
+                Y = 0,
+                Width = 0,
+                Height = 0,
+                Visual = Visual,
+                Wclass = Gdk.WindowClass.InputOutput,
+                Colormap = Colormap,
+                EventMask = (int)(Gdk.EventMask.ExposureMask | Gdk.EventMask.VisibilityNotifyMask)
+            };
 
             Gdk.WindowAttributesType attributes_mask =
                 Gdk.WindowAttributesType.X |
@@ -76,7 +81,7 @@ namespace Banshee.NowPlaying
                 Gdk.WindowAttributesType.Visual |
                 Gdk.WindowAttributesType.Colormap;
 
-            video_window = new Gdk.Window (GdkWindow, attributes, attributes_mask);
+            video_window = new Gdk.Window (null, attributes, attributes_mask);
             video_window.UserData = Handle;
 
             video_window.SetBackPixmap (null, false);



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