Browse Source

UI: Add Push-to-talk/mute settings to audio settings

Palana 10 years ago
parent
commit
c23c071ba2

+ 5 - 0
obs/data/locale/en-US.ini

@@ -333,6 +333,10 @@ Basic.Settings.Audio.DesktopDevice2="Desktop Audio Device 2"
 Basic.Settings.Audio.AuxDevice="Mic/Auxiliary Audio Device"
 Basic.Settings.Audio.AuxDevice2="Mic/Auxiliary Audio Device 2"
 Basic.Settings.Audio.AuxDevice3="Mic/Auxiliary Audio Device 3"
+Basic.Settings.Audio.EnablePushToMute="Enable Push-to-mute"
+Basic.Settings.Audio.PushToMuteDelay="Push-to-mute delay"
+Basic.Settings.Audio.EnablePushToTalk="Enable Push-to-talk"
+Basic.Settings.Audio.PushToTalkDelay="Push-to-talk delay"
 
 # basic mode 'advanced' settings
 Basic.Settings.Advanced="Advanced"
@@ -397,6 +401,7 @@ Hotkeys.MouseButton="Mouse %1"
 # audio hotkeys
 Mute="Mute"
 Unmute="Unmute"
+Push-to-mute="Push-to-mute"
 Push-to-talk="Push-to-talk"
 
 # scene item hotkeys

+ 10 - 1
obs/forms/OBSBasicSettings.ui

@@ -2014,7 +2014,16 @@
            </property>
           </widget>
          </item>
-         <item row="7" column="1">
+         <item row="7" colspan="2">
+          <widget class="QScrollArea" name="audioSourceScrollArea">
+           <property name="widgetResizable">
+            <bool>true</bool>
+           </property>
+           <widget class="QWidget" name="audioSourceWidget">
+           </widget>
+          </widget>
+         </item>
+         <item row="8" column="1">
           <widget class="QLabel" name="audioMsg">
            <property name="styleSheet">
             <string notr="true">color: rgb(255, 0, 4);</string>

+ 169 - 0
obs/window-basic-settings.cpp

@@ -317,6 +317,23 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
 	LoadColorRanges();
 	LoadFormats();
 
+	auto ReloadAudioSources = [](void *data, calldata_t *param)
+	{
+		auto settings = static_cast<OBSBasicSettings*>(data);
+		auto source   = static_cast<obs_source_t*>(calldata_ptr(param,
+					"source"));
+
+		if (!(obs_source_get_output_flags(source) & OBS_SOURCE_AUDIO))
+			return;
+
+		QMetaObject::invokeMethod(settings, "ReloadAudioSources",
+				Qt::QueuedConnection);
+	};
+	sourceCreated.Connect(obs_get_signal_handler(), "source_create",
+			ReloadAudioSources, this);
+	channelChanged.Connect(obs_get_signal_handler(), "channel_change",
+			ReloadAudioSources, this);
+
 	auto ReloadHotkeys = [](void *data, calldata_t*)
 	{
 		auto settings = static_cast<OBSBasicSettings*>(data);
@@ -1245,6 +1262,135 @@ void OBSBasicSettings::LoadAudioDevices()
 	}
 }
 
+void OBSBasicSettings::LoadAudioSources()
+{
+	auto layout = new QFormLayout();
+	layout->setVerticalSpacing(15);
+	layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
+
+	ui->audioSourceScrollArea->takeWidget()->deleteLater();
+	audioSourceSignals.clear();
+	audioSources.clear();
+
+	auto widget = new QWidget();
+	widget->setLayout(layout);
+	ui->audioSourceScrollArea->setWidget(widget);
+
+	const char *enablePtm = Str("Basic.Settings.Audio.EnablePushToMute");
+	const char *ptmDelay  = Str("Basic.Settings.Audio.PushToMuteDelay");
+	const char *enablePtt = Str("Basic.Settings.Audio.EnablePushToTalk");
+	const char *pttDelay  = Str("Basic.Settings.Audio.PushToTalkDelay");
+	auto AddSource = [&](obs_source_t *source)
+	{
+		if (!(obs_source_get_output_flags(source) & OBS_SOURCE_AUDIO))
+			return true;
+
+		auto form = new QFormLayout();
+		form->setVerticalSpacing(0);
+		form->setHorizontalSpacing(5);
+		form->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
+
+		auto ptmCB = new SilentUpdateCheckBox();
+		ptmCB->setText(enablePtm);
+		ptmCB->setChecked(obs_source_push_to_mute_enabled(source));
+		form->addRow(ptmCB);
+
+		auto ptmSB = new SilentUpdateSpinBox();
+		ptmSB->setSuffix(" ms");
+		ptmSB->setRange(0, INT_MAX);
+		ptmSB->setValue(obs_source_get_push_to_mute_delay(source));
+		form->addRow(ptmDelay, ptmSB);
+
+		auto pttCB = new SilentUpdateCheckBox();
+		pttCB->setText(enablePtt);
+		pttCB->setChecked(obs_source_push_to_talk_enabled(source));
+		form->addRow(pttCB);
+
+		auto pttSB = new SilentUpdateSpinBox();
+		pttSB->setSuffix(" ms");
+		pttSB->setRange(0, INT_MAX);
+		pttSB->setValue(obs_source_get_push_to_talk_delay(source));
+		form->addRow(pttDelay, pttSB);
+
+		HookWidget(ptmCB, CHECK_CHANGED,  AUDIO_CHANGED);
+		HookWidget(ptmSB, SCROLL_CHANGED, AUDIO_CHANGED);
+		HookWidget(pttCB, CHECK_CHANGED,  AUDIO_CHANGED);
+		HookWidget(pttSB, SCROLL_CHANGED, AUDIO_CHANGED);
+
+		audioSourceSignals.reserve(audioSourceSignals.size() + 4);
+
+		auto handler = obs_source_get_signal_handler(source);
+		audioSourceSignals.emplace_back(handler, "push_to_mute_changed",
+				[](void *data, calldata_t *param)
+		{
+			QMetaObject::invokeMethod(static_cast<QObject*>(data),
+				"setCheckedSilently",
+				Q_ARG(bool, calldata_bool(param, "enabled")));
+		}, ptmCB);
+		audioSourceSignals.emplace_back(handler, "push_to_mute_delay",
+				[](void *data, calldata_t *param)
+		{
+			QMetaObject::invokeMethod(static_cast<QObject*>(data),
+				"setValueSilently",
+				Q_ARG(int, calldata_int(param, "delay")));
+		}, ptmSB);
+		audioSourceSignals.emplace_back(handler, "push_to_talk_changed",
+				[](void *data, calldata_t *param)
+		{
+			QMetaObject::invokeMethod(static_cast<QObject*>(data),
+				"setCheckedSilently",
+				Q_ARG(bool, calldata_bool(param, "enabled")));
+		}, pttCB);
+		audioSourceSignals.emplace_back(handler, "push_to_talk_delay",
+				[](void *data, calldata_t *param)
+		{
+			QMetaObject::invokeMethod(static_cast<QObject*>(data),
+				"setValueSilently",
+				Q_ARG(int, calldata_int(param, "delay")));
+		}, pttSB);
+
+		audioSources.emplace_back(OBSGetWeakRef(source),
+				ptmCB, pttSB, pttCB, pttSB);
+
+		auto label = new OBSSourceLabel(source);
+		connect(label, &OBSSourceLabel::Removed,
+				[=]()
+				{
+					LoadAudioSources();
+				});
+		connect(label, &OBSSourceLabel::Destroyed,
+				[=]()
+				{
+					LoadAudioSources();
+				});
+
+		layout->addRow(label, form);
+		return true;
+	};
+
+	for (int i = 0; i < MAX_CHANNELS; i++) {
+		obs_source_t *source = obs_get_output_source(i);
+		if (!source) continue;
+
+		AddSource(source);
+		obs_source_release(source);
+	}
+
+	using AddSource_t = decltype(AddSource);
+	obs_enum_sources([](void *data, obs_source_t *source)
+	{
+		auto &AddSource = *static_cast<AddSource_t*>(data);
+		AddSource(source);
+		return true;
+	}, static_cast<void*>(&AddSource));
+
+
+	if (layout->rowCount() == 0)
+		ui->audioSourceScrollArea->hide();
+	else
+		ui->audioSourceScrollArea->show();
+}
+
 void OBSBasicSettings::LoadAudioSettings()
 {
 	uint32_t sampleRate = config_get_uint(main->Config(), "Audio",
@@ -1272,6 +1418,7 @@ void OBSBasicSettings::LoadAudioSettings()
 		ui->channelSetup->setCurrentIndex(1);
 
 	LoadAudioDevices();
+	LoadAudioSources();
 
 	loading = false;
 }
@@ -1866,6 +2013,23 @@ void OBSBasicSettings::SaveAudioSettings()
 	SaveComboData(ui->auxAudioDevice2, "Audio", "AuxDevice2");
 	SaveComboData(ui->auxAudioDevice3, "Audio", "AuxDevice3");
 
+	for (auto &audioSource : audioSources) {
+		auto source  = OBSGetStrongRef(get<0>(audioSource));
+		if (!source)
+			continue;
+
+		auto &ptmCB  = get<1>(audioSource);
+		auto &ptmSB  = get<2>(audioSource);
+		auto &pttCB  = get<3>(audioSource);
+		auto &pttSB  = get<4>(audioSource);
+
+		obs_source_enable_push_to_mute(source, ptmCB->isChecked());
+		obs_source_set_push_to_mute_delay(source, ptmSB->value());
+
+		obs_source_enable_push_to_talk(source, pttCB->isChecked());
+		obs_source_set_push_to_talk_delay(source, pttSB->value());
+	}
+
 	main->ResetAudioDevices();
 }
 
@@ -2236,6 +2400,11 @@ void OBSBasicSettings::AudioChangedRestart()
 	}
 }
 
+void OBSBasicSettings::ReloadAudioSources()
+{
+	LoadAudioSources();
+}
+
 void OBSBasicSettings::VideoChangedRestart()
 {
 	if (!loading) {

+ 35 - 0
obs/window-basic-settings.hpp

@@ -35,6 +35,30 @@ class OBSHotkeyWidget;
 
 #include "ui_OBSBasicSettings.h"
 
+class SilentUpdateCheckBox : public QCheckBox {
+	Q_OBJECT
+
+public slots:
+	void setCheckedSilently(bool checked)
+	{
+		bool blocked = blockSignals(true);
+		setChecked(checked);
+		blockSignals(blocked);
+	}
+};
+
+class SilentUpdateSpinBox : public QSpinBox {
+	Q_OBJECT
+
+public slots:
+	void setValueSilently(int val)
+	{
+		bool blocked = blockSignals(true);
+		setValue(val);
+		blockSignals(blocked);
+	}
+};
+
 class OBSFFDeleter
 {
 public:
@@ -77,6 +101,15 @@ private:
 	OBSPropertiesView *streamEncoderProps = nullptr;
 	OBSPropertiesView *recordEncoderProps = nullptr;
 
+	using AudioSource_t =
+		std::tuple<OBSWeakSource,
+			QPointer<QCheckBox>, QPointer<QSpinBox>,
+			QPointer<QCheckBox>, QPointer<QSpinBox>>;
+	std::vector<AudioSource_t> audioSources;
+	std::vector<OBSSignal> audioSourceSignals;
+	OBSSignal sourceCreated;
+	OBSSignal channelChanged;
+
 	std::vector<std::pair<bool, QPointer<OBSHotkeyWidget>>> hotkeys;
 	OBSSignal hotkeyRegistered;
 	OBSSignal hotkeyUnregistered;
@@ -161,6 +194,7 @@ private:
 	void LoadListValues(QComboBox *widget, obs_property_t *prop,
 		const char *configName);
 	void LoadAudioDevices();
+	void LoadAudioSources();
 
 	/* video */
 	void LoadRendererList();
@@ -205,6 +239,7 @@ private slots:
 	void GeneralChanged();
 	void AudioChanged();
 	void AudioChangedRestart();
+	void ReloadAudioSources();
 	void OutputsChanged();
 	void Stream1Changed();
 	void VideoChanged();