Skip to content

Commit

Permalink
GStreamerSharp: bring back option to disable gapless
Browse files Browse the repository at this point in the history
Our current unmanaged backend still has this option, so we should
match the new managed backend to the same expectations. This brings
back some code paths (and comments) from the unmanaged backend that
were not present in the managed one (namely the use of the pending_*
and next_track_pending fields).

We plan to remove the Gapless setting soon (so it is always enabled
by default and can't be changed), but we're not quite ready yet,
given the number of bugs that are still affected by this setting (we
have fixed some recently, which were backported to 2.6.2, but we're
not there yet). We will track this progress in bgo#638943.

Even though disabling gapless is an option that is not perfect
(right now I'm experiencing an issue with volume being changed at
transition), it is good to have it until our first 3.0 RC, so
we can ask users to tell us if any given problems they
experience with the new managed backend are gapless-related or
not. We should concentrate in fixing gapless bugs rather than
non-gapless issues that this brings.
  • Loading branch information
knocte committed Mar 12, 2014
1 parent 433daac commit 9a04093
Showing 1 changed file with 82 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// Stephan Sundermann <[email protected]>
//
// Copyright (C) 2010 Novell, Inc.
// Copyright (C) 2013 Andrés G. Aragoneses
// Copyright (C) 2013-2014 Andrés G. Aragoneses
// Copyright (C) 2013 Stephan Sundermann
//
// Permission is hereby granted, free of charge, to any person obtaining
Expand All @@ -33,8 +33,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;

using Mono.Unix;
Expand All @@ -43,9 +41,6 @@
using Gst.PbUtils;

using Hyena;
using Hyena.Data;

using Banshee.Base;
using Banshee.Collection;
using Banshee.Streaming;
using Banshee.MediaEngine;
Expand Down Expand Up @@ -296,6 +291,11 @@ public Pad RequestTeePad ()
DvdManager dvd_manager = null;
Visualization visualization;

bool gapless_enabled;
private bool next_track_pending;
private SafeUri pending_uri;
private bool pending_maybe_video;

public PlayerEngine ()
{
Log.InformationFormat ("GStreamer# {0} Initializing; {1}.{2}",
Expand Down Expand Up @@ -348,7 +348,6 @@ protected override void Initialize ()

playbin.AddNotification ("volume", OnVolumeChanged);
playbin.Bus.AddWatch (OnBusMessage);
playbin.Connect ("about-to-finish", OnAboutToFinish);

cdda_manager = new CddaManager (playbin);
dvd_manager = new DvdManager (playbin);
Expand All @@ -363,6 +362,7 @@ protected override void Initialize ()

InstallPreferences ();
audio_sink.ReplayGainEnabled = ReplayGainEnabledSchema.Get ();
GaplessEnabled = GaplessEnabledSchema.Get ();
}

public override void Dispose ()
Expand Down Expand Up @@ -418,8 +418,13 @@ void OnAboutToFinish (object o, GLib.SignalArgs args)
CurrentTrack.UpdateLastPlayed ();

next_track_set.Reset ();
OnEventChanged (PlayerEvent.RequestNextTrack);
pending_uri = null;
next_track_pending = true;

OnEventChanged (PlayerEvent.RequestNextTrack);
// Gapless playback with Playbin2 requires that the about-to-finish callback does not return until
// the next uri has been set. Block here for a second or until the RequestNextTrack event has
// finished triggering.
if (!next_track_set.WaitOne (1000, false)) {
Log.Warning ("[Gapless]: Timed out while waiting for next track to be set.");
next_track_set.Set ();
Expand All @@ -428,10 +433,13 @@ void OnAboutToFinish (object o, GLib.SignalArgs args)

public override void SetNextTrackUri (SafeUri uri, bool maybeVideo)
{
next_track_pending = false;
if (next_track_set.WaitOne (0, false)) {
// We've been asked to set the next track, but have taken too
// long to get here. Bail for now, and the EoS handling will
// pick up the pieces.
pending_uri = uri;
pending_maybe_video = maybeVideo;
return;
}

Expand Down Expand Up @@ -460,14 +468,42 @@ public override void Seek (uint position, bool accurate_seek)
OnEventChanged (PlayerEvent.Seek);
}

private void OnEos ()
{
if (!next_track_pending &&
(!GaplessEnabled || (CurrentTrack != null && CurrentTrack.HasAttribute (TrackMediaAttributes.VideoStream)))) {
// We don't request next track in OnEoS if gapless playback is enabled and current track has no video stream contained.
// The request next track is already called in OnAboutToFinish().
OnEventChanged (PlayerEvent.RequestNextTrack);
} else if (pending_uri != null) {
Log.Warning ("[Gapless] EOS signalled while waiting for next track. This means that Banshee " +
"was too slow at calculating what track to play next. " +
"If this happens frequently, please file a bug");
OnStateChanged (PlayerState.Loading);
OpenUri (pending_uri, pending_maybe_video);
Play ();
pending_uri = null;
} else if (!GaplessEnabled || (CurrentTrack != null && CurrentTrack.HasAttribute (TrackMediaAttributes.VideoStream))) {
// This should be unreachable - the RequestNextTrack event is delegated to the main thread
// and so blocks the bus callback from delivering the EOS message.
//
// Playback should continue as normal from here, when the RequestNextTrack message gets handled.
Log.Warning ("[Gapless] EndOfStream message received before the next track has been set. " +
"If this happens frequently, please file a bug");
} else {
Log.Debug ("[Gapless] Reach the last music under repeat off mode");
}
}

private bool OnBusMessage (Bus bus, Message msg)
{
switch (msg.Type) {
case MessageType.Eos:
StopIterating ();
Close (false);
OnEventChanged (PlayerEvent.EndOfStream);
OnEventChanged (PlayerEvent.RequestNextTrack);

OnEos ();
break;

case MessageType.StateChanged:
Expand Down Expand Up @@ -552,6 +588,14 @@ private void OnVolumeChanged (object o, GLib.NotifyArgs args)

private void HandleStreamStart ()
{
if (!GaplessEnabled) {
return;
}

// Must do it here because the next track is already playing.

// If the state is anything other than loaded, assume we were just playing a track and should
// EoS it and increment its playcount etc.
if (CurrentState != PlayerState.Loaded && CurrentState != PlayerState.Loading) {
// Set the current track as fully played before signaling EndOfStream.
ServiceManager.PlayerEngine.IncrementLastPlayed (1.0);
Expand Down Expand Up @@ -778,6 +822,22 @@ public override bool CanSeek {
get { return true; }
}

private bool GaplessEnabled {
get { return gapless_enabled; }
set
{
if (value == gapless_enabled) {
return;
}
gapless_enabled = value;
if (value) {
playbin.Connect ("about-to-finish", OnAboutToFinish);
} else {
playbin.Disconnect ("about-to-finish", OnAboutToFinish);
}
}
}

private static Format query_format = Format.Time;
public override uint Position {
get {
Expand Down Expand Up @@ -980,6 +1040,7 @@ public override bool InDvdMenu {
#region Preferences

private PreferenceBase replaygain_preference;
private PreferenceBase gapless_preference;

private void InstallPreferences ()
{
Expand All @@ -993,6 +1054,11 @@ private void InstallPreferences ()
Catalog.GetString ("For tracks that have ReplayGain data, automatically scale (normalize) playback volume"),
delegate { audio_sink.ReplayGainEnabled = ReplayGainEnabledSchema.Get (); }
));
gapless_preference = service["general"]["misc"].Add (new SchemaPreference<bool> (GaplessEnabledSchema,
Catalog.GetString ("Enable _gapless playback"),
Catalog.GetString ("Eliminate the small playback gap on track change. Useful for concept albums and classical music"),
() => { GaplessEnabled = GaplessEnabledSchema.Get (); }
));
}

private void UninstallPreferences ()
Expand All @@ -1013,6 +1079,13 @@ private void UninstallPreferences ()
"If ReplayGain data is present on tracks when playing, allow volume scaling"
);

public static readonly SchemaEntry<bool> GaplessEnabledSchema = new SchemaEntry<bool> (
"player_engine", "gapless_playback_enabled",
true,
"Enable gapless playback",
"Eliminate the small playback gap on track change. Useful for concept albums and classical music"
);

#endregion
}
}

0 comments on commit 9a04093

Please sign in to comment.