Fix a bug where the engine would skip a song that didn't exist, but then not play the next song.

This commit is contained in:
David Sansome 2011-03-20 19:18:54 +00:00
parent bbd5b04244
commit e761f2bdc8
4 changed files with 19 additions and 15 deletions

View File

@ -24,7 +24,6 @@
#include "config.h"
#include "gstengine.h"
#include "gstenginepipeline.h"
#include "core/boundfuturewatcher.h"
#include "core/utilities.h"
#ifdef HAVE_IMOBILEDEVICE
@ -493,8 +492,8 @@ bool GstEngine::Play(quint64 offset_nanosec) {
return false;
QFuture<GstStateChangeReturn> future = current_pipeline_->SetState(GST_STATE_PLAYING);
BoundFutureWatcher<GstStateChangeReturn, quint64>* watcher =
new BoundFutureWatcher<GstStateChangeReturn, quint64>(offset_nanosec, this);
PlayFutureWatcher* watcher = new PlayFutureWatcher(
PlayFutureWatcherArg(offset_nanosec, current_pipeline_.get()), this);
watcher->setFuture(future);
connect(watcher, SIGNAL(finished()), SLOT(PlayDone()));
@ -502,17 +501,22 @@ bool GstEngine::Play(quint64 offset_nanosec) {
}
void GstEngine::PlayDone() {
BoundFutureWatcher<GstStateChangeReturn, quint64>* watcher =
static_cast<BoundFutureWatcher<GstStateChangeReturn, quint64>*>(sender());
PlayFutureWatcher* watcher = static_cast<PlayFutureWatcher*>(sender());
watcher->deleteLater();
GstStateChangeReturn ret = watcher->result();
quint64 offset_nanosec = watcher->data();
quint64 offset_nanosec = watcher->data().first;
if (!current_pipeline_) {
return;
}
// Don't dereference this - it might be invalid
GstEnginePipeline* dangerous_pipeline = watcher->data().second;
if (dangerous_pipeline != current_pipeline_.get()) {
return;
}
if (ret == GST_STATE_CHANGE_FAILURE) {
// Failure, but we got a redirection URL - try loading that instead
QUrl redirect_url = current_pipeline_->redirect_url();
@ -675,6 +679,10 @@ void GstEngine::timerEvent(QTimerEvent* e) {
}
void GstEngine::HandlePipelineError(const QString& message, int domain, int error_code) {
GstEnginePipeline* pipeline_sender = qobject_cast<GstEnginePipeline*>(sender());
if (!pipeline_sender || pipeline_sender != current_pipeline_.get())
return;
qWarning() << "Gstreamer error:" << message;
current_pipeline_.reset();

View File

@ -24,6 +24,7 @@
#include "bufferconsumer.h"
#include "enginebase.h"
#include "core/boundfuturewatcher.h"
#include "core/timeconstants.h"
#include <QFuture>
@ -125,6 +126,9 @@ class GstEngine : public Engine::Base, public BufferConsumer {
void PlayDone();
private:
typedef QPair<quint64, GstEnginePipeline*> PlayFutureWatcherArg;
typedef BoundFutureWatcher<GstStateChangeReturn, PlayFutureWatcherArg> PlayFutureWatcher;
// Callbacks
static void CanDecodeNewPadCallback(GstElement*, GstPad*, gboolean, gpointer);
static void CanDecodeLastCallback(GstElement*, gpointer);

View File

@ -54,7 +54,6 @@ GstEnginePipeline::GstEnginePipeline(GstEngine* engine)
next_end_offset_nanosec_(-1),
ignore_next_seek_(false),
ignore_tags_(false),
ignore_errors_(false),
pipeline_is_initialised_(false),
pipeline_is_connected_(false),
pending_seek_nanosec_(-1),
@ -109,7 +108,6 @@ bool GstEnginePipeline::ReplaceDecodeBin(GstElement* new_bin) {
// deletion in the main thread
}
ignore_errors_ = false;
uridecodebin_ = new_bin;
segment_start_ = 0;
segment_start_received_ = false;
@ -310,10 +308,7 @@ GstBusSyncReply GstEnginePipeline::BusCallbackSync(GstBus*, GstMessage* msg, gpo
break;
case GST_MESSAGE_ERROR:
if (!instance->ignore_errors_) {
instance->ignore_errors_ = true;
QtConcurrent::run(instance, &GstEnginePipeline::ErrorMessageReceived, msg);
}
instance->ErrorMessageReceived(msg);
break;
case GST_MESSAGE_ELEMENT:

View File

@ -188,9 +188,6 @@ class GstEnginePipeline : public QObject {
// get sent while the Player still thinks it's playing the last song
bool ignore_tags_;
// Set after the first error to ignore any others that arrive.
bool ignore_errors_;
// When the gstreamer source requests a redirect we store the URL here and
// callers can pick it up after the state change to PLAYING fails.
QUrl redirect_url_;