Handle redirect messages from mmssrc properly. Fixes issue #385.
This commit is contained in:
parent
f205326ff3
commit
9106abb1a0
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
QSet<QString> SongLoader::sRawUriSchemes;
|
||||
|
||||
SongLoader::SongLoader(QObject *parent)
|
||||
: QObject(parent),
|
||||
timeout_timer_(new QTimer(this)),
|
||||
|
@ -37,6 +39,11 @@ SongLoader::SongLoader(QObject *parent)
|
|||
success_(false),
|
||||
parser_(NULL)
|
||||
{
|
||||
if (sRawUriSchemes.isEmpty()) {
|
||||
sRawUriSchemes << "udp" << "mms" << "mmsh" << "mmst" << "mmsu" << "rtsp"
|
||||
<< "rtspu" << "rtspt" << "rtsph";
|
||||
}
|
||||
|
||||
timeout_timer_->setSingleShot(true);
|
||||
connect(timeout_timer_, SIGNAL(timeout()), SLOT(Timeout()));
|
||||
}
|
||||
|
@ -55,6 +62,13 @@ SongLoader::Result SongLoader::Load(const QUrl& url, int timeout_msec) {
|
|||
return LoadLocal();
|
||||
}
|
||||
|
||||
if (sRawUriSchemes.contains(url_.scheme())) {
|
||||
// The URI scheme indicates that it can't possibly be a playlist, so add
|
||||
// it as a raw stream.
|
||||
AddAsRawStream();
|
||||
return Success;
|
||||
}
|
||||
|
||||
timeout_timer_->start(timeout_msec);
|
||||
return LoadRemote();
|
||||
}
|
||||
|
@ -325,17 +339,21 @@ void SongLoader::StopTypefind() {
|
|||
qDebug() << "Loading" << url_ << "as raw stream";
|
||||
|
||||
// It wasn't a playlist - just put the URL in as a stream
|
||||
Song song;
|
||||
song.set_valid(true);
|
||||
song.set_filetype(Song::Type_Stream);
|
||||
song.set_filename(url_.toString());
|
||||
song.set_title(url_.toString());
|
||||
songs_ << song;
|
||||
AddAsRawStream();
|
||||
}
|
||||
|
||||
emit LoadFinished(success_);
|
||||
}
|
||||
|
||||
void SongLoader::AddAsRawStream() {
|
||||
Song song;
|
||||
song.set_valid(true);
|
||||
song.set_filetype(Song::Type_Stream);
|
||||
song.set_filename(url_.toString());
|
||||
song.set_title(url_.toString());
|
||||
songs_ << song;
|
||||
}
|
||||
|
||||
void SongLoader::Timeout() {
|
||||
state_ = Finished;
|
||||
success_ = false;
|
||||
|
|
|
@ -75,7 +75,11 @@ private:
|
|||
void EndOfStreamReached();
|
||||
void MagicReady();
|
||||
|
||||
void AddAsRawStream();
|
||||
|
||||
private:
|
||||
static QSet<QString> sRawUriSchemes;
|
||||
|
||||
QUrl url_;
|
||||
SongList songs_;
|
||||
|
||||
|
|
|
@ -474,7 +474,19 @@ void GstEngine::StartFadeout() {
|
|||
|
||||
bool GstEngine::Play( uint offset ) {
|
||||
// Try to play input pipeline; if fails, destroy input bin
|
||||
if (!current_pipeline_->SetState(GST_STATE_PLAYING)) {
|
||||
forever {
|
||||
if (current_pipeline_->SetState(GST_STATE_PLAYING))
|
||||
break; // Success
|
||||
|
||||
// Failure, but we got a redirection URL - try loading that instead
|
||||
QUrl redirect_url = current_pipeline_->redirect_url();
|
||||
if (!redirect_url.isEmpty() && redirect_url != current_pipeline_->url()) {
|
||||
qDebug() << "Redirecting to" << redirect_url;
|
||||
current_pipeline_ = CreatePipeline(redirect_url);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Failure - give up
|
||||
qWarning() << "Could not set thread to PLAYING.";
|
||||
current_pipeline_.reset();
|
||||
return false;
|
||||
|
|
|
@ -213,24 +213,49 @@ GstBusSyncReply GstEnginePipeline::BusCallbackSync(GstBus*, GstMessage* msg, gpo
|
|||
instance->ErrorMessageReceived(msg);
|
||||
break;
|
||||
|
||||
case GST_MESSAGE_ELEMENT:
|
||||
instance->ElementMessageReceived(msg);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return GST_BUS_PASS;
|
||||
}
|
||||
|
||||
void GstEnginePipeline::ElementMessageReceived(GstMessage* msg) {
|
||||
const GstStructure* structure = gst_message_get_structure(msg);
|
||||
|
||||
if (gst_structure_has_name(structure, "redirect")) {
|
||||
const char* uri = gst_structure_get_string(structure, "new-location");
|
||||
|
||||
// Set the redirect URL. In mmssrc redirect messages come during the
|
||||
// initial state change to PLAYING, so callers can pick up this URL after
|
||||
// the state change has failed.
|
||||
redirect_url_ = QUrl::fromEncoded(uri);
|
||||
}
|
||||
}
|
||||
|
||||
void GstEnginePipeline::ErrorMessageReceived(GstMessage* msg) {
|
||||
GError* error;
|
||||
gchar* debugs;
|
||||
|
||||
gst_message_parse_error(msg, &error, &debugs);
|
||||
QString message = QString::fromLocal8Bit(error->message);
|
||||
|
||||
qDebug() << debugs;
|
||||
QString debugstr = QString::fromLocal8Bit(debugs);
|
||||
|
||||
g_error_free(error);
|
||||
free(debugs);
|
||||
|
||||
if (!redirect_url_.isEmpty() && debugstr.contains(
|
||||
"A redirect message was posted on the bus and should have been handled by the application.")) {
|
||||
// mmssrc posts a message on the bus *and* makes an error message when it
|
||||
// wants to do a redirect. We handle the message, but now we have to
|
||||
// ignore the error too.
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << debugstr;
|
||||
emit Error(message);
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,8 @@ class GstEnginePipeline : public QObject {
|
|||
qint64 length() const;
|
||||
GstState state() const;
|
||||
|
||||
QUrl redirect_url() const { return redirect_url_; }
|
||||
|
||||
public slots:
|
||||
void SetVolumeModifier(qreal mod);
|
||||
|
||||
|
@ -95,8 +97,9 @@ class GstEnginePipeline : public QObject {
|
|||
static void SourceDrainedCallback(GstURIDecodeBin*, gpointer);
|
||||
static bool StopUriDecodeBin(gpointer bin);
|
||||
void TagMessageReceived(GstMessage*);
|
||||
QString ParseTag(GstTagList* list, const char* tag) const;
|
||||
void ErrorMessageReceived(GstMessage*);
|
||||
void ElementMessageReceived(GstMessage*);
|
||||
QString ParseTag(GstTagList* list, const char* tag) const;
|
||||
|
||||
void UpdateVolume();
|
||||
bool ReplaceDecodeBin(const QUrl& url);
|
||||
|
@ -130,6 +133,10 @@ class GstEnginePipeline : public QObject {
|
|||
QUrl url_;
|
||||
QUrl next_url_;
|
||||
|
||||
// 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_;
|
||||
|
||||
int volume_percent_;
|
||||
qreal volume_modifier_;
|
||||
|
||||
|
|
Loading…
Reference in New Issue