diff --git a/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs b/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs
index 0b0acdd..61dd4d8 100644
--- a/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs
+++ b/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs
@@ -478,6 +478,12 @@ namespace Banshee.Collection
             get { return can_play; }
             set { can_play = value; }
         }
+
+        private bool enabled = true;
+        public bool Enabled {
+            get { return enabled && can_play; }
+            set { enabled = value; }
+        }
         
         public virtual string MetadataHash {
             get {
diff --git a/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs b/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs
index 8ab3aae..5600c17 100644
--- a/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs
+++ b/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs
@@ -186,7 +186,7 @@ namespace Banshee.Collection.Database
         }
 
         private string unfiltered_query;
-        public string UnfilteredQuery {
+        public virtual string UnfilteredQuery {
             get {
                 return unfiltered_query ?? (unfiltered_query = String.Format (
                     "FROM {0} WHERE {1} {2}",
diff --git a/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs b/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
index 47e22f8..78f742e 100644
--- a/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
+++ b/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
@@ -56,7 +56,7 @@ namespace Banshee.Database
         // NOTE: Whenever there is a change in ANY of the database schema,
         //       this version MUST be incremented and a migration method
         //       MUST be supplied to match the new version number
-        protected const int CURRENT_VERSION = 33;
+        protected const int CURRENT_VERSION = 34;
         protected const int CURRENT_METADATA_VERSION = 6;
         
 #region Migration Driver
@@ -778,6 +778,17 @@ namespace Banshee.Database
 
 #endregion
 
+#region Version 34
+
+        [DatabaseVersion (34)]
+        private bool Migrate_34 ()
+        {
+            Execute ("ALTER TABLE CorePlaylistEntries ADD COLUMN Generated INTEGER NOT NULL DEFAULT 0");
+            return true;
+        }
+
+#endregion
+
 #pragma warning restore 0169
         
 #region Fresh database setup
@@ -939,7 +950,8 @@ namespace Banshee.Database
                     EntryID             INTEGER PRIMARY KEY,
                     PlaylistID          INTEGER NOT NULL,
                     TrackID             INTEGER NOT NULL,
-                    ViewOrder           INTEGER NOT NULL DEFAULT 0
+                    ViewOrder           INTEGER NOT NULL DEFAULT 0,
+                    Generated           INTEGER NOT NULL DEFAULT 0
                 )
             ");
             Execute("CREATE INDEX CorePlaylistEntriesIndex ON CorePlaylistEntries(PlaylistID, TrackID)");
diff --git a/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs b/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
index ca33e5a..97b3902 100644
--- a/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
+++ b/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
@@ -81,6 +81,7 @@ namespace Banshee.Playlist
         {
             add_track_range_command = new HyenaSqliteCommand (@"
                 INSERT INTO CorePlaylistEntries
+                    (EntryID, PlaylistID, TrackID, ViewOrder)
                     SELECT null, ?, ItemID, OrderId + ?
                         FROM CoreCache WHERE ModelID = ?
                         LIMIT ?, ?"
@@ -88,11 +89,13 @@ namespace Banshee.Playlist
 
             add_track_command = new HyenaSqliteCommand (@"
                 INSERT INTO CorePlaylistEntries
+                    (EntryID, PlaylistID, TrackID, ViewOrder)
                     VALUES (null, ?, ?, ?)"
             );
 
             add_track_range_from_joined_model_sql = @"
                 INSERT INTO CorePlaylistEntries
+                    (EntryID, PlaylistID, TrackID, ViewOrder)
                     SELECT null, ?, TrackID, OrderId + ?
                         FROM CoreCache c INNER JOIN {0} e ON c.ItemID = e.{1}
                         WHERE ModelID = ?
diff --git a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/BaseTrackListView.cs b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/BaseTrackListView.cs
index 50b5690..193bac9 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/BaseTrackListView.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/BaseTrackListView.cs
@@ -48,7 +48,7 @@ namespace Banshee.Collection.Gui
         public BaseTrackListView () : base ()
         {
             RulesHint = true;
-            RowSensitivePropertyName = "CanPlay";
+            RowOpaquePropertyName = "Enabled";
             RowBoldPropertyName = "IsPlaying";
             
             ServiceManager.PlayerEngine.ConnectEvent (OnPlayerEvent, PlayerEvent.StateChange);
diff --git a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellCreativeCommons.cs b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellCreativeCommons.cs
index 6912b74..170e473 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellCreativeCommons.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellCreativeCommons.cs
@@ -86,14 +86,14 @@ namespace Banshee.Collection.Gui
                     Cairo.Rectangle pixbuf_area = new Cairo.Rectangle (draw_x,
                         (cellHeight - render_pixbuf.Height) / 2, render_pixbuf.Width, render_pixbuf.Height);
                     
-                    if (!context.Sensitive) {
+                    if (!context.Opaque) {
                         context.Context.Save ();
                     }
                     
                     Gdk.CairoHelper.SetSourcePixbuf (context.Context, render_pixbuf, pixbuf_area.X, pixbuf_area.Y);
                     context.Context.Rectangle (pixbuf_area);
                     
-                    if (!context.Sensitive) {
+                    if (!context.Opaque) {
                         context.Context.Clip ();
                         context.Context.PaintWithAlpha (0.5);
                         context.Context.Restore ();
diff --git a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellStatusIndicator.cs b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellStatusIndicator.cs
index c9c763d..4e3d91f 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellStatusIndicator.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellStatusIndicator.cs
@@ -142,14 +142,14 @@ namespace Banshee.Collection.Gui
             Cairo.Rectangle pixbuf_area = new Cairo.Rectangle ((cellWidth - render_pixbuf.Width) / 2, 
                 (cellHeight - render_pixbuf.Height) / 2, render_pixbuf.Width, render_pixbuf.Height);
             
-            if (!context.Sensitive) {
+            if (!context.Opaque) {
                 context.Context.Save ();
             }
             
             Gdk.CairoHelper.SetSourcePixbuf (context.Context, render_pixbuf, pixbuf_area.X, pixbuf_area.Y);
             context.Context.Rectangle (pixbuf_area);
             
-            if (!context.Sensitive) {
+            if (!context.Opaque) {
                 context.Context.Clip ();
                 context.Context.PaintWithAlpha (0.5);
                 context.Context.Restore ();
diff --git a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellTrack.cs b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellTrack.cs
index 226f55f..31783cf 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellTrack.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellTrack.cs
@@ -81,7 +81,7 @@ namespace Banshee.Collection.Gui
             context.Context.MoveTo (4, ((int)cellHeight - text_height) / 2);
             Cairo.Color color = context.Theme.Colors.GetWidgetColor (
                 context.TextAsForeground ? GtkColorClass.Foreground : GtkColorClass.Text, state);
-            color.A = (!context.Sensitive) ? 0.3 : 1.0;
+            color.A = (!context.Opaque) ? 0.3 : 1.0;
             context.Context.Color = color;
             
             PangoCairoHelper.ShowLayout (context.Context, context.Layout);
diff --git a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue.addin.xml b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue.addin.xml
index 014a6cb..05ddffb 100644
--- a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue.addin.xml
+++ b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue.addin.xml
@@ -7,7 +7,7 @@
     name="Play Queue"
     category="User Interface"
     description="Provides a source that acts as a queue of playing tracks. When the queue is populated, all playback happens from the queue in a forced order."
-    author="Aaron Bockover"
+    author="Aaron Bockover, Alexander Kojevnikov"
     url="http://banshee-project.org/"
     defaultEnabled="true">
 
diff --git a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue.csproj b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue.csproj
index 5fe9ce6..751578b 100644
--- a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue.csproj
+++ b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue.csproj
@@ -72,6 +72,9 @@
     <Compile Include="Banshee.PlayQueue\PlayQueueSource.cs" />
     <Compile Include="Banshee.PlayQueue\PlayQueueActions.cs" />
     <Compile Include="Banshee.PlayQueue\IPlayQueue.cs" />
+    <Compile Include="Banshee.PlayQueue\ConfigurationPane.cs" />
+    <Compile Include="Banshee.PlayQueue\PlayQueueTrackListModel.cs" />
+    <Compile Include="Banshee.PlayQueue\QueueableSourceComboBox.cs" />
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="Resources\ActiveSourceUI.xml">
diff --git a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/ConfigurationPane.cs b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/ConfigurationPane.cs
new file mode 100644
index 0000000..f890353
--- /dev/null
+++ b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/ConfigurationPane.cs
@@ -0,0 +1,222 @@
+//
+// ConfigurationPane.cs
+//
+// Author:
+//   Alexander Kojevnikov <alexander@kojevnikov.com>
+//
+// Copyright (C) 2009 Alexander Kojevnikov
+//
+// 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 Gtk;
+using Mono.Unix;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Banshee.PlaybackController;
+using Banshee.Sources;
+
+namespace Banshee.PlayQueue
+{
+    public class ConfigurationPane : Hyena.Widgets.RoundedFrame
+    {
+        public event EventHandler<ModeChangedEventArgs> ModeChanged;
+        public event EventHandler<SourceChangedEventArgs> SourceChanged;
+        public event EventHandler<SongsNumberChangedEventArgs> PlayedSongsNumberChanged;
+        public event EventHandler<SongsNumberChangedEventArgs> UpcomingSongsNumberChanged;
+        public event EventHandler RefreshButtonClicked;
+
+        private readonly List<Widget> sensitive_widgets = new List<Widget> ();
+        private readonly Dictionary<string, PlaybackShuffleMode> modes = new Dictionary<string, PlaybackShuffleMode> {
+            { Catalog.GetString ("Off"), PlaybackShuffleMode.Linear },
+            { Catalog.GetString ("By Song"), PlaybackShuffleMode.Song },
+            { Catalog.GetString ("By Album"), PlaybackShuffleMode.Album },
+            { Catalog.GetString ("By Artist"), PlaybackShuffleMode.Artist },
+        };
+
+        public ConfigurationPane (PlaybackShuffleMode mode, string source_name,
+            int played_songs_number, int upcoming_songs_number) : base ()
+        {
+            var main_table = new Table (2, 5, false);
+            main_table.BorderWidth = 5;
+            main_table.ColumnSpacing = 5;
+
+            var populate_label = new Label (Catalog.GetString ("R_andomly populate the Play Queue:"));
+            var mode_combo = new ComboBox (modes.Keys.OrderBy (s => modes[s]).ToArray ());
+            populate_label.MnemonicWidget = mode_combo;
+            mode_combo.Changed += delegate {
+                var value = modes[mode_combo.ActiveText];
+                foreach (var widget in sensitive_widgets) {
+                    widget.Sensitive = value != PlaybackShuffleMode.Linear;
+                }
+                var handler = ModeChanged;
+                if (handler != null) {
+                    handler (this, new ModeChangedEventArgs (value));
+                }
+            };
+            var populate_box = new HBox ();
+            populate_box.PackStart (populate_label, false, false, 0);
+            populate_box.PackStart (mode_combo, false, false, 5);
+            main_table.Attach (populate_box, 0, 1, 0, 1,
+                AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Fill,
+                main_table.ColumnSpacing, main_table.RowSpacing);
+
+            var from_label = new Label (Catalog.GetString ("_From:"));
+            sensitive_widgets.Add (from_label);
+            var source_combo_box = new QueueableSourceComboBox (source_name);
+            from_label.MnemonicWidget = source_combo_box;
+            sensitive_widgets.Add (source_combo_box);
+            source_combo_box.Changed += delegate {
+                var handler = SourceChanged;
+                if (handler != null) {
+                    handler (this, new SourceChangedEventArgs (source_combo_box.Source));
+                }
+            };
+            var from_box = new HBox ();
+            from_box.PackStart (from_label, false, false, 0);
+            from_box.PackStart (source_combo_box, true, true, 5);
+            main_table.Attach (from_box, 0, 1, 1, 2,
+                AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Fill,
+                main_table.ColumnSpacing, main_table.RowSpacing);
+
+            // Translators: this label will be part of the following sentense: "Show X recently played tracks"
+            var show_label = new Label (Catalog.GetString ("Show"));
+            show_label.Xalign = 1f;
+            main_table.Attach (show_label, 1, 2, 0, 1,
+                AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Fill,
+                main_table.ColumnSpacing, main_table.RowSpacing);
+
+            SpinButton played_songs_spin_button = new SpinButton (0, 100, 1);
+            played_songs_spin_button.Value = played_songs_number;
+            played_songs_spin_button.ValueChanged += delegate {
+                var handler = PlayedSongsNumberChanged;
+                if (handler != null) {
+                    handler (this, new SongsNumberChangedEventArgs ((int) played_songs_spin_button.Value));
+                }
+            };
+            main_table.Attach (played_songs_spin_button, 2, 3, 0, 1,
+                AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Fill, 0, 0);
+
+            // Translators: this label will be part of the following sentense: "Show X recently played tracks"
+            var recent_songs_label = new Label (Catalog.GetString ("re_cently played tracks"));
+            recent_songs_label.MnemonicWidget = played_songs_spin_button;
+            recent_songs_label.Xalign = 0f;
+            main_table.Attach (recent_songs_label, 3, 4, 0, 1,
+                AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Fill,
+                main_table.ColumnSpacing, main_table.RowSpacing);
+
+            // Translators: this label will be part of the following sentense: "and X upcoming tracks"
+            var and_label = new Label (Catalog.GetString ("and"));
+            sensitive_widgets.Add (and_label);
+            and_label.Xalign = 1f;
+            main_table.Attach (and_label, 1, 2, 1, 2,
+                AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Fill,
+                main_table.ColumnSpacing, main_table.RowSpacing);
+
+            SpinButton upcoming_songs_spin_button = new SpinButton (1, 100, 1);
+            sensitive_widgets.Add (upcoming_songs_spin_button);
+            upcoming_songs_spin_button.Value = upcoming_songs_number;
+            upcoming_songs_spin_button.ValueChanged += delegate {
+                var handler = UpcomingSongsNumberChanged;
+                if (handler != null) {
+                    handler (this, new SongsNumberChangedEventArgs ((int) upcoming_songs_spin_button.Value));
+                }
+            };
+            main_table.Attach (upcoming_songs_spin_button, 2, 3, 1, 2,
+                AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Fill, 0, 0);
+
+            // Translators: this label will be part of the following sentense: "and X upcoming tracks"
+            var upcoming_songs_label = new Label (Catalog.GetString ("_upcoming tracks"));
+            upcoming_songs_label.MnemonicWidget = upcoming_songs_spin_button;
+            sensitive_widgets.Add (upcoming_songs_label);
+            upcoming_songs_label.Xalign = 0f;
+            main_table.Attach (upcoming_songs_label, 3, 4, 1, 2,
+                AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Fill,
+                main_table.ColumnSpacing, main_table.RowSpacing);
+
+            var refresh_button = new Button (Stock.Refresh);
+            sensitive_widgets.Add (refresh_button);
+            refresh_button.Clicked += delegate {
+                var handler = RefreshButtonClicked;
+                if (handler != null) {
+                    handler (this, new EventArgs ());
+                }
+            };
+            var refresh_alignment = new Alignment (1f, .5f, 0f, 0f);
+            refresh_alignment.Add (refresh_button);
+            main_table.Attach (refresh_alignment, 4, 5, 0, 2);
+
+            Add (main_table);
+
+            // Select the population mode.
+            mode_combo.Model.Foreach (delegate (TreeModel model, TreePath path, TreeIter iter) {
+                if (modes[(string)model.GetValue (iter, 0)] == mode) {
+                    mode_combo.SetActiveIter (iter);
+                    return true;
+                }
+                return false;
+            });
+        }
+    }
+
+    public sealed class ModeChangedEventArgs : EventArgs
+    {
+        private PlaybackShuffleMode value;
+
+        public ModeChangedEventArgs (PlaybackShuffleMode value)
+        {
+            this.value = value;
+        }
+
+        public PlaybackShuffleMode Value {
+            get { return this.value; }
+        }
+    }
+
+    public sealed class SourceChangedEventArgs : EventArgs
+    {
+        private ITrackModelSource value;
+
+        public SourceChangedEventArgs (ITrackModelSource value)
+        {
+            this.value = value;
+        }
+
+        public ITrackModelSource Value {
+            get { return this.value; }
+        }
+    }
+
+    public sealed class SongsNumberChangedEventArgs : EventArgs
+    {
+        private int value;
+
+        public SongsNumberChangedEventArgs (int value)
+        {
+            this.value = value;
+        }
+
+        public int Value {
+            get { return this.value; }
+        }
+    }
+}
diff --git a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
index 8742d56..4271094 100644
--- a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
+++ b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
@@ -1,10 +1,12 @@
 //
 // PlayQueueSource.cs
 //
-// Author:
+// Authors:
 //   Aaron Bockover <abockover@novell.com>
+//   Alexander Kojevnikov <alexander@kojevnikov.com>
 //
 // Copyright (C) 2008 Novell, Inc.
+// Copyright (C) 2009 Alexander Kojevnikov
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -27,9 +29,12 @@
 //
 
 using System;
+using System.Collections.Generic;
+using System.Linq;
 
 using Mono.Unix;
 
+using Hyena.Collections;
 using Hyena.Data.Sqlite;
 
 using Banshee.ServiceStack;
@@ -48,17 +53,22 @@ namespace Banshee.PlayQueue
 {
     public class PlayQueueSource : PlaylistSource, IBasicPlaybackController, IPlayQueue, IDBusExportable, IDisposable
     {
-        private static string special_playlist_name = "Play Queue";//typeof (PlayQueueSource).ToString ();
+        private static string special_playlist_name = "Play Queue";
 
         private ITrackModelSource prior_playback_source;
-        private DatabaseTrackInfo playing_track;
+        private DatabaseTrackInfo current_track;
+        private long offset;
         private TrackInfo prior_playback_track;
         private PlayQueueActions actions;
         private bool was_playing = false;
-        
-        protected override bool HasArtistAlbum {
-            get { return false; }
-        }
+        protected DateTime source_set_at = DateTime.MinValue;
+        private ConfigurationPane pane;
+
+        private PlaybackShuffleMode populate_mode = (PlaybackShuffleMode) PopulateModeSchema.Get ();
+        private string populate_from_name = PopulateFromSchema.Get ();
+        private ITrackModelSource populate_from = null;
+        private int played_songs_number = PlayedSongsNumberSchema.Get ();
+        private int upcoming_songs_number = UpcomingSongsNumberSchema.Get ();
         
         public PlayQueueSource () : base (Catalog.GetString ("Play Queue"), null)
         {
@@ -70,12 +80,13 @@ namespace Banshee.PlayQueue
             Order = 20;
             Properties.SetString ("Icon.Name", "source-playlist");
             Properties.SetString ("RemoveTracksActionLabel", Catalog.GetString ("Remove From Play Queue"));
-            
+
             DatabaseTrackModel.ForcedSortQuery = "CorePlaylistEntries.ViewOrder ASC, CorePlaylistEntries.EntryID ASC";
             DatabaseTrackModel.CanReorder = true;
-            
+
             ServiceManager.PlayerEngine.ConnectEvent (OnPlayerEvent);
-            ServiceManager.PlaybackController.Transition += OnCanonicalPlaybackControllerTransition;
+            ServiceManager.SourceManager.ActiveSourceChanged += OnActiveSourceChanged;
+            ServiceManager.PlaybackController.TrackStarted += OnTrackStarted;
 
             ServiceManager.SourceManager.AddSource (this);
             
@@ -92,18 +103,60 @@ namespace Banshee.PlayQueue
             ServiceManager.SourceManager.VideoLibrary.TracksChanged += HandleTracksChanged;
             ServiceManager.SourceManager.VideoLibrary.TracksDeleted += HandleTracksDeleted;
             
-            TrackModel.Reloaded += delegate {
-                if (Count == 0) {
-                    if (this == ServiceManager.PlaybackController.Source || this == ServiceManager.PlaybackController.NextSource) {
-                        ServiceManager.PlaybackController.NextSource = ServiceManager.PlaybackController.Source = PriorSource;
-                    }
-                }
-            };
-            
-            Reload ();
+            populate_from = ServiceManager.SourceManager.Sources.FirstOrDefault (
+                source => source.Name == populate_from_name) as ITrackModelSource;
+            if (populate_from != null) {
+                populate_from.Reload ();
+            }
+
+            Offset = CurrentOffsetSchema.Get ();
+
+            int track_index = CurrentTrackSchema.Get ();
+            if (track_index < Count) {
+                current_track = TrackModel[track_index] as DatabaseTrackInfo;
+            }
+
             SetAsPlaybackSourceUnlessPlaying ();
         }
-        
+
+        protected override void Initialize ()
+        {
+            base.Initialize ();
+
+            pane = new ConfigurationPane (populate_mode, populate_from_name, played_songs_number, upcoming_songs_number);
+            pane.ModeChanged += delegate(object sender, ModeChangedEventArgs e) {
+                populate_mode = e.Value;
+                PopulateModeSchema.Set ((int) e.Value);
+                UpdatePlayQueue ();
+            };
+            pane.SourceChanged += delegate(object sender, SourceChangedEventArgs e) {
+                populate_from = e.Value;
+                populate_from_name = e.Value.Name;
+                PopulateFromSchema.Set (e.Value.Name);
+                source_set_at = DateTime.Now;
+                populate_from.Reload ();
+                OnRefresh ();
+            };
+            pane.PlayedSongsNumberChanged += delegate(object sender, SongsNumberChangedEventArgs e) {
+                played_songs_number = e.Value;
+                PlayedSongsNumberSchema.Set (e.Value);
+                UpdatePlayQueue ();
+            };
+            pane.UpcomingSongsNumberChanged += delegate(object sender, SongsNumberChangedEventArgs e) {
+                upcoming_songs_number = e.Value;
+                UpcomingSongsNumberSchema.Set (e.Value);
+                UpdatePlayQueue ();
+            };
+            pane.RefreshButtonClicked += delegate {
+                OnRefresh ();
+            };
+
+            BaseClientWindow nereid = ServiceManager.Get<IService> ("NereidPlayerInterface") as Banshee.Gui.BaseClientWindow;
+            if (nereid != null) {
+                nereid.ViewContainer.PackEnd (pane, false, false, 0);
+            }
+        }
+
 #region IPlayQueue, IDBusExportable
 
         public void EnqueueUri (string uri)
@@ -113,33 +166,66 @@ namespace Banshee.PlayQueue
 
         public void EnqueueUri (string uri, bool prepend)
         {
-            EnqueueId (DatabaseTrackInfo.GetTrackIdForUri (uri), prepend);
+            EnqueueId (DatabaseTrackInfo.GetTrackIdForUri (uri), prepend, false);
         }
         
         public void EnqueueTrack (TrackInfo track, bool prepend)
         {
             DatabaseTrackInfo db_track = track as DatabaseTrackInfo;
             if (db_track != null) {
-                EnqueueId (db_track.TrackId, prepend);
+                EnqueueId (db_track.TrackId, prepend, false);
             } else {
                 EnqueueUri (track.Uri.AbsoluteUri, prepend);
             }
         }
         
-        private void EnqueueId (int trackId, bool prepend)
+        private void EnqueueId (int trackId, bool prepend, bool generated)
         {
             if (trackId <= 0) {
                 return;
             }
-            
-            if (prepend) {
-                ServiceManager.DbConnection.Execute ("UPDATE CorePlaylistEntries SET ViewOrder = ViewOrder + 1 WHERE PlaylistID = ?", DbId);
+
+            long view_order;
+            if (prepend && current_track != null) {
+                // We are going to prepend the track to the play queue, which means
+                // adding it after the current_track. Now find the corresponding view_order.
+                view_order = ServiceManager.DbConnection.Query<long> (@"
+                    SELECT ViewOrder + 1
+                    FROM CorePlaylistEntries
+                    WHERE PlaylistID = ? AND EntryID = ?",
+                    DbId, Convert.ToInt64 (current_track.CacheEntryId)
+                );
+            } else {
+                if (generated) {
+                    // view_order will point after the last track in the queue.
+                    view_order = MaxViewOrder;
+                }
+                else {
+                    // view_order will point after the last non-generated track in the queue.
+                    view_order = ServiceManager.DbConnection.Query<long> (@"
+                        SELECT MAX(ViewOrder) + 1
+                        FROM CorePlaylistEntries
+                        WHERE PlaylistID = ? AND Generated = 0",
+                        DbId
+                    );
+                }
             }
 
-            HyenaSqliteCommand insert_command = new HyenaSqliteCommand (String.Format (
-                @"INSERT INTO CorePlaylistEntries (PlaylistID, TrackID, ViewOrder) VALUES ({0}, ?, {1})", 
-                    DbId, prepend ? 0 : MaxViewOrder));
-            ServiceManager.DbConnection.Execute (insert_command, trackId);
+            // Increment the order of all tracks after view_order
+            ServiceManager.DbConnection.Execute (@"
+                UPDATE CorePlaylistEntries
+                SET ViewOrder = ViewOrder + 1
+                WHERE PlaylistID = ? AND ViewOrder >= ?",
+                DbId, view_order
+            );
+
+            // Add the track to the queue using the view order calculated above.
+            ServiceManager.DbConnection.Execute (@"
+                INSERT INTO CorePlaylistEntries
+                (PlaylistID, TrackID, ViewOrder, Generated)
+                VALUES (?, ?, ?, ?)",
+                DbId, trackId, view_order, generated ? 1 : 0
+            );
 
             OnTracksAdded ();
             NotifyUser ();
@@ -154,10 +240,53 @@ namespace Banshee.PlayQueue
         }
 
 #endregion
-        
+
+        public override bool AddSelectedTracks (Source source)
+        {
+            if ((Parent == null || source == Parent || source.Parent == Parent) && AcceptsInputFromSource (source)) {
+                DatabaseTrackListModel model = (source as ITrackModelSource).TrackModel as DatabaseTrackListModel;
+                if (model == null) {
+                    return false;
+                }
+
+                // Get the ViewOrder of the current_track
+                long current_view_order = current_track == null ? 0 : ServiceManager.DbConnection.Query<long> (@"
+                    SELECT ViewOrder
+                    FROM CorePlaylistEntries
+                    WHERE PlaylistID = ? AND EntryID = ?",
+                    DbId, Convert.ToInt64 (current_track.CacheEntryId)
+                );
+
+                // view_order will point to the last pending non-generated track in the queue
+                // or to the current_track if all tracks are generated. We want to insert tracks after it.
+                long view_order = Math.Max(current_view_order, ServiceManager.DbConnection.Query<long> (@"
+                    SELECT MAX(ViewOrder)
+                    FROM CorePlaylistEntries
+                    WHERE PlaylistID = ? AND ViewOrder > ? AND Generated = 0",
+                    DbId, current_view_order
+                ));
+
+                // Add the tracks to the end of the queue.
+                WithTrackSelection (model, AddTrackRange);
+
+                // Shift generated tracks to the end of the queue.
+                ServiceManager.DbConnection.Execute (@"
+                    UPDATE CorePlaylistEntries
+                    SET ViewOrder = ViewOrder - ? + ?
+                    WHERE PlaylistID = ? AND ViewOrder > ? AND Generated = 1",
+                    view_order, MaxViewOrder, DbId, view_order
+                );
+
+                OnTracksAdded ();
+                OnUserNotifyUpdated ();
+                return true;
+            }
+            return false;
+        }
+
         private void SetAsPlaybackSourceUnlessPlaying ()
         {
-            if (Count > 0 && ServiceManager.PlaybackController.Source != this) {
+            if (current_track != null && ServiceManager.PlaybackController.Source != this) {
                 PriorSource = ServiceManager.PlaybackController.Source;
                 ServiceManager.PlaybackController.NextSource = this;
             }
@@ -165,19 +294,39 @@ namespace Banshee.PlayQueue
 
         public void Clear ()
         {
-            playing_track = null;
-            RemoveTrackRange (DatabaseTrackModel, new Hyena.Collections.RangeCollection.Range (0, Count));
+            ServiceManager.DbConnection.Execute (@"
+                DELETE FROM CorePlaylistEntries
+                WHERE PlaylistID = ?", DbId
+            );
+            offset = 0;
+            current_track = null;
+
+            if (this == ServiceManager.PlaybackController.Source && ServiceManager.PlayerEngine.IsPlaying ()) {
+                ServiceManager.PlayerEngine.Close();
+            }
+
             Reload ();
+            UpdatePlayQueue ();
         }
 
         public void Dispose ()
         {
+            int track_index = current_track == null ? Count : Math.Max (0, TrackModel.IndexOf (current_track));
+            CurrentTrackSchema.Set (track_index);
+
             ServiceManager.PlayerEngine.DisconnectEvent (OnPlayerEvent);
+            ServiceManager.SourceManager.ActiveSourceChanged -= OnActiveSourceChanged;
+            ServiceManager.PlaybackController.TrackStarted -= OnTrackStarted;
 
             if (actions != null) {
                 actions.Dispose ();
             }
 
+            if (pane != null) {
+                pane.Destroy ();
+                pane = null;
+            }
+
             if (ClearOnQuitSchema.Get ()) {
                 Clear ();
             }
@@ -201,22 +350,50 @@ namespace Banshee.PlayQueue
 
         protected override void OnTracksAdded ()
         {
+            int old_count = Count;
+
             base.OnTracksAdded ();
+
+            if (current_track == null && old_count < Count) {
+                current_track = TrackModel[old_count] as DatabaseTrackInfo;
+            }
+
             SetAsPlaybackSourceUnlessPlaying ();
         }
-        
-        private void OnCanonicalPlaybackControllerTransition (object o, EventArgs args)
+
+        protected override void OnTracksRemoved ()
         {
-            if (Count > 0) {
-                PriorSource = ServiceManager.PlaybackController.Source;
-                ServiceManager.PlaybackController.Source = this;
+            base.OnTracksRemoved ();
+
+            if (this == ServiceManager.PlaybackController.Source &&
+                ServiceManager.PlayerEngine.IsPlaying () &&
+                TrackModel.IndexOf (ServiceManager.PlayerEngine.CurrentTrack) == -1) {
+                if (ServiceManager.PlayerEngine.CurrentState == PlayerState.Paused || current_track == null) {
+                    ServiceManager.PlayerEngine.Close();
+                } else {
+                    ServiceManager.PlayerEngine.OpenPlay (current_track);
+                }
             }
+            UpdatePlayQueue ();
         }
-        
+
+        protected override void RemoveTrackRange (DatabaseTrackListModel model, RangeCollection.Range range)
+        {
+            base.RemoveTrackRange (model, range);
+
+            int index = TrackModel.IndexOf (current_track);
+            if (range.Start <= index && index <= range.End) {
+                current_track = range.End + 1 < Count ? TrackModel[range.End + 1] as DatabaseTrackInfo : null;
+            }
+        }
+
         private void OnPlayerEvent (PlayerEventArgs args)
         {
             if (args.Event == PlayerEvent.EndOfStream) {
-                if (RemovePlayingTrack () && Count == 0) {
+                if (this == ServiceManager.PlaybackController.Source &&
+                    TrackModel.IndexOf (current_track) == Count - 1) {
+                    current_track = null;
+                    UpdatePlayQueue ();
                     if (was_playing) {
                         ServiceManager.PlaybackController.PriorTrack = prior_playback_track;
                     } else {
@@ -224,15 +401,33 @@ namespace Banshee.PlayQueue
                     }
                 }
             } else if (args.Event == PlayerEvent.StartOfStream) {
-                if (this == ServiceManager.PlaybackController.Source) {
-                    playing_track = ServiceManager.PlayerEngine.CurrentTrack as DatabaseTrackInfo;
+                if (TrackModel.IndexOf (ServiceManager.PlayerEngine.CurrentTrack) != -1) {
+                    current_track = ServiceManager.PlayerEngine.CurrentTrack as DatabaseTrackInfo;
+                    SetAsPlaybackSourceUnlessPlaying ();
+                    UpdatePlayQueue ();
                 } else {
-                    playing_track = null;
                     prior_playback_track = ServiceManager.PlayerEngine.CurrentTrack;
                 }
             }
         }
 
+        public override void Reload ()
+        {
+            base.Reload ();
+
+            if (current_track == null) {
+                if (this == ServiceManager.PlaybackController.Source ||
+                    this == ServiceManager.PlaybackController.NextSource) {
+                    ServiceManager.PlaybackController.NextSource = PriorSource;
+                }
+            }
+        }
+
+        protected override DatabaseTrackListModel CreateTrackModelFor (DatabaseSource src)
+        {
+            return new PlayQueueTrackListModel (ServiceManager.DbConnection, DatabaseTrackInfo.Provider, (PlayQueueSource) src);
+        }
+
         bool IBasicPlaybackController.First ()
         {
             return ((IBasicPlaybackController)this).Next (false);
@@ -240,9 +435,12 @@ namespace Banshee.PlayQueue
         
         bool IBasicPlaybackController.Next (bool restart)
         {
-            RemovePlayingTrack ();
-            
-            if (Count == 0) {
+            if (current_track != null && ServiceManager.PlayerEngine.CurrentTrack == current_track) {
+                int index = TrackModel.IndexOf (current_track) + 1;
+                current_track = index < Count ? TrackModel[index] as DatabaseTrackInfo : null;
+            }
+            if (current_track == null) {
+                UpdatePlayQueue ();
                 ServiceManager.PlaybackController.Source = PriorSource;
                 if (was_playing) {
                     ServiceManager.PlaybackController.PriorTrack = prior_playback_track;
@@ -252,26 +450,156 @@ namespace Banshee.PlayQueue
                 }
                 return true;
             }
-            
-            ServiceManager.PlayerEngine.OpenPlay ((DatabaseTrackInfo)TrackModel[0]);
+
+            ServiceManager.PlayerEngine.OpenPlay (current_track);
             return true;
         }
         
         bool IBasicPlaybackController.Previous (bool restart)
         {
+            if (current_track != null && ServiceManager.PlayerEngine.CurrentTrack == current_track) {
+                int index = TrackModel.IndexOf (current_track);
+                if (index > 0) {
+                    current_track = TrackModel[index - 1] as DatabaseTrackInfo;
+                }
+                ServiceManager.PlayerEngine.OpenPlay (current_track);
+            }
             return true;
         }
         
-        private bool RemovePlayingTrack ()
+        private void UpdatePlayQueue ()
         {
-            if (playing_track != null) {
-                RemoveTrack (playing_track);
-                playing_track = null;
-                return true;
+            // Find the ViewOrder of the current_track.
+            long view_order;
+            if (current_track == null) {
+                view_order = ServiceManager.DbConnection.Query<long> (@"
+                    SELECT MAX(ViewOrder) + 1
+                    FROM CorePlaylistEntries
+                    WHERE PlaylistID = ?", DbId
+                );
+            }
+            else {
+                view_order = ServiceManager.DbConnection.Query<long> (@"
+                    SELECT ViewOrder
+                    FROM CorePlaylistEntries
+                    WHERE PlaylistID = ? AND EntryID = ?",
+                    DbId, Convert.ToInt64 (current_track.CacheEntryId)
+                );
+            }
+
+            // Offset the model so that no more than played_songs_number tracks are shown before the current_track.
+            Offset = played_songs_number == 0 ? view_order : ServiceManager.DbConnection.Query<long> (@"
+                SELECT MIN(ViewOrder)
+                FROM (
+                    SELECT ViewOrder
+                    FROM CorePlaylistEntries
+                    WHERE PlaylistID = ? AND ViewOrder < ?
+                    ORDER BY ViewOrder DESC
+                    LIMIT ?
+                )", DbId, view_order, played_songs_number
+            );
+
+            // Check if we need to add more tracks.
+            int tracks_to_add = upcoming_songs_number - Count + 1 +
+                (current_track == null ? 0 : TrackModel.IndexOf (current_track));
+            if (tracks_to_add > 0 && Populate && populate_from != null) {
+                // Add songs from the selected source.
+                for (int i = 0; i < tracks_to_add; i++) {
+                    var track = populate_from.TrackModel.GetRandom (source_set_at, populate_mode, false)
+                        as DatabaseTrackInfo;
+                    if (track != null) {
+                        track.LastPlayed = DateTime.Now;
+                        // track.Save() is quite slow, update LastPlayedStamp directly in the database.
+                        ServiceManager.DbConnection.Execute (@"
+                            UPDATE CoreTracks
+                            SET LastPlayedStamp = ?
+                            WHERE TrackID = ?",
+                            Hyena.DateTimeUtil.ToTimeT (track.LastPlayed), track.TrackId
+                        );
+                        EnqueueId (track.TrackId, false, true);
+                    }
+                }
+                OnTracksAdded ();
+                if (current_track == null && Count > 0) {
+                    // If the queue was empty, make the first added track the current one.
+                    current_track = TrackModel[0] as DatabaseTrackInfo;
+                    ServiceManager.PlayerEngine.OpenPlay (current_track);
+                }
             }
-            return false;
         }
-        
+
+        public bool IsTrackEnabled (TrackInfo track)
+        {
+            int current_index = current_track == null ? Count : TrackModel.IndexOf (current_track);
+            int index = TrackModel.IndexOf (track);
+            return index >= current_index;
+        }
+
+        public long Offset {
+            get { return offset; }
+            protected set {
+                if (value != offset) {
+                    offset = value;
+                    CurrentOffsetSchema.Set ((int) offset);
+                    Reload ();
+                }
+            }
+        }
+
+        private void OnRefresh ()
+        {
+            int index = current_track == null ? Count : TrackModel.IndexOf (current_track);
+            if (index + 1 < Count) {
+                // Get the list of generated tracks.
+                var generated = new HashSet<long> ();
+                foreach(long trackID in ServiceManager.DbConnection.QueryEnumerable<long> ( @"
+                    SELECT TrackID FROM CorePlaylistEntries WHERE PlaylistID = ? AND Generated = 1", DbId)) {
+                    generated.Add (trackID);
+                }
+
+                // Collect the indices of all generated tracks.
+                var ranges = new RangeCollection ();
+                for (int i = index + 1; i < Count; i++) {
+                    if (generated.Contains (((DatabaseTrackInfo)TrackModel[i]).TrackId)) {
+                        ranges.Add (i);
+                    }
+                }
+
+                bool removed = false;
+                foreach (var range in ranges.Ranges) {
+                    RemoveTrackRange (DatabaseTrackModel, range);
+                    removed = true;
+                }
+
+                if (removed) {
+                    OnTracksRemoved ();
+                }
+            }
+            else if (Count == 0) {
+                UpdatePlayQueue ();
+            }
+        }
+
+        private void OnActiveSourceChanged (SourceEventArgs args)
+        {
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                if (args.Source == this) {
+                    pane.ShowAll ();
+                } else {
+                    pane.Hide ();
+                }
+            });
+        }
+
+        private void OnTrackStarted(object sender, EventArgs e)
+        {
+            SetAsPlaybackSourceUnlessPlaying ();
+        }
+
+        private bool Populate {
+            get { return populate_mode != PlaybackShuffleMode.Linear; }
+        }
+
         private ITrackModelSource PriorSource {
             get {
                 if (prior_playback_source == null || prior_playback_source == this) {
@@ -287,15 +615,23 @@ namespace Banshee.PlayQueue
                 was_playing = ServiceManager.PlayerEngine.IsPlaying ();
             }
         }
-        
+
         public override bool CanRename {
             get { return false; }
         }
-        
+
+        public override bool CanSearch {
+            get { return false; }
+        }
+
         public override bool ShowBrowser {
             get { return false; }
         }
-        
+
+        protected override bool HasArtistAlbum {
+            get { return false; }
+        }
+
         public override bool ConfirmRemoveTracks {
             get { return false; }
         }
@@ -311,12 +647,54 @@ namespace Banshee.PlayQueue
         public override bool CanUnmap {
             get { return false; }
         }
-        
+
         public static readonly SchemaEntry<bool> ClearOnQuitSchema = new SchemaEntry<bool> (
             "plugins.play_queue", "clear_on_quit",
             false,
             "Clear on Quit",
             "Clear the play queue when quitting"
         );
+
+        public static readonly SchemaEntry<int> CurrentTrackSchema = new SchemaEntry<int> (
+            "plugins.play_queue", "current_track",
+            0,
+            "Current Track",
+            "Current track in the Play Queue"
+        );
+
+        public static readonly SchemaEntry<int> CurrentOffsetSchema = new SchemaEntry<int> (
+            "plugins.play_queue", "current_offset",
+            0,
+            "Current Offset",
+            "Current offset of the Play Queue"
+        );
+
+        public static readonly SchemaEntry<int> PopulateModeSchema = new SchemaEntry<int> (
+            "plugins.play_queue", "populate_mode",
+            (int) PlaybackShuffleMode.Linear,
+            "Play Queue population mode",
+            "How (and if) the Play Queue should be randomly populated"
+        );
+
+        public static readonly SchemaEntry<string> PopulateFromSchema = new SchemaEntry<string> (
+            "plugins.play_queue", "populate_from",
+            ServiceManager.SourceManager.MusicLibrary.Name,
+            "Source to poplulate from",
+            "Name of the source to populate the the Play Queue from"
+        );
+
+        public static readonly SchemaEntry<int> PlayedSongsNumberSchema = new SchemaEntry<int> (
+            "plugins.play_queue", "played_songs_number",
+            10,
+            "Played Songs Number",
+            "Number of played songs to show in the Play Queue"
+        );
+
+        public static readonly SchemaEntry<int> UpcomingSongsNumberSchema = new SchemaEntry<int> (
+            "plugins.play_queue", "upcoming_songs_number",
+            10,
+            "Upcoming Songs Number",
+            "Number of upcoming songs to show in the Play Queue"
+        );
     }
 }
diff --git a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueTrackListModel.cs b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueTrackListModel.cs
new file mode 100644
index 0000000..4663551
--- /dev/null
+++ b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueTrackListModel.cs
@@ -0,0 +1,64 @@
+//
+// PlayQueueSource.cs
+//
+// Author:
+//   Alexander Kojevnikov <alexander@kojevnikov.com>
+//
+// Copyright (C) 2009 Alexander Kojevnikov
+//
+// 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 Banshee.Database;
+using Banshee.Collection;
+using Banshee.Collection.Database;
+
+namespace Banshee.PlayQueue
+{
+    public class PlayQueueTrackListModel : DatabaseTrackListModel
+    {
+        private readonly PlayQueueSource source;
+
+        public PlayQueueTrackListModel (
+            BansheeDbConnection conn, IDatabaseTrackModelProvider provider, PlayQueueSource source) :
+            base (conn, provider, source)
+        {
+            this.source = source;
+        }
+
+        public override TrackInfo this[int index] {
+            get {
+                lock (this) {
+                    var track = cache.GetValue (index);
+                    track.Enabled = source.IsTrackEnabled (track);
+                    return track;
+                }
+            }
+        }
+
+        public override string UnfilteredQuery {
+           get {
+               return String.Format ("{0} AND ViewOrder >= {1}", base.UnfilteredQuery, source.Offset);
+           }
+       }
+   }
+}
\ No newline at end of file
diff --git a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/QueueableSourceComboBox.cs b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/QueueableSourceComboBox.cs
new file mode 100644
index 0000000..83d8362
--- /dev/null
+++ b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/QueueableSourceComboBox.cs
@@ -0,0 +1,106 @@
+// QueueableSourceComboBox.cs
+//
+// Authors:
+//   Alexander Kojevnikov <alexander@kojevnikov.com>
+//
+// Copyright (C) 2009 Alexander Kojevnikov
+//
+// 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 Gtk;
+
+using Banshee.Library;
+using Banshee.ServiceStack;
+using Banshee.Sources;
+using Banshee.Sources.Gui;
+
+namespace Banshee.PlayQueue
+{
+    public class QueueableSourceComboBox : ComboBox
+    {
+        private readonly TreeModelFilter filter;
+
+        public QueueableSourceComboBox (string source_name)
+        {
+            SourceRowRenderer renderer = new SourceRowRenderer ();
+            renderer.ParentWidget = this;
+            PackStart (renderer, true);
+            SetCellDataFunc (renderer, new CellLayoutDataFunc (SourceRowRenderer.CellDataHandler));
+
+            var store = new SourceModel ();
+            filter = new TreeModelFilter (store, null);
+            filter.VisibleFunc = (model, iter) => IsQueueable (((SourceModel)model).GetSource (iter));
+            Model = filter;
+
+            store.Refresh ();
+
+            SetActiveSource (source_name);
+        }
+
+        private void SetActiveSource (string name)
+        {
+            TreeIter first;
+            if (filter.GetIterFirst (out first)) {
+                TreeIter iter = FindSource (name, first);
+                if (!iter.Equals (TreeIter.Zero)) {
+                    SetActiveIter (iter);
+                }
+            }
+        }
+
+        private bool IsQueueable (Source source)
+        {
+            return source != null && (
+                source is MusicLibrarySource || source.Parent is MusicLibrarySource ||
+                source is VideoLibrarySource || source.Parent is VideoLibrarySource);
+        }
+
+        private TreeIter FindSource (string name, TreeIter iter)
+        {
+            do {
+                var source = filter.GetValue (iter, 0) as ISource;
+                if (source != null && source.Name == name) {
+                    return iter;
+                }
+
+                TreeIter citer;
+                if (filter.IterChildren (out citer, iter)) {
+                    var yiter = FindSource (name, citer);
+                    if (!yiter.Equals (TreeIter.Zero)) {
+                        return yiter;
+                    }
+                }
+            } while (filter.IterNext (ref iter));
+
+            return TreeIter.Zero;
+        }
+
+        public ITrackModelSource Source {
+            get {
+                TreeIter iter;
+                if (GetActiveIter (out iter)) {
+                    return filter.GetValue(iter, 0) as ITrackModelSource;
+                }
+                return null;
+            }
+        }
+    }
+}
diff --git a/src/Extensions/Banshee.PlayQueue/Makefile.am b/src/Extensions/Banshee.PlayQueue/Makefile.am
index 68ca5cc..cda5765 100644
--- a/src/Extensions/Banshee.PlayQueue/Makefile.am
+++ b/src/Extensions/Banshee.PlayQueue/Makefile.am
@@ -4,9 +4,12 @@ LINK = $(REF_EXTENSION_PLAYQUEUE)
 INSTALL_DIR = $(EXTENSIONS_INSTALL_DIR)
 
 SOURCES =  \
+	Banshee.PlayQueue/ConfigurationPane.cs \
 	Banshee.PlayQueue/IPlayQueue.cs \
 	Banshee.PlayQueue/PlayQueueActions.cs \
-	Banshee.PlayQueue/PlayQueueSource.cs 
+	Banshee.PlayQueue/PlayQueueSource.cs \
+	Banshee.PlayQueue/PlayQueueTrackListModel.cs \
+	Banshee.PlayQueue/QueueableSourceComboBox.cs
 
 RESOURCES =  \
 	Banshee.PlayQueue.addin.xml \
diff --git a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs
index b1e663b..9863da6 100644
--- a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs
+++ b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastSource.cs
@@ -98,6 +98,7 @@ namespace Banshee.Podcasting.Gui
             MediaTypes = TrackMediaAttributes.Podcast;
             NotMediaTypes = TrackMediaAttributes.AudioBook;
             SyncCondition = "(substr(CoreTracks.Uri, 0, 4) != 'http' AND CoreTracks.PlayCount = 0)";
+            TrackModel.Reloaded += OnReloaded;
 
             Properties.SetString ("Icon.Name", "podcast");
             
@@ -197,7 +198,14 @@ namespace Banshee.Podcasting.Gui
                 AfterInitialized ();
             }
         }
-        
+
+        void OnReloaded(object sender, EventArgs e)
+        {
+            for (int i=0; i < TrackModel.Count; i++) {
+                PodcastTrackInfo.From (TrackModel[i]);
+            }
+        }
+
         // Probably don't want this -- do we want to allow actually removing the item?  It will be
         // repopulated the next time we update the podcast feed...
         /*protected override void DeleteTrack (DatabaseTrackInfo track)
diff --git a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastTrackInfo.cs b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastTrackInfo.cs
index 410c804..ad92b35 100644
--- a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastTrackInfo.cs
+++ b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Data/PodcastTrackInfo.cs
@@ -64,6 +64,7 @@ namespace Banshee.Podcasting.Data
                 PodcastTrackInfo pi = track.ExternalObject as PodcastTrackInfo;
                 if (pi != null) {
                     track.ReleaseDate = pi.PublishedDate;
+                    track.Enabled = !pi.Item.IsRead;
                 }
                 return pi;
             }
diff --git a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/ColumnCellPodcastStatusIndicator.cs b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/ColumnCellPodcastStatusIndicator.cs
index a724134..6e849de 100644
--- a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/ColumnCellPodcastStatusIndicator.cs
+++ b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/ColumnCellPodcastStatusIndicator.cs
@@ -84,7 +84,7 @@ namespace Banshee.Podcasting.Gui
             PodcastTrackInfo podcast = PodcastTrackInfo.From (BoundTrack);
             if (podcast != null) {
                 if (podcast.Activity == PodcastItemActivity.DownloadPending) {
-                    context.Sensitive = false;
+                    context.Opaque = false;
                 }
             }
             
diff --git a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastItemView.cs b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastItemView.cs
index 312d2aa..6825962 100644
--- a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastItemView.cs
+++ b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastItemView.cs
@@ -47,27 +47,6 @@ using Banshee.Podcasting.Data;
 
 namespace Banshee.Podcasting.Gui
 {
-    public class PodcastItemView : TrackListView
-    {
-        public PodcastItemView () : base ()
-        {
-        }
-        
-        protected override void ColumnCellDataProvider (ColumnCell cell, object boundItem)
-        {
-            ColumnCellText text_cell = cell as ColumnCellText;
-            if (text_cell == null) {
-                return;
-            }
-            
-            PodcastTrackInfo podcast = PodcastTrackInfo.From (boundItem as TrackInfo);
-            if (podcast == null) {
-                return;
-            }
-            
-            text_cell.Opacity = podcast.IsNew ? 1.0 : 0.5;
-        }
-    }
     /*public class PodcastItemView : ListView<TrackInfo>
     {
         private PersistentColumnController columnController;
diff --git a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastSourceContents.cs b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastSourceContents.cs
index b1e408b..66a6a60 100644
--- a/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastSourceContents.cs
+++ b/src/Extensions/Banshee.Podcasting/Banshee.Podcasting.Gui/PodcastSourceContents.cs
@@ -53,7 +53,7 @@ namespace Banshee.Podcasting.Gui
 {
     public class PodcastSourceContents : FilteredListSourceContents, ITrackModelSourceContents
     {
-        private PodcastItemView track_view;
+        private TrackListView track_view;
         private PodcastFeedView feed_view;
         private PodcastUnheardFilterView unheard_view;
         private DownloadStatusFilterView download_view;
@@ -64,7 +64,7 @@ namespace Banshee.Podcasting.Gui
 
         protected override void InitializeViews ()
         {
-            SetupMainView (track_view = new PodcastItemView ());
+            SetupMainView (track_view = new TrackListView ());
             SetupFilterView (unheard_view = new PodcastUnheardFilterView ());
             SetupFilterView (download_view = new DownloadStatusFilterView ());
             SetupFilterView (feed_view = new PodcastFeedView ());
diff --git a/src/Libraries/Hyena.Gui/Hyena.Data.Gui/CellContext.cs b/src/Libraries/Hyena.Gui/Hyena.Data.Gui/CellContext.cs
index 603ab61..ca84c18 100644
--- a/src/Libraries/Hyena.Gui/Hyena.Data.Gui/CellContext.cs
+++ b/src/Libraries/Hyena.Gui/Hyena.Data.Gui/CellContext.cs
@@ -42,7 +42,7 @@ namespace Hyena.Data.Gui
         private Gdk.Rectangle area;
         private Gdk.Rectangle clip;
         private bool text_as_foreground = false;
-        private bool sensitive = true;
+        private bool opaque = true;
         
         public Cairo.Context Context {
             get { return context; }
@@ -84,9 +84,9 @@ namespace Hyena.Data.Gui
             set { text_as_foreground = value; }
         }
         
-        public bool Sensitive {
-            get { return sensitive; }
-            set { sensitive = value; }
+        public bool Opaque {
+            get { return opaque; }
+            set { opaque = value; }
         }
     }
 }
diff --git a/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs b/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs
index 2e07217..a462d0b 100644
--- a/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs
+++ b/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs
@@ -44,7 +44,6 @@ namespace Hyena.Data.Gui
         private Pango.Weight font_weight = Pango.Weight.Normal;
         private Pango.EllipsizeMode ellipsize_mode = Pango.EllipsizeMode.End;
         private Pango.Alignment alignment = Pango.Alignment.Left;
-        private double opacity = 1.0;
         private int text_width;
         private int text_height;
         private string text_format = null;
@@ -80,7 +79,7 @@ namespace Hyena.Data.Gui
             context.Context.MoveTo (Spacing, ((int)cellHeight - text_height) / 2);
             Cairo.Color color = context.Theme.Colors.GetWidgetColor (
                 context.TextAsForeground ? GtkColorClass.Foreground : GtkColorClass.Text, state);
-            color.A = (!context.Sensitive) ? 0.3 : opacity;
+            color.A = context.Opaque ? 1.0 : 0.5;
             context.Context.Color = color;
 
             PangoCairoHelper.ShowLayout (context.Context, context.Layout);
@@ -156,11 +155,6 @@ namespace Hyena.Data.Gui
             set { ellipsize_mode = value; }
         }
         
-        public virtual double Opacity {
-            get { return opacity; }
-            set { opacity = value; }
-        }
-        
         internal static int ComputeRowHeight (Widget widget)
         {
             int w_width, row_height;
diff --git a/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Model.cs b/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Model.cs
index b28793d..7d5e129 100644
--- a/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Model.cs
+++ b/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Model.cs
@@ -143,42 +143,42 @@ namespace Hyena.Data.Gui
         public virtual IListModel<T> Model {
             get { return model; }
         }
-        
-        private string row_sensitive_property_name = "Sensitive";
-        private PropertyInfo row_sensitive_property_info;
-        bool row_sensitive_property_invalid = false;
-        
-        public string RowSensitivePropertyName {
-            get { return row_sensitive_property_name; }
-            set { 
-                if (value == row_sensitive_property_name) {
+
+        private string row_opaque_property_name = "Sensitive";
+        private PropertyInfo row_opaque_property_info;
+        bool row_opaque_property_invalid = false;
+
+        public string RowOpaquePropertyName {
+            get { return row_opaque_property_name; }
+            set {
+                if (value == row_opaque_property_name) {
                     return;
                 }
-                
-                row_sensitive_property_name = value;
-                row_sensitive_property_info = null;
-                row_sensitive_property_invalid = false;
-                
+
+                row_opaque_property_name = value;
+                row_opaque_property_info = null;
+                row_opaque_property_invalid = false;
+
                 InvalidateList ();
             }
         }
-        
-        private bool IsRowSensitive (object item)
+
+        private bool IsRowOpaque (object item)
         {
-            if (item == null || row_sensitive_property_invalid) {
+            if (item == null || row_opaque_property_invalid) {
                 return true;
             }
-         
-            if (row_sensitive_property_info == null || row_sensitive_property_info.ReflectedType != item.GetType ()) {
-                row_sensitive_property_info = item.GetType ().GetProperty (row_sensitive_property_name);
-                if (row_sensitive_property_info == null || row_sensitive_property_info.PropertyType != typeof (bool)) {
-                    row_sensitive_property_info = null;
-                    row_sensitive_property_invalid = true;
+
+            if (row_opaque_property_info == null || row_opaque_property_info.ReflectedType != item.GetType ()) {
+                row_opaque_property_info = item.GetType ().GetProperty (row_opaque_property_name);
+                if (row_opaque_property_info == null || row_opaque_property_info.PropertyType != typeof (bool)) {
+                    row_opaque_property_info = null;
+                    row_opaque_property_invalid = true;
                     return true;
                 }
             }
-            
-            return (bool)row_sensitive_property_info.GetValue (item, null);
+
+            return (bool)row_opaque_property_info.GetValue (item, null);
         }
         
         private string row_bold_property_name = "IsBold";
@@ -217,14 +217,5 @@ namespace Hyena.Data.Gui
             
             return (bool)row_bold_property_info.GetValue (item, null);
         }
-        
-        #pragma warning disable 0169
-        
-        private bool IsRowSensitive (int index)
-        {
-            return IsRowSensitive (model[index]);
-        }
-        
-        #pragma warning restore 0169
     }
 }
diff --git a/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs b/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs
index d376eb7..d4c424e 100644
--- a/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs
+++ b/src/Libraries/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs
@@ -131,7 +131,7 @@ namespace Hyena.Data.Gui
             cell_area.Height = header_rendering_alloc.Height;
             
             cell_context.Clip = clip;
-            cell_context.Sensitive = true;
+            cell_context.Opaque = true;
             cell_context.TextAsForeground = true;
 
             bool have_drawn_separator = false;
@@ -320,7 +320,7 @@ namespace Hyena.Data.Gui
             }
             
             object item = model[row_index];
-            bool sensitive = IsRowSensitive (item);
+            bool opaque = IsRowOpaque (item);
             bool bold = IsRowBold (item);
             
             Rectangle cell_area = new Rectangle ();
@@ -334,18 +334,18 @@ namespace Hyena.Data.Gui
                 
                 cell_area.Width = column_cache[ci].Width;
                 cell_area.X = column_cache[ci].X1 + area.X;
-                PaintCell (item, ci, row_index, cell_area, sensitive, bold, state, false);
+                PaintCell (item, ci, row_index, cell_area, opaque, bold, state, false);
             }
             
             if (pressed_column_is_dragging && pressed_column_index >= 0) {
                 cell_area.Width = column_cache[pressed_column_index].Width;
                 cell_area.X = pressed_column_x_drag + list_rendering_alloc.X -
                     list_interaction_alloc.X - HadjustmentValue;
-                PaintCell (item, pressed_column_index, row_index, cell_area, sensitive, bold, state, true);
+                PaintCell (item, pressed_column_index, row_index, cell_area, opaque, bold, state, true);
             }
         }
         
-        private void PaintCell (object item, int column_index, int row_index, Rectangle area, bool sensitive, bool bold,
+        private void PaintCell (object item, int column_index, int row_index, Rectangle area, bool opaque, bool bold,
             StateType state, bool dragging)
         {
             ColumnCell cell = column_cache[column_index].Column.GetCell (0);
@@ -368,7 +368,7 @@ namespace Hyena.Data.Gui
             cairo_context.Save ();
             cairo_context.Translate (area.X, area.Y);
             cell_context.Area = area;
-            cell_context.Sensitive = sensitive;
+            cell_context.Opaque = opaque;
             cell.Render (cell_context, dragging ? StateType.Normal : state, area.Width, area.Height);
             cairo_context.Restore ();
         }
