Fix some confusion with auto/manual track changes
This commit is contained in:
parent
caa63d3095
commit
d51c7444ab
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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_;
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user