Fix some confusion with auto/manual track changes

This commit is contained in:
David Sansome 2010-04-12 01:59:21 +00:00
parent caa63d3095
commit d51c7444ab
10 changed files with 51 additions and 42 deletions

View File

@ -20,6 +20,8 @@ namespace Engine
* It is vital to be Idle just after the track has ended!
*/
enum State { Empty, Idle, Playing, Paused };
enum TrackChangeType { First, Manual, Auto };
}
typedef Engine::Base EngineBase;

View File

@ -32,7 +32,6 @@ Engine::Base::Base()
fadeout_enabled_(true),
fadeout_duration_(2000),
crossfade_enabled_(true),
crossfade_next_track_(false),
about_to_end_emitted_(false)
{
}
@ -40,7 +39,7 @@ Engine::Base::Base()
Engine::Base::~Base() {
}
bool Engine::Base::Load(const QUrl &url) {
bool Engine::Base::Load(const QUrl &url, TrackChangeType) {
url_ = url;
about_to_end_emitted_ = false;
return true;

View File

@ -55,10 +55,9 @@ class Base : public QObject, boost::noncopyable {
virtual uint length() const { return 0; }
// Helpers
virtual bool Load(const QUrl &url);
bool Play(const QUrl &u) { return Load(u) && Play(); }
virtual bool Load(const QUrl &url, TrackChangeType change);
bool Play(const QUrl &u, TrackChangeType c) { return Load(u, c) && Play(); }
void SetVolume( uint value );
void SetCrossfadeNextTrack(bool enable) { crossfade_next_track_ = enable; }
inline uint volume() const { return volume_; }
virtual const Scope &scope() { return scope_; }
@ -102,7 +101,6 @@ class Base : public QObject, boost::noncopyable {
int fadeout_duration_;
bool crossfade_enabled_;
bool autocrossfade_enabled_;
bool crossfade_next_track_;
private:
bool about_to_end_emitted_;

View File

@ -285,17 +285,18 @@ void GstEngine::UpdateScope() {
}
}
bool GstEngine::Load(const QUrl& url) {
Engine::Base::Load(url);
bool GstEngine::Load(const QUrl& url, Engine::TrackChangeType change) {
Engine::Base::Load(url, change);
const bool crossfade = current_pipeline_ && crossfade_enabled_ &&
crossfade_next_track_;
const bool crossfade = current_pipeline_ &&
((crossfade_enabled_ && change == Engine::Manual) ||
(autocrossfade_enabled_ && change == Engine::Auto));
shared_ptr<GstEnginePipeline> pipeline(CreatePipeline(url));
if (!pipeline)
return false;
if (crossfade && current_pipeline_)
if (crossfade)
StartFadeout();
current_pipeline_ = pipeline;
@ -305,10 +306,8 @@ bool GstEngine::Load(const QUrl& url) {
SetEqualizerParameters(equalizer_preamp_, equalizer_gains_);
// Maybe fade in this track
if (crossfade) {
if (crossfade)
current_pipeline_->StartFader(fadeout_duration_, QTimeLine::Forward);
crossfade_next_track_ = false;
}
return true;
}
@ -316,6 +315,7 @@ bool GstEngine::Load(const QUrl& url) {
void GstEngine::StartFadeout() {
fadeout_pipeline_ = current_pipeline_;
disconnect(fadeout_pipeline_.get(), 0, 0, 0);
fadeout_pipeline_->set_forwards_buffers(false);
ClearScopeBuffers();
fadeout_pipeline_->StartFader(fadeout_duration_, QTimeLine::Backward);

View File

@ -76,7 +76,7 @@ class GstEngine : public Engine::Base {
const QString& factoryName, GstElement* bin = 0, const QString& name = 0);
public slots:
bool Load(const QUrl&);
bool Load(const QUrl&, Engine::TrackChangeType change);
bool Play(uint offset);
void Stop();
void Pause();

View File

@ -24,6 +24,7 @@ GstEnginePipeline::GstEnginePipeline()
: QObject(NULL),
valid_(false),
sink_(GstEngine::kAutoSink),
forwards_buffers_(false),
volume_percent_(100),
volume_modifier_(1.0),
fader_(NULL),
@ -228,13 +229,15 @@ void GstEnginePipeline::NewPadCallback(GstElement*, GstPad* pad, gboolean, gpoin
}
void GstEnginePipeline::HandoffCallback(GstPad*, GstBuffer* buf, gpointer self) {
bool GstEnginePipeline::HandoffCallback(GstPad*, GstBuffer* buf, gpointer self) {
GstEnginePipeline* instance = reinterpret_cast<GstEnginePipeline*>(self);
if (instance->forwards_buffers_) {
gst_buffer_ref(buf);
emit instance->BufferFound(buf);
}
return true;
}
void GstEnginePipeline::EventCallback(GstPad*, GstEvent* event, gpointer self) {

View File

@ -73,7 +73,7 @@ class GstEnginePipeline : public QObject {
static GstBusSyncReply BusCallbackSync(GstBus*, GstMessage*, gpointer);
static gboolean BusCallback(GstBus*, GstMessage*, gpointer);
static void NewPadCallback(GstElement*, GstPad*, gboolean, gpointer);
static void HandoffCallback(GstPad*, GstBuffer*, gpointer);
static bool HandoffCallback(GstPad*, GstBuffer*, gpointer);
static void EventCallback(GstPad*, GstEvent*, gpointer);
void UpdateVolume();

View File

@ -426,7 +426,7 @@ void MainWindow::QueueFiles(const QList<QUrl>& urls) {
QModelIndex playlist_index = playlist_->InsertPaths(urls);
if (playlist_index.isValid() && player_->GetState() != Engine::Playing)
player_->PlayAt(playlist_index.row(), true);
player_->PlayAt(playlist_index.row(), Engine::First);
}
void MainWindow::ReportError(const QString& message) {
@ -510,7 +510,7 @@ void MainWindow::PlayIndex(const QModelIndex& index) {
if (!index.isValid())
return;
player_->PlayAt(index.row(), true);
player_->PlayAt(index.row(), Engine::Manual);
}
void MainWindow::AddLibraryItemToPlaylist(const QModelIndex& index) {
@ -522,7 +522,7 @@ void MainWindow::AddLibraryItemToPlaylist(const QModelIndex& index) {
playlist_->InsertSongs(library_->GetChildSongs(idx));
if (first_song.isValid() && player_->GetState() != Engine::Playing)
player_->PlayAt(first_song.row(), true);
player_->PlayAt(first_song.row(), Engine::First);
}
void MainWindow::VolumeWheelEvent(int delta) {
@ -625,7 +625,7 @@ void MainWindow::InsertRadioItem(RadioItem* item) {
QList<RadioItem*>() << item);
if (first_song.isValid() && player_->GetState() != Engine::Playing)
player_->PlayAt(first_song.row(), true);
player_->PlayAt(first_song.row(), Engine::Manual);
}
void MainWindow::PlaylistRightClick(const QPoint& global_pos, const QModelIndex& index) {
@ -696,7 +696,7 @@ void MainWindow::PlaylistPlay() {
if (playlist_->current_index() == playlist_menu_index_.row()) {
player_->PlayPause();
} else {
player_->PlayAt(playlist_menu_index_.row(), true);
player_->PlayAt(playlist_menu_index_.row(), Engine::Manual);
}
}

View File

@ -57,7 +57,8 @@ Player::Player(Playlist* playlist, LastFMService* lastfm, QObject* parent)
playlist_(playlist),
lastfm_(lastfm),
current_item_options_(PlaylistItem::Default),
engine_(new GstEngine)
engine_(new GstEngine),
stream_change_type_(Engine::First)
{
settings_.beginGroup("Player");
@ -81,7 +82,7 @@ void Player::Init() {
qFatal("Error initialising audio engine");
connect(engine_, SIGNAL(StateChanged(Engine::State)), SLOT(EngineStateChanged(Engine::State)));
connect(engine_, SIGNAL(TrackAboutToEnd()), SLOT(Next()));
connect(engine_, SIGNAL(TrackAboutToEnd()), SLOT(NextAuto()));
connect(engine_, SIGNAL(TrackEnded()), SLOT(TrackEnded()));
connect(engine_, SIGNAL(MetaData(Engine::SimpleMetaBundle)),
SLOT(EngineMetadataReceived(Engine::SimpleMetaBundle)));
@ -93,16 +94,21 @@ void Player::ReloadSettings() {
engine_->ReloadSettings();
}
void Player::Next() {
void Player::NextAuto() {
Next(Engine::Auto);
}
void Player::Next(Engine::TrackChangeType change) {
if (playlist_->current_item_options() & PlaylistItem::ContainsMultipleTracks) {
stream_change_type_ = change;
playlist_->current_item()->LoadNext();
return;
}
NextItem();
NextItem(change);
}
void Player::NextItem() {
void Player::NextItem(Engine::TrackChangeType change) {
int i = playlist_->next_index();
playlist_->set_current_index(i);
if (i == -1) {
@ -110,8 +116,7 @@ void Player::NextItem() {
return;
}
engine_->SetCrossfadeNextTrack(true);
PlayAt(i, false);
PlayAt(i, change);
}
void Player::TrackEnded() {
@ -120,7 +125,7 @@ void Player::TrackEnded() {
return;
}
Next();
Next(Engine::Auto);
}
void Player::PlayPause() {
@ -148,7 +153,7 @@ void Player::PlayPause() {
if (i == -1) i = playlist_->last_played_index();
if (i == -1) i = 0;
PlayAt(i, false);
PlayAt(i, Engine::First);
break;
}
}
@ -167,7 +172,7 @@ void Player::Previous() {
return;
}
PlayAt(i, false);
PlayAt(i, Engine::Manual);
}
void Player::EngineStateChanged(Engine::State state) {
@ -196,8 +201,8 @@ Engine::State Player::GetState() const {
return engine_->state();
}
void Player::PlayAt(int index, bool manual_change) {
if (manual_change)
void Player::PlayAt(int index, Engine::TrackChangeType change) {
if (change != Engine::Auto)
playlist_->set_current_index(-1); // to reshuffle
playlist_->set_current_index(index);
@ -208,7 +213,7 @@ void Player::PlayAt(int index, bool manual_change) {
if (item->options() & PlaylistItem::SpecialPlayBehaviour)
item->StartLoading();
else {
engine_->Play(item->Url());
engine_->Play(item->Url(), change);
if (lastfm_->IsScrobblingEnabled())
lastfm_->NowPlaying(item->Metadata());
@ -226,7 +231,7 @@ void Player::StreamReady(const QUrl& original_url, const QUrl& media_url) {
if (!item || item->Url() != original_url)
return;
engine_->Play(media_url);
engine_->Play(media_url, stream_change_type_);
current_item_ = item->Metadata();
current_item_options_ = item->options();
@ -386,7 +391,7 @@ void Player::Play() {
engine_->Unpause();
break;
default:
Next();
Next(Engine::Manual);
break;
}
}
@ -441,7 +446,7 @@ int Player::AddTrack(const QString& track, bool play_now) {
if (index.isValid()) {
if (play_now) {
Next();
Next(Engine::First);
}
return 0; // Success.
}
@ -471,7 +476,7 @@ void Player::SetRandom(bool enable) {
}
void Player::PlayTrack(int index) {
PlayAt(index, true);
PlayAt(index, Engine::Manual);
}
void Player::PlaylistChanged() {

View File

@ -78,9 +78,9 @@ class Player : public QObject {
public slots:
void ReloadSettings();
void PlayAt(int index, bool manual_change);
void PlayAt(int index, Engine::TrackChangeType change);
void PlayPause();
void NextItem();
void NextItem(Engine::TrackChangeType change = Engine::Auto);
void Previous();
void SetVolume(int value);
void Seek(int seconds);
@ -99,7 +99,7 @@ class Player : public QObject {
void Pause();
void Stop();
void Play();
void Next();
void Next(Engine::TrackChangeType change = Engine::Manual);
void Prev();
int PositionGet() const;
void PositionSet(int);
@ -142,6 +142,7 @@ class Player : public QObject {
private slots:
void EngineStateChanged(Engine::State);
void EngineMetadataReceived(const Engine::SimpleMetaBundle& bundle);
void NextAuto();
private:
QVariantMap GetMetadata(const PlaylistItem& item) const;
@ -154,6 +155,7 @@ class Player : public QObject {
Song current_item_;
EngineBase* engine_;
Engine::TrackChangeType stream_change_type_;
};
#endif // PLAYER_H