banshee r4350 - in trunk/banshee: . src/Core/Banshee.ThickClient src/Core/Banshee.ThickClient/Banshee.Collection.Gui src/Core/Banshee.ThickClient/Banshee.Gui.Widgets src/Extensions/Banshee.NowPlaying src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying src/Libraries/Hyena.Gui/Hyena.Gui



Author: abock
Date: Tue Aug 12 01:02:34 2008
New Revision: 4350
URL: http://svn.gnome.org/viewvc/banshee?rev=4350&view=rev

Log:
2008-08-11  Aaron Bockover  <abock gnome org>

    * src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/LargeTrackInfoDisplay.cs:
    Implemented a new high resolution track info display; quite optimized for
    smooth xfade at higher resolutions through cairo; sits in the now playing
    source and works in full screen

    * src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs:
    Support Cairo Surface caching

    * src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ClassicTrackInfoDisplay.cs:
    Fixed some windowing issues

    * src/Libraries/Hyena.Gui/Hyena.Gui/CairoExtensions.cs: Added a
    CreateSurfaceForPixbuf method

    * src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/VideoDisplay.cs:
    Removed non-video rendering code (idle logo, album art)

    * src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingTrackInfoDisplay.cs:
    LargeTrackInfoDisplay themed for the now playing source

    * src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingContents.cs:
    Base contents widget for now playing source; random things can be packed,
    including the video display and the album art view

    * src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/XOverlayVideoDisplay.cs:
    Eliminate an internal GdkWindow, attaching the video window to the root

    * src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingInterface.cs:
    Use the NowPlayingContents widget as the main widget to be detached for
    fullscreen mode

    * src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/FullscreenWindow.cs:
    Fixed rendering/mapping issue

    * src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ArtworkRenderer.cs:
    Support specifying which corners to round



Added:
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/LargeTrackInfoDisplay.cs
   trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingContents.cs
   trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingTrackInfoDisplay.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ArtworkRenderer.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ClassicTrackInfoDisplay.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp
   trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am
   trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying.mdp
   trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/FullscreenWindow.cs
   trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingInterface.cs
   trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/VideoDisplay.cs
   trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/XOverlayVideoDisplay.cs
   trunk/banshee/src/Extensions/Banshee.NowPlaying/Makefile.am
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui/CairoExtensions.cs

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ArtworkRenderer.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ArtworkRenderer.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ArtworkRenderer.cs	Tue Aug 12 01:02:34 2008
@@ -49,6 +49,14 @@
             double x, double y, double width, double height, bool drawBorder, double radius, 
             bool fill, Color fillColor)
         {
+            RenderThumbnail (cr, pixbuf, dispose, x, y, width, height, drawBorder, radius, 
+                fill, fillColor, CairoCorners.All);
+        }
+        
+        public static void RenderThumbnail (Cairo.Context cr, Gdk.Pixbuf pixbuf, bool dispose,
+            double x, double y, double width, double height, bool drawBorder, double radius, 
+            bool fill, Color fillColor, CairoCorners corners)
+        {
             if (pixbuf == null || pixbuf.Handle == IntPtr.Zero) {
                 return;
             }
@@ -66,11 +74,15 @@
                 cr.Fill();
             }
             
-            CairoExtensions.RoundedRectangle (cr, p_x, p_y, pixbuf.Width, pixbuf.Height, radius);
+            CairoExtensions.RoundedRectangle (cr, p_x, p_y, pixbuf.Width, pixbuf.Height, radius, corners);
             Gdk.CairoHelper.SetSourcePixbuf (cr, pixbuf, p_x, p_y);
             cr.Fill ();
             
             if (!drawBorder) {
+                if (dispose) {
+                    DisposePixbuf (pixbuf);
+                }
+                
                 return;
             }
             
@@ -78,12 +90,12 @@
             if (radius < 1) {
                 cr.Antialias = Antialias.None;
                 
-                CairoExtensions.RoundedRectangle (cr, x + 1.5, y + 1.5, width - 3, height - 3, radius);
+                CairoExtensions.RoundedRectangle (cr, x + 1.5, y + 1.5, width - 3, height - 3, radius, corners);
                 cr.Color = cover_border_light_color;
                 cr.Stroke ();
             }
             
-            CairoExtensions.RoundedRectangle (cr, x + 0.5, y + 0.5, width - 1, height - 1, radius);
+            CairoExtensions.RoundedRectangle (cr, x + 0.5, y + 0.5, width - 1, height - 1, radius, corners);
             cr.Color = cover_border_dark_color;
             cr.Stroke ();
             

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ClassicTrackInfoDisplay.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ClassicTrackInfoDisplay.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ClassicTrackInfoDisplay.cs	Tue Aug 12 01:02:34 2008
@@ -64,8 +64,7 @@
         
         protected override void OnRealized ()
         {
-            WidgetFlags |= WidgetFlags.Realized | WidgetFlags.NoWindow;
-            GdkWindow = Parent.GdkWindow;
+            base.OnRealized ();
             
             WindowAttr attributes = new WindowAttr ();
             attributes.WindowType = Gdk.WindowType.Child;
@@ -85,8 +84,6 @@
             
             event_window = new Gdk.Window (GdkWindow, attributes, attributes_mask);
             event_window.UserData = Handle;
-            
-            base.OnRealized ();
         }
         
         protected override void OnUnrealized ()
@@ -94,7 +91,7 @@
             WidgetFlags ^= WidgetFlags.Realized;
             
             event_window.UserData = IntPtr.Zero;
-            event_window.Destroy ();
+            Hyena.Gui.GtkWorkarounds.WindowDestroy (event_window);
             event_window = null;
             
             base.OnUnrealized ();

Added: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/LargeTrackInfoDisplay.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/LargeTrackInfoDisplay.cs	Tue Aug 12 01:02:34 2008
@@ -0,0 +1,245 @@
+//
+// LargeTrackInfoDisplay.cs
+//
+// Author:
+//   Aaron Bockover <abockover novell com>
+//
+// Copyright (C) 2008 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+
+using Gtk;
+using Cairo;
+
+using Hyena.Gui;
+using Banshee.Collection;
+using Banshee.Collection.Gui;
+
+namespace Banshee.Gui.Widgets
+{
+    public class LargeTrackInfoDisplay : TrackInfoDisplay
+    {
+        private Gdk.Rectangle text_alloc;
+    
+        public LargeTrackInfoDisplay ()
+        {
+        }
+        
+        protected LargeTrackInfoDisplay (IntPtr native) : base (native)
+        {
+        }
+        
+        protected override int MissingIconSizeRequest {
+            get { return 128; }
+        }
+        
+        protected virtual int MaxArtworkSize {
+            get { return 300; }
+        }
+        
+        protected virtual int Spacing {
+            get { return 10; }
+        }
+        
+        protected override int ArtworkSizeRequest {
+            get { return Math.Min (Math.Min (Allocation.Height, Allocation.Width), MaxArtworkSize); }
+        }
+
+        protected virtual Gdk.Rectangle RenderAllocation {
+            get {
+                int width = ArtworkSizeRequest * 2 + Spacing;
+                int height = (int)Math.Ceiling (ArtworkSizeRequest * 1.2);
+                int x = Allocation.X + (Allocation.Width - width) / 2;
+                int y = Allocation.Y + (Allocation.Height - height) / 2;
+                return new Gdk.Rectangle (x, y, width, height);
+            }
+        }
+        
+        protected override void OnSizeAllocated (Gdk.Rectangle allocation)
+        {
+            base.OnSizeAllocated (allocation);
+            QueueDraw ();
+        }
+       
+        protected override void RenderCoverArt (Cairo.Context cr, Gdk.Pixbuf pixbuf)
+        {
+            if (pixbuf == null) {
+                return;
+            }
+            
+            Gdk.Rectangle alloc = RenderAllocation;
+            int asr = ArtworkSizeRequest;
+            int reflect = (int)(pixbuf.Height * 0.2);
+            int surface_w = pixbuf.Width;
+            int surface_h = pixbuf.Height + reflect;
+            int x = alloc.X + alloc.Width - asr;
+            int y = alloc.Y;
+            
+            Surface surface = SurfaceLookup (pixbuf);
+            if (surface == null) {
+                surface = CreateSurfaceForPixbuf (cr, pixbuf, reflect);
+                SurfaceCache (pixbuf, surface);
+            }
+                
+            cr.Rectangle (x, y, asr, alloc.Height);
+            cr.Color = BackgroundColor;
+            cr.Fill ();
+            
+            x += (asr - surface_w) / 2;
+            y += surface_h > asr ? 0 : (asr - surface_h) / 2;
+            
+            cr.SetSource (surface, x, y);
+            cr.Paint ();
+        }
+        
+        private Surface CreateSurfaceForPixbuf (Cairo.Context window_cr, Gdk.Pixbuf pixbuf, int reflect)
+        {
+            Surface surface = window_cr.Target.CreateSimilar (window_cr.Target.Content, 
+                pixbuf.Width, pixbuf.Height + reflect);
+            Cairo.Context cr = new Context (surface);
+            
+            cr.Save ();
+            
+            Gdk.CairoHelper.SetSourcePixbuf (cr, pixbuf, 0, 0);
+            cr.Paint ();
+            
+            cr.Rectangle (0, pixbuf.Height, pixbuf.Width, reflect);
+            cr.Clip ();
+            
+            Matrix matrix = new Matrix ();
+            matrix.InitScale (1, -1);
+            matrix.Translate (0, -(2 * pixbuf.Height) + 1);
+            cr.Transform (matrix);
+            
+            Gdk.CairoHelper.SetSourcePixbuf (cr, pixbuf, 0, 0);
+            cr.Paint ();
+            
+            cr.Restore ();
+            
+            Color bg_transparent = BackgroundColor;
+            bg_transparent.A = 0.65;
+            
+            LinearGradient mask = new LinearGradient (0, pixbuf.Height, 0, pixbuf.Height + reflect);
+            mask.AddColorStop (0, bg_transparent);
+            mask.AddColorStop (1, BackgroundColor);
+            
+            cr.Rectangle (0, pixbuf.Height, pixbuf.Width, reflect);
+            cr.Pattern = mask;
+            cr.Fill ();
+            
+            ((IDisposable)cr).Dispose ();
+            return surface;
+        }
+        
+        protected override void RenderTrackInfo (Context cr, TrackInfo track, bool renderTrack, bool renderArtistAlbum)
+        {
+            if (track == null) {
+                return;
+            }
+
+            Gdk.Rectangle alloc = RenderAllocation;
+            int width = ArtworkSizeRequest;
+            int fl_width, fl_height, sl_width, sl_height, tl_width, tl_height;
+
+            string first_line = GetFirstLineText (track);
+            
+            // FIXME: This is incredibly bad, but we don't want to break
+            // translations right now. It needs to be replaced for 1.4!!
+            string line = GetSecondLineText (track);
+            string second_line = line, third_line = line;
+            int split_pos = line.LastIndexOf ("<span");
+            if (split_pos >= 0) {
+                second_line = line.Substring (0, split_pos - 1) + "</span>";
+                third_line = String.Format ("<span color=\"{0}\">{1}",
+                    CairoExtensions.ColorGetHex (TextColor, false),
+                    line.Substring (split_pos, line.Length - split_pos));
+            }
+
+            // Set up the text layouts
+            Pango.Layout first_line_layout = null;
+            CairoExtensions.CreateLayout (this, cr, ref first_line_layout);
+            first_line_layout.Width = (int)(width * Pango.Scale.PangoScale);
+            first_line_layout.Ellipsize = Pango.EllipsizeMode.End;
+            first_line_layout.Alignment = Pango.Alignment.Right;
+
+            int base_size = first_line_layout.FontDescription.Size;
+                        
+            Pango.Layout second_line_layout = first_line_layout.Copy ();
+            Pango.Layout third_line_layout = first_line_layout.Copy ();
+
+            first_line_layout.FontDescription.Size = (int)(base_size * Pango.Scale.XLarge);
+            
+            // Compute the layout coordinates
+            first_line_layout.SetMarkup (first_line);
+            first_line_layout.GetPixelSize (out fl_width, out fl_height);
+            second_line_layout.SetMarkup (second_line);
+            second_line_layout.GetPixelSize (out sl_width, out sl_height);
+            third_line_layout.SetMarkup (third_line);
+            third_line_layout.GetPixelSize (out tl_width, out tl_height);
+
+            text_alloc.X = alloc.X;
+            text_alloc.Width = width;
+            text_alloc.Height = fl_height + sl_height + tl_height;
+            text_alloc.Y = alloc.Y + (ArtworkSizeRequest - text_alloc.Height) / 2;
+
+            // Render the layouts
+            cr.Antialias = Cairo.Antialias.Default;
+            
+            if (renderTrack) {
+                cr.MoveTo (text_alloc.X, text_alloc.Y);
+                cr.Color = TextColor;
+                PangoCairoHelper.ShowLayout (cr, first_line_layout);
+            }
+
+            if (!renderArtistAlbum) {
+                first_line_layout.Dispose ();
+                second_line_layout.Dispose ();
+                third_line_layout.Dispose ();
+                return;
+            }
+            
+            cr.MoveTo (text_alloc.X, text_alloc.Y + fl_height);
+            PangoCairoHelper.ShowLayout (cr, second_line_layout);
+            
+            cr.MoveTo (text_alloc.X, text_alloc.Y + fl_height + sl_height);
+            PangoCairoHelper.ShowLayout (cr, third_line_layout);
+            
+            first_line_layout.Dispose ();
+            second_line_layout.Dispose ();
+            third_line_layout.Dispose ();
+        }
+        
+        protected override void Invalidate ()
+        {
+            if (CurrentPixbuf == null || CurrentTrack == null || IncomingPixbuf == null || IncomingTrack == null) {
+                QueueDraw ();
+            } else {
+                Gdk.Rectangle alloc = RenderAllocation;
+                QueueDrawArea (text_alloc.X, text_alloc.Y, text_alloc.Width, text_alloc.Height);
+                QueueDrawArea (alloc.X + text_alloc.Width + Spacing, alloc.Y, 
+                    alloc.Width - text_alloc.Width - Spacing, alloc.Height);
+            }
+        }
+    }
+}

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs	Tue Aug 12 01:02:34 2008
@@ -28,7 +28,7 @@
 //
 
 using System;
-using System.Collections;
+using System.Collections.Generic;
 using Mono.Unix;
 
 using Gtk;
@@ -74,17 +74,17 @@
         }
         
         private Cairo.Color background_color;
-        protected Cairo.Color BackgroundColor {
+        protected virtual Cairo.Color BackgroundColor {
             get { return background_color; }
         }
         
         private Cairo.Color text_color;
-        protected Cairo.Color TextColor {
+        protected virtual Cairo.Color TextColor {
             get { return text_color; }
         }
         
         private Cairo.Color text_light_color;
-        protected Cairo.Color TextLightColor {
+        protected virtual Cairo.Color TextLightColor {
             get { return text_light_color; }
         }
         
@@ -100,6 +100,7 @@
         
         private uint idle_timeout_id = 0;
         private SingleActorStage stage = new SingleActorStage ();
+        private Dictionary<Pixbuf, Cairo.Surface> surface_cache = new Dictionary<Pixbuf, Cairo.Surface> ();
         
         protected TrackInfoDisplay (IntPtr native) : base (native)
         {
@@ -117,6 +118,8 @@
                 PlayerEvent.StartOfStream | 
                 PlayerEvent.TrackInfoUpdated | 
                 PlayerEvent.StateChange);
+                
+            WidgetFlags |= WidgetFlags.NoWindow;
         }
         
         public override void Dispose ()
@@ -132,15 +135,31 @@
             stage.Iteration -= OnStageIteration;
             stage = null;
             
+            SurfaceCacheFlush ();
+            
             base.Dispose ();
         }
         
+        protected override void OnRealized ()
+        {
+            GdkWindow = Parent.GdkWindow;
+            base.OnRealized ();
+        }
+        
+        protected override void OnUnrealized ()
+        {
+            base.OnUnrealized ();
+            SurfaceCacheFlush ();
+        }
+        
         protected override void OnSizeAllocated (Rectangle allocation)
         {
             base.OnSizeAllocated (allocation);
             
             if (current_track == null) {
                 LoadCurrentTrack ();
+            } else {
+                LoadPixbuf (current_track);
             }
         }
 
@@ -165,18 +184,38 @@
         
         protected override bool OnExposeEvent (EventExpose evnt)
         {
-            if (!Visible || !IsMapped || (incoming_track == null && current_track == null)) {
+            bool idle = incoming_track == null && current_track == null;
+            if (!Visible || !IsMapped || (idle && !CanRenderIdle)) {
                 return true;
             }
             
             Cairo.Context cr = Gdk.CairoHelper.Create (evnt.Window);
-            cr.Rectangle (Allocation.X, Allocation.Y, Allocation.Width, Allocation.Height);
-            cr.Clip ();
-            RenderAnimation (cr);
+            
+            foreach (Gdk.Rectangle damage in evnt.Region.GetRectangles ()) {
+                cr.Rectangle (damage.X, damage.Y, damage.Width, damage.Height);
+                cr.Clip ();
+            
+                if (idle) {
+                    RenderIdle (cr);
+                } else {
+                    RenderAnimation (cr);
+                }
+            
+                cr.ResetClip ();
+            }
+            
             CairoExtensions.DisposeContext (cr);
             
             return true;
         }
+
+        protected virtual bool CanRenderIdle {
+            get { return false; }
+        }
+        
+        protected virtual void RenderIdle (Cairo.Context cr)
+        {
+        }
         
         private void RenderAnimation (Cairo.Context cr)
         {
@@ -238,8 +277,10 @@
         
         protected virtual void RenderCoverArt (Cairo.Context cr, Pixbuf pixbuf)
         {
-            ArtworkRenderer.RenderThumbnail (cr, pixbuf, false, Allocation.X, Allocation.Y, Allocation.Height, Allocation.Height, 
-                !IsMissingPixbuf (pixbuf), 0, IsMissingPixbuf (pixbuf), background_color);
+            ArtworkRenderer.RenderThumbnail (cr, pixbuf, false, Allocation.X, Allocation.Y, 
+                ArtworkSizeRequest, ArtworkSizeRequest, 
+                !IsMissingPixbuf (pixbuf), 0, 
+                IsMissingPixbuf (pixbuf), BackgroundColor);
         }
 
         protected bool IsMissingPixbuf (Pixbuf pb)
@@ -249,6 +290,14 @@
         
         protected abstract void RenderTrackInfo (Cairo.Context cr, TrackInfo track, bool renderTrack, bool renderArtistAlbum);
         
+        protected virtual int ArtworkSizeRequest {
+            get { return Allocation.Height; }
+        }
+        
+        protected virtual int MissingIconSizeRequest {
+            get { return 32; }
+        }
+        
         private void OnPlayerEvent (PlayerEventArgs args)
         {
             if (args.Event == PlayerEvent.StartOfStream || args.Event == PlayerEvent.TrackInfoUpdated) {
@@ -294,18 +343,27 @@
             }
 
             incoming_track = track;
-
-            Gdk.Pixbuf pixbuf = artwork_manager.LookupScale (track.ArtworkId, Allocation.Height);
             
+            LoadPixbuf (track);
+
+            if (stage.Actor == null) {
+                stage.Reset ();
+            }
+        }
+        
+        private void LoadPixbuf (TrackInfo track)
+        {
+            Gdk.Pixbuf pixbuf = artwork_manager.LookupScale (track.ArtworkId, ArtworkSizeRequest);
+
             if (pixbuf == null) {
                 if ((track.MediaAttributes & TrackMediaAttributes.VideoStream) != 0) {
                     if (missing_video_pixbuf == null) {
-                        missing_video_pixbuf = IconThemeUtils.LoadIcon (32, "video-x-generic");
+                        missing_video_pixbuf = IconThemeUtils.LoadIcon (MissingIconSizeRequest, "video-x-generic");
                     }
                     incoming_pixbuf = missing_video_pixbuf;
                 } else {
                     if (missing_audio_pixbuf == null) {
-                        missing_audio_pixbuf = IconThemeUtils.LoadIcon (32, "audio-x-generic");
+                        missing_audio_pixbuf = IconThemeUtils.LoadIcon (MissingIconSizeRequest, "audio-x-generic");
                     }
                     incoming_pixbuf = missing_audio_pixbuf;
                 }
@@ -313,8 +371,8 @@
                 incoming_pixbuf = pixbuf;
             }
             
-            if (stage.Actor == null) {
-                stage.Reset ();
+            if (track == current_track) {
+                current_pixbuf = incoming_pixbuf;
             }
         }
         
@@ -322,13 +380,15 @@
         
         private void OnStageIteration (object o, EventArgs args)
         {
-            QueueDraw ();
+            Invalidate ();
             
             if (stage.Actor != null) {
                 last_fps = stage.Actor.FramesPerSecond;
                 return;
             }
             
+            SurfaceCacheFlush ();
+            
             if (ApplicationContext.Debugging) {
                 Log.DebugFormat ("TrackInfoDisplay RenderAnimation: {0:0.00} FPS", last_fps);
             }
@@ -345,6 +405,11 @@
             OnArtworkChanged ();
         }
         
+        protected virtual void Invalidate ()
+        {
+            QueueDraw ();
+        }
+        
         protected virtual void OnArtworkChanged ()
         {
         }
@@ -389,7 +454,7 @@
             }
             
             return String.Format ("<span color=\"{0}\">{1}</span>",  
-                CairoExtensions.ColorGetHex (text_color, false),
+                CairoExtensions.ColorGetHex (TextColor, false),
                 markup);
         }
         
@@ -397,7 +462,7 @@
         {
             string [] new_args = new string [args.Length + 2];
             new_args[0] = String.Format ("<span color=\"{0}\" size=\"small\">", 
-                CairoExtensions.ColorGetHex (text_light_color, false));
+                CairoExtensions.ColorGetHex (TextLightColor, false));
             new_args[1] = "</span>";
             
             for (int i = 0; i < args.Length; i++) {
@@ -430,5 +495,46 @@
             }
             return markup;
         }
+        
+        protected void SurfaceExpire (Gdk.Pixbuf pixbuf)
+        {
+            if (pixbuf == null) {
+                return;
+            }
+            
+            Cairo.Surface surface = null;
+            if (surface_cache.TryGetValue (pixbuf, out surface)) {
+                surface.Destroy ();
+                surface_cache.Remove (pixbuf);
+            }
+        }
+        
+        protected void SurfaceCacheFlush ()
+        {
+            foreach (Cairo.Surface surface in surface_cache.Values) {
+                surface.Destroy ();
+            }
+            
+            surface_cache.Clear ();
+        }
+        
+        protected void SurfaceCache (Gdk.Pixbuf pixbuf, Cairo.Surface surface)
+        {
+            if (pixbuf == null || surface == null) {
+                return;
+            }
+            
+            SurfaceExpire (pixbuf);
+            surface_cache.Add (pixbuf, surface);
+        }
+        
+        protected Cairo.Surface SurfaceLookup (Gdk.Pixbuf pixbuf)
+        {
+            Cairo.Surface surface = null;
+            if (pixbuf != null) {
+                surface_cache.TryGetValue (pixbuf, out surface);
+            }
+            return surface;
+        }
     }
 }

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp	Tue Aug 12 01:02:34 2008
@@ -119,6 +119,7 @@
     <File name="Banshee.Collection.Gui/QueryFilterView.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Gui.Widgets/ClassicTrackInfoDisplay.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Library.Gui/PhotoFolderImportSource.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.Widgets/LargeTrackInfoDisplay.cs" subtype="Code" buildaction="Compile" />
   </Contents>
   <References>
     <ProjectReference type="Project" localcopy="False" refto="Hyena.Gui" />

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am	Tue Aug 12 01:02:34 2008
@@ -52,6 +52,7 @@
 	Banshee.Gui.Widgets/ConnectedMessageBar.cs \
 	Banshee.Gui.Widgets/ConnectedSeekSlider.cs \
 	Banshee.Gui.Widgets/ConnectedVolumeButton.cs \
+	Banshee.Gui.Widgets/LargeTrackInfoDisplay.cs \
 	Banshee.Gui.Widgets/MainMenu.cs \
 	Banshee.Gui.Widgets/NextButton.cs \
 	Banshee.Gui.Widgets/PlaylistMenuItem.cs \

Modified: trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying.mdp
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying.mdp	(original)
+++ trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying.mdp	Tue Aug 12 01:02:34 2008
@@ -1,4 +1,4 @@
-<Project name="Banshee.NowPlaying" fileversion="2.0" language="C#" clr-version="Net_2_0" UseParentDirectoryAsNamespace="True" ctype="DotNetProject">
+<Project name="Banshee.NowPlaying" fileversion="2.0" language="C#" UseParentDirectoryAsNamespace="True" clr-version="Net_2_0" ctype="DotNetProject">
   <Configurations active="Debug">
     <Configuration name="Debug" ctype="DotNetProjectConfiguration">
       <Output directory="../../../bin" assemblyKeyFile="." assembly="Banshee.NowPlaying" />
@@ -12,7 +12,6 @@
     <File name="Banshee.NowPlaying/NowPlayingSource.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.NowPlaying/NowPlayingInterface.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.NowPlaying/VideoDisplay.cs" subtype="Code" buildaction="Compile" />
-    <File name="Resources/idle-logo.png" subtype="Code" buildaction="EmbedAsResource" />
     <File name="Banshee.NowPlaying/FullscreenWindow.cs" subtype="Code" buildaction="Compile" />
     <File name="Resources/ActiveSourceUI.xml" subtype="Code" buildaction="EmbedAsResource" />
     <File name="Banshee.NowPlaying/XOverlayVideoDisplay.cs" subtype="Code" buildaction="Compile" />
@@ -22,6 +21,9 @@
     <File name="Banshee.NowPlaying/FullscreenAdapter.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.NowPlaying/IScreensaverManager.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.NowPlaying/ScreensaverManager.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.NowPlaying/NowPlayingContents.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.NowPlaying/NowPlayingTrackInfoDisplay.cs" subtype="Code" buildaction="Compile" />
+    <File name="Resources/idle-logo.png" subtype="Code" buildaction="EmbedAsResource" />
   </Contents>
   <References>
     <ProjectReference type="Project" localcopy="True" refto="Banshee.Core" />
@@ -36,6 +38,7 @@
     <ProjectReference type="Gac" localcopy="True" refto="gdk-sharp, Version=2.10.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
     <ProjectReference type="Gac" localcopy="True" refto="Mono.Cairo, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" />
   </References>
+  <GtkDesignInfo gtkVersion="2.12.1" />
   <MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="True" RelativeMakefileName="./Makefile.am">
     <BuildFilesVar Sync="True" Name="SOURCES" />
     <DeployFilesVar />

Modified: trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/FullscreenWindow.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/FullscreenWindow.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/FullscreenWindow.cs	Tue Aug 12 01:02:34 2008
@@ -46,6 +46,7 @@
         public FullscreenWindow (Window parent) : base (WindowType.Toplevel)
         {
             Title = parent.Title;
+            AppPaintable = true;
             
             this.parent = parent;
             this.action_service = ServiceManager.Get<InterfaceActionService> ();
@@ -55,6 +56,12 @@
             SetupWidget ();
         }
         
+        protected override bool OnExposeEvent (Gdk.EventExpose evnt)
+        {
+            evnt.Window.DrawRectangle (Style.BlackGC, true, Allocation);
+            return base.OnExposeEvent (evnt);
+        }
+        
         protected override bool OnKeyPressEvent (Gdk.EventKey evnt)
         {
             PlayerEngineService player = ServiceManager.PlayerEngine;
@@ -145,6 +152,10 @@
         protected override void OnShown ()
         {
             base.OnShown ();
+            if (Child != null) {
+                Child.Show ();
+            }
+            
             OnHideCursorTimeout ();
             ConfigureWindow ();
             HasFocus = true;

Added: trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingContents.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingContents.cs	Tue Aug 12 01:02:34 2008
@@ -0,0 +1,104 @@
+//
+// NowPlayingContents.cs
+//
+// Author:
+//   Aaron Bockover <abockover novell com>
+//
+// Copyright (C) 2008 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using Gtk;
+
+using Banshee.Gui.Widgets;
+
+namespace Banshee.NowPlaying
+{
+    public class NowPlayingContents : Table, IDisposable
+    {
+        private VideoDisplay video_display;
+        private bool video_display_initial_shown = false;
+        
+        private TrackInfoDisplay track_info_display;
+    
+        public NowPlayingContents () : base (1, 1, false)
+        {
+            NoShowAll = true;
+        
+            video_display = new XOverlayVideoDisplay ();
+            video_display.IdleStateChanged += OnVideoDisplayIdleStateChanged;
+            Attach (video_display, 0, 1, 0, 1, 
+                AttachOptions.Expand | AttachOptions.Fill, 
+                AttachOptions.Expand | AttachOptions.Fill, 0, 0);
+                
+            track_info_display = new NowPlayingTrackInfoDisplay ();
+            Attach (track_info_display, 0, 1, 0, 1, 
+                AttachOptions.Expand | AttachOptions.Fill, 
+                AttachOptions.Expand | AttachOptions.Fill, 0, 0);
+        }
+        
+        public override void Dispose ()
+        {
+            if (video_display != null) {
+                video_display.IdleStateChanged -= OnVideoDisplayIdleStateChanged;
+                video_display = null;
+            }
+            
+            base.Dispose ();
+        }
+        
+        protected override void OnShown ()
+        {
+            base.OnShown ();
+            
+            // Ugly hack to ensure the video window is mapped/realized
+            if (!video_display_initial_shown) {
+                video_display_initial_shown = true;
+                video_display.Show ();
+                GLib.Idle.Add (delegate { 
+                    CheckIdle (); 
+                    return false;
+                });
+                return;
+            }
+            
+            CheckIdle ();
+        }
+        
+        protected override void OnHidden ()
+        {
+            base.OnHidden ();
+            video_display.Hide ();
+        }
+
+        private void CheckIdle ()
+        {
+            video_display.Visible = !video_display.IsIdle;
+            track_info_display.Visible = video_display.IsIdle;
+        }
+
+        private void OnVideoDisplayIdleStateChanged (object o, EventArgs args)
+        {
+            CheckIdle ();
+        }
+    }
+}

Modified: trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingInterface.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingInterface.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingInterface.cs	Tue Aug 12 01:02:34 2008
@@ -41,21 +41,17 @@
     public class NowPlayingInterface : VBox, ISourceContents
     {   
         private NowPlayingSource source;
-        private VideoDisplay video_display;
         private Hyena.Widgets.RoundedFrame frame;
         private Gtk.Window video_window;
         private FullscreenAdapter fullscreen_adapter;
         private ScreensaverManager screensaver;
-
-        public VideoDisplay VideoDisplay {
-            get { return video_display; }
-        }
+        private NowPlayingContents contents;
         
         public NowPlayingInterface ()
         {
             GtkElementsService service = ServiceManager.Get<GtkElementsService> ();
             
-            video_display = new XOverlayVideoDisplay ();
+            contents = new NowPlayingContents ();
             
             // This is my really sweet hack - it's where the video widget
             // is sent when the source is not active. This keeps the video
@@ -65,7 +61,7 @@
             video_window = new FullscreenWindow (service.PrimaryWindow);
             video_window.Hidden += OnFullscreenWindowHidden;
             video_window.Realize ();
-            video_window.Add (video_display);
+            video_window.Add (contents);
             
             frame = new Hyena.Widgets.RoundedFrame ();
             frame.SetFillColor (new Cairo.Color (0, 0, 0));
@@ -84,20 +80,19 @@
             screensaver.Dispose ();
         }
 
-        
         private void MoveVideoExternal (bool hidden)
         {
-            if (video_display.Parent != video_window) {
-                video_display.Visible = !hidden;
-                video_display.Reparent (video_window);
+            if (contents.Parent != video_window) {
+                contents.Visible = !hidden;
+                contents.Reparent (video_window);
             }
         }
         
         private void MoveVideoInternal ()
         {
-            if (video_display.Parent != frame) {
-                video_display.Reparent (frame);
-                video_display.Show ();
+            if (contents.Parent != frame) {
+                contents.Reparent (frame);
+                contents.Show ();
             }
         }
         
@@ -162,7 +157,7 @@
         {
             if (fullscreen) {
                 MoveVideoExternal (true);
-                video_window.ShowAll ();
+                video_window.Show ();
                 fullscreen_adapter.Fullscreen (video_window, true);
                 screensaver.Inhibit ();
             } else {

Added: trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingTrackInfoDisplay.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/NowPlayingTrackInfoDisplay.cs	Tue Aug 12 01:02:34 2008
@@ -0,0 +1,87 @@
+//
+// NowPlayingTrackInfoDisplay.cs
+//
+// Author:
+//   Aaron Bockover <abockover novell com>
+//
+// Copyright (C) 2008 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using Gtk;
+using Cairo;
+
+using Hyena.Gui;
+using Banshee.Gui.Widgets;
+
+namespace Banshee.NowPlaying
+{
+    public class NowPlayingTrackInfoDisplay : LargeTrackInfoDisplay
+    {
+        private static Cairo.Color background_color = CairoExtensions.RgbToColor (0);
+        private static Cairo.Color text_color = CairoExtensions.RgbToColor (0xffffff);
+        private static Cairo.Color text_light_color = CairoExtensions.RgbToColor (0x777777);
+        private static Gdk.Pixbuf idle_pixbuf;
+        
+        public NowPlayingTrackInfoDisplay ()
+        {
+        }
+    
+        protected NowPlayingTrackInfoDisplay (IntPtr native) : base (native)
+        {
+        }
+        
+        protected override Cairo.Color BackgroundColor {
+            get { return background_color; }
+        }
+
+        protected override Cairo.Color TextColor {
+            get { return text_color; }
+        }
+
+        protected override Cairo.Color TextLightColor {
+            get { return text_light_color; }
+        }
+        
+        protected override bool CanRenderIdle {
+            get { return true; }
+        }
+        
+        protected override void RenderIdle (Cairo.Context cr)
+        {
+            if (idle_pixbuf == null) {
+                idle_pixbuf = Gdk.Pixbuf.LoadFromResource ("idle-logo.png");
+            }
+            
+            if (idle_pixbuf == null) {
+                return;
+            }
+            
+            cr.Save ();
+            cr.Translate (Allocation.X + ((Allocation.Width - idle_pixbuf.Width) / 2), 
+                Allocation.Y + ((Allocation.Height - idle_pixbuf.Height) / 2));
+            Gdk.CairoHelper.SetSourcePixbuf (cr, idle_pixbuf, 0, 0);
+            cr.Paint ();
+            cr.Restore ();
+        }
+    }
+}

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	Tue Aug 12 01:02:34 2008
@@ -37,17 +37,20 @@
 {   
     public abstract class VideoDisplay : Gtk.Widget
     {
-        private Gdk.Pixbuf idle_pixbuf;
-        private bool render_idle = true;
-        private bool render_video = false;
-        private Gdk.Pixbuf last_coverart_pixbuf;
-        private string last_coverart_id;
+        private bool is_idle = true;
+        
+        public event EventHandler IdleStateChanged;
+        
+        public bool IsIdle {
+            get { return is_idle; }
+        }
 
         public VideoDisplay ()
         {
             ServiceManager.PlayerEngine.ConnectEvent (OnPlayerEvent,
                 PlayerEvent.StartOfStream |
                 PlayerEvent.EndOfStream);
+            
             ToggleIdleVisibility ();
         }
 
@@ -63,64 +66,17 @@
         
         protected override bool OnExposeEvent (Gdk.EventExpose evnt)
         {
+            RenderWindow.DrawRectangle (Style.BlackGC, true, 
+                new Gdk.Rectangle (0, 0, Allocation.Width, Allocation.Height));
+            
             if (RenderWindow == null || !RenderWindow.IsVisible) {
                 return true;
             }
             
-            if (render_video && ServiceManager.PlayerEngine.SupportsVideo) {
+            if (!is_idle && ServiceManager.PlayerEngine.SupportsVideo) {
                 ExposeVideo (evnt);
-                return true;
-            }
-
-            if (render_idle || !DrawCoverArt ()) {
-                DrawIdle ();
-            }
-
-            return true;
-        }
-        
-        private void DrawIdle ()
-        {
-            if (idle_pixbuf == null) {
-                idle_pixbuf = Gdk.Pixbuf.LoadFromResource ("idle-logo.png");
-            }
-            
-            if (idle_pixbuf == null) {
-                return;
-            }
-            
-            RenderWindow.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);
-        }
-        
-        private bool DrawCoverArt ()
-        {
-            TrackInfo track = ServiceManager.PlayerEngine.CurrentTrack;
-            if (track == null) {
-                return false;
             }
             
-            Gdk.Pixbuf display_pixbuf = null;
-            
-            if (track.ArtworkId == last_coverart_id) {
-                display_pixbuf = last_coverart_pixbuf;
-            } else if (Banshee.Base.CoverArtSpec.CoverExists (track.ArtworkId)) {
-                if (last_coverart_pixbuf != null) {
-                    last_coverart_pixbuf.Dispose ();
-                }
-                last_coverart_id = track.ArtworkId;
-                display_pixbuf = last_coverart_pixbuf = new Gdk.Pixbuf (Banshee.Base.CoverArtSpec.GetPath (last_coverart_id));
-            } else {
-                return false;
-            }
-            
-            int img_w = Math.Min (Allocation.Width, display_pixbuf.Width);
-            int img_h = Math.Min (Allocation.Height, display_pixbuf.Height);
-            RenderWindow.DrawPixbuf (Style.BackgroundGC (StateType.Normal), display_pixbuf, 0, 0, 
-                (Allocation.Width - img_w) / 2, (Allocation.Height - img_h) / 2, 
-                img_w, img_h, Gdk.RgbDither.Normal, 0, 0
-            );
             return true;
         }
         
@@ -132,9 +88,18 @@
         private void ToggleIdleVisibility ()
         {
             TrackInfo track = ServiceManager.PlayerEngine.CurrentTrack;
-            render_idle = track == null;
-            render_video = !render_idle && (track.MediaAttributes & TrackMediaAttributes.VideoStream) != 0;
+            is_idle = track == null || (track.MediaAttributes & TrackMediaAttributes.VideoStream) == 0;
             QueueDraw ();
+            
+            OnIdleStateChanged ();
+        }
+        
+        protected virtual void OnIdleStateChanged ()
+        {
+            EventHandler handler = IdleStateChanged;
+            if (handler != null) {
+                handler (this, EventArgs.Empty);
+            }
         }
         
         public new void QueueDraw ()

Modified: trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/XOverlayVideoDisplay.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/XOverlayVideoDisplay.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.NowPlaying/Banshee.NowPlaying/XOverlayVideoDisplay.cs	Tue Aug 12 01:02:34 2008
@@ -42,40 +42,23 @@
 
         public XOverlayVideoDisplay () : base ()
         {
+            WidgetFlags = WidgetFlags.NoWindow;
         }
         
         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.Visual = Visual;
-            attributes.Wclass = Gdk.WindowClass.InputOutput;
-            attributes.Colormap = Colormap;
-            attributes.EventMask = (int)(Gdk.EventMask.ExposureMask | Gdk.EventMask.VisibilityNotifyMask);
             
-            Gdk.WindowAttributesType attributes_mask = 
-                Gdk.WindowAttributesType.X | 
-                Gdk.WindowAttributesType.Y | 
-                Gdk.WindowAttributesType.Visual | 
-                Gdk.WindowAttributesType.Colormap;
-                
-            GdkWindow = new Gdk.Window (Parent.GdkWindow, attributes, attributes_mask);
-            GdkWindow.UserData = Handle;
+            GdkWindow = Parent.GdkWindow;
             
             if (video_window != null) {
                 video_window.Reparent (GdkWindow, 0, 0);
-                video_window.MoveResize (0, 0, Allocation.Width, Allocation.Height);
+                video_window.MoveResize (Allocation.X, Allocation.Y, Allocation.Width, Allocation.Height);
                 video_window.ShowUnraised ();
                 return;
             }
             
-            attributes = new Gdk.WindowAttr ();
+            Gdk.WindowAttr attributes = new Gdk.WindowAttr ();
             attributes.WindowType = Gdk.WindowType.Child;
             attributes.X = 0;
             attributes.Y = 0;
@@ -86,7 +69,7 @@
             attributes.Colormap = Colormap;
             attributes.EventMask = (int)(Gdk.EventMask.ExposureMask | Gdk.EventMask.VisibilityNotifyMask);
             
-            attributes_mask = 
+            Gdk.WindowAttributesType attributes_mask = 
                 Gdk.WindowAttributesType.X | 
                 Gdk.WindowAttributesType.Y | 
                 Gdk.WindowAttributesType.Visual | 
@@ -110,18 +93,14 @@
 
         protected override void OnMapped ()
         {
-            WidgetFlags |= WidgetFlags.Mapped;
-            
-            GdkWindow.Show ();
+            base.OnMapped ();
             video_window.ShowUnraised ();
         }
         
         protected override void OnUnmapped ()
         {
-            WidgetFlags &= ~WidgetFlags.Mapped;
-            
             video_window.Hide ();
-            GdkWindow.Hide ();
+            base.OnUnmapped ();
         }
         
         protected override void OnSizeAllocated (Gdk.Rectangle allocation)
@@ -130,7 +109,7 @@
                 return;
             }
             
-            Gdk.Rectangle rect = new Gdk.Rectangle (0, 0, allocation.Width, allocation.Height);
+            Gdk.Rectangle rect = new Gdk.Rectangle (allocation.X, allocation.Y, allocation.Width, allocation.Height);
             video_window.MoveResize (rect);
             
             base.OnSizeAllocated (allocation);

Modified: trunk/banshee/src/Extensions/Banshee.NowPlaying/Makefile.am
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.NowPlaying/Makefile.am	(original)
+++ trunk/banshee/src/Extensions/Banshee.NowPlaying/Makefile.am	Tue Aug 12 01:02:34 2008
@@ -9,8 +9,10 @@
 	Banshee.NowPlaying/FullscreenWindow.cs \
 	Banshee.NowPlaying/IFullscreenAdapter.cs \
 	Banshee.NowPlaying/IScreensaverManager.cs \
+	Banshee.NowPlaying/NowPlayingContents.cs \
 	Banshee.NowPlaying/NowPlayingInterface.cs \
 	Banshee.NowPlaying/NowPlayingSource.cs \
+	Banshee.NowPlaying/NowPlayingTrackInfoDisplay.cs \
 	Banshee.NowPlaying/OverlayWindow.cs \
 	Banshee.NowPlaying/ScreensaverManager.cs \
 	Banshee.NowPlaying/VideoDisplay.cs \

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui/CairoExtensions.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui/CairoExtensions.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui/CairoExtensions.cs	Tue Aug 12 01:02:34 2008
@@ -63,6 +63,17 @@
                 PangoCairoHelper.ContextSetResolution (context, resolution);
             }
         }
+        
+        public static Surface CreateSurfaceForPixbuf (Cairo.Context cr, Gdk.Pixbuf pixbuf)
+        {
+            Surface surface = cr.Target.CreateSimilar (cr.Target.Content, pixbuf.Width, pixbuf.Height);
+            Cairo.Context surface_cr = new Context (surface);
+            surface_cr.Rectangle (0, 0, pixbuf.Width, pixbuf.Height);
+            Gdk.CairoHelper.SetSourcePixbuf (surface_cr, pixbuf, 0, 0);
+            surface_cr.Fill ();
+            ((IDisposable)surface_cr).Dispose ();
+            return surface;
+        }
     
         public static Cairo.Color GdkColorToCairoColor(Gdk.Color color)
         {



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