add fallback option if multiple audio matches are active (#95)

This commit is contained in:
WarmUpTill 2021-01-07 18:59:06 +01:00 committed by GitHub
parent 2b90493ae9
commit 17c4fefb37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 333 additions and 143 deletions

View File

@ -186,6 +186,8 @@ AdvSceneSwitcher.audioTab.title="Audio"
AdvSceneSwitcher.audioTab.condition.above="über"
AdvSceneSwitcher.audioTab.condition.below="unter"
AdvSceneSwitcher.audioTab.entry="Wenn die Lautstärke von {{audioSources}} {{condition}} {{volumeWidget}} ist für {{duration}} wechsle zu {{scenes}} mit {{transitions}}"
AdvSceneSwitcher.audioTab.multiMatchfallbackCondition="Wenn mehrere Einträge zutreffen ..."
AdvSceneSwitcher.audioTab.multiMatchfallback="... für {{duration}} wechsle zu {{scenes}} mit {{transitions}}"
; Hotkey
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Starte den Erweiteren Szenenwechsler"

View File

@ -186,6 +186,8 @@ AdvSceneSwitcher.audioTab.title="Audio"
AdvSceneSwitcher.audioTab.condition.above="above"
AdvSceneSwitcher.audioTab.condition.below="below"
AdvSceneSwitcher.audioTab.entry="When the volume of {{audioSources}} is {{condition}} {{volumeWidget}} for {{duration}} switch to {{scenes}} using {{transitions}}"
AdvSceneSwitcher.audioTab.multiMatchfallbackCondition="If multiple entries match ..."
AdvSceneSwitcher.audioTab.multiMatchfallback="... for {{duration}} switch to {{scenes}} using {{transitions}}"
; Hotkey
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Start the Advanced Scene Switcher"

View File

@ -2861,151 +2861,178 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QListWidget" name="audioSwitches">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sortingEnabled">
<bool>false</bool>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_22">
<item>
<widget class="QListWidget" name="audioSwitches">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sortingEnabled">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_53">
<item>
<widget class="QPushButton" name="audioAdd">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">addIconSmall</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="audioRemove">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">removeIconSmall</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_114">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="Line" name="line_38">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_115">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="audioUp">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>../../../forms/images/up.svg</normaloff>../../../forms/images/up.svg</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string>upArrowIconSmall</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="audioDown">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>../../../forms/images/down.svg</normaloff>../../../forms/images/down.svg</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string>downArrowIconSmall</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_56">
<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>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_53">
<item>
<widget class="QPushButton" name="audioAdd">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">addIconSmall</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="audioRemove">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string notr="true">removeIconSmall</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_114">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="Line" name="line_38">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_115">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="audioUp">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>../../../forms/images/up.svg</normaloff>../../../forms/images/up.svg</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string>upArrowIconSmall</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="audioDown">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>../../../forms/images/down.svg</normaloff>../../../forms/images/down.svg</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0">
<string>downArrowIconSmall</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_56">
<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 class="QGroupBox" name="audioFallback">
<property name="title">
<string>AdvSceneSwitcher.audioTab.multiMatchfallbackCondition</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_23">
<item>
<layout class="QHBoxLayout" name="audioFallbackLayout"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>

View File

@ -184,6 +184,7 @@ public slots:
void on_audioRemove_clicked();
void on_audioUp_clicked();
void on_audioDown_clicked();
void on_audioFallback_toggled(bool on);
void on_priorityUp_clicked();
void on_priorityDown_clicked();

View File

@ -44,6 +44,13 @@ struct AudioSwitch : virtual SceneSwitcherEntry {
friend void swap(AudioSwitch &first, AudioSwitch &second);
};
struct AudioSwitchFallback : virtual SceneSwitcherEntry {
const char *getType() { return "audio_fallback"; }
bool enable = false;
double duration = 0;
unsigned int matchCount = 0;
};
class AudioSwitchWidget : public SwitchWidget {
Q_OBJECT
@ -71,3 +78,18 @@ private:
AudioSwitch *switchData;
};
class AudioSwitchFallbackWidget : public SwitchWidget {
Q_OBJECT
public:
AudioSwitchFallbackWidget(AudioSwitchFallback *s);
private slots:
void DurationChanged(double dur);
private:
QDoubleSpinBox *duration;
AudioSwitchFallback *switchData;
};

View File

@ -111,6 +111,7 @@ struct SwitcherData {
QDateTime liveTime;
std::deque<AudioSwitch> audioSwitches;
AudioSwitchFallback audioFallback;
std::vector<int> functionNamesByPriority = std::vector<int>{
default_priority_0, default_priority_1, default_priority_2,
@ -188,6 +189,8 @@ struct SwitcherData {
OBSWeakSource &transition);
void checkAudioSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition);
void checkAudioSwitchFallback(OBSWeakSource &scene,
OBSWeakSource &transition);
void checkNoMatchSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition, int &sleep);
void checkSwitchCooldown(bool &match);

View File

@ -72,12 +72,43 @@ void AdvSceneSwitcher::on_audioDown_clicked()
switcher->audioSwitches[index + 1]);
}
void AdvSceneSwitcher::on_audioFallback_toggled(bool on)
{
if (loading || !switcher)
return;
std::lock_guard<std::mutex> lock(switcher->m);
switcher->audioFallback.enable = on;
}
void SwitcherData::checkAudioSwitchFallback(OBSWeakSource &scene,
OBSWeakSource &transition)
{
bool durationReached =
((unsigned long long)audioFallback.matchCount * interval) /
1000.0 >=
audioFallback.duration;
if (durationReached) {
scene = (audioFallback.usePreviousScene) ? previousScene
: audioFallback.scene;
transition = audioFallback.transition;
if (verbose)
audioFallback.logMatch();
}
audioFallback.matchCount++;
}
void SwitcherData::checkAudioSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition)
{
if (AudioSwitch::pause)
return;
bool fallbackChecked = false; // false if one or no match
for (AudioSwitch &s : audioSwitches) {
if (!s.initialized())
continue;
@ -103,19 +134,56 @@ void SwitcherData::checkAudioSwitch(bool &match, OBSWeakSource &scene,
}
bool durationReached =
(s.matchCount * (unsigned int)interval) / 1000.0 >=
((unsigned long long)s.matchCount * interval) /
1000.0 >=
s.duration;
if (volumeThresholdreached && durationReached && audioActive) {
if (match) {
checkAudioSwitchFallback(scene, transition);
fallbackChecked = true;
break;
}
scene = (s.usePreviousScene) ? previousScene : s.scene;
transition = s.transition;
match = true;
if (verbose)
s.logMatch();
break;
if (!audioFallback.enable)
break;
}
}
if (!fallbackChecked)
audioFallback.matchCount = 0;
}
void saveAudioFallback(obs_data_t *obj, AudioSwitchFallback &audioFallback)
{
obs_source_t *fallbackSceneSource =
obs_weak_source_get_source(audioFallback.scene);
obs_source_t *fallbackTransition =
obs_weak_source_get_source(audioFallback.transition);
const char *fallbackSceneName =
obs_source_get_name(fallbackSceneSource);
const char *fallbackTransitionName =
obs_source_get_name(fallbackTransition);
obs_data_set_bool(obj, "audioFallbackEnable", audioFallback.enable);
obs_data_set_string(obj, "audioFallbackScene",
audioFallback.usePreviousScene ? previous_scene_name
: fallbackSceneName);
obs_data_set_string(obj, "audioFallbackTransition",
fallbackTransitionName);
obs_data_set_double(obj, "audioFallbackDuration",
audioFallback.duration);
obs_source_release(fallbackSceneSource);
obs_source_release(fallbackTransition);
}
void SwitcherData::saveAudioSwitches(obs_data_t *obj)
@ -159,6 +227,25 @@ void SwitcherData::saveAudioSwitches(obs_data_t *obj)
}
obs_data_set_array(obj, "audioSwitches", audioArray);
obs_data_array_release(audioArray);
saveAudioFallback(obj, audioFallback);
}
void loadAudioFallback(obs_data_t *obj, AudioSwitchFallback &audioFallback)
{
const char *fallbackSceneName =
obs_data_get_string(obj, "audioFallbackScene");
const char *fallbackTransitionName =
obs_data_get_string(obj, "audioFallbackTransition");
audioFallback.enable = obs_data_get_bool(obj, "audioFallbackEnable");
audioFallback.duration =
obs_data_get_double(obj, "audioFallbackDuration");
audioFallback.scene = GetWeakSourceByName(fallbackSceneName);
audioFallback.transition =
GetWeakTransitionByName(fallbackTransitionName);
audioFallback.usePreviousScene =
strcmp(fallbackSceneName, previous_scene_name) == 0;
}
void SwitcherData::loadAudioSwitches(obs_data_t *obj)
@ -190,6 +277,8 @@ void SwitcherData::loadAudioSwitches(obs_data_t *obj)
obs_data_release(array_obj);
}
obs_data_array_release(audioArray);
loadAudioFallback(obj, audioFallback);
}
void AdvSceneSwitcher::setupAudioTab()
@ -205,6 +294,11 @@ void AdvSceneSwitcher::setupAudioTab()
if (switcher->audioSwitches.size() == 0)
addPulse = PulseWidget(ui->audioAdd, QColor(Qt::green));
AudioSwitchFallbackWidget *fb =
new AudioSwitchFallbackWidget(&switcher->audioFallback);
ui->audioFallbackLayout->addWidget(fb);
ui->audioFallback->setChecked(switcher->audioFallback.enable);
}
void AudioSwitch::setVolumeLevel(void *data,
@ -494,3 +588,42 @@ void AudioSwitchWidget::DurationChanged(double dur)
std::lock_guard<std::mutex> lock(switcher->m);
switchData->duration = dur;
}
AudioSwitchFallbackWidget::AudioSwitchFallbackWidget(AudioSwitchFallback *s)
: SwitchWidget(s)
{
duration = new QDoubleSpinBox();
duration->setMinimum(0.0);
duration->setMaximum(99.000000);
duration->setSuffix("s");
QWidget::connect(duration, SIGNAL(valueChanged(double)), this,
SLOT(DurationChanged(double)));
if (s) {
duration->setValue(s->duration);
}
QHBoxLayout *mainLayout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{scenes}}", scenes},
{"{{duration}}", duration},
{"{{transitions}}", transitions}};
placeWidgets(
obs_module_text("AdvSceneSwitcher.audioTab.multiMatchfallback"),
mainLayout, widgetPlaceholders);
setLayout(mainLayout);
switchData = s;
loading = false;
}
void AudioSwitchFallbackWidget::DurationChanged(double dur)
{
if (loading || !switchData)
return;
std::lock_guard<std::mutex> lock(switcher->m);
switchData->duration = dur;
}