2018-02-27 18:06:05 +01:00
|
|
|
/*
|
|
|
|
* Strawberry Music Player
|
2018-06-28 01:15:32 +02:00
|
|
|
* This file was part of Amarok / Clementine
|
2018-02-27 18:06:05 +01:00
|
|
|
* Copyright 2003 Mark Kretschmann
|
2018-06-28 01:15:32 +02:00
|
|
|
* Copyright 2004 - 2005 Max Howell, <max.howell@methylblue.com>
|
|
|
|
* Copyright 2010 David Sansome <me@davidsansome.com>
|
2021-03-20 21:14:47 +01:00
|
|
|
* Copyright 2017-2021 Jonas Kvinge <jonas@jkvinge.net>
|
2018-02-27 18:06:05 +01:00
|
|
|
*
|
|
|
|
* 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
|
2019-02-22 20:24:38 +01:00
|
|
|
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
2018-02-27 18:06:05 +01:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <cmath>
|
2018-05-01 00:41:33 +02:00
|
|
|
|
|
|
|
#include <QtGlobal>
|
2018-06-28 01:15:32 +02:00
|
|
|
#include <QVariant>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QUrl>
|
2018-02-27 18:06:05 +01:00
|
|
|
#include <QSettings>
|
|
|
|
|
2022-12-28 03:12:00 +01:00
|
|
|
#include "utilities/envutils.h"
|
|
|
|
#include "utilities/timeconstants.h"
|
2020-11-04 22:22:26 +01:00
|
|
|
#include "core/networkproxyfactory.h"
|
2024-04-11 02:56:01 +02:00
|
|
|
#include "core/settings.h"
|
2018-05-01 00:41:33 +02:00
|
|
|
#include "enginebase.h"
|
2018-06-28 01:15:32 +02:00
|
|
|
#include "settings/backendsettingspage.h"
|
2020-11-04 22:16:20 +01:00
|
|
|
#include "settings/networkproxysettingspage.h"
|
2022-06-04 15:51:35 +02:00
|
|
|
#ifdef HAVE_SPOTIFY
|
|
|
|
# include "settings/spotifysettingspage.h"
|
|
|
|
#endif
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2023-04-22 19:13:42 +02:00
|
|
|
EngineBase::EngineBase(QObject *parent)
|
2021-06-20 19:04:08 +02:00
|
|
|
: QObject(parent),
|
2024-02-20 01:08:00 +01:00
|
|
|
exclusive_mode_(false),
|
2021-06-20 19:04:08 +02:00
|
|
|
volume_control_(true),
|
|
|
|
volume_(100),
|
2018-02-27 18:06:05 +01:00
|
|
|
beginning_nanosec_(0),
|
|
|
|
end_nanosec_(0),
|
2023-06-27 04:05:01 +02:00
|
|
|
ebur128_loudness_normalizing_gain_db_(0.0),
|
2018-02-27 18:06:05 +01:00
|
|
|
scope_(kScopeSize),
|
2021-06-20 23:53:28 +02:00
|
|
|
buffering_(false),
|
|
|
|
equalizer_enabled_(false),
|
2018-06-28 01:15:32 +02:00
|
|
|
rg_enabled_(false),
|
|
|
|
rg_mode_(0),
|
2021-04-22 21:55:26 +02:00
|
|
|
rg_preamp_(0.0),
|
|
|
|
rg_fallbackgain_(0.0),
|
2018-06-28 01:15:32 +02:00
|
|
|
rg_compression_(true),
|
2023-06-27 04:05:01 +02:00
|
|
|
ebur128_loudness_normalization_(false),
|
|
|
|
ebur128_target_level_lufs_(-23.0),
|
2020-10-07 20:29:26 +02:00
|
|
|
buffer_duration_nanosec_(BackendSettingsPage::kDefaultBufferDuration * kNsecPerMsec),
|
|
|
|
buffer_low_watermark_(BackendSettingsPage::kDefaultBufferLowWatermark),
|
|
|
|
buffer_high_watermark_(BackendSettingsPage::kDefaultBufferHighWatermark),
|
2018-02-27 18:06:05 +01:00
|
|
|
fadeout_enabled_(true),
|
|
|
|
crossfade_enabled_(true),
|
|
|
|
autocrossfade_enabled_(false),
|
|
|
|
crossfade_same_album_(false),
|
2019-04-08 18:46:11 +02:00
|
|
|
fadeout_pause_enabled_(false),
|
2018-06-28 01:15:32 +02:00
|
|
|
fadeout_duration_(2),
|
|
|
|
fadeout_duration_nanosec_(2 * kNsecPerSec),
|
2021-06-20 23:53:28 +02:00
|
|
|
fadeout_pause_duration_(0),
|
|
|
|
fadeout_pause_duration_nanosec_(0),
|
2020-11-04 22:16:20 +01:00
|
|
|
proxy_authentication_(false),
|
2021-05-11 19:14:00 +02:00
|
|
|
channels_enabled_(false),
|
|
|
|
channels_(0),
|
2022-03-05 01:30:49 +01:00
|
|
|
bs2b_enabled_(false),
|
2022-08-24 20:34:10 +02:00
|
|
|
http2_enabled_(true),
|
2023-03-19 23:02:17 +01:00
|
|
|
strict_ssl_enabled_(false),
|
2018-02-27 18:06:05 +01:00
|
|
|
about_to_end_emitted_(false) {}
|
|
|
|
|
2023-04-22 19:13:42 +02:00
|
|
|
EngineBase::~EngineBase() = default;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2023-04-22 19:13:42 +02:00
|
|
|
EngineBase::Type EngineBase::TypeFromName(const QString &name) {
|
|
|
|
|
2024-04-09 23:20:26 +02:00
|
|
|
if (name.compare(QLatin1String("gstreamer"), Qt::CaseInsensitive) == 0) return Type::GStreamer;
|
|
|
|
if (name.compare(QLatin1String("vlc"), Qt::CaseInsensitive) == 0) return Type::VLC;
|
2023-04-22 19:13:42 +02:00
|
|
|
|
|
|
|
return Type::None;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
QString EngineBase::Name(const Type type) {
|
|
|
|
|
|
|
|
switch (type) {
|
2024-04-09 23:20:26 +02:00
|
|
|
case Type::GStreamer: return QStringLiteral("gstreamer");
|
|
|
|
case Type::VLC: return QStringLiteral("vlc");
|
2023-04-22 19:13:42 +02:00
|
|
|
case Type::None:
|
2024-04-09 23:20:26 +02:00
|
|
|
default: return QStringLiteral("None");
|
2023-04-22 19:13:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
QString EngineBase::Description(const Type type) {
|
|
|
|
|
|
|
|
switch (type) {
|
2024-04-09 23:20:26 +02:00
|
|
|
case Type::GStreamer: return QStringLiteral("GStreamer");
|
|
|
|
case Type::VLC: return QStringLiteral("VLC");
|
2023-04-22 19:13:42 +02:00
|
|
|
case Type::None:
|
2024-04-09 23:20:26 +02:00
|
|
|
default: return QStringLiteral("None");
|
2023-04-22 19:13:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-06-27 04:05:01 +02:00
|
|
|
bool EngineBase::Load(const QUrl &media_url, const QUrl &stream_url, const TrackChangeFlags, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec, const std::optional<double> ebur128_integrated_loudness_lufs) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
Q_UNUSED(force_stop_at_end);
|
|
|
|
|
2023-04-21 16:20:00 +02:00
|
|
|
media_url_ = media_url;
|
2019-09-07 23:34:13 +02:00
|
|
|
stream_url_ = stream_url;
|
2018-02-27 18:06:05 +01:00
|
|
|
beginning_nanosec_ = beginning_nanosec;
|
|
|
|
end_nanosec_ = end_nanosec;
|
|
|
|
|
2023-06-27 04:05:01 +02:00
|
|
|
ebur128_loudness_normalizing_gain_db_ = 0.0;
|
|
|
|
if (ebur128_loudness_normalization_ && ebur128_integrated_loudness_lufs) {
|
|
|
|
auto computeGain_dB = [](double source_dB, double target_dB) {
|
|
|
|
// Let's suppose the `source_dB` is -12 dB, while `target_dB` is -23 dB.
|
|
|
|
// In that case, we'd need to apply -11 dB of gain, which is computed as:
|
|
|
|
// -12 dB + x dB = -23 dB --> x dB = -23 dB - (-12 dB)
|
|
|
|
return target_dB - source_dB;
|
|
|
|
};
|
|
|
|
|
|
|
|
ebur128_loudness_normalizing_gain_db_ = computeGain_dB(*ebur128_integrated_loudness_lufs, ebur128_target_level_lufs_);
|
|
|
|
}
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
about_to_end_emitted_ = false;
|
2021-06-10 23:13:03 +02:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-08-03 00:05:06 +02:00
|
|
|
bool EngineBase::Play(const QUrl &media_url, const QUrl &stream_url, const bool pause, const TrackChangeFlags flags, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec, const quint64 offset_nanosec, const std::optional<double> ebur128_integrated_loudness_lufs) {
|
2018-06-28 01:15:32 +02:00
|
|
|
|
2023-06-27 04:05:01 +02:00
|
|
|
if (!Load(media_url, stream_url, flags, force_stop_at_end, beginning_nanosec, end_nanosec, ebur128_integrated_loudness_lufs)) {
|
2018-06-28 01:15:32 +02:00
|
|
|
return false;
|
2021-06-10 23:13:03 +02:00
|
|
|
}
|
2018-06-28 01:15:32 +02:00
|
|
|
|
2024-08-03 00:05:06 +02:00
|
|
|
return Play(pause, offset_nanosec);
|
2022-03-22 21:19:59 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
}
|
|
|
|
|
2023-04-22 19:13:42 +02:00
|
|
|
void EngineBase::UpdateVolume(const uint volume) {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2022-12-03 03:46:59 +01:00
|
|
|
volume_ = volume;
|
2024-08-25 01:06:30 +02:00
|
|
|
Q_EMIT VolumeChanged(volume);
|
2022-03-22 21:19:59 +01:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2023-04-22 19:13:42 +02:00
|
|
|
void EngineBase::SetVolume(const uint volume) {
|
2022-12-03 03:46:59 +01:00
|
|
|
|
|
|
|
volume_ = volume;
|
|
|
|
SetVolumeSW(volume);
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2023-04-22 19:13:42 +02:00
|
|
|
void EngineBase::ReloadSettings() {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2024-04-11 02:56:01 +02:00
|
|
|
Settings s;
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
s.beginGroup(BackendSettingsPage::kSettingsGroup);
|
2019-01-09 20:02:40 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
output_ = s.value("output").toString();
|
|
|
|
device_ = s.value("device");
|
2019-01-09 20:02:40 +01:00
|
|
|
|
2024-02-20 01:08:00 +01:00
|
|
|
exclusive_mode_ = s.value("exclusive_mode", false).toBool();
|
|
|
|
|
2019-03-09 16:48:45 +01:00
|
|
|
volume_control_ = s.value("volume_control", true).toBool();
|
|
|
|
|
2021-05-11 19:14:00 +02:00
|
|
|
channels_enabled_ = s.value("channels_enabled", false).toBool();
|
|
|
|
channels_ = s.value("channels", 0).toInt();
|
|
|
|
|
2020-10-07 20:29:26 +02:00
|
|
|
buffer_duration_nanosec_ = s.value("bufferduration", BackendSettingsPage::kDefaultBufferDuration).toLongLong() * kNsecPerMsec;
|
|
|
|
buffer_low_watermark_ = s.value("bufferlowwatermark", BackendSettingsPage::kDefaultBufferLowWatermark).toDouble();
|
|
|
|
buffer_high_watermark_ = s.value("bufferhighwatermark", BackendSettingsPage::kDefaultBufferHighWatermark).toDouble();
|
2019-01-09 20:02:40 +01:00
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
rg_enabled_ = s.value("rgenabled", false).toBool();
|
|
|
|
rg_mode_ = s.value("rgmode", 0).toInt();
|
2021-04-22 21:55:26 +02:00
|
|
|
rg_preamp_ = s.value("rgpreamp", 0.0).toDouble();
|
|
|
|
rg_fallbackgain_ = s.value("rgfallbackgain", 0.0).toDouble();
|
2018-06-28 01:15:32 +02:00
|
|
|
rg_compression_ = s.value("rgcompression", true).toBool();
|
|
|
|
|
2023-06-27 04:05:01 +02:00
|
|
|
ebur128_loudness_normalization_ = s.value("ebur128_loudness_normalization", false).toBool();
|
|
|
|
ebur128_target_level_lufs_ = s.value("ebur128_target_level_lufs", -23.0).toDouble();
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
fadeout_enabled_ = s.value("FadeoutEnabled", false).toBool();
|
|
|
|
crossfade_enabled_ = s.value("CrossfadeEnabled", false).toBool();
|
|
|
|
autocrossfade_enabled_ = s.value("AutoCrossfadeEnabled", false).toBool();
|
|
|
|
crossfade_same_album_ = !s.value("NoCrossfadeSameAlbum", true).toBool();
|
|
|
|
fadeout_pause_enabled_ = s.value("FadeoutPauseEnabled", false).toBool();
|
2018-06-28 01:15:32 +02:00
|
|
|
fadeout_duration_ = s.value("FadeoutDuration", 2000).toLongLong();
|
|
|
|
fadeout_duration_nanosec_ = (fadeout_duration_ * kNsecPerMsec);
|
|
|
|
fadeout_pause_duration_ = s.value("FadeoutPauseDuration", 250).toLongLong();
|
|
|
|
fadeout_pause_duration_nanosec_ = (fadeout_pause_duration_ * kNsecPerMsec);
|
2019-01-09 20:02:40 +01:00
|
|
|
|
2022-03-05 01:30:49 +01:00
|
|
|
bs2b_enabled_ = s.value("bs2b", false).toBool();
|
|
|
|
|
2022-08-24 20:34:10 +02:00
|
|
|
bool http2_enabled = s.value("http2", false).toBool();
|
|
|
|
if (http2_enabled != http2_enabled_) {
|
|
|
|
http2_enabled_ = http2_enabled;
|
2024-04-09 23:20:26 +02:00
|
|
|
Utilities::SetEnv("SOUP_FORCE_HTTP1", http2_enabled_ ? QLatin1String("") : QStringLiteral("1"));
|
2024-06-12 02:13:27 +02:00
|
|
|
qLog(Debug) << "SOUP_FORCE_HTTP1:" << (http2_enabled_ ? "OFF" : "ON");
|
2022-08-24 20:34:10 +02:00
|
|
|
}
|
|
|
|
|
2023-03-19 23:02:17 +01:00
|
|
|
strict_ssl_enabled_ = s.value("strict_ssl", false).toBool();
|
|
|
|
|
2018-06-28 01:15:32 +02:00
|
|
|
s.endGroup();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2020-11-04 22:16:20 +01:00
|
|
|
s.beginGroup(NetworkProxySettingsPage::kSettingsGroup);
|
2023-02-18 14:09:27 +01:00
|
|
|
const NetworkProxyFactory::Mode proxy_mode = static_cast<NetworkProxyFactory::Mode>(s.value("mode", static_cast<int>(NetworkProxyFactory::Mode::System)).toInt());
|
|
|
|
if (proxy_mode == NetworkProxyFactory::Mode::Manual && s.contains("engine") && s.value("engine").toBool()) {
|
2020-11-04 22:16:20 +01:00
|
|
|
QString proxy_host = s.value("hostname").toString();
|
|
|
|
int proxy_port = s.value("port").toInt();
|
|
|
|
if (proxy_host.isEmpty() || proxy_port <= 0) {
|
|
|
|
proxy_address_.clear();
|
|
|
|
proxy_authentication_ = false;
|
|
|
|
proxy_user_.clear();
|
|
|
|
proxy_pass_.clear();
|
|
|
|
}
|
|
|
|
else {
|
2024-04-09 23:20:26 +02:00
|
|
|
proxy_address_ = QStringLiteral("%1:%2").arg(proxy_host).arg(proxy_port);
|
2020-11-04 22:16:20 +01:00
|
|
|
proxy_authentication_ = s.value("use_authentication").toBool();
|
|
|
|
proxy_user_ = s.value("username").toString();
|
|
|
|
proxy_pass_ = s.value("password").toString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
proxy_address_.clear();
|
|
|
|
proxy_authentication_ = false;
|
|
|
|
proxy_user_.clear();
|
|
|
|
proxy_pass_.clear();
|
|
|
|
}
|
2021-05-11 19:14:00 +02:00
|
|
|
|
2020-11-04 22:16:20 +01:00
|
|
|
s.endGroup();
|
|
|
|
|
2022-06-04 15:51:35 +02:00
|
|
|
#ifdef HAVE_SPOTIFY
|
|
|
|
s.beginGroup(SpotifySettingsPage::kSettingsGroup);
|
|
|
|
spotify_username_ = s.value("username").toString();
|
|
|
|
QByteArray password = s.value("password").toByteArray();
|
|
|
|
if (password.isEmpty()) spotify_password_.clear();
|
|
|
|
else spotify_password_ = QString::fromUtf8(QByteArray::fromBase64(password));
|
|
|
|
s.endGroup();
|
|
|
|
#endif
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2023-04-22 19:13:42 +02:00
|
|
|
void EngineBase::EmitAboutToFinish() {
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2021-08-23 21:21:08 +02:00
|
|
|
if (about_to_end_emitted_) {
|
2018-02-27 18:06:05 +01:00
|
|
|
return;
|
2021-08-23 21:21:08 +02:00
|
|
|
}
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
about_to_end_emitted_ = true;
|
2023-04-21 15:06:44 +02:00
|
|
|
|
2024-08-25 01:06:30 +02:00
|
|
|
Q_EMIT TrackAboutToEnd();
|
2023-04-21 15:06:44 +02:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
2018-07-01 01:29:52 +02:00
|
|
|
|
2023-04-22 19:13:42 +02:00
|
|
|
bool EngineBase::ValidOutput(const QString &output) {
|
2018-07-01 01:29:52 +02:00
|
|
|
|
2019-09-15 20:27:32 +02:00
|
|
|
Q_UNUSED(output);
|
|
|
|
|
2018-07-01 01:29:52 +02:00
|
|
|
return (true);
|
|
|
|
|
|
|
|
}
|