Add exclusive mode option for WASAPI
This commit is contained in:
parent
306b3f72d8
commit
f84ce3f1d1
|
@ -39,6 +39,7 @@
|
||||||
|
|
||||||
EngineBase::EngineBase(QObject *parent)
|
EngineBase::EngineBase(QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
|
exclusive_mode_(false),
|
||||||
volume_control_(true),
|
volume_control_(true),
|
||||||
volume_(100),
|
volume_(100),
|
||||||
beginning_nanosec_(0),
|
beginning_nanosec_(0),
|
||||||
|
@ -167,6 +168,8 @@ void EngineBase::ReloadSettings() {
|
||||||
output_ = s.value("output").toString();
|
output_ = s.value("output").toString();
|
||||||
device_ = s.value("device");
|
device_ = s.value("device");
|
||||||
|
|
||||||
|
exclusive_mode_ = s.value("exclusive_mode", false).toBool();
|
||||||
|
|
||||||
volume_control_ = s.value("volume_control", true).toBool();
|
volume_control_ = s.value("volume_control", true).toBool();
|
||||||
|
|
||||||
channels_enabled_ = s.value("channels_enabled", false).toBool();
|
channels_enabled_ = s.value("channels_enabled", false).toBool();
|
||||||
|
|
|
@ -129,6 +129,7 @@ class EngineBase : public QObject {
|
||||||
virtual QString DefaultOutput() = 0;
|
virtual QString DefaultOutput() = 0;
|
||||||
virtual bool CustomDeviceSupport(const QString &output) = 0;
|
virtual bool CustomDeviceSupport(const QString &output) = 0;
|
||||||
virtual bool ALSADeviceSupport(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).
|
// 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.
|
// 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);
|
void VolumeChanged(const uint volume);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool exclusive_mode_;
|
||||||
bool volume_control_;
|
bool volume_control_;
|
||||||
uint volume_;
|
uint volume_;
|
||||||
quint64 beginning_nanosec_;
|
quint64 beginning_nanosec_;
|
||||||
|
|
|
@ -73,6 +73,7 @@ const char *GstEngine::kAVDTPSink = "avdtpsink";
|
||||||
const char *GstEngine::InterAudiosink = "interaudiosink";
|
const char *GstEngine::InterAudiosink = "interaudiosink";
|
||||||
const char *GstEngine::kDirectSoundSink = "directsoundsink";
|
const char *GstEngine::kDirectSoundSink = "directsoundsink";
|
||||||
const char *GstEngine::kOSXAudioSink = "osxaudiosink";
|
const char *GstEngine::kOSXAudioSink = "osxaudiosink";
|
||||||
|
const char *GstEngine::kWASAPISink = "wasapisink";
|
||||||
const int GstEngine::kDiscoveryTimeoutS = 10;
|
const int GstEngine::kDiscoveryTimeoutS = 10;
|
||||||
const qint64 GstEngine::kTimerIntervalNanosec = 1000 * kNsecPerMsec; // 1s
|
const qint64 GstEngine::kTimerIntervalNanosec = 1000 * kNsecPerMsec; // 1s
|
||||||
const qint64 GstEngine::kPreloadGapNanosec = 8000 * kNsecPerMsec; // 8s
|
const qint64 GstEngine::kPreloadGapNanosec = 8000 * kNsecPerMsec; // 8s
|
||||||
|
@ -459,6 +460,10 @@ bool GstEngine::ALSADeviceSupport(const QString &output) {
|
||||||
return (output == kALSASink);
|
return (output == kALSASink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GstEngine::ExclusiveModeSupport(const QString &output) {
|
||||||
|
return output == kWASAPISink;
|
||||||
|
}
|
||||||
|
|
||||||
void GstEngine::ReloadSettings() {
|
void GstEngine::ReloadSettings() {
|
||||||
|
|
||||||
EngineBase::ReloadSettings();
|
EngineBase::ReloadSettings();
|
||||||
|
@ -794,6 +799,7 @@ SharedPtr<GstEnginePipeline> GstEngine::CreatePipeline() {
|
||||||
|
|
||||||
SharedPtr<GstEnginePipeline> ret = make_shared<GstEnginePipeline>();
|
SharedPtr<GstEnginePipeline> ret = make_shared<GstEnginePipeline>();
|
||||||
ret->set_output_device(output_, device_);
|
ret->set_output_device(output_, device_);
|
||||||
|
ret->set_exclusive_mode(exclusive_mode_);
|
||||||
ret->set_volume_enabled(volume_control_);
|
ret->set_volume_enabled(volume_control_);
|
||||||
ret->set_stereo_balancer_enabled(stereo_balancer_enabled_);
|
ret->set_stereo_balancer_enabled(stereo_balancer_enabled_);
|
||||||
ret->set_equalizer_enabled(equalizer_enabled_);
|
ret->set_equalizer_enabled(equalizer_enabled_);
|
||||||
|
|
|
@ -81,6 +81,7 @@ class GstEngine : public EngineBase, public GstBufferConsumer {
|
||||||
QString DefaultOutput() override { return kAutoSink; }
|
QString DefaultOutput() override { return kAutoSink; }
|
||||||
bool CustomDeviceSupport(const QString &output) override;
|
bool CustomDeviceSupport(const QString &output) override;
|
||||||
bool ALSADeviceSupport(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 SetStartup(GstStartup *gst_startup) { gst_startup_ = gst_startup; }
|
||||||
void EnsureInitialized() { gst_startup_->EnsureInitialized(); }
|
void EnsureInitialized() { gst_startup_->EnsureInitialized(); }
|
||||||
|
@ -152,6 +153,7 @@ class GstEngine : public EngineBase, public GstBufferConsumer {
|
||||||
static const char *InterAudiosink;
|
static const char *InterAudiosink;
|
||||||
static const char *kDirectSoundSink;
|
static const char *kDirectSoundSink;
|
||||||
static const char *kOSXAudioSink;
|
static const char *kOSXAudioSink;
|
||||||
|
static const char *kWASAPISink;
|
||||||
static const int kDiscoveryTimeoutS;
|
static const int kDiscoveryTimeoutS;
|
||||||
static const qint64 kTimerIntervalNanosec;
|
static const qint64 kTimerIntervalNanosec;
|
||||||
static const qint64 kPreloadGapNanosec;
|
static const qint64 kPreloadGapNanosec;
|
||||||
|
|
|
@ -74,6 +74,7 @@ GstEnginePipeline::GstEnginePipeline(QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
id_(sId++),
|
id_(sId++),
|
||||||
valid_(false),
|
valid_(false),
|
||||||
|
exclusive_mode_(false),
|
||||||
volume_enabled_(true),
|
volume_enabled_(true),
|
||||||
stereo_balancer_enabled_(false),
|
stereo_balancer_enabled_(false),
|
||||||
eq_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) {
|
void GstEnginePipeline::set_volume_enabled(const bool enabled) {
|
||||||
volume_enabled_ = 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
|
#ifndef Q_OS_WIN32
|
||||||
if (g_object_class_find_property(G_OBJECT_GET_CLASS(audiosink_), "volume")) {
|
if (g_object_class_find_property(G_OBJECT_GET_CLASS(audiosink_), "volume")) {
|
||||||
qLog(Debug) << output_ << "has volume, enabling volume synchronization.";
|
qLog(Debug) << output_ << "has volume, enabling volume synchronization.";
|
||||||
|
|
|
@ -62,6 +62,7 @@ class GstEnginePipeline : public QObject {
|
||||||
|
|
||||||
// Call these setters before Init
|
// Call these setters before Init
|
||||||
void set_output_device(const QString &output, const QVariant &device);
|
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_volume_enabled(const bool enabled);
|
||||||
void set_stereo_balancer_enabled(const bool enabled);
|
void set_stereo_balancer_enabled(const bool enabled);
|
||||||
void set_equalizer_enabled(const bool enabled);
|
void set_equalizer_enabled(const bool enabled);
|
||||||
|
@ -202,6 +203,7 @@ class GstEnginePipeline : public QObject {
|
||||||
bool valid_;
|
bool valid_;
|
||||||
QString output_;
|
QString output_;
|
||||||
QVariant device_;
|
QVariant device_;
|
||||||
|
bool exclusive_mode_;
|
||||||
bool volume_enabled_;
|
bool volume_enabled_;
|
||||||
bool stereo_balancer_enabled_;
|
bool stereo_balancer_enabled_;
|
||||||
bool eq_enabled_;
|
bool eq_enabled_;
|
||||||
|
|
|
@ -264,6 +264,11 @@ bool VLCEngine::ALSADeviceSupport(const QString &output) {
|
||||||
return (output == "alsa");
|
return (output == "alsa");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VLCEngine::ExclusiveModeSupport(const QString &output) {
|
||||||
|
Q_UNUSED(output);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
uint VLCEngine::position() const {
|
uint VLCEngine::position() const {
|
||||||
|
|
||||||
if (!Initialized() || !libvlc_media_player_is_playing(player_)) return 0;
|
if (!Initialized() || !libvlc_media_player_is_playing(player_)) return 0;
|
||||||
|
|
|
@ -70,6 +70,7 @@ class VLCEngine : public EngineBase {
|
||||||
QString DefaultOutput() override { return ""; }
|
QString DefaultOutput() override { return ""; }
|
||||||
bool CustomDeviceSupport(const QString &output) override;
|
bool CustomDeviceSupport(const QString &output) override;
|
||||||
bool ALSADeviceSupport(const QString &output) override;
|
bool ALSADeviceSupport(const QString &output) override;
|
||||||
|
bool ExclusiveModeSupport(const QString &output) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
libvlc_instance_t *instance_;
|
libvlc_instance_t *instance_;
|
||||||
|
|
|
@ -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_->checkbox_channels, &QCheckBox::toggled, ui_->widget_channels, &QSpinBox::setEnabled);
|
||||||
QObject::connect(ui_->button_buffer_defaults, &QPushButton::clicked, this, &BackendSettingsPage::BufferDefaults);
|
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() {
|
BackendSettingsPage::~BackendSettingsPage() {
|
||||||
|
@ -149,6 +155,10 @@ void BackendSettingsPage::Load() {
|
||||||
ui_->widget_alsa_plugin->hide();
|
ui_->widget_alsa_plugin->hide();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
ui_->checkbox_exclusive_mode->setChecked(s.value("exclusive_mode", false).toBool());
|
||||||
|
#endif
|
||||||
|
|
||||||
if (EngineInitialized()) Load_Engine(enginetype);
|
if (EngineInitialized()) Load_Engine(enginetype);
|
||||||
|
|
||||||
ui_->checkbox_volume_control->setChecked(s.value("volume_control", true).toBool());
|
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);
|
if (ui_->combobox_output->count() >= 1) Load_Device(output, device);
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
ui_->widget_exclusive_mode->setEnabled(engine()->ExclusiveModeSupport(output));
|
||||||
|
#endif
|
||||||
|
|
||||||
FadingOptionsChanged();
|
FadingOptionsChanged();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -481,6 +495,10 @@ void BackendSettingsPage::Save() {
|
||||||
else s.remove("alsaplugin");
|
else s.remove("alsaplugin");
|
||||||
#endif
|
#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("volume_control", ui_->checkbox_volume_control->isChecked());
|
||||||
|
|
||||||
s.setValue("channels_enabled", ui_->checkbox_channels->isChecked());
|
s.setValue("channels_enabled", ui_->checkbox_channels->isChecked());
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>717</width>
|
<width>717</width>
|
||||||
<height>1245</height>
|
<height>1259</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -153,6 +153,47 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget_exclusive_mode" native="true">
|
||||||
|
<layout class="QHBoxLayout" name="layout_exclusive_mode">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkbox_exclusive_mode">
|
||||||
|
<property name="text">
|
||||||
|
<string>Exclusive mode (Experimental)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="spacer_exclusive_mode">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
Loading…
Reference in New Issue