Add option to also check for configured volume level

This commit is contained in:
WarmUpTill
2022-01-22 18:52:30 +01:00
committed by WarmUpTill
parent fda9b1c3ea
commit f287a1041d
3 changed files with 222 additions and 30 deletions

View File

@@ -89,10 +89,13 @@ AdvSceneSwitcher.logic.not="If not"
; Macro Conditions
AdvSceneSwitcher.condition.audio="Audio"
AdvSceneSwitcher.condition.audio.state.below="below"
AdvSceneSwitcher.condition.audio.state.exact="exactly"
AdvSceneSwitcher.condition.audio.state.above="above"
AdvSceneSwitcher.condition.audio.state.mute="muted"
AdvSceneSwitcher.condition.audio.state.unmute="unmuted"
AdvSceneSwitcher.condition.audio.entry="Volume of {{audioSources}} is {{condition}} {{volume}}"
AdvSceneSwitcher.condition.audio.type.output="Output volume"
AdvSceneSwitcher.condition.audio.type.volume="Configured volume level"
AdvSceneSwitcher.condition.audio.entry="{{checkType}} of {{audioSources}} is {{condition}} {{volume}}"
AdvSceneSwitcher.condition.cursor="Cursor"
AdvSceneSwitcher.condition.cursor.type.region="is in region"
AdvSceneSwitcher.condition.cursor.type.moving="is moving"

View File

@@ -6,9 +6,23 @@
#include <QComboBox>
#include <chrono>
enum class AudioCondition {
enum class AudioConditionCheckType {
OUTPUT_VOLUME,
CONFIGURED_VOLUME,
};
enum class AudioOutputCondition {
ABOVE,
BELOW,
// TODO: To be removed
MUTE,
UNMUTE,
};
enum class AudioVolumeCondition {
ABOVE,
EXACT,
BELOW,
MUTE,
UNMUTE,
};
@@ -34,10 +48,16 @@ public:
OBSWeakSource _audioSource;
int _volume = 0;
AudioCondition _condition = AudioCondition::ABOVE;
AudioConditionCheckType _checkType =
AudioConditionCheckType::OUTPUT_VOLUME;
AudioOutputCondition _outputCondition = AudioOutputCondition::ABOVE;
AudioVolumeCondition _volumeCondition = AudioVolumeCondition::ABOVE;
obs_volmeter_t *_volmeter = nullptr;
private:
bool CheckOutputCondition();
bool CheckVolumeCondition();
float _peak = -std::numeric_limits<float>::infinity();
static bool _registered;
static const std::string id;
@@ -64,10 +84,13 @@ private slots:
void SourceChanged(const QString &text);
void VolumeThresholdChanged(int vol);
void ConditionChanged(int cond);
void CheckTypeChanged(int cond);
signals:
void HeaderInfoChanged(const QString &);
protected:
QComboBox *_checkTypes;
QComboBox *_audioSources;
QComboBox *_condition;
QSpinBox *_volume;

View File

@@ -10,11 +10,23 @@ bool MacroConditionAudio::_registered = MacroConditionFactory::Register(
{MacroConditionAudio::Create, MacroConditionAudioEdit::Create,
"AdvSceneSwitcher.condition.audio"});
static std::map<AudioCondition, std::string> audioConditionTypes = {
{AudioCondition::ABOVE, "AdvSceneSwitcher.condition.audio.state.above"},
{AudioCondition::BELOW, "AdvSceneSwitcher.condition.audio.state.below"},
{AudioCondition::MUTE, "AdvSceneSwitcher.condition.audio.state.mute"},
{AudioCondition::UNMUTE,
static std::map<AudioOutputCondition, std::string> audioOutputConditionTypes = {
{AudioOutputCondition::ABOVE,
"AdvSceneSwitcher.condition.audio.state.above"},
{AudioOutputCondition::BELOW,
"AdvSceneSwitcher.condition.audio.state.below"},
};
static std::map<AudioVolumeCondition, std::string> audioVolumeConditionTypes = {
{AudioVolumeCondition::ABOVE,
"AdvSceneSwitcher.condition.audio.state.above"},
{AudioVolumeCondition::EXACT,
"AdvSceneSwitcher.condition.audio.state.exact"},
{AudioVolumeCondition::BELOW,
"AdvSceneSwitcher.condition.audio.state.below"},
{AudioVolumeCondition::MUTE,
"AdvSceneSwitcher.condition.audio.state.mute"},
{AudioVolumeCondition::UNMUTE,
"AdvSceneSwitcher.condition.audio.state.unmute"},
};
@@ -24,43 +36,85 @@ MacroConditionAudio::~MacroConditionAudio()
obs_volmeter_destroy(_volmeter);
}
bool MacroConditionAudio::CheckCondition()
bool MacroConditionAudio::CheckOutputCondition()
{
bool ret = false;
auto s = obs_weak_source_get_source(_audioSource);
switch (_condition) {
case AudioCondition::ABOVE:
switch (_outputCondition) {
case AudioOutputCondition::ABOVE:
// peak will have a value from -60 db to 0 db
ret = ((double)_peak + 60) * 1.7 > _volume;
break;
case AudioCondition::BELOW:
case AudioOutputCondition::BELOW:
// peak will have a value from -60 db to 0 db
ret = ((double)_peak + 60) * 1.7 < _volume;
break;
case AudioCondition::MUTE:
ret = obs_source_muted(s);
break;
case AudioCondition::UNMUTE:
ret = !obs_source_muted(s);
break;
default:
break;
}
// Reset for next check
_peak = -std::numeric_limits<float>::infinity();
obs_source_release(s);
return ret;
}
bool MacroConditionAudio::CheckVolumeCondition()
{
bool ret = false;
auto s = obs_weak_source_get_source(_audioSource);
switch (_volumeCondition) {
case AudioVolumeCondition::ABOVE:
ret = obs_source_get_volume(s) > _volume / 100.f;
break;
case AudioVolumeCondition::EXACT:
ret = obs_source_get_volume(s) == _volume / 100.f;
break;
case AudioVolumeCondition::BELOW:
ret = obs_source_get_volume(s) < _volume / 100.f;
break;
case AudioVolumeCondition::MUTE:
ret = obs_source_muted(s);
break;
case AudioVolumeCondition::UNMUTE:
ret = !obs_source_muted(s);
break;
default:
break;
}
obs_source_release(s);
return ret;
}
bool MacroConditionAudio::CheckCondition()
{
switch (_checkType) {
case AudioConditionCheckType::OUTPUT_VOLUME:
return CheckOutputCondition();
case AudioConditionCheckType::CONFIGURED_VOLUME:
return CheckVolumeCondition();
default:
break;
}
return false;
}
bool MacroConditionAudio::Save(obs_data_t *obj)
{
MacroCondition::Save(obj);
obs_data_set_string(obj, "audioSource",
GetWeakSourceName(_audioSource).c_str());
obs_data_set_int(obj, "volume", _volume);
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
obs_data_set_int(obj, "checkType", static_cast<int>(_checkType));
obs_data_set_int(obj, "outputCondition",
static_cast<int>(_outputCondition));
obs_data_set_int(obj, "volumeCondition",
static_cast<int>(_volumeCondition));
return true;
}
@@ -81,14 +135,66 @@ obs_volmeter_t *AddVolmeterToSource(MacroConditionAudio *entry,
return volmeter;
}
// TODO: Remove in future version
static void convertOldSettingsFormat(obs_data_t *obj)
{
auto oldCond = static_cast<AudioOutputCondition>(
obs_data_get_int(obj, "condition"));
switch (oldCond) {
case AudioOutputCondition::ABOVE:
obs_data_set_int(
obj, "checkType",
static_cast<int>(
AudioConditionCheckType::OUTPUT_VOLUME));
obs_data_set_int(obj, "outputCondition",
static_cast<int>(AudioOutputCondition::ABOVE));
break;
case AudioOutputCondition::BELOW:
obs_data_set_int(
obj, "checkType",
static_cast<int>(
AudioConditionCheckType::OUTPUT_VOLUME));
obs_data_set_int(obj, "outputCondition",
static_cast<int>(AudioOutputCondition::BELOW));
break;
case AudioOutputCondition::MUTE:
obs_data_set_int(
obj, "checkType",
static_cast<int>(
AudioConditionCheckType::CONFIGURED_VOLUME));
obs_data_set_int(obj, "volumeCondition",
static_cast<int>(AudioVolumeCondition::MUTE));
break;
case AudioOutputCondition::UNMUTE:
obs_data_set_int(
obj, "checkType",
static_cast<int>(
AudioConditionCheckType::CONFIGURED_VOLUME));
obs_data_set_int(
obj, "volumeCondition",
static_cast<int>(AudioVolumeCondition::UNMUTE));
break;
default:
break;
}
}
bool MacroConditionAudio::Load(obs_data_t *obj)
{
if (!obs_data_has_user_value(obj, "checkType")) {
convertOldSettingsFormat(obj);
}
MacroCondition::Load(obj);
const char *audioSourceName = obs_data_get_string(obj, "audioSource");
_audioSource = GetWeakSourceByName(audioSourceName);
_volume = obs_data_get_int(obj, "volume");
_condition =
static_cast<AudioCondition>(obs_data_get_int(obj, "condition"));
_checkType = static_cast<AudioConditionCheckType>(
obs_data_get_int(obj, "checkType"));
_outputCondition = static_cast<AudioOutputCondition>(
obs_data_get_int(obj, "outputCondition"));
_volumeCondition = static_cast<AudioVolumeCondition>(
obs_data_get_int(obj, "volumeCondition"));
_volmeter = AddVolmeterToSource(this, _audioSource);
return true;
}
@@ -122,9 +228,26 @@ void MacroConditionAudio::ResetVolmeter()
_volmeter = AddVolmeterToSource(this, _audioSource);
}
static inline void populateConditionSelection(QComboBox *list)
static inline void populateCheckTypes(QComboBox *list)
{
for (auto entry : audioConditionTypes) {
list->addItem(obs_module_text(
"AdvSceneSwitcher.condition.audio.type.output"));
list->addItem(obs_module_text(
"AdvSceneSwitcher.condition.audio.type.volume"));
}
static inline void populateOutputConditionSelection(QComboBox *list)
{
list->clear();
for (auto entry : audioOutputConditionTypes) {
list->addItem(obs_module_text(entry.second.c_str()));
}
}
static inline void populateVolumeConditionSelection(QComboBox *list)
{
list->clear();
for (auto entry : audioVolumeConditionTypes) {
list->addItem(obs_module_text(entry.second.c_str()));
}
}
@@ -133,6 +256,7 @@ MacroConditionAudioEdit::MacroConditionAudioEdit(
QWidget *parent, std::shared_ptr<MacroConditionAudio> entryData)
: QWidget(parent)
{
_checkTypes = new QComboBox();
_audioSources = new QComboBox();
_condition = new QComboBox();
_volume = new QSpinBox();
@@ -141,6 +265,8 @@ MacroConditionAudioEdit::MacroConditionAudioEdit(
_volume->setMaximum(100);
_volume->setMinimum(0);
QWidget::connect(_checkTypes, SIGNAL(currentIndexChanged(int)), this,
SLOT(CheckTypeChanged(int)));
QWidget::connect(_volume, SIGNAL(valueChanged(int)), this,
SLOT(VolumeThresholdChanged(int)));
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this,
@@ -149,11 +275,12 @@ MacroConditionAudioEdit::MacroConditionAudioEdit(
SIGNAL(currentTextChanged(const QString &)), this,
SLOT(SourceChanged(const QString &)));
populateCheckTypes(_checkTypes);
populateAudioSelection(_audioSources);
populateConditionSelection(_condition);
QHBoxLayout *switchLayout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{checkType}}", _checkTypes},
{"{{audioSources}}", _audioSources},
{"{{volume}}", _volume},
{"{{condition}}", _condition},
@@ -224,7 +351,31 @@ void MacroConditionAudioEdit::ConditionChanged(int cond)
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_condition = static_cast<AudioCondition>(cond);
if (_entryData->_checkType == AudioConditionCheckType::OUTPUT_VOLUME) {
_entryData->_outputCondition =
static_cast<AudioOutputCondition>(cond);
} else {
_entryData->_volumeCondition =
static_cast<AudioVolumeCondition>(cond);
}
SetWidgetVisibility();
}
void MacroConditionAudioEdit::CheckTypeChanged(int cond)
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_checkType = static_cast<AudioConditionCheckType>(cond);
const QSignalBlocker b(_condition);
if (_entryData->_checkType == AudioConditionCheckType::OUTPUT_VOLUME) {
populateOutputConditionSelection(_condition);
} else {
populateVolumeConditionSelection(_condition);
}
SetWidgetVisibility();
}
@@ -237,7 +388,16 @@ void MacroConditionAudioEdit::UpdateEntryData()
_audioSources->setCurrentText(
GetWeakSourceName(_entryData->_audioSource).c_str());
_volume->setValue(_entryData->_volume);
_condition->setCurrentIndex(static_cast<int>(_entryData->_condition));
_checkTypes->setCurrentIndex(static_cast<int>(_entryData->_checkType));
if (_entryData->_checkType == AudioConditionCheckType::OUTPUT_VOLUME) {
populateOutputConditionSelection(_condition);
_condition->setCurrentIndex(
static_cast<int>(_entryData->_outputCondition));
} else {
populateVolumeConditionSelection(_condition);
_condition->setCurrentIndex(
static_cast<int>(_entryData->_volumeCondition));
}
UpdateVolmeterSource();
SetWidgetVisibility();
}
@@ -248,9 +408,15 @@ void MacroConditionAudioEdit::SetWidgetVisibility()
return;
}
_volume->setVisible(_entryData->_condition == AudioCondition::ABOVE ||
_entryData->_condition == AudioCondition::BELOW);
_volMeter->setVisible(_entryData->_condition == AudioCondition::ABOVE ||
_entryData->_condition == AudioCondition::BELOW);
_volume->setVisible(
_entryData->_checkType ==
AudioConditionCheckType::OUTPUT_VOLUME ||
(_entryData->_checkType ==
AudioConditionCheckType::CONFIGURED_VOLUME &&
(_entryData->_volumeCondition == AudioVolumeCondition::ABOVE ||
_entryData->_volumeCondition == AudioVolumeCondition::EXACT ||
_entryData->_volumeCondition == AudioVolumeCondition::BELOW)));
_volMeter->setVisible(_entryData->_checkType ==
AudioConditionCheckType::OUTPUT_VOLUME);
adjustSize();
}