[banshee] [PlayQueue] Add 'Add after' feature for adding songs to queue



commit e51ceb17babb47baab57d30a052c15d95b337364
Author: Alex Launi <alex launi gmail com>
Date:   Thu Oct 21 22:06:31 2010 -0400

    [PlayQueue] Add 'Add after' feature for adding songs to queue
    
    Allows adding tracks to the play queue after the currently playing song, artist, or album.
    https://bugzilla.gnome.org/show_bug.cgi?id=632845

 .../Banshee.PlayQueue/Banshee.PlayQueue.csproj     |    1 +
 .../Banshee.PlayQueue/PlayQueueActions.cs          |   51 ++++++++-
 .../Banshee.PlayQueue/PlayQueueSource.cs           |  117 +++++++++++++++++---
 .../Banshee.PlayQueue/QueueMode.cs                 |   38 +++++++
 src/Extensions/Banshee.PlayQueue/Makefile.am       |    3 +-
 .../Banshee.PlayQueue/Resources/GlobalUI.xml       |    5 +
 6 files changed, 194 insertions(+), 21 deletions(-)
---
diff --git a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue.csproj b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue.csproj
index 41a0b34..afed885 100644
--- a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue.csproj
+++ b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue.csproj
@@ -105,6 +105,7 @@
     <Compile Include="Banshee.PlayQueue\PlayQueueTrackListModel.cs" />
     <Compile Include="Banshee.PlayQueue\QueueableSourceComboBox.cs" />
     <Compile Include="Banshee.PlayQueue\HeaderWidget.cs" />
+    <Compile Include="Banshee.PlayQueue\QueueMode.cs" />
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="Resources\ActiveSourceUI.xml">
diff --git a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueActions.cs b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueActions.cs
index fd24691..8a97fdf 100644
--- a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueActions.cs
+++ b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueActions.cs
@@ -33,6 +33,7 @@ using Gtk;
 
 using Hyena;
 
+using Banshee.MediaEngine;
 using Banshee.ServiceStack;
 using Banshee.Sources;
 
@@ -49,7 +50,27 @@ namespace Banshee.PlayQueue
                 new ActionEntry ("AddToPlayQueueAction", Stock.Add,
                     Catalog.GetString ("Add to Play Queue"), "q",
                     Catalog.GetString ("Append selected songs to the play queue"),
-                    OnAddToPlayQueue)
+                    OnAddToPlayQueue),
+
+                new ActionEntry ("AddToPlayQueueAfterAction", null,
+                    Catalog.GetString ("Add after"), null,
+                    Catalog.GetString ("Add selected songs after the currently playing track, album, or artist"),
+                    null),
+
+                new ActionEntry ("AddToPlayQueueAfterCurrentTrackAction", null,
+                    Catalog.GetString ("Current track"), null,
+                    Catalog.GetString ("Add selected songs to the play queue after the currently playing song"),
+                    OnAddToPlayQueueAfterCurrentTrack),
+
+                new ActionEntry ("AddToPlayQueueAfterCurrentTrackAlbum", null,
+                    Catalog.GetString ("Current album"), null,
+                    Catalog.GetString ("Add selected songs to the play queue after the currently playing album"),
+                    OnAddToPlayQueueAfterCurrentAlbum),
+
+                new ActionEntry ("AddToPlayQueueAfterCurrentTrackArtist", null,
+                    Catalog.GetString ("Current artist"), null,
+                    Catalog.GetString ("Add selected songs to the play queue after the currently playing artist"),
+                    OnAddToPlayQueueAfterCurrentArtist)
             });
 
             AddImportant (
@@ -87,6 +108,7 @@ namespace Banshee.PlayQueue
 
             playqueue.Updated += OnUpdated;
             ServiceManager.SourceManager.ActiveSourceChanged += OnSourceUpdated;
+            ServiceManager.PlayerEngine.ConnectEvent (OnPlayerEvent, PlayerEvent.StateChange);
 
             OnUpdated (null, null);
 
@@ -102,9 +124,34 @@ namespace Banshee.PlayQueue
 
         #region Action Handlers
 
+        private void OnPlayerEvent (PlayerEventArgs args)
+        {
+            this["AddToPlayQueueAfterAction"].Sensitive = ServiceManager.PlayerEngine.IsPlaying ();
+        }
+
         private void OnAddToPlayQueue (object o, EventArgs args)
         {
-            playqueue.AddSelectedTracks (ServiceManager.SourceManager.ActiveSource);
+            AddSelectedToPlayQueue (QueueMode.Normal);
+        }
+
+        private void OnAddToPlayQueueAfterCurrentTrack (object sender, EventArgs e)
+        {
+            AddSelectedToPlayQueue (QueueMode.AfterCurrentTrack);
+        }
+
+        private void OnAddToPlayQueueAfterCurrentAlbum (object sender, EventArgs e)
+        {
+            AddSelectedToPlayQueue (QueueMode.AfterCurrentAlbum);
+        }
+
+        private void OnAddToPlayQueueAfterCurrentArtist (object sender, EventArgs e)
+        {
+            AddSelectedToPlayQueue (QueueMode.AfterCurrentArtist);
+        }
+
+        private void AddSelectedToPlayQueue (QueueMode mode)
+        {
+            playqueue.AddSelectedTracks (ServiceManager.SourceManager.ActiveSource, mode);
         }
 
         private void OnClearPlayQueue (object o, EventArgs args)
diff --git a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
index ea85d49..f17facc 100644
--- a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
+++ b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
@@ -320,7 +320,12 @@ namespace Banshee.PlayQueue
 
 #endregion
 
-        public override bool AddSelectedTracks (Source source)
+        public override bool AddSelectedTracks (Source souce)
+        {
+            return AddSelectedTracks (souce, QueueMode.Normal);
+        }
+
+        public bool AddSelectedTracks (Source source, QueueMode mode)
         {
             if ((Parent == null || source == Parent || source.Parent == Parent) && AcceptsInputFromSource (source)) {
                 DatabaseTrackListModel model = (source as ITrackModelSource).TrackModel as DatabaseTrackListModel;
@@ -328,8 +333,10 @@ namespace Banshee.PlayQueue
                     return false;
                 }
 
+                long view_order = CalculateViewOrder (mode);
+                long max_view_order = MaxViewOrder;
                 long current_view_order = CurrentTrackViewOrder;
-
+        
                 // If the current_track is not playing, insert before it.
                 int index = -1;
                 if (current_track != null && !ServiceManager.PlayerEngine.IsPlaying (current_track)) {
@@ -337,27 +344,16 @@ namespace Banshee.PlayQueue
                     index = TrackModel.IndexOf (current_track);
                 }
 
-                // 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
-                ));
-
                 WithTrackSelection (model, shuffler.RecordInsertions);
 
                 // 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
-                );
+                if (mode != QueueMode.Normal) {
+                    ShiftForAddedAfter (view_order, max_view_order);
+                }
+
+                ShiftGeneratedTracks (view_order);
 
                 OnTracksAdded ();
                 OnUserNotifyUpdated ();
@@ -373,6 +369,91 @@ namespace Banshee.PlayQueue
             return false;
         }
 
+        private long CalculateViewOrder (QueueMode mode)
+        {
+            long view_order = 0;
+            long current_view_order = CurrentTrackViewOrder;
+
+            switch (mode) {
+            case QueueMode.AfterCurrentTrack:
+                // view_order will point to the currently playing track.
+                // We want to insert tracks after this one.
+                view_order = current_view_order;
+                break;
+            case QueueMode.AfterCurrentAlbum:
+                // view order will point to the last track of the currently
+                // playing album.
+                IterateTrackModelUntilEndMatch (out view_order, true);
+                break;
+            case QueueMode.AfterCurrentArtist:
+                // view order will point to the last track of the currently
+                // playing artist.
+                IterateTrackModelUntilEndMatch (out view_order, false);
+                break;
+            case QueueMode.Normal:
+                // 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.
+                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
+                ));
+                break;
+            default:
+                throw new ArgumentException ("Handling for that QueueMode has not been defined");
+            }
+
+            return view_order;
+        }
+
+        private void IterateTrackModelUntilEndMatch (out long viewOrder, bool checkAlbum)
+        {
+            var t = TrackModel;
+            bool in_match = false;
+            long current_view_order = CurrentTrackViewOrder;
+
+            string current_album = ServiceManager.PlayerEngine.CurrentTrack.AlbumTitle;
+            string current_artist = ServiceManager.PlayerEngine.CurrentTrack.AlbumArtist;
+
+            // view order will point to the last track that has the same album and artist of the
+            // currently playing track.
+            viewOrder = current_view_order;
+            for (int i = 0; i < t.Count; i++) {
+                var track = t[i];
+                if (current_artist == track.AlbumArtist && (!checkAlbum || current_album == track.AlbumTitle)) {
+                    in_match = true;
+                    viewOrder++;
+                } else if (!in_match) {
+                    continue;
+                } else {
+                    viewOrder--;
+                    break;
+                }
+            }
+        }
+
+        private void ShiftForAddedAfter (long viewOrder, long maxViewOrder)
+        {
+            ServiceManager.DbConnection.Execute (@"
+                UPDATE CorePlaylistEntries
+                SET ViewOrder = ViewOrder - ? + ?
+                WHERE PlaylistID = ? AND ViewOrder > ? AND ViewOrder < ?",
+                viewOrder, MaxViewOrder, DbId, viewOrder, maxViewOrder
+            );
+        }
+
+        private void ShiftGeneratedTracks (long viewOrder)
+        {
+            // Shift generated tracks to the end of the queue.
+            ServiceManager.DbConnection.Execute (@"
+                UPDATE CorePlaylistEntries
+                SET ViewOrder = ViewOrder - ? + ?
+                WHERE PlaylistID = ? AND ViewOrder > ? AND Generated = 1",
+                viewOrder, MaxViewOrder, DbId, viewOrder
+            );
+        }
+
         private void SetAsPlaybackSourceUnlessPlaying ()
         {
             if (current_track != null && ServiceManager.PlaybackController.Source != this) {
diff --git a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/QueueMode.cs b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/QueueMode.cs
new file mode 100644
index 0000000..6d17ddd
--- /dev/null
+++ b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/QueueMode.cs
@@ -0,0 +1,38 @@
+// 
+// QueueMode.cs
+// 
+// Author:
+//   Alex Launi <alex launi gmail com>
+// 
+// Copyright (c) 2010 Alex Launi
+// 
+// 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;
+
+namespace Banshee.PlayQueue
+{
+    public enum QueueMode {
+        Normal,
+        AfterCurrentTrack,
+        AfterCurrentArtist,
+        AfterCurrentAlbum
+    }
+}
+
diff --git a/src/Extensions/Banshee.PlayQueue/Makefile.am b/src/Extensions/Banshee.PlayQueue/Makefile.am
index fd5b24b..a4c9440 100644
--- a/src/Extensions/Banshee.PlayQueue/Makefile.am
+++ b/src/Extensions/Banshee.PlayQueue/Makefile.am
@@ -9,7 +9,8 @@ SOURCES =  \
 	Banshee.PlayQueue/PlayQueueActions.cs \
 	Banshee.PlayQueue/PlayQueueSource.cs \
 	Banshee.PlayQueue/PlayQueueTrackListModel.cs \
-	Banshee.PlayQueue/QueueableSourceComboBox.cs
+	Banshee.PlayQueue/QueueableSourceComboBox.cs \
+	Banshee.PlayQueue/QueueMode.cs
 
 RESOURCES =  \
 	Banshee.PlayQueue.addin.xml \
diff --git a/src/Extensions/Banshee.PlayQueue/Resources/GlobalUI.xml b/src/Extensions/Banshee.PlayQueue/Resources/GlobalUI.xml
index 565604b..cabea01 100644
--- a/src/Extensions/Banshee.PlayQueue/Resources/GlobalUI.xml
+++ b/src/Extensions/Banshee.PlayQueue/Resources/GlobalUI.xml
@@ -10,6 +10,11 @@
     <popup name="TrackContextMenu" action="TrackContextMenuAction">
         <placeholder name="AboveAddToPlaylist">
             <menuitem name="AddToPlayQueue" action="AddToPlayQueueAction"></menuitem>
+            <menu name="AddToPlayQueueAfterMenu" action="AddToPlayQueueAfterAction">
+            	<menuitem name="AddToPlayQueueAfterCurrentTrack" action="AddToPlayQueueAfterCurrentTrackAction"></menuitem>
+            	<menuitem name="AddToPlayQueueAfterCurrentAlbum" action="AddToPlayQueueAfterCurrentTrackAlbum"></menuitem>
+            	<menuitem name="AddToPlayQueueAfterCurrentArtist" action="AddToPlayQueueAfterCurrentTrackArtist"></menuitem>
+            </menu>
         </placeholder>
     </popup>
 </ui>



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