Attached updated patch against trunk and necessary resources (drop into
ThickClient's Resources directory).
On Sun, 24 Feb 2008 04:58:14 +0000, Alex Hixon
<hixon alexander mediati org> wrote:
> Hi all,
>
> Posting this patch here for some review/discussion.
>
> There are really two major changes that this patch makes, the first being
> changing the API of ICanonicalPlaybackController and
> IBasicPlaybackController. Basically, all I'm doing here is changing Next
> ()
> to Next (bool restartAtEnd). If restartAtEnd is true, the implementing
> class shouldn't stop playback merely because there are no more tracks to
> play linearly, it should queue up the first track if there are none left.
> Anyway, simple stuff.
>
> The other issue that'll probably get a bit more discussion is the way we
> handle changing the Sensitive state on the shuffle/repeat toggle button
> widgets. At the moment, it should be possible to do:
> (action_service.UIManager.GetWidget
("/FooterToolbar/ShuffleToggleButton")
> as Widget).Sensitive = false;, but this doesn't quite work for some
> reason.
> Instead, we end up getting a GtkMenuSeperator widget (at least, that's
> what
> I think it was called - this is off the top of my head). If we loop
> through
> the child elements of FooterToolbar, we end up with something like this:
>
> ShuffleToggleButton | Separator | RepeatToggleButton | Separator |
> StatusBar | Separator | TrackMetadataAction
>
> So, from the looks of things, it's getting the widget /adjacent/ to the
> widget we really want. So, at the moment, to work around this, we loop
> through the children of FooterToolbar and find items that are of type
> MultiStateToggleButton, and set their Sensitive value to false. Not sure
> if
> this is a problem with the way I'm approaching the issue, or a bug in
> Gtk#.
>
> Anyway, the attached patch works as advertised - it adds support for the
> shuffle and repeat footer togglebuttons, and implements the necessary
> logic
> to drive them all. It also disables shuffle and repeat while we're
looking
> at the Last.fm radio source.
>
> Comments, suggestions on the implementation?
>
> Cheers,
> Alex Hixon
--
Cheers,
Alex HixonIndex: Extensions/Banshee.NotificationArea/Banshee.NotificationArea/TrackInfoPopup.cs
===================================================================
--- Extensions/Banshee.NotificationArea/Banshee.NotificationArea/TrackInfoPopup.cs (revision 3319)
+++ Extensions/Banshee.NotificationArea/Banshee.NotificationArea/TrackInfoPopup.cs (working copy)
@@ -55,7 +55,7 @@
// Position label and linear progress bar
HBox position_box = new HBox ();
- position_box.Spacing = 10;
+ //position_box.Spacing = 10;
position_label = new Label ();
position_label.Xalign = 0.0f;
Index: Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs
===================================================================
--- Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs (revision 3319)
+++ Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs (working copy)
@@ -47,6 +47,9 @@
using Banshee.MediaEngine;
using Banshee.Collection;
using Banshee.ServiceStack;
+
+using Banshee.Gui;
+using Banshee.Gui.Widgets;
namespace Banshee.Lastfm.Radio
{
@@ -174,16 +177,50 @@
OnUpdated ();
}
+ private void SetStatusIconSensitive (bool val) {
+ Toolbar footer = (action_service.UIManager.GetWidget ("/FooterToolbar") as Toolbar);
+
+ foreach (Widget child in footer.Children) {
+ try {
+ GenericToolItem<Gtk.Widget> w = (GenericToolItem<Gtk.Widget>) child;
+
+ if (w.Widget is MultiStateToggleButton) {
+ w.Widget.Sensitive = val;
+ }
+ } catch {
+ }
+ }
+ }
+
private bool shuffle;
+ private int repeat;
+ private InterfaceActionService action_service;
public override void Activate ()
{
+ if (action_service == null) {
+ action_service = ServiceManager.Get<InterfaceActionService> ("InterfaceActionService");
+ }
+
base.Activate ();
- //shuffle = (action_service.GlobalActions ["ShuffleAction"] as ToggleAction).Active;
- //(action_service.GlobalActions ["ShuffleAction"] as ToggleAction).Active = false;
- //Globals.ActionManager["ShuffleAction"].Sensitive = false;
+ SetStatusIconSensitive (false);
+ shuffle = (action_service.PlaybackActions ["ShuffleAction"] as ToggleAction).Active;
+ (action_service.PlaybackActions ["ShuffleAction"] as ToggleAction).Active = false;
+ action_service.PlaybackActions ["ShuffleAction"].Sensitive = false;
+
+ if ((action_service.PlaybackActions ["RepeatNoneAction"] as ToggleAction).Active) {
+ repeat = 0;
+ } else if ((action_service.PlaybackActions ["RepeatAllAction"] as ToggleAction).Active) {
+ repeat = 1;
+ } else {
+ repeat = 2;
+ }
+
+ (action_service.PlaybackActions ["RepeatNoneAction"] as ToggleAction).Active = true;
+
+ action_service.PlaybackActions ["RepeatNoneAction"].Sensitive = false;
+ action_service.PlaybackActions ["RepeatAllAction"].Sensitive = false;
+ action_service.PlaybackActions ["RepeatSingleAction"].Sensitive = false;
- //action_service.GlobalActions ["PreviousAction"].Sensitive = false;
-
// We lazy load the Last.fm connection, so if we're not already connected, do it
if (lastfm.Connection.State == ConnectionState.Connected)
TuneAndLoad ();
@@ -206,10 +243,22 @@
public override void Deactivate ()
{
- //(Globals.ActionManager["ShuffleAction"] as ToggleAction).Active = shuffle;
- //Globals.ActionManager["ShuffleAction"].Sensitive = true;
+ (action_service.PlaybackActions ["ShuffleAction"] as ToggleAction).Active = shuffle;
+ action_service.PlaybackActions ["ShuffleAction"].Sensitive = true;
- //Globals.ActionManager["PreviousAction"].Sensitive = true;
+ action_service.PlaybackActions ["PreviousAction"].Sensitive = true;
+
+ SetStatusIconSensitive (true);
+
+ action_service.PlaybackActions ["RepeatNoneAction"].Sensitive = true;
+ action_service.PlaybackActions ["RepeatAllAction"].Sensitive = true;
+ action_service.PlaybackActions ["RepeatSingleAction"].Sensitive = true;
+
+ if (repeat == 1) {
+ (action_service.PlaybackActions ["RepeatAllAction"] as ToggleAction).Active = true;
+ } else if (repeat == 2) {
+ (action_service.PlaybackActions ["RepeatSingleAction"] as ToggleAction).Active = true;
+ }
}
// Last.fm requires you to 'tune' to a station before requesting a track list/playing it
Index: Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
===================================================================
--- Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs (revision 3319)
+++ Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs (working copy)
@@ -190,10 +190,10 @@
void IBasicPlaybackController.First ()
{
- ((IBasicPlaybackController)this).Next ();
+ ((IBasicPlaybackController)this).Next (false);
}
- void IBasicPlaybackController.Next ()
+ void IBasicPlaybackController.Next (bool restartAtEnd)
{
RemoveFirstTrack ();
Index: Clients/Nereid/Nereid/PlayerInterface.cs
===================================================================
--- Clients/Nereid/Nereid/PlayerInterface.cs (revision 3319)
+++ Clients/Nereid/Nereid/PlayerInterface.cs (working copy)
@@ -57,8 +57,8 @@
// Major Layout Components
private VBox primary_vbox;
private Toolbar header_toolbar;
+ private Toolbar footer_toolbar;
private HPaned views_pane;
- private HBox footer_box;
private ViewContainer view_container;
// Major Interaction Components
@@ -196,28 +196,33 @@
private void BuildFooter ()
{
- footer_box = new HBox ();
- footer_box.Spacing = 2;
+ footer_toolbar = (Toolbar)ActionService.UIManager.GetWidget ("/FooterToolbar");
+ footer_toolbar.ShowArrow = false;
+ footer_toolbar.ToolbarStyle = ToolbarStyle.BothHoriz;
+ footer_toolbar.IconSize = IconSize.Menu;
status_label = new Label ();
status_label.ModifyFg (StateType.Normal, Hyena.Gui.GtkUtilities.ColorBlend (
status_label.Style.Foreground (StateType.Normal), status_label.Style.Background (StateType.Normal)));
- ActionButton song_properties_button = new ActionButton
+ /*ActionButton song_properties_button = new ActionButton
(ActionService.TrackActions["TrackPropertiesAction"]);
song_properties_button.IconSize = IconSize.Menu;
song_properties_button.Padding = 0;
- song_properties_button.LabelVisible = false;
+ song_properties_button.LabelVisible = false;*/
- //footer_box.PackStart (shuffle_toggle_button, false, false, 0);
- //footer_box.PackStart (repeat_toggle_button, false, false, 0);
- footer_box.PackStart (status_label, true, true, 0);
- footer_box.PackStart (song_properties_button, false, false, 0);
+ ActionService.PopulateToolbarPlaceholder (footer_toolbar, "/FooterToolbar/Statusbar", status_label, true);
+
+ MultiStateToggleButton shuffle_toggle_button = new ShuffleToggleButton (ActionService);
+ ActionService.PopulateToolbarPlaceholder (footer_toolbar, "/FooterToolbar/ShuffleToggleAction", shuffle_toggle_button);
+
+ MultiStateToggleButton repeat_toggle_button = new RepeatToggleButton (ActionService);
+ ActionService.PopulateToolbarPlaceholder (footer_toolbar, "/FooterToolbar/RepeatToggleAction", repeat_toggle_button);
Alignment align = new Alignment (0.5f, 0.5f, 1.0f, 1.0f);
- align.TopPadding = 2;
+ align.TopPadding = 0;
align.BottomPadding = 0;
- align.Add (footer_box);
+ align.Add (footer_toolbar);
align.ShowAll ();
primary_vbox.PackStart (align, false, true, 0);
@@ -264,6 +269,7 @@
};
header_toolbar.ExposeEvent += OnHeaderToolbarExposeEvent;
+ footer_toolbar.ExposeEvent += OnFooterToolbarExposeEvent;
}
#endregion
@@ -364,6 +370,19 @@
}
}
+ private void OnFooterToolbarExposeEvent (object o, ExposeEventArgs args)
+ {
+ // This forces the toolbar to look like it's just a regular plain container
+ // since the stock toolbar look makes Banshee look ugly.
+ footer_toolbar.GdkWindow.DrawRectangle (Style.BackgroundGC (footer_toolbar.State),
+ true, footer_toolbar.Allocation);
+
+ // Manually expose all the toolbar's children
+ foreach (Widget child in footer_toolbar.Children) {
+ footer_toolbar.PropagateExpose (child, args.Event);
+ }
+ }
+
#endregion
#region Implement Interfaces
Index: Core/Banshee.ThickClient/Banshee.Gui/ToggleStates.cs
===================================================================
--- Core/Banshee.ThickClient/Banshee.Gui/ToggleStates.cs (revision 0)
+++ Core/Banshee.ThickClient/Banshee.Gui/ToggleStates.cs (revision 0)
@@ -0,0 +1,83 @@
+//
+// ToggleStates.cs
+//
+// Author:
+// Aaron Bockover <abockover novell com>
+//
+// Copyright (C) 2005-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 Mono.Unix;
+using Banshee.Widgets;
+
+namespace Banshee.Gui
+{
+ public class RepeatNoneToggleState : ToggleState
+ {
+ public RepeatNoneToggleState()
+ {
+ Icon = IconThemeUtils.LoadIcon (16, "view-sort-descending");
+ Label = Catalog.GetString("Repeat None");
+ }
+ }
+
+ public class RepeatSingleToggleState : ToggleState
+ {
+ public RepeatSingleToggleState()
+ {
+ Icon = Gdk.Pixbuf.LoadFromResource("media-repeat-single.png");
+ Label = Catalog.GetString("Repeat Single");
+ }
+ }
+
+ public class RepeatAllToggleState : ToggleState
+ {
+ public RepeatAllToggleState()
+ {
+ Icon = IconThemeUtils.LoadIcon (16, "media-playlist-repeat");
+ Label = Catalog.GetString("Repeat All");
+ }
+ }
+
+ public class ShuffleEnabledToggleState : ToggleState
+ {
+ public ShuffleEnabledToggleState()
+ {
+ Icon = IconThemeUtils.LoadIcon (16, "media-playlist-shuffle");
+ Label = Catalog.GetString("Shuffle");
+ MatchActive = true;
+ MatchValue = true;
+ }
+ }
+
+ public class ShuffleDisabledToggleState : ToggleState
+ {
+ public ShuffleDisabledToggleState()
+ {
+ Icon = Gdk.Pixbuf.LoadFromResource("media-playlist-continuous.png");
+ Label = Catalog.GetString("Continuous");
+ MatchActive = true;
+ MatchValue = false;
+ }
+ }
+}
Index: Core/Banshee.ThickClient/Banshee.Gui/PlaybackActions.cs
===================================================================
--- Core/Banshee.ThickClient/Banshee.Gui/PlaybackActions.cs (revision 3319)
+++ Core/Banshee.ThickClient/Banshee.Gui/PlaybackActions.cs (working copy)
@@ -92,7 +92,7 @@
new RadioActionEntry ("RepeatSingleAction", null,
Catalog.GetString ("Repeat Si_ngle"), null,
Catalog.GetString ("Repeat the current playing song"), 2)
- }, 0, null);
+ }, 0, OnRepeatAction);
actionService.GlobalActions.Add (new ActionEntry [] {
new ActionEntry ("PlaybackMenuAction", null,
@@ -206,5 +206,16 @@
? PlaybackShuffleMode.Shuffle
: PlaybackShuffleMode.Linear;
}
+
+ private void OnRepeatAction (object o, ChangedArgs args)
+ {
+ if (args.Current.Value == 0) {
+ ServiceManager.PlaybackController.RepeatMode = PlaybackRepeatMode.None;
+ } else if (args.Current.Value == 1) {
+ ServiceManager.PlaybackController.RepeatMode = PlaybackRepeatMode.RepeatAll;
+ } else if (args.Current.Value == 2) {
+ ServiceManager.PlaybackController.RepeatMode = PlaybackRepeatMode.RepeatSingle;
+ }
+ }
}
}
Index: Core/Banshee.ThickClient/Banshee.Gui.Widgets/PlaybackToggleButtons.cs
===================================================================
--- Core/Banshee.ThickClient/Banshee.Gui.Widgets/PlaybackToggleButtons.cs (revision 0)
+++ Core/Banshee.ThickClient/Banshee.Gui.Widgets/PlaybackToggleButtons.cs (revision 0)
@@ -0,0 +1,90 @@
+//
+// PlaybackToggleButtons.cs
+//
+// Author:
+// Alexander Hixon <hixon alexander mediati org>
+//
+// 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;
+using Banshee.Widgets;
+using Banshee.ServiceStack;
+
+namespace Banshee.Gui.Widgets
+{
+ public interface InterfaceToggleButton
+ {
+ string ToggleButtonType {
+ get;
+ }
+ }
+
+ public class ShuffleToggleButton : MultiStateToggleButton, InterfaceToggleButton
+ {
+ private InterfaceActionService action_service;
+
+ public ShuffleToggleButton (InterfaceActionService actionService) : base ()
+ {
+ action_service = actionService;
+
+ this.AddState(typeof(ShuffleDisabledToggleState),
+ action_service["Playback.ShuffleAction"] as ToggleAction);
+ this.AddState(typeof(ShuffleEnabledToggleState),
+ action_service["Playback.ShuffleAction"] as ToggleAction);
+ this.Relief = ReliefStyle.None;
+ this.ShowLabel = false;
+ }
+
+ public string ToggleButtonType
+ {
+ get { return "Shuffle"; }
+ }
+ }
+
+ public class RepeatToggleButton : MultiStateToggleButton, InterfaceToggleButton
+ {
+ private InterfaceActionService action_service;
+
+ public RepeatToggleButton (InterfaceActionService actionService) : base ()
+ {
+ action_service = actionService;
+
+ this.AddState(typeof(RepeatNoneToggleState),
+ action_service["Playback.RepeatNoneAction"] as ToggleAction);
+ this.AddState(typeof(RepeatAllToggleState),
+ action_service["Playback.RepeatAllAction"] as ToggleAction);
+ this.AddState(typeof(RepeatSingleToggleState),
+ action_service["Playback.RepeatSingleAction"] as ToggleAction);
+ this.Relief = ReliefStyle.None;
+ this.ShowLabel = false;
+ }
+
+ public string ToggleButtonType
+ {
+ get { return "Repeat"; }
+ }
+ }
+}
\ No newline at end of file
Index: Core/Banshee.ThickClient/Makefile.am
===================================================================
--- Core/Banshee.ThickClient/Makefile.am (revision 3319)
+++ Core/Banshee.ThickClient/Makefile.am (working copy)
@@ -43,6 +43,7 @@
Banshee.Gui.Widgets/ConnectedMessageBar.cs \
Banshee.Gui.Widgets/ConnectedSeekSlider.cs \
Banshee.Gui.Widgets/ConnectedVolumeButton.cs \
+ Banshee.Gui.Widgets/PlaybackToggleButtons.cs \
Banshee.Gui.Widgets/PlaylistMenuItem.cs \
Banshee.Gui.Widgets/TrackInfoDisplay.cs \
Banshee.Gui.Widgets/UserJobTile.cs \
@@ -59,6 +60,7 @@
Banshee.Gui/InterfaceActionService.cs \
Banshee.Gui/PlaybackActions.cs \
Banshee.Gui/SourceActions.cs \
+ Banshee.Gui/ToggleStates.cs \
Banshee.Gui/TrackActions.cs \
Banshee.Gui/ViewActions.cs \
Banshee.Library.Gui/FileImportSource.cs \
@@ -91,7 +93,12 @@
Resources/source-playlist-16.png \
Resources/source-playlist-22.png \
Resources/source-smart-playlist-16.png \
- Resources/source-smart-playlist-22.png
+ Resources/source-smart-playlist-22.png \
+ Resources/media-playlist-continuous.png \
+ Resources/media-playlist-shuffle.png \
+ Resources/media-repeat-all.png \
+ Resources/media-repeat-none.png \
+ Resources/media-repeat-single.png
include $(top_srcdir)/build/build.mk
Index: Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml
===================================================================
--- Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml (revision 3319)
+++ Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml (working copy)
@@ -70,9 +70,9 @@
<menuitem name="RestartSong" action="RestartSongAction"/>
<separator/>
<placeholder name="PlaybackMenuAdditions"/>
- <!--<menuitem name="RepeatNone" action="RepeatNoneAction"/>
+ <menuitem name="RepeatNone" action="RepeatNoneAction"/>
<menuitem name="RepeatAll" action="RepeatAllAction"/>
- <menuitem name="RepeatSingle" action="RepeatSingleAction"/>-->
+ <menuitem name="RepeatSingle" action="RepeatSingleAction"/>
<separator/>
<menuitem name="Shuffle" action="ShuffleAction"/>
</menu>
@@ -92,6 +92,14 @@
<menuitem name="About" action="AboutAction"/>
</menu>
</menubar>
+
+ <toolbar name="FooterToolbar">
+ <placeholder name="ShuffleToggleAction" />
+ <placeholder name="RepeatToggleAction" />
+
+ <placeholder name="Statusbar" />
+ <toolitem action="TrackPropertiesAction" />
+ </toolbar>
<popup name="LibraryContextMenu" action="LibraryContextMenuAction">
<menuitem name="NewPlaylist" action="NewPlaylistAction"/>
Index: Core/Banshee.Services/Banshee.PlaybackController/ICanonicalPlaybackController.cs
===================================================================
--- Core/Banshee.Services/Banshee.PlaybackController/ICanonicalPlaybackController.cs (revision 3319)
+++ Core/Banshee.Services/Banshee.PlaybackController/ICanonicalPlaybackController.cs (working copy)
@@ -31,7 +31,7 @@
public interface ICanonicalPlaybackController : IPlaybackController
{
new void First ();
- new void Next ();
+ new void Next (bool restartAtEnd);
new void Previous ();
}
}
Index: Core/Banshee.Services/Banshee.PlaybackController/PlaybackControllerService.cs
===================================================================
--- Core/Banshee.Services/Banshee.PlaybackController/PlaybackControllerService.cs (revision 3319)
+++ Core/Banshee.Services/Banshee.PlaybackController/PlaybackControllerService.cs (working copy)
@@ -97,7 +97,11 @@
switch (args.Event) {
case PlayerEngineEvent.EndOfStream:
if (!StopWhenFinished) {
- Next ();
+ if (RepeatMode == PlaybackRepeatMode.RepeatSingle) {
+ QueuePlayTrack ();
+ } else {
+ Next ();
+ }
} else {
OnStopped ();
}
@@ -128,12 +132,17 @@
public void Next ()
{
+ Next (RepeatMode == PlaybackRepeatMode.RepeatAll);
+ }
+
+ public void Next (bool restartAtEnd)
+ {
OnTransition ();
if (Source is IBasicPlaybackController) {
- ((IBasicPlaybackController)Source).Next ();
+ ((IBasicPlaybackController)Source).Next (restartAtEnd);
} else {
- ((ICanonicalPlaybackController)this).Next ();
+ ((ICanonicalPlaybackController)this).Next (restartAtEnd);
}
}
@@ -155,7 +164,7 @@
}
}
- void ICanonicalPlaybackController.Next ()
+ void ICanonicalPlaybackController.Next (bool restartAtEnd)
{
TrackInfo tmp_track = CurrentTrack;
@@ -170,6 +179,14 @@
if (tmp_track != null) {
previous_stack.Push (tmp_track);
}
+ } else if (restartAtEnd && Source.Count > 0) {
+ if (tmp_track != null) {
+ previous_stack.Push (tmp_track);
+ }
+
+ CurrentTrack = Source.TrackModel[0];
+ QueuePlayTrack ();
+ return;
} else {
return;
}
Index: Core/Banshee.Services/Banshee.PlaybackController/IBasicPlaybackController.cs
===================================================================
--- Core/Banshee.Services/Banshee.PlaybackController/IBasicPlaybackController.cs (revision 3319)
+++ Core/Banshee.Services/Banshee.PlaybackController/IBasicPlaybackController.cs (working copy)
@@ -31,7 +31,7 @@
public interface IBasicPlaybackController
{
void First ();
- void Next ();
+ void Next (bool restartAtEnd);
void Previous ();
}
}
Attachment:
media-Resources.tar.gz
Description: GNU Zip compressed data