@@ -57,6 +57,7 @@
|
||||
#include "core/enginemetadata.h"
|
||||
#include "constants/timeconstants.h"
|
||||
#include "enginebase.h"
|
||||
#include "gsturl.h"
|
||||
#include "gstengine.h"
|
||||
#include "gstenginepipeline.h"
|
||||
#include "gstbufferconsumer.h"
|
||||
@@ -179,15 +180,18 @@ EngineBase::State GstEngine::state() const {
|
||||
|
||||
void GstEngine::StartPreloading(const QUrl &media_url, const QUrl &stream_url, const bool force_stop_at_end, const qint64 beginning_offset_nanosec, const qint64 end_offset_nanosec) {
|
||||
|
||||
const QByteArray gst_url = FixupUrl(stream_url);
|
||||
const GstUrl gst_url = FixupUrl(stream_url);
|
||||
|
||||
// No crossfading, so we can just queue the new URL in the existing pipeline and get gapless playback (hopefully)
|
||||
if (current_pipeline_) {
|
||||
current_pipeline_->PrepareNextUrl(media_url, stream_url, gst_url, beginning_offset_nanosec, force_stop_at_end ? end_offset_nanosec : 0);
|
||||
if (!gst_url.source_device.isEmpty()) {
|
||||
current_pipeline_->SetSourceDevice(gst_url.source_device);
|
||||
}
|
||||
current_pipeline_->PrepareNextUrl(media_url, stream_url, gst_url.url, beginning_offset_nanosec, force_stop_at_end ? end_offset_nanosec : 0);
|
||||
// Add request to discover the stream
|
||||
if (discoverer_ && media_url.scheme() != u"spotify"_s) {
|
||||
if (!gst_discoverer_discover_uri_async(discoverer_, gst_url.constData())) {
|
||||
qLog(Error) << "Failed to start stream discovery for" << gst_url;
|
||||
if (!gst_discoverer_discover_uri_async(discoverer_, gst_url.url.constData())) {
|
||||
qLog(Error) << "Failed to start stream discovery for" << gst_url.url;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -198,7 +202,7 @@ bool GstEngine::Load(const QUrl &media_url, const QUrl &stream_url, const Engine
|
||||
|
||||
EngineBase::Load(media_url, stream_url, change, force_stop_at_end, beginning_offset_nanosec, end_offset_nanosec, ebur128_integrated_loudness_lufs);
|
||||
|
||||
const QByteArray gst_url = FixupUrl(stream_url);
|
||||
const GstUrl gst_url = FixupUrl(stream_url);
|
||||
|
||||
bool crossfade = current_pipeline_ && ((crossfade_enabled_ && change & EngineBase::TrackChangeType::Manual) || (autocrossfade_enabled_ && change & EngineBase::TrackChangeType::Auto) || ((crossfade_enabled_ || autocrossfade_enabled_) && change & EngineBase::TrackChangeType::Intro));
|
||||
|
||||
@@ -215,9 +219,14 @@ bool GstEngine::Load(const QUrl &media_url, const QUrl &stream_url, const Engine
|
||||
}
|
||||
}
|
||||
|
||||
GstEnginePipelinePtr pipeline = CreatePipeline(media_url, stream_url, gst_url, static_cast<qint64>(beginning_offset_nanosec), force_stop_at_end ? end_offset_nanosec : 0, ebur128_loudness_normalizing_gain_db_);
|
||||
GstEnginePipelinePtr pipeline = CreatePipeline(media_url, stream_url, gst_url.url, static_cast<qint64>(beginning_offset_nanosec), force_stop_at_end ? end_offset_nanosec : 0, ebur128_loudness_normalizing_gain_db_);
|
||||
if (!pipeline) return false;
|
||||
|
||||
// Set the source device if one was extracted from the URL
|
||||
if (!gst_url.source_device.isEmpty()) {
|
||||
pipeline->SetSourceDevice(gst_url.source_device);
|
||||
}
|
||||
|
||||
GstEnginePipelinePtr old_pipeline = current_pipeline_;
|
||||
current_pipeline_ = pipeline;
|
||||
|
||||
@@ -253,8 +262,8 @@ bool GstEngine::Load(const QUrl &media_url, const QUrl &stream_url, const Engine
|
||||
|
||||
// Add request to discover the stream
|
||||
if (discoverer_ && media_url.scheme() != u"spotify"_s) {
|
||||
if (!gst_discoverer_discover_uri_async(discoverer_, gst_url.constData())) {
|
||||
qLog(Error) << "Failed to start stream discovery for" << gst_url;
|
||||
if (!gst_discoverer_discover_uri_async(discoverer_, gst_url.url.constData())) {
|
||||
qLog(Error) << "Failed to start stream discovery for" << gst_url.url;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -814,16 +823,16 @@ void GstEngine::BufferingFinished() {
|
||||
|
||||
}
|
||||
|
||||
QByteArray GstEngine::FixupUrl(const QUrl &url) {
|
||||
GstUrl GstEngine::FixupUrl(const QUrl &url) {
|
||||
|
||||
QByteArray uri;
|
||||
GstUrl gst_url;
|
||||
|
||||
// It's a file:// url with a hostname set.
|
||||
// QUrl::fromLocalFile does this when given a \\host\share\file path on Windows.
|
||||
// Munge it back into a path that gstreamer will recognise.
|
||||
if (url.isLocalFile() && !url.host().isEmpty()) {
|
||||
QString str = "file:////"_L1 + url.host() + url.path();
|
||||
uri = str.toUtf8();
|
||||
gst_url.url = str.toUtf8();
|
||||
}
|
||||
else if (url.scheme() == "cdda"_L1) {
|
||||
QString str;
|
||||
@@ -837,16 +846,15 @@ QByteArray GstEngine::FixupUrl(const QUrl &url) {
|
||||
// We keep the device in mind, and we will set it later using SourceSetupCallback
|
||||
QStringList path = url.path().split(u'/');
|
||||
str = QStringLiteral("cdda://%1").arg(path.takeLast());
|
||||
QString device = path.join(u'/');
|
||||
if (current_pipeline_) current_pipeline_->SetSourceDevice(device);
|
||||
gst_url.source_device = path.join(u'/');
|
||||
}
|
||||
uri = str.toUtf8();
|
||||
gst_url.url = str.toUtf8();
|
||||
}
|
||||
else {
|
||||
uri = url.toEncoded();
|
||||
gst_url.url = url.toEncoded();
|
||||
}
|
||||
|
||||
return uri;
|
||||
return gst_url;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include "includes/shared_ptr.h"
|
||||
#include "enginebase.h"
|
||||
#include "gsturl.h"
|
||||
#include "gstenginepipeline.h"
|
||||
#include "gstbufferconsumer.h"
|
||||
|
||||
@@ -123,7 +124,7 @@ class GstEngine : public EngineBase, public GstBufferConsumer {
|
||||
void PipelineFinished(const int pipeline_id);
|
||||
|
||||
private:
|
||||
QByteArray FixupUrl(const QUrl &url);
|
||||
GstUrl FixupUrl(const QUrl &url);
|
||||
|
||||
void StartFadeout(GstEnginePipelinePtr pipeline);
|
||||
void StartFadeoutPause();
|
||||
|
||||
32
src/engine/gsturl.h
Normal file
32
src/engine/gsturl.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2025, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GSTURL_H
|
||||
#define GSTURL_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
class GstUrl {
|
||||
public:
|
||||
QByteArray url;
|
||||
QString source_device;
|
||||
};
|
||||
|
||||
#endif // GSTURL_H
|
||||
Reference in New Issue
Block a user