Almost. SpotifyClient streams new tracks to a new media pipeline.
Bugs: - If the transition work, there is no audio output, but the pipeline is filled with data. - Sometimes the transition doesn't work and a complete new gstpipeline is created. Not sure why yet.
This commit is contained in:
parent
c62cc10759
commit
a1855f84bc
@ -41,7 +41,11 @@ MediaPipeline::~MediaPipeline() {
|
||||
}
|
||||
|
||||
bool MediaPipeline::Init(int sample_rate, int channels) {
|
||||
if (is_initialised()) return false;
|
||||
qLog(Debug) << "MediaPipeline::Init";
|
||||
if (is_initialised()) {
|
||||
qLog(Debug) << "is_initialised() true";
|
||||
return false;
|
||||
}
|
||||
|
||||
pipeline_ = gst_pipeline_new("pipeline");
|
||||
|
||||
@ -51,6 +55,7 @@ bool MediaPipeline::Init(int sample_rate, int channels) {
|
||||
tcpsink_ = gst_element_factory_make("tcpclientsink", nullptr);
|
||||
|
||||
if (!pipeline_ || !appsrc_ || !tcpsink_) {
|
||||
qLog(Debug) << "!pipeline_ || !appsrc_ || !tcpsink_";
|
||||
if (pipeline_) {
|
||||
gst_object_unref(GST_OBJECT(pipeline_));
|
||||
qLog(Debug) << "have pipeline_";
|
||||
|
@ -775,6 +775,7 @@ void SpotifyClient::MetadataUpdatedCallback(sp_session* session) {
|
||||
}
|
||||
|
||||
void SpotifyClient::ContinueGaplessPlayback(const PrefetchTrackRequest& req) {
|
||||
qLog(Debug) << "ContinueGaplessPlayback" << gapless_playback_;
|
||||
if (!gapless_playback_)
|
||||
return;
|
||||
|
||||
@ -787,9 +788,9 @@ void SpotifyClient::ContinueGaplessPlayback(const PrefetchTrackRequest& req) {
|
||||
sp_error error = sp_session_player_load(session_, req.track_);
|
||||
qLog(Debug) << Q_FUNC_INFO << sp_error_message(error);
|
||||
|
||||
//int port = media_pipeline_->port();
|
||||
//media_pipeline_.reset(new MediaPipeline(port,
|
||||
// sp_track_duration(req.track_)));
|
||||
qLog(Debug) << "EndOfTrackCallback - new pipeline";
|
||||
media_pipeline_.reset(media_pipeline_prefetch_);
|
||||
media_pipeline_prefetch_ = nullptr;
|
||||
|
||||
error = sp_session_player_play(session_, true);
|
||||
qLog(Debug) << Q_FUNC_INFO << sp_error_message(error);
|
||||
@ -855,14 +856,13 @@ void SpotifyClient::EndOfTrackCallback(sp_session* session) {
|
||||
|
||||
if (me->gapless_playback_ && !me->prefetched_tracks_.isEmpty()) {
|
||||
for (const PrefetchTrackRequest req : me->prefetched_tracks_.values()) {
|
||||
qLog(Debug) << "EndOfTrackCallback - something prefetched";
|
||||
if (me->gapless_playback_ && me->media_pipeline_prefetch_) {
|
||||
qLog(Debug) << "EndOfTrackCallback - new pipeline";
|
||||
me->media_pipeline_.reset(me->media_pipeline_prefetch_);
|
||||
me->media_pipeline_prefetch_ = nullptr;
|
||||
me->ContinueGaplessPlayback(req);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qLog(Debug) << "EndOfTrackCallback - reset";
|
||||
me->media_pipeline_.reset();
|
||||
}
|
||||
}
|
||||
@ -970,6 +970,7 @@ int SpotifyClient::GetDownloadProgress(sp_playlist* playlist) {
|
||||
}
|
||||
|
||||
void SpotifyClient::StartPlayback(const pb::spotify::PlaybackRequest& req) {
|
||||
qLog(Debug) << "StartPlayback";
|
||||
QString uri = QString::fromStdString(req.track_uri());
|
||||
|
||||
// Get a link object from the URI
|
||||
@ -1069,8 +1070,11 @@ void SpotifyClient::PrefetchTrack(const pb::spotify::PlaybackRequest &req) {
|
||||
|
||||
prefetched_tracks_.insert(uri, prefetch_request);
|
||||
|
||||
qLog(Debug) << "media_pipeline_prefetch_ to port" << req.media_port();
|
||||
media_pipeline_prefetch_ = new MediaPipeline(req.media_port(),
|
||||
sp_track_duration(track));
|
||||
|
||||
ContinueGaplessPlayback(prefetch_request);
|
||||
}
|
||||
|
||||
void SpotifyClient::SendPlaybackError(const QString& error) {
|
||||
|
@ -369,10 +369,14 @@ bool GstEngine::Load(const QUrl& url, Engine::TrackChangeFlags change,
|
||||
!crossfade_same_album_)
|
||||
crossfade = false;
|
||||
|
||||
if (current_pipeline_)
|
||||
qLog(Debug) << !crossfade << "true" << (current_pipeline_->url() == gst_url) <<
|
||||
(change & Engine::Auto);
|
||||
if (!crossfade && current_pipeline_ && current_pipeline_->url() == gst_url &&
|
||||
change & Engine::Auto) {
|
||||
// We're not crossfading, and the pipeline is already playing the URI we
|
||||
// want, so just do nothing.
|
||||
qLog(Debug) << "do nothing";
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -650,7 +654,7 @@ void GstEngine::timerEvent(QTimerEvent* e) {
|
||||
const qint64 remaining = current_length - current_position;
|
||||
|
||||
const qint64 fudge =
|
||||
kTimerIntervalNanosec + 100 * kNsecPerMsec; // Mmm fudge
|
||||
kTimerIntervalNanosec + 2500 * kNsecPerMsec; // Mmm fudge
|
||||
const qint64 gap = buffer_duration_nanosec_ +
|
||||
(autocrossfade_enabled_ ? fadeout_duration_nanosec_
|
||||
: kPreloadGapNanosec);
|
||||
@ -699,11 +703,11 @@ void GstEngine::EndOfStreamReached(int pipeline_id, bool has_next_track) {
|
||||
if (!current_pipeline_.get() || current_pipeline_->id() != pipeline_id)
|
||||
return;
|
||||
|
||||
qLog(Debug) << "EndOfStreamReached" << pipeline_id << has_next_track;
|
||||
|
||||
if (!has_next_track) {
|
||||
current_pipeline_.reset();
|
||||
BufferingFinished();
|
||||
} else {
|
||||
current_pipeline_->SpotifyMovedToNextTrack();
|
||||
}
|
||||
emit TrackEnded();
|
||||
}
|
||||
|
@ -154,11 +154,10 @@ bool GstEnginePipeline::ReplaceDecodeBin(const QUrl& url) {
|
||||
uridecodebin_next_spotify_ = nullptr;
|
||||
} else {
|
||||
new_bin = NewSpotifyBin();
|
||||
// Tell spotify to start sending data to us.
|
||||
InternetModel::Service<SpotifyService>()->server()->StartPlaybackLater(
|
||||
url.toString(), spotify_port_);
|
||||
}
|
||||
|
||||
// Tell spotify to start sending data to us.
|
||||
InternetModel::Service<SpotifyService>()->server()->StartPlaybackLater(
|
||||
url.toString(), spotify_port_);
|
||||
} else {
|
||||
new_bin = engine_->CreateElement("uridecodebin");
|
||||
g_object_set(G_OBJECT(new_bin), "uri", url.toEncoded().constData(),
|
||||
@ -194,6 +193,8 @@ GstElement* GstEnginePipeline::NewSpotifyBin() {
|
||||
gst_element_add_pad(GST_ELEMENT(new_bin), gst_ghost_pad_new("src", pad));
|
||||
gst_object_unref(GST_OBJECT(pad));
|
||||
|
||||
qDebug() << "NewSpotifyBin done";
|
||||
|
||||
return new_bin;
|
||||
}
|
||||
|
||||
@ -500,12 +501,13 @@ GstBusSyncReply GstEnginePipeline::BusCallbackSync(GstBus*, GstMessage* msg,
|
||||
gpointer self) {
|
||||
GstEnginePipeline* instance = reinterpret_cast<GstEnginePipeline*>(self);
|
||||
|
||||
qLog(Debug) << instance->id() << "sync bus message"
|
||||
<< GST_MESSAGE_TYPE_NAME(msg);
|
||||
//qLog(Debug) << instance->id() << "sync bus message"
|
||||
// << GST_MESSAGE_TYPE_NAME(msg);
|
||||
|
||||
switch (GST_MESSAGE_TYPE(msg)) {
|
||||
case GST_MESSAGE_EOS:
|
||||
if (instance->has_next_valid_url()) {
|
||||
qDebug() << "TransitionToNext from EOS";
|
||||
QMetaObject::invokeMethod(instance, "TransitionToNext", Qt::QueuedConnection);
|
||||
} else {
|
||||
emit instance->EndOfStreamReached(instance->id(), instance->has_next_valid_url());
|
||||
@ -950,6 +952,7 @@ void GstEnginePipeline::SourceSetupCallback(GstURIDecodeBin* bin,
|
||||
}
|
||||
|
||||
void GstEnginePipeline::TransitionToNext() {
|
||||
qLog(Debug) << "TransitionToNext";
|
||||
GstElement* old_decode_bin = uridecodebin_;
|
||||
|
||||
ignore_tags_ = true;
|
||||
@ -1191,20 +1194,7 @@ void GstEnginePipeline::SetNextUrl(const QUrl& url, qint64 beginning_nanosec,
|
||||
SpotifyService* spotify = InternetModel::Service<SpotifyService>();
|
||||
QMetaObject::invokeMethod(spotify, "SetNextUrl", Qt::QueuedConnection,
|
||||
Q_ARG(QUrl, url), Q_ARG(int, spotify_port_));
|
||||
|
||||
TransitionToNext();
|
||||
}
|
||||
}
|
||||
|
||||
void GstEnginePipeline::SpotifyMovedToNextTrack() {
|
||||
url_ = next_url_;
|
||||
end_offset_nanosec_ = next_end_offset_nanosec_;
|
||||
next_url_ = QUrl();
|
||||
next_beginning_offset_nanosec_ = 0;
|
||||
next_end_offset_nanosec_ = 0;
|
||||
|
||||
// This function gets called when the source has been drained, even if the
|
||||
// song hasn't finished playing yet. We'll get a new stream when it really
|
||||
// does finish, so emit TrackEnded then.
|
||||
emit_track_ended_on_stream_start_ = true;
|
||||
|
||||
gst_element_seek_simple(pipeline_, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, 0);
|
||||
}
|
||||
|
@ -83,7 +83,6 @@ class GstEnginePipeline : public QObject {
|
||||
qint64 end_nanosec);
|
||||
bool has_next_valid_url() const { return next_url_.isValid(); }
|
||||
QUrl next_url() const { return next_url_; }
|
||||
void SpotifyMovedToNextTrack();
|
||||
|
||||
// Get information about the music playback
|
||||
QUrl url() const { return url_; }
|
||||
|
@ -39,7 +39,7 @@ SpotifyServer::SpotifyServer(QObject* parent)
|
||||
}
|
||||
|
||||
void SpotifyServer::Init() {
|
||||
if (!server_->listen(QHostAddress::LocalHost, 56154)) {
|
||||
if (!server_->listen(QHostAddress::LocalHost)) {
|
||||
qLog(Error) << "Couldn't open server socket" << server_->errorString();
|
||||
}
|
||||
}
|
||||
|
@ -354,8 +354,8 @@ void SpotifyService::StartBlobProcess() {
|
||||
SLOT(BlobProcessError(QProcess::ProcessError)));
|
||||
|
||||
qLog(Info) << "Starting" << blob_path;
|
||||
//blob_process_->start(
|
||||
// blob_path, QStringList() << QString::number(server_->server_port()));
|
||||
blob_process_->start(
|
||||
blob_path, QStringList() << QString::number(server_->server_port()));
|
||||
}
|
||||
|
||||
bool SpotifyService::IsBlobInstalled() const {
|
||||
|
Loading…
x
Reference in New Issue
Block a user