diff --git a/src/engine/enginebase.cpp b/src/engine/enginebase.cpp index d40b8fed..fdd93017 100644 --- a/src/engine/enginebase.cpp +++ b/src/engine/enginebase.cpp @@ -39,6 +39,7 @@ EngineBase::EngineBase(QObject *parent) : QObject(parent), + exclusive_mode_(false), volume_control_(true), volume_(100), beginning_nanosec_(0), @@ -167,6 +168,8 @@ void EngineBase::ReloadSettings() { output_ = s.value("output").toString(); device_ = s.value("device"); + exclusive_mode_ = s.value("exclusive_mode", false).toBool(); + volume_control_ = s.value("volume_control", true).toBool(); channels_enabled_ = s.value("channels_enabled", false).toBool(); diff --git a/src/engine/enginebase.h b/src/engine/enginebase.h index 00afc663..bf7a5de5 100644 --- a/src/engine/enginebase.h +++ b/src/engine/enginebase.h @@ -129,6 +129,7 @@ class EngineBase : public QObject { virtual QString DefaultOutput() = 0; virtual bool CustomDeviceSupport(const QString &output) = 0; virtual bool ALSADeviceSupport(const QString &output) = 0; + virtual bool ExclusiveModeSupport(const QString &output) = 0; // Plays a media stream represented with the URL 'u' from the given 'beginning' to the given 'end' (usually from 0 to a song's length). // Both markers should be passed in nanoseconds. 'end' can be negative, indicating that the real length of 'u' stream is unknown. @@ -188,6 +189,7 @@ class EngineBase : public QObject { void VolumeChanged(const uint volume); protected: + bool exclusive_mode_; bool volume_control_; uint volume_; quint64 beginning_nanosec_; diff --git a/src/engine/gstengine.cpp b/src/engine/gstengine.cpp index 95cf34cf..980187cd 100644 --- a/src/engine/gstengine.cpp +++ b/src/engine/gstengine.cpp @@ -73,6 +73,7 @@ const char *GstEngine::kAVDTPSink = "avdtpsink"; const char *GstEngine::InterAudiosink = "interaudiosink"; const char *GstEngine::kDirectSoundSink = "directsoundsink"; const char *GstEngine::kOSXAudioSink = "osxaudiosink"; +const char *GstEngine::kWASAPISink = "wasapisink"; const int GstEngine::kDiscoveryTimeoutS = 10; const qint64 GstEngine::kTimerIntervalNanosec = 1000 * kNsecPerMsec; // 1s const qint64 GstEngine::kPreloadGapNanosec = 8000 * kNsecPerMsec; // 8s @@ -459,6 +460,10 @@ bool GstEngine::ALSADeviceSupport(const QString &output) { return (output == kALSASink); } +bool GstEngine::ExclusiveModeSupport(const QString &output) { + return output == kWASAPISink; +} + void GstEngine::ReloadSettings() { EngineBase::ReloadSettings(); @@ -794,6 +799,7 @@ SharedPtr GstEngine::CreatePipeline() { SharedPtr ret = make_shared(); ret->set_output_device(output_, device_); + ret->set_exclusive_mode(exclusive_mode_); ret->set_volume_enabled(volume_control_); ret->set_stereo_balancer_enabled(stereo_balancer_enabled_); ret->set_equalizer_enabled(equalizer_enabled_); diff --git a/src/engine/gstengine.h b/src/engine/gstengine.h index 8ceecaa9..be7828f7 100644 --- a/src/engine/gstengine.h +++ b/src/engine/gstengine.h @@ -81,6 +81,7 @@ class GstEngine : public EngineBase, public GstBufferConsumer { QString DefaultOutput() override { return kAutoSink; } bool CustomDeviceSupport(const QString &output) override; bool ALSADeviceSupport(const QString &output) override; + bool ExclusiveModeSupport(const QString &output) override; void SetStartup(GstStartup *gst_startup) { gst_startup_ = gst_startup; } void EnsureInitialized() { gst_startup_->EnsureInitialized(); } @@ -152,6 +153,7 @@ class GstEngine : public EngineBase, public GstBufferConsumer { static const char *InterAudiosink; static const char *kDirectSoundSink; static const char *kOSXAudioSink; + static const char *kWASAPISink; static const int kDiscoveryTimeoutS; static const qint64 kTimerIntervalNanosec; static const qint64 kPreloadGapNanosec; diff --git a/src/engine/gstenginepipeline.cpp b/src/engine/gstenginepipeline.cpp index 8194947c..dd2f89e6 100644 --- a/src/engine/gstenginepipeline.cpp +++ b/src/engine/gstenginepipeline.cpp @@ -74,6 +74,7 @@ GstEnginePipeline::GstEnginePipeline(QObject *parent) : QObject(parent), id_(sId++), valid_(false), + exclusive_mode_(false), volume_enabled_(true), stereo_balancer_enabled_(false), eq_enabled_(false), @@ -221,6 +222,10 @@ void GstEnginePipeline::set_output_device(const QString &output, const QVariant } +void GstEnginePipeline::set_exclusive_mode(const bool exclusive_mode) { + exclusive_mode_ = exclusive_mode; +} + void GstEnginePipeline::set_volume_enabled(const bool enabled) { volume_enabled_ = enabled; } @@ -520,6 +525,13 @@ bool GstEnginePipeline::InitAudioBin(QString &error) { } + if (g_object_class_find_property(G_OBJECT_GET_CLASS(audiosink_), "exclusive")) { + if (exclusive_mode_) { + qLog(Debug) << "Setting exclusive mode for" << output_; + } + g_object_set(G_OBJECT(audiosink_), "exclusive", exclusive_mode_, nullptr); + } + #ifndef Q_OS_WIN32 if (g_object_class_find_property(G_OBJECT_GET_CLASS(audiosink_), "volume")) { qLog(Debug) << output_ << "has volume, enabling volume synchronization."; diff --git a/src/engine/gstenginepipeline.h b/src/engine/gstenginepipeline.h index 7119855c..8db5deac 100644 --- a/src/engine/gstenginepipeline.h +++ b/src/engine/gstenginepipeline.h @@ -62,6 +62,7 @@ class GstEnginePipeline : public QObject { // Call these setters before Init void set_output_device(const QString &output, const QVariant &device); + void set_exclusive_mode(const bool exclusive_mode); void set_volume_enabled(const bool enabled); void set_stereo_balancer_enabled(const bool enabled); void set_equalizer_enabled(const bool enabled); @@ -202,6 +203,7 @@ class GstEnginePipeline : public QObject { bool valid_; QString output_; QVariant device_; + bool exclusive_mode_; bool volume_enabled_; bool stereo_balancer_enabled_; bool eq_enabled_; diff --git a/src/engine/vlcengine.cpp b/src/engine/vlcengine.cpp index 5741733a..a1bc449e 100644 --- a/src/engine/vlcengine.cpp +++ b/src/engine/vlcengine.cpp @@ -264,6 +264,11 @@ bool VLCEngine::ALSADeviceSupport(const QString &output) { return (output == "alsa"); } +bool VLCEngine::ExclusiveModeSupport(const QString &output) { + Q_UNUSED(output); + return false; +} + uint VLCEngine::position() const { if (!Initialized() || !libvlc_media_player_is_playing(player_)) return 0; diff --git a/src/engine/vlcengine.h b/src/engine/vlcengine.h index c62ba831..c7982ba7 100644 --- a/src/engine/vlcengine.h +++ b/src/engine/vlcengine.h @@ -70,6 +70,7 @@ class VLCEngine : public EngineBase { QString DefaultOutput() override { return ""; } bool CustomDeviceSupport(const QString &output) override; bool ALSADeviceSupport(const QString &output) override; + bool ExclusiveModeSupport(const QString &output) override; private: libvlc_instance_t *instance_; diff --git a/src/settings/backendsettingspage.cpp b/src/settings/backendsettingspage.cpp index b59a8105..29103bb9 100644 --- a/src/settings/backendsettingspage.cpp +++ b/src/settings/backendsettingspage.cpp @@ -96,6 +96,12 @@ BackendSettingsPage::BackendSettingsPage(SettingsDialog *dialog, QWidget *parent QObject::connect(ui_->checkbox_channels, &QCheckBox::toggled, ui_->widget_channels, &QSpinBox::setEnabled); QObject::connect(ui_->button_buffer_defaults, &QPushButton::clicked, this, &BackendSettingsPage::BufferDefaults); +#ifdef Q_OS_WIN32 + ui_->widget_exclusive_mode->show(); +#else + ui_->widget_exclusive_mode->hide(); +#endif + } BackendSettingsPage::~BackendSettingsPage() { @@ -149,6 +155,10 @@ void BackendSettingsPage::Load() { ui_->widget_alsa_plugin->hide(); #endif +#ifdef Q_OS_WIN32 + ui_->checkbox_exclusive_mode->setChecked(s.value("exclusive_mode", false).toBool()); +#endif + if (EngineInitialized()) Load_Engine(enginetype); ui_->checkbox_volume_control->setChecked(s.value("volume_control", true).toBool()); @@ -333,6 +343,10 @@ void BackendSettingsPage::Load_Output(QString output, QVariant device) { if (ui_->combobox_output->count() >= 1) Load_Device(output, device); +#ifdef Q_OS_WIN32 + ui_->widget_exclusive_mode->setEnabled(engine()->ExclusiveModeSupport(output)); +#endif + FadingOptionsChanged(); } @@ -481,6 +495,10 @@ void BackendSettingsPage::Save() { else s.remove("alsaplugin"); #endif +#ifdef Q_OS_WIN32 + s.setValue("exclusive_mode", ui_->checkbox_exclusive_mode->isChecked()); +#endif + s.setValue("volume_control", ui_->checkbox_volume_control->isChecked()); s.setValue("channels_enabled", ui_->checkbox_channels->isChecked()); diff --git a/src/settings/backendsettingspage.ui b/src/settings/backendsettingspage.ui index a9399bfa..041435b4 100644 --- a/src/settings/backendsettingspage.ui +++ b/src/settings/backendsettingspage.ui @@ -7,7 +7,7 @@ 0 0 717 - 1245 + 1259 @@ -153,6 +153,47 @@ + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Exclusive mode (Experimental) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + +