From 0ce9c515aff9f14e8054cf7e76e9c24039cecd76 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Mon, 5 Dec 2022 17:21:40 +0100 Subject: [PATCH] Add option to check / set audio monitoring of sources --- data/locale/en-US.ini | 10 ++++-- data/locale/es-ES.ini | 4 +-- data/locale/ru-RU.ini | 2 +- data/locale/tr-TR.ini | 2 +- data/locale/zh-CN.ini | 4 +-- src/macro-core/macro-action-audio.cpp | 26 +++++++++++++++ src/macro-core/macro-action-audio.hpp | 4 +++ src/macro-core/macro-condition-audio.cpp | 40 +++++++++++++++++++++++- src/macro-core/macro-condition-audio.hpp | 5 +++ src/utils/utility.cpp | 8 +++++ src/utils/utility.hpp | 1 + 11 files changed, 97 insertions(+), 9 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 55912402..4be139f2 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -114,7 +114,8 @@ AdvSceneSwitcher.condition.audio.state.unmute="unmuted" AdvSceneSwitcher.condition.audio.type.output="Output volume" AdvSceneSwitcher.condition.audio.type.volume="Configured volume level" AdvSceneSwitcher.condition.audio.type.syncOffset="Sync offset" -AdvSceneSwitcher.condition.audio.entry="{{checkType}} of {{audioSources}} is {{condition}}{{volume}}{{syncOffset}}" +AdvSceneSwitcher.condition.audio.type.monitor="Audio monitoring" +AdvSceneSwitcher.condition.audio.entry="{{checkType}} of {{audioSources}} is {{condition}}{{volume}}{{syncOffset}}{{monitorTypes}}" AdvSceneSwitcher.condition.cursor="Cursor" AdvSceneSwitcher.condition.cursor.type.region="is in region" AdvSceneSwitcher.condition.cursor.type.moving="is moving" @@ -386,13 +387,14 @@ AdvSceneSwitcher.action.audio.type.unmute="Unmute" AdvSceneSwitcher.action.audio.type.sourceVolume="Set source volume" AdvSceneSwitcher.action.audio.type.masterVolume="Set master volume" AdvSceneSwitcher.action.audio.type.syncOffset="Set sync offset" +AdvSceneSwitcher.action.audio.type.monitor="Set audio monitoring" AdvSceneSwitcher.action.audio.fade.type.duration="over a duration of" AdvSceneSwitcher.action.audio.fade.type.rate="at a rate of" AdvSceneSwitcher.action.audio.fade.duration="{{fade}}Fade {{fadeTypes}} {{duration}} seconds." AdvSceneSwitcher.action.audio.fade.rate="{{fade}}Fade {{fadeTypes}} {{rate}}per second." AdvSceneSwitcher.action.audio.fade.wait="Wait for fade to complete." AdvSceneSwitcher.action.audio.fade.abort="Abort already active fade." -AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}" +AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}" AdvSceneSwitcher.action.recording="Recording" AdvSceneSwitcher.action.recording.type.stop="Stop recording" AdvSceneSwitcher.action.recording.type.start="Start recording" @@ -891,3 +893,7 @@ AdvSceneSwitcher.duration.condition.more="For at least" AdvSceneSwitcher.duration.condition.equal="For exactly" AdvSceneSwitcher.duration.condition.less="For at most" AdvSceneSwitcher.duration.condition.within="Within the last" + +AdvSceneSwitcher.audio.monitor.none="Monitor Off" +AdvSceneSwitcher.audio.monitor.monitorOnly="Monitor Only (mute output)" +AdvSceneSwitcher.audio.monitor.both="Monitor and Output" diff --git a/data/locale/es-ES.ini b/data/locale/es-ES.ini index 0dc9ce71..0c4f64ef 100644 --- a/data/locale/es-ES.ini +++ b/data/locale/es-ES.ini @@ -105,7 +105,7 @@ AdvSceneSwitcher.condition.audio.state.mute="silenciado" AdvSceneSwitcher.condition.audio.state.unmute="no silenciado" AdvSceneSwitcher.condition.audio.type.output="Volumen de salida" AdvSceneSwitcher.condition.audio.type.volume="Nivel de volumen configurado" -AdvSceneSwitcher.condition.audio.entry="{{checkType}} de {{audioSources}} es {{condition}}{{volume}}{{syncOffset}}" +AdvSceneSwitcher.condition.audio.entry="{{checkType}} de {{audioSources}} es {{condition}}{{volume}}{{syncOffset}}{{monitorTypes}}" AdvSceneSwitcher.condition.cursor="Cursor" AdvSceneSwitcher.condition.cursor.type.region="está en la región" AdvSceneSwitcher.condition.cursor.type.moving="se está moviendo" @@ -347,7 +347,7 @@ AdvSceneSwitcher.action.audio.fade.duration="{{fade}}Fade {{fadeTypes}} {{durati AdvSceneSwitcher.action.audio.fade.rate="{{fade}}Fade {{fadeTypes}} {{rate}}por segundo." AdvSceneSwitcher.action.audio.fade.wait="Espere a que se complete el desvanecimiento". AdvSceneSwitcher.action.audio.fade.abort="Cancelar atenuación ya activa." -AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}" +AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}" AdvSceneSwitcher.action.recording="Grabando" AdvSceneSwitcher.action.recording.type.stop="Detener grabación" AdvSceneSwitcher.action.recording.type.start="Iniciar grabación" diff --git a/data/locale/ru-RU.ini b/data/locale/ru-RU.ini index 19b1f503..32e83cf8 100644 --- a/data/locale/ru-RU.ini +++ b/data/locale/ru-RU.ini @@ -128,7 +128,7 @@ AdvSceneSwitcher.action.audio.type.mute="Замьютить" AdvSceneSwitcher.action.audio.type.unmute="Размьютить" AdvSceneSwitcher.action.audio.type.sourceVolume="Установить громкость источника" AdvSceneSwitcher.action.audio.type.masterVolume="Установить главную громкость" -AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}" +AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}" AdvSceneSwitcher.action.recording="Запись" AdvSceneSwitcher.action.recording.type.stop="Остановить запись" AdvSceneSwitcher.action.recording.type.start="Начать запись" diff --git a/data/locale/tr-TR.ini b/data/locale/tr-TR.ini index bec83986..9d2bb456 100644 --- a/data/locale/tr-TR.ini +++ b/data/locale/tr-TR.ini @@ -277,7 +277,7 @@ AdvSceneSwitcher.action.audio.type.mute="Sessiz" AdvSceneSwitcher.action.audio.type.unmute="Ses açmak" AdvSceneSwitcher.action.audio.type.sourceVolume="Kaynak ses seviyesini ayarla" AdvSceneSwitcher.action.audio.type.masterVolume="Ana ses seviyesini ayarla" -AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}" +AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}" AdvSceneSwitcher.action.recording="Kayıt" AdvSceneSwitcher.action.recording.type.stop="Kayıt Durdur" AdvSceneSwitcher.action.recording.type.start="Kayıt Başlat" diff --git a/data/locale/zh-CN.ini b/data/locale/zh-CN.ini index 570fbf05..a19d8e8f 100644 --- a/data/locale/zh-CN.ini +++ b/data/locale/zh-CN.ini @@ -112,7 +112,7 @@ AdvSceneSwitcher.condition.audio.state.mute="静音" AdvSceneSwitcher.condition.audio.state.unmute="取消静音" AdvSceneSwitcher.condition.audio.type.output="输出音频" AdvSceneSwitcher.condition.audio.type.volume="配置音量级别" -AdvSceneSwitcher.condition.audio.entry="{{checkType}} 的 {{audioSources}} 是 {{condition}}{{volume}}{{syncOffset}}" +AdvSceneSwitcher.condition.audio.entry="{{checkType}} 的 {{audioSources}} 是 {{condition}}{{volume}}{{syncOffset}}{{monitorTypes}}" AdvSceneSwitcher.condition.cursor="屏幕区域" AdvSceneSwitcher.condition.cursor.type.region="当前位置" AdvSceneSwitcher.condition.cursor.type.moving="正在移动" @@ -385,7 +385,7 @@ AdvSceneSwitcher.action.audio.fade.duration="{{fade}}淡出 {{fadeTypes}} {{dura AdvSceneSwitcher.action.audio.fade.rate="{{fade}}淡出 {{fadeTypes}} {{rate}}每秒." AdvSceneSwitcher.action.audio.fade.wait="等待淡入淡出完成." AdvSceneSwitcher.action.audio.fade.abort="中止已处于活动状态的淡入淡出." -AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}" +AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{syncOffset}}{{monitorTypes}}" AdvSceneSwitcher.action.recording="录制" AdvSceneSwitcher.action.recording.type.stop="停止录制" AdvSceneSwitcher.action.recording.type.start="开始录制" diff --git a/src/macro-core/macro-action-audio.cpp b/src/macro-core/macro-action-audio.cpp index 0e518ab0..32ac176e 100644 --- a/src/macro-core/macro-action-audio.cpp +++ b/src/macro-core/macro-action-audio.cpp @@ -21,6 +21,8 @@ const static std::map actionTypes = { "AdvSceneSwitcher.action.audio.type.masterVolume"}, {MacroActionAudio::Action::SYNC_OFFSET, "AdvSceneSwitcher.action.audio.type.syncOffset"}, + {MacroActionAudio::Action::MONITOR, + "AdvSceneSwitcher.action.audio.type.monitor"}, }; const static std::map fadeTypes = { @@ -189,6 +191,9 @@ bool MacroActionAudio::PerformAction() case MacroActionAudio::Action::SYNC_OFFSET: obs_source_set_sync_offset(s, _syncOffset * nsPerMs); break; + case MacroActionAudio::Action::MONITOR: + obs_source_set_monitoring_type(s, _monitorType); + break; default: break; } @@ -219,6 +224,7 @@ bool MacroActionAudio::Save(obs_data_t *obj) GetWeakSourceName(_audioSource).c_str()); obs_data_set_int(obj, "action", static_cast(_action)); obs_data_set_int(obj, "syncOffset", _syncOffset); + obs_data_set_int(obj, "monitor", _monitorType); obs_data_set_int(obj, "volume", _volume); obs_data_set_double(obj, "rate", _rate); obs_data_set_bool(obj, "fade", _fade); @@ -237,6 +243,8 @@ bool MacroActionAudio::Load(obs_data_t *obj) _action = static_cast( obs_data_get_int(obj, "action")); _syncOffset = obs_data_get_int(obj, "syncOffset"); + _monitorType = static_cast( + obs_data_get_int(obj, "monitor")); _volume = obs_data_get_int(obj, "volume"); _rate = obs_data_get_double(obj, "rate"); _fade = obs_data_get_bool(obj, "fade"); @@ -288,6 +296,7 @@ MacroActionAudioEdit::MacroActionAudioEdit( _actions(new QComboBox), _fadeTypes(new QComboBox), _syncOffset(new QSpinBox), + _monitorTypes(new QComboBox), _volumePercent(new QSpinBox), _fade(new QCheckBox), _duration(new DurationSelection(parent, false)), @@ -314,6 +323,7 @@ MacroActionAudioEdit::MacroActionAudioEdit( populateActionSelection(_actions); populateAudioSelection(_audioSources); populateFadeTypeSelection(_fadeTypes); + populateMonitorTypeSelection(_monitorTypes); QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, SLOT(ActionChanged(int))); @@ -322,6 +332,8 @@ MacroActionAudioEdit::MacroActionAudioEdit( SLOT(SourceChanged(const QString &))); QWidget::connect(_syncOffset, SIGNAL(valueChanged(int)), this, SLOT(SyncOffsetChanged(int))); + QWidget::connect(_monitorTypes, SIGNAL(currentIndexChanged(int)), this, + SLOT(MonitorTypeChanged(int))); QWidget::connect(_volumePercent, SIGNAL(valueChanged(int)), this, SLOT(VolumeChanged(int))); QWidget::connect(_fade, SIGNAL(stateChanged(int)), this, @@ -341,6 +353,7 @@ MacroActionAudioEdit::MacroActionAudioEdit( {"{{audioSources}}", _audioSources}, {"{{actions}}", _actions}, {"{{syncOffset}}", _syncOffset}, + {"{{monitorTypes}}", _monitorTypes}, {"{{volume}}", _volumePercent}, {"{{fade}}", _fade}, {"{{duration}}", _duration}, @@ -384,6 +397,8 @@ void MacroActionAudioEdit::SetWidgetVisibility() MacroActionAudio::Action::MASTER_VOLUME); _syncOffset->setVisible(_entryData->_action == MacroActionAudio::Action::SYNC_OFFSET); + _monitorTypes->setVisible(_entryData->_action == + MacroActionAudio::Action::MONITOR); _fadeTypes->setDisabled(!_entryData->_fade); _wait->setDisabled(!_entryData->_fade); @@ -435,6 +450,7 @@ void MacroActionAudioEdit::UpdateEntryData() GetWeakSourceName(_entryData->_audioSource).c_str()); _actions->setCurrentIndex(static_cast(_entryData->_action)); _syncOffset->setValue(_entryData->_syncOffset); + _monitorTypes->setCurrentIndex(_entryData->_monitorType); _volumePercent->setValue(_entryData->_volume); _fade->setChecked(_entryData->_fade); _duration->SetDuration(_entryData->_duration); @@ -478,6 +494,16 @@ void MacroActionAudioEdit::SyncOffsetChanged(int value) _entryData->_syncOffset = value; } +void MacroActionAudioEdit::MonitorTypeChanged(int value) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_monitorType = static_cast(value); +} + void MacroActionAudioEdit::VolumeChanged(int value) { if (_loading || !_entryData) { diff --git a/src/macro-core/macro-action-audio.hpp b/src/macro-core/macro-action-audio.hpp index ee0b3d5a..df10b30a 100644 --- a/src/macro-core/macro-action-audio.hpp +++ b/src/macro-core/macro-action-audio.hpp @@ -29,6 +29,7 @@ public: SOURCE_VOLUME, MASTER_VOLUME, SYNC_OFFSET, + MONITOR, }; enum class FadeType { @@ -39,6 +40,7 @@ public: Action _action = Action::MUTE; FadeType _fadeType = FadeType::DURATION; int64_t _syncOffset = 0; + obs_monitoring_type _monitorType = OBS_MONITORING_TYPE_NONE; int _volume = 0; bool _fade = false; Duration _duration; @@ -79,6 +81,7 @@ private slots: void SourceChanged(const QString &text); void ActionChanged(int value); void SyncOffsetChanged(int value); + void MonitorTypeChanged(int value); void VolumeChanged(int value); void FadeChanged(int value); void DurationChanged(double seconds); @@ -94,6 +97,7 @@ protected: QComboBox *_actions; QComboBox *_fadeTypes; QSpinBox *_syncOffset; + QComboBox *_monitorTypes; QSpinBox *_volumePercent; QCheckBox *_fade; DurationSelection *_duration; diff --git a/src/macro-core/macro-condition-audio.cpp b/src/macro-core/macro-condition-audio.cpp index db41e567..b2cd8fb8 100644 --- a/src/macro-core/macro-condition-audio.cpp +++ b/src/macro-core/macro-condition-audio.cpp @@ -18,6 +18,8 @@ static std::map checkTypes = { "AdvSceneSwitcher.condition.audio.type.volume"}, {MacroConditionAudio::Type::SYNC_OFFSET, "AdvSceneSwitcher.condition.audio.type.syncOffset"}, + {MacroConditionAudio::Type::MONITOR, + "AdvSceneSwitcher.condition.audio.type.monitor"}, }; static std::map @@ -115,6 +117,19 @@ bool MacroConditionAudio::CheckSyncOffset() return ret; } +bool MacroConditionAudio::CheckMonitor() +{ + if (!_audioSource) { + return false; + } + + bool ret = false; + auto s = obs_weak_source_get_source(_audioSource); + ret = obs_source_get_monitoring_type(s) == _monitorType; + obs_source_release(s); + return ret; +} + bool MacroConditionAudio::CheckCondition() { switch (_checkType) { @@ -124,6 +139,8 @@ bool MacroConditionAudio::CheckCondition() return CheckVolumeCondition(); case MacroConditionAudio::Type::SYNC_OFFSET: return CheckSyncOffset(); + case MacroConditionAudio::Type::MONITOR: + return CheckMonitor(); default: break; } @@ -137,6 +154,7 @@ bool MacroConditionAudio::Save(obs_data_t *obj) GetWeakSourceName(_audioSource).c_str()); obs_data_set_int(obj, "volume", _volume); obs_data_set_int(obj, "syncOffset", _syncOffset); + obs_data_set_int(obj, "monitor", _monitorType); obs_data_set_int(obj, "checkType", static_cast(_checkType)); obs_data_set_int(obj, "outputCondition", static_cast(_outputCondition)); @@ -169,6 +187,8 @@ bool MacroConditionAudio::Load(obs_data_t *obj) _audioSource = GetWeakSourceByName(audioSourceName); _volume = obs_data_get_int(obj, "volume"); _syncOffset = obs_data_get_int(obj, "syncOffset"); + _monitorType = static_cast( + obs_data_get_int(obj, "monitor")); _checkType = static_cast( obs_data_get_int(obj, "checkType")); _outputCondition = static_cast( @@ -243,7 +263,8 @@ MacroConditionAudioEdit::MacroConditionAudioEdit( _audioSources(new QComboBox()), _condition(new QComboBox()), _volume(new QSpinBox()), - _syncOffset(new QSpinBox()) + _syncOffset(new QSpinBox()), + _monitorTypes(new QComboBox) { _volume->setSuffix("%"); _volume->setMaximum(100); @@ -259,6 +280,8 @@ MacroConditionAudioEdit::MacroConditionAudioEdit( SLOT(VolumeThresholdChanged(int))); QWidget::connect(_syncOffset, SIGNAL(valueChanged(int)), this, SLOT(SyncOffsetChanged(int))); + QWidget::connect(_monitorTypes, SIGNAL(currentIndexChanged(int)), this, + SLOT(MonitorTypeChanged(int))); QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this, SLOT(ConditionChanged(int))); QWidget::connect(_audioSources, @@ -267,6 +290,7 @@ MacroConditionAudioEdit::MacroConditionAudioEdit( populateCheckTypes(_checkTypes); populateAudioSelection(_audioSources); + populateMonitorTypeSelection(_monitorTypes); QHBoxLayout *switchLayout = new QHBoxLayout; std::unordered_map widgetPlaceholders = { @@ -274,6 +298,7 @@ MacroConditionAudioEdit::MacroConditionAudioEdit( {"{{audioSources}}", _audioSources}, {"{{volume}}", _volume}, {"{{syncOffset}}", _syncOffset}, + {"{{monitorTypes}}", _monitorTypes}, {"{{condition}}", _condition}, }; placeWidgets(obs_module_text("AdvSceneSwitcher.condition.audio.entry"), @@ -345,6 +370,16 @@ void MacroConditionAudioEdit::SyncOffsetChanged(int value) _entryData->_syncOffset = value; } +void MacroConditionAudioEdit::MonitorTypeChanged(int value) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_monitorType = static_cast(value); +} + void MacroConditionAudioEdit::ConditionChanged(int cond) { if (_loading || !_entryData) { @@ -393,6 +428,7 @@ void MacroConditionAudioEdit::UpdateEntryData() GetWeakSourceName(_entryData->_audioSource).c_str()); _volume->setValue(_entryData->_volume); _syncOffset->setValue(_entryData->_syncOffset); + _monitorTypes->setCurrentIndex(_entryData->_monitorType); _checkTypes->setCurrentIndex(static_cast(_entryData->_checkType)); if (_entryData->_checkType == MacroConditionAudio::Type::OUTPUT_VOLUME) { @@ -433,6 +469,8 @@ void MacroConditionAudioEdit::SetWidgetVisibility() MacroConditionAudio::Type::CONFIGURED_VOLUME); _syncOffset->setVisible(_entryData->_checkType == MacroConditionAudio::Type::SYNC_OFFSET); + _monitorTypes->setVisible(_entryData->_checkType == + MacroConditionAudio::Type::MONITOR); _volMeter->setVisible(_entryData->_checkType == MacroConditionAudio::Type::OUTPUT_VOLUME); adjustSize(); diff --git a/src/macro-core/macro-condition-audio.hpp b/src/macro-core/macro-condition-audio.hpp index 35e4f1e1..6f31eef0 100644 --- a/src/macro-core/macro-condition-audio.hpp +++ b/src/macro-core/macro-condition-audio.hpp @@ -29,6 +29,7 @@ public: OUTPUT_VOLUME, CONFIGURED_VOLUME, SYNC_OFFSET, + MONITOR, }; enum class OutputCondition { @@ -47,6 +48,7 @@ public: OBSWeakSource _audioSource; int _volume = 0; int64_t _syncOffset = 0; + obs_monitoring_type _monitorType = OBS_MONITORING_TYPE_NONE; Type _checkType = Type::OUTPUT_VOLUME; OutputCondition _outputCondition = OutputCondition::ABOVE; VolumeCondition _volumeCondition = VolumeCondition::ABOVE; @@ -56,6 +58,7 @@ private: bool CheckOutputCondition(); bool CheckVolumeCondition(); bool CheckSyncOffset(); + bool CheckMonitor(); float _peak = -std::numeric_limits::infinity(); static bool _registered; @@ -85,6 +88,7 @@ private slots: void ConditionChanged(int cond); void CheckTypeChanged(int cond); void SyncOffsetChanged(int value); + void MonitorTypeChanged(int value); signals: void HeaderInfoChanged(const QString &); @@ -95,6 +99,7 @@ protected: QComboBox *_condition; QSpinBox *_volume; QSpinBox *_syncOffset; + QComboBox *_monitorTypes; VolControl *_volMeter = nullptr; std::shared_ptr _entryData; diff --git a/src/utils/utility.cpp b/src/utils/utility.cpp index d7595f3f..75c7acc9 100644 --- a/src/utils/utility.cpp +++ b/src/utils/utility.cpp @@ -824,6 +824,14 @@ void populateProfileSelection(QComboBox *box) box->setCurrentIndex(0); } +void populateMonitorTypeSelection(QComboBox *list) +{ + list->addItem(obs_module_text("AdvSceneSwitcher.audio.monitor.none")); + list->addItem( + obs_module_text("AdvSceneSwitcher.audio.monitor.monitorOnly")); + list->addItem(obs_module_text("AdvSceneSwitcher.audio.monitor.both")); +} + bool windowPosValid(QPoint pos) { return !!QGuiApplication::screenAt(pos); diff --git a/src/utils/utility.hpp b/src/utils/utility.hpp index 49427204..a6fde492 100644 --- a/src/utils/utility.hpp +++ b/src/utils/utility.hpp @@ -81,6 +81,7 @@ void populateFilterSelection(QComboBox *list, OBSWeakSource weakSource = nullptr); void populateSourceGroupSelection(QComboBox *list); void populateProfileSelection(QComboBox *list); +void populateMonitorTypeSelection(QComboBox *list); bool windowPosValid(QPoint pos); bool doubleEquals(double left, double right, double epsilon); void setButtonIcon(QPushButton *button, const char *path);