Add audio tab (#36)

* add volumemeter widget

* add audio tab UI

* add checkAudioSwitch functionality

* use constexpr instead of preprocessing
This commit is contained in:
WarmUpTill
2020-09-21 00:52:42 +02:00
committed by GitHub
parent 3fd3801e56
commit 8d023ee385
16 changed files with 2087 additions and 92 deletions

View File

@@ -169,6 +169,7 @@ else ()
src/headers/switcher-data-structs.hpp
src/headers/utility.hpp
src/headers/curl-helper.hpp
src/headers/volume-control.hpp
)
set(advanced-scene-switcher_SOURCES
@@ -189,7 +190,9 @@ else ()
src/pause-switch.cpp
src/random.cpp
src/time-switch.cpp
src/audio-switch.cpp
src/curl-helper.cpp
src/volume-control.cpp
)
set(advanced-scene-switcher_UI

View File

@@ -2404,7 +2404,7 @@
<attribute name="title">
<string notr="true">File</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_6">
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
@@ -3657,6 +3657,257 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="audioTab">
<attribute name="title">
<string>Audio</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<layout class="QVBoxLayout" name="audioControlLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_52">
<item>
<widget class="QLabel" name="label_66">
<property name="text">
<string>When the volume of</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="audioSources">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_67">
<property name="text">
<string>is above</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="audioVolumeThreshold">
<property name="suffix">
<string>%</string>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_68">
<property name="text">
<string>switch to</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="audioScenes">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_69">
<property name="text">
<string>using</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="audioTransitions"/>
</item>
<item>
<spacer name="horizontalSpacer_54">
<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>
<item>
<widget class="QWidget" name="audioPlaceholder" native="true"/>
</item>
</layout>
</item>
<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>
</widget>
</item>
</layout>

View File

@@ -45,7 +45,7 @@ void SceneSwitcher::populateSceneSelection(QComboBox *sel, bool addPrevious)
}
if (addPrevious)
sel->addItem(PREVIOUS_SCENE_NAME);
sel->addItem(previous_scene_name);
}
void SceneSwitcher::populateTransitionSelection(QComboBox *sel)
@@ -90,6 +90,7 @@ void SceneSwitcher::loadUI()
setupMediaTab();
setupFileTab();
setupTimeTab();
setupAudioTab();
setTabOrder();
@@ -119,6 +120,7 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
switcher->saveFileSwitches(obj);
switcher->saveMediaSwitches(obj);
switcher->saveTimeSwitches(obj);
switcher->saveAudioSwitches(obj);
switcher->saveGeneralSettings(obj);
obs_data_set_obj(save_data, "advanced-scene-switcher", obj);
@@ -144,6 +146,7 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
switcher->loadFileSwitches(obj);
switcher->loadMediaSwitches(obj);
switcher->loadTimeSwitches(obj);
switcher->loadAudioSwitches(obj);
switcher->loadGeneralSettings(obj);
obs_data_release(obj);
@@ -213,27 +216,27 @@ void SwitcherData::Thread()
for (int switchFuncName : functionNamesByPriority) {
switch (switchFuncName) {
case READ_FILE_FUNC:
case read_file_func:
checkSwitchInfoFromFile(match, scene,
transition);
checkFileContent(match, scene, transition);
break;
case IDLE_FUNC:
case idle_func:
checkIdleSwitch(match, scene, transition);
break;
case EXE_FUNC:
case exe_func:
checkExeSwitch(match, scene, transition);
break;
case SCREEN_REGION_FUNC:
case screen_region_func:
checkScreenRegionSwitch(match, scene,
transition);
break;
case WINDOW_TITLE_FUNC:
case window_title_func:
checkWindowTitleSwitch(match, scene,
transition);
break;
case ROUND_TRIP_FUNC:
case round_trip_func:
checkSceneRoundTrip(match, scene, transition,
lock);
if (sceneChangedDuringWait()) //scene might have changed during the sleep
@@ -241,12 +244,15 @@ void SwitcherData::Thread()
goto startLoop;
}
break;
case MEDIA_FUNC:
case media_func:
checkMediaSwitch(match, scene, transition);
break;
case TIME_FUNC:
case time_func:
checkTimeSwitch(match, scene, transition);
break;
case audio_func:
checkAudioSwitch(match, scene, transition);
break;
}
if (switcher->stop) {
@@ -442,13 +448,13 @@ extern "C" void InitSceneSwitcher()
"startStopToggleSwitcherHotkey",
"Toggle Start/Stop for the Advanced Scene Switcher",
startStopToggleHotkeyFunc, NULL);
loadKeybinding(toggleHotkeyId, TOGGLE_HOTKEY_PATH);
loadKeybinding(toggleHotkeyId, toggle_hotkey_path);
obs_hotkey_id startHotkeyId = obs_hotkey_register_frontend(
"startSwitcherHotkey", "Start the Advanced Scene Switcher",
startHotkeyFunc, NULL);
loadKeybinding(startHotkeyId, START_HOTKEY_PATH);
loadKeybinding(startHotkeyId, start_hotkey_path);
obs_hotkey_id stopHotkeyId = obs_hotkey_register_frontend(
"stopSwitcherHotkey", "Stop the Advanced Scene Switcher",
stopHotkeyFunc, NULL);
loadKeybinding(stopHotkeyId, STOP_HOTKEY_PATH);
loadKeybinding(stopHotkeyId, stop_hotkey_path);
}

327
src/audio-switch.cpp Normal file
View File

@@ -0,0 +1,327 @@
#include "headers/advanced-scene-switcher.hpp"
#include "headers/volume-control.hpp"
void SceneSwitcher::on_audioSwitches_currentRowChanged(int idx)
{
if (loading)
return;
if (idx == -1)
return;
QListWidgetItem *item = ui->audioSwitches->item(idx);
QString audioScenestr = item->data(Qt::UserRole).toString();
std::lock_guard<std::mutex> lock(switcher->m);
for (auto &s : switcher->audioSwitches) {
if (audioScenestr.compare(s.audioSwitchStr.c_str()) == 0) {
QString sceneName = GetWeakSourceName(s.scene).c_str();
QString audioSrouceName =
GetWeakSourceName(s.audioSource).c_str();
QString transitionName =
GetWeakSourceName(s.transition).c_str();
ui->audioScenes->setCurrentText(sceneName);
ui->audioTransitions->setCurrentText(transitionName);
ui->audioSources->setCurrentText(audioSrouceName);
ui->audioVolumeThreshold->setValue(s.volumeThreshold);
volMeter->GetSlider()->setValue(s.volumeThreshold);
break;
}
}
}
void SceneSwitcher::on_audioSources_currentTextChanged(const QString &text)
{
SetAudioVolumeMeter(text);
}
void SceneSwitcher::SetAudioVolumeMeter(const QString &name)
{
obs_source_t *soruce =
obs_get_source_by_name(name.toUtf8().constData());
if (!soruce) {
return;
}
if (volMeter) {
ui->audioControlLayout->removeWidget(volMeter);
delete volMeter;
}
volMeter = new VolControl(soruce);
ui->audioControlLayout->addWidget(volMeter);
obs_source_release(soruce);
QWidget::connect(volMeter->GetSlider(), SIGNAL(valueChanged(int)),
ui->audioVolumeThreshold, SLOT(setValue(int)));
QWidget::connect(ui->audioVolumeThreshold, SIGNAL(valueChanged(int)),
volMeter->GetSlider(), SLOT(setValue(int)));
}
int SceneSwitcher::audioFindByData(const QString &source, const int &volume)
{
QRegExp rx(MakeAudioSwitchName(QStringLiteral(".*"),
QStringLiteral(".*"), source, volume));
int count = ui->audioSwitches->count();
for (int i = 0; i < count; i++) {
QListWidgetItem *item = ui->audioSwitches->item(i);
QString str = item->data(Qt::UserRole).toString();
if (rx.exactMatch(str))
return i;
}
return -1;
}
void SceneSwitcher::on_audioAdd_clicked()
{
QString sceneName = ui->audioScenes->currentText();
QString transitionName = ui->audioTransitions->currentText();
QString audioSourceName = ui->audioSources->currentText();
int vol = ui->audioVolumeThreshold->value();
if (sceneName.isEmpty() || audioSourceName.isEmpty())
return;
OBSWeakSource source = GetWeakSourceByQString(sceneName);
OBSWeakSource audioSource = GetWeakSourceByQString(audioSourceName);
OBSWeakSource transition = GetWeakTransitionByQString(transitionName);
QString text = MakeAudioSwitchName(sceneName, transitionName,
audioSourceName, vol);
QVariant v = QVariant::fromValue(text);
int idx = audioFindByData(audioSourceName, vol);
if (idx == -1) {
std::lock_guard<std::mutex> lock(switcher->m);
switcher->audioSwitches.emplace_back(
source, transition, audioSource, vol,
(sceneName == QString(previous_scene_name)),
text.toUtf8().constData());
QListWidgetItem *item =
new QListWidgetItem(text, ui->audioSwitches);
item->setData(Qt::UserRole, v);
} else {
QListWidgetItem *item = ui->audioSwitches->item(idx);
item->setText(text);
item->setData(Qt::UserRole, v);
{
std::lock_guard<std::mutex> lock(switcher->m);
for (auto &s : switcher->audioSwitches) {
if (s.audioSource == audioSource &&
s.volumeThreshold == vol) {
s.scene = source;
s.transition = transition;
s.usePreviousScene =
(sceneName ==
QString(previous_scene_name));
s.audioSwitchStr =
text.toUtf8().constData();
break;
}
}
}
}
}
void SceneSwitcher::on_audioRemove_clicked()
{
QListWidgetItem *item = ui->audioSwitches->currentItem();
if (!item)
return;
std::string text =
item->data(Qt::UserRole).toString().toUtf8().constData();
{
std::lock_guard<std::mutex> lock(switcher->m);
auto &switches = switcher->audioSwitches;
for (auto it = switches.begin(); it != switches.end(); ++it) {
auto &s = *it;
if (s.audioSwitchStr == text) {
switches.erase(it);
break;
}
}
}
delete item;
}
void SceneSwitcher::on_audioUp_clicked()
{
int index = ui->audioSwitches->currentRow();
if (index != -1 && index != 0) {
ui->audioSwitches->insertItem(
index - 1, ui->audioSwitches->takeItem(index));
ui->audioSwitches->setCurrentRow(index - 1);
std::lock_guard<std::mutex> lock(switcher->m);
iter_swap(switcher->audioSwitches.begin() + index,
switcher->audioSwitches.begin() + index - 1);
}
}
void SceneSwitcher::on_audioDown_clicked()
{
int index = ui->audioSwitches->currentRow();
if (index != -1 && index != ui->audioSwitches->count() - 1) {
ui->audioSwitches->insertItem(
index + 1, ui->audioSwitches->takeItem(index));
ui->audioSwitches->setCurrentRow(index + 1);
std::lock_guard<std::mutex> lock(switcher->m);
iter_swap(switcher->audioSwitches.begin() + index,
switcher->audioSwitches.begin() + index + 1);
}
}
void SwitcherData::checkAudioSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition)
{
if (audioSwitches.size() == 0)
return;
for (AudioSwitch &s : audioSwitches) {
obs_source_t *as = obs_weak_source_get_source(s.audioSource);
const char *name = obs_source_get_name(as);
bool audioActive = obs_source_active(as);
obs_source_release(as);
// peak will have a value from -60 db to 0 db
bool volumeThresholdreached = (s.peak + 60) * 1.7 >
s.volumeThreshold;
if (volumeThresholdreached && audioActive) {
scene = (s.usePreviousScene) ? previousScene : s.scene;
transition = s.transition;
match = true;
if (verbose)
blog(LOG_INFO,
"Advanced Scene Switcher audio match for %s",
name);
break;
}
}
}
void SwitcherData::saveAudioSwitches(obs_data_t *obj)
{
obs_data_array_t *audioArray = obs_data_array_create();
for (AudioSwitch &s : switcher->audioSwitches) {
obs_data_t *array_obj = obs_data_create();
obs_source_t *sceneSource = obs_weak_source_get_source(s.scene);
obs_source_t *transition =
obs_weak_source_get_source(s.transition);
obs_source_t *audioSrouce =
obs_weak_source_get_source(s.audioSource);
if ((s.usePreviousScene || sceneSource) && transition) {
const char *sceneName =
obs_source_get_name(sceneSource);
const char *transitionName =
obs_source_get_name(transition);
const char *audioSourceName =
obs_source_get_name(audioSrouce);
obs_data_set_string(array_obj, "scene",
s.usePreviousScene
? previous_scene_name
: sceneName);
obs_data_set_string(array_obj, "transition",
transitionName);
obs_data_set_string(array_obj, "audioSource",
audioSourceName);
obs_data_set_int(array_obj, "volume",
s.volumeThreshold);
obs_data_array_push_back(audioArray, array_obj);
}
obs_source_release(sceneSource);
obs_source_release(transition);
obs_source_release(audioSrouce);
obs_data_release(array_obj);
}
obs_data_set_array(obj, "audioSwitches", audioArray);
obs_data_array_release(audioArray);
}
void SwitcherData::loadAudioSwitches(obs_data_t *obj)
{
switcher->audioSwitches.clear();
obs_data_array_t *audioArray = obs_data_get_array(obj, "audioSwitches");
size_t count = obs_data_array_count(audioArray);
for (size_t i = 0; i < count; i++) {
obs_data_t *array_obj = obs_data_array_item(audioArray, i);
const char *scene = obs_data_get_string(array_obj, "scene");
const char *transition =
obs_data_get_string(array_obj, "transition");
const char *audioSource =
obs_data_get_string(array_obj, "audioSource");
int vol = obs_data_get_int(array_obj, "volume");
std::string audioSwitchStr =
MakeAudioSwitchName(scene, transition, audioSource, vol)
.toUtf8()
.constData();
switcher->audioSwitches.emplace_back(
GetWeakSourceByName(scene),
GetWeakTransitionByName(transition),
GetWeakSourceByName(audioSource), vol,
(strcmp(scene, previous_scene_name) == 0),
audioSwitchStr);
obs_data_release(array_obj);
}
obs_data_array_release(audioArray);
}
void SceneSwitcher::setupAudioTab()
{
populateSceneSelection(ui->audioScenes, true);
populateTransitionSelection(ui->audioTransitions);
auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */
{
QComboBox *combo = reinterpret_cast<QComboBox *>(data);
uint32_t flags = obs_source_get_output_flags(source);
if ((flags & OBS_SOURCE_AUDIO) != 0) {
const char *name = obs_source_get_name(source);
combo->addItem(name);
}
return true;
};
obs_enum_sources(sourceEnum, ui->audioSources);
for (auto &s : switcher->audioSwitches) {
std::string sceneName = (s.usePreviousScene)
? previous_scene_name
: GetWeakSourceName(s.scene);
std::string transitionName = GetWeakSourceName(s.transition);
std::string audioSourceName = GetWeakSourceName(s.audioSource);
QString listText = MakeAudioSwitchName(sceneName.c_str(),
transitionName.c_str(),
audioSourceName.c_str(),
s.volumeThreshold);
QListWidgetItem *item =
new QListWidgetItem(listText, ui->audioSwitches);
item->setData(Qt::UserRole, listText);
}
}

View File

@@ -265,6 +265,7 @@ void SceneSwitcher::on_exportSettings_clicked()
switcher->saveFileSwitches(obj);
switcher->saveMediaSwitches(obj);
switcher->saveTimeSwitches(obj);
switcher->saveAudioSwitches(obj);
switcher->saveGeneralSettings(obj);
obs_data_save_json(obj, file.fileName().toUtf8().constData());
@@ -309,6 +310,7 @@ void SceneSwitcher::on_importSettings_clicked()
switcher->loadFileSwitches(obj);
switcher->loadMediaSwitches(obj);
switcher->loadTimeSwitches(obj);
switcher->loadAudioSwitches(obj);
switcher->loadGeneralSettings(obj);
obs_data_release(obj);
@@ -362,6 +364,9 @@ int findTabIndex(QTabBar *bar, int pos)
case 11:
tabName = "Sequence";
break;
case 12:
tabName = "Audio";
break;
}
for (int i = 0; i < bar->count(); ++i) {
@@ -442,6 +447,8 @@ void SwitcherData::saveGeneralSettings(obs_data_t *obj)
switcher->functionNamesByPriority[6]);
obs_data_set_int(obj, "priority7",
switcher->functionNamesByPriority[7]);
obs_data_set_int(obj, "priority8",
switcher->functionNamesByPriority[8]);
obs_data_set_int(obj, "threadPriority", switcher->threadPriority);
@@ -457,11 +464,12 @@ void SwitcherData::saveGeneralSettings(obs_data_t *obj)
obs_data_set_int(obj, "timeTabPos", switcher->tabOrder[9]);
obs_data_set_int(obj, "idleTabPos", switcher->tabOrder[10]);
obs_data_set_int(obj, "sequenceTabPos", switcher->tabOrder[11]);
obs_data_set_int(obj, "audioTabPos", switcher->tabOrder[12]);
}
void SwitcherData::loadGeneralSettings(obs_data_t *obj)
{
obs_data_set_default_int(obj, "interval", DEFAULT_INTERVAL);
obs_data_set_default_int(obj, "interval", default_interval);
switcher->interval = obs_data_get_int(obj, "interval");
obs_data_set_default_int(obj, "switch_if_not_matching", NO_SWITCH);
@@ -494,14 +502,15 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
switcher->verbose = obs_data_get_bool(obj, "verbose");
obs_data_set_default_int(obj, "priority0", DEFAULT_PRIORITY_0);
obs_data_set_default_int(obj, "priority1", DEFAULT_PRIORITY_1);
obs_data_set_default_int(obj, "priority2", DEFAULT_PRIORITY_2);
obs_data_set_default_int(obj, "priority3", DEFAULT_PRIORITY_3);
obs_data_set_default_int(obj, "priority4", DEFAULT_PRIORITY_4);
obs_data_set_default_int(obj, "priority5", DEFAULT_PRIORITY_5);
obs_data_set_default_int(obj, "priority6", DEFAULT_PRIORITY_6);
obs_data_set_default_int(obj, "priority7", DEFAULT_PRIORITY_7);
obs_data_set_default_int(obj, "priority0", default_priority_0);
obs_data_set_default_int(obj, "priority1", default_priority_1);
obs_data_set_default_int(obj, "priority2", default_priority_2);
obs_data_set_default_int(obj, "priority3", default_priority_3);
obs_data_set_default_int(obj, "priority4", default_priority_4);
obs_data_set_default_int(obj, "priority5", default_priority_5);
obs_data_set_default_int(obj, "priority6", default_priority_6);
obs_data_set_default_int(obj, "priority7", default_priority_7);
obs_data_set_default_int(obj, "priority8", default_priority_8);
switcher->functionNamesByPriority[0] =
(obs_data_get_int(obj, "priority0"));
@@ -519,15 +528,18 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
(obs_data_get_int(obj, "priority6"));
switcher->functionNamesByPriority[7] =
(obs_data_get_int(obj, "priority7"));
switcher->functionNamesByPriority[8] =
(obs_data_get_int(obj, "priority8"));
if (!switcher->prioFuncsValid()) {
switcher->functionNamesByPriority[0] = (DEFAULT_PRIORITY_0);
switcher->functionNamesByPriority[1] = (DEFAULT_PRIORITY_1);
switcher->functionNamesByPriority[2] = (DEFAULT_PRIORITY_2);
switcher->functionNamesByPriority[3] = (DEFAULT_PRIORITY_3);
switcher->functionNamesByPriority[4] = (DEFAULT_PRIORITY_4);
switcher->functionNamesByPriority[5] = (DEFAULT_PRIORITY_5);
switcher->functionNamesByPriority[6] = (DEFAULT_PRIORITY_6);
switcher->functionNamesByPriority[7] = (DEFAULT_PRIORITY_7);
switcher->functionNamesByPriority[0] = (default_priority_0);
switcher->functionNamesByPriority[1] = (default_priority_1);
switcher->functionNamesByPriority[2] = (default_priority_2);
switcher->functionNamesByPriority[3] = (default_priority_3);
switcher->functionNamesByPriority[4] = (default_priority_4);
switcher->functionNamesByPriority[5] = (default_priority_5);
switcher->functionNamesByPriority[6] = (default_priority_6);
switcher->functionNamesByPriority[7] = (default_priority_7);
switcher->functionNamesByPriority[8] = (default_priority_8);
}
obs_data_set_default_int(obj, "threadPriority",
@@ -546,6 +558,7 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
obs_data_set_default_int(obj, "timeTabPos", 9);
obs_data_set_default_int(obj, "idleTabPos", 10);
obs_data_set_default_int(obj, "sequenceTabPos", 11);
obs_data_set_default_int(obj, "audioTabPos", 12);
switcher->tabOrder.emplace_back(
(int)(obs_data_get_int(obj, "generalTabPos")));
@@ -571,6 +584,8 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
(int)(obs_data_get_int(obj, "idleTabPos")));
switcher->tabOrder.emplace_back(
(int)(obs_data_get_int(obj, "sequenceTabPos")));
switcher->tabOrder.emplace_back(
(int)(obs_data_get_int(obj, "audioTabPos")));
}
void SceneSwitcher::setupGeneralTab()
@@ -625,30 +640,33 @@ void SceneSwitcher::setupGeneralTab()
for (int p : switcher->functionNamesByPriority) {
std::string s = "";
switch (p) {
case READ_FILE_FUNC:
case read_file_func:
s = "File Content";
break;
case ROUND_TRIP_FUNC:
case round_trip_func:
s = "Scene Sequence";
break;
case IDLE_FUNC:
case idle_func:
s = "Idle Detection";
break;
case EXE_FUNC:
case exe_func:
s = "Executable";
break;
case SCREEN_REGION_FUNC:
case screen_region_func:
s = "Screen Region";
break;
case WINDOW_TITLE_FUNC:
case window_title_func:
s = "Window Title";
break;
case MEDIA_FUNC:
case media_func:
s = "Media";
break;
case TIME_FUNC:
case time_func:
s = "Time";
break;
case audio_func:
s = "Audio";
break;
}
QString text(s.c_str());
QListWidgetItem *item =

View File

@@ -10,6 +10,7 @@
#include "ui_advanced-scene-switcher.h"
#endif
#include "switcher-data-structs.hpp"
#include "volume-control.hpp"
class QCloseEvent;
@@ -21,6 +22,7 @@ class SceneSwitcher : public QDialog {
public:
std::unique_ptr<Ui_SceneSwitcher> ui;
VolControl *volMeter = nullptr;
bool loading = true;
SceneSwitcher(QWidget *parent);
@@ -43,12 +45,14 @@ public:
int IgnoreIdleWindowsFindByData(const QString &window);
int randomFindByData(const QString &scene);
int timeFindByData(const timeTrigger &trigger, const QTime &time);
int audioFindByData(const QString &source, const int &volume);
void UpdateNonMatchingScene(const QString &name);
void UpdateAutoStopScene(const QString &name);
void UpdateAutoStartScene(const QString &name);
void UpdateIdleDataTransition(const QString &name);
void UpdateIdleDataScene(const QString &name);
void SetAudioVolumeMeter(const QString &name);
void loadUI();
void populateSceneSelection(QComboBox *sel, bool addPrevious);
@@ -66,6 +70,7 @@ public:
void setupMediaTab();
void setupFileTab();
void setupTimeTab();
void setupAudioTab();
void setTabOrder();
public slots:
@@ -175,6 +180,13 @@ public slots:
void on_timeUp_clicked();
void on_timeDown_clicked();
void on_audioAdd_clicked();
void on_audioRemove_clicked();
void on_audioUp_clicked();
void on_audioDown_clicked();
void on_audioSwitches_currentRowChanged(int idx);
void on_audioSources_currentTextChanged(const QString &text);
void on_priorityUp_clicked();
void on_priorityDown_clicked();
void on_threadPriority_currentTextChanged(const QString &text);
@@ -182,6 +194,8 @@ public slots:
void updateScreenRegionCursorPos();
void on_close_clicked();
private:
};
/********************************************************************************
@@ -234,9 +248,9 @@ void switchScene(OBSWeakSource &scene, OBSWeakSource &transition,
* Hotkey helper
********************************************************************************/
#define TOGGLE_HOTKEY_PATH "hotkey_toggle.txt"
#define STOP_HOTKEY_PATH "hotkey_stop.txt"
#define START_HOTKEY_PATH "hotkey_start.txt"
constexpr auto toggle_hotkey_path = "hotkey_toggle.txt";
constexpr auto stop_hotkey_path = "hotkey_stop.txt";
constexpr auto start_hotkey_path = "hotkey_start.txt";
void stopHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
bool pressed);

View File

@@ -11,29 +11,31 @@
#include <curl/curl.h>
#include "utility.hpp"
#define DEFAULT_INTERVAL 300
constexpr auto default_interval = 300;
#define DEFAULT_IDLE_TIME 60
constexpr auto default_idle_time = 60;
#define PREVIOUS_SCENE_NAME "Previous Scene"
constexpr auto previous_scene_name = "Previous Scene";
#define READ_FILE_FUNC 0
#define ROUND_TRIP_FUNC 1
#define IDLE_FUNC 2
#define EXE_FUNC 3
#define SCREEN_REGION_FUNC 4
#define WINDOW_TITLE_FUNC 5
#define MEDIA_FUNC 6
#define TIME_FUNC 7
constexpr auto read_file_func = 0;
constexpr auto round_trip_func = 1;
constexpr auto idle_func = 2;
constexpr auto exe_func = 3;
constexpr auto screen_region_func = 4;
constexpr auto window_title_func = 5;
constexpr auto media_func = 6;
constexpr auto time_func = 7;
constexpr auto audio_func = 8;
#define DEFAULT_PRIORITY_0 READ_FILE_FUNC
#define DEFAULT_PRIORITY_1 ROUND_TRIP_FUNC
#define DEFAULT_PRIORITY_2 IDLE_FUNC
#define DEFAULT_PRIORITY_3 EXE_FUNC
#define DEFAULT_PRIORITY_4 SCREEN_REGION_FUNC
#define DEFAULT_PRIORITY_5 WINDOW_TITLE_FUNC
#define DEFAULT_PRIORITY_6 MEDIA_FUNC
#define DEFAULT_PRIORITY_7 TIME_FUNC
constexpr auto default_priority_0 = read_file_func;
constexpr auto default_priority_1 = round_trip_func;
constexpr auto default_priority_2 = idle_func;
constexpr auto default_priority_3 = exe_func;
constexpr auto default_priority_4 = screen_region_func;
constexpr auto default_priority_5 = window_title_func;
constexpr auto default_priority_6 = media_func;
constexpr auto default_priority_7 = time_func;
constexpr auto default_priority_8 = audio_func;
/********************************************************************************
* Data structs for each scene switching method
@@ -199,7 +201,7 @@ struct FileIOData {
struct IdleData {
bool idleEnable = false;
int time = DEFAULT_IDLE_TIME;
int time = default_idle_time;
OBSWeakSource scene;
OBSWeakSource transition;
bool usePreviousScene;
@@ -238,7 +240,6 @@ struct TimeSwitch {
OBSWeakSource transition;
timeTrigger trigger;
QTime time;
bool matched;
bool usePreviousScene;
std::string timeSwitchStr;
@@ -255,6 +256,107 @@ struct TimeSwitch {
}
};
struct AudioSwitch {
OBSWeakSource scene;
OBSWeakSource audioSource;
OBSWeakSource transition;
int volumeThreshold;
float peak;
bool usePreviousScene;
obs_volmeter_t *volmeter;
std::string audioSwitchStr;
static void setVolumeLevel(void *data,
const float magnitude[MAX_AUDIO_CHANNELS],
const float peak[MAX_AUDIO_CHANNELS],
const float inputPeak[MAX_AUDIO_CHANNELS])
{
UNUSED_PARAMETER(magnitude);
UNUSED_PARAMETER(inputPeak);
AudioSwitch *s = static_cast<AudioSwitch *>(data);
s->peak = peak[0];
for (int i = 1; i < MAX_AUDIO_CHANNELS; i++)
if (peak[i] > s->peak)
s->peak = peak[i];
}
inline AudioSwitch(OBSWeakSource scene_, OBSWeakSource transition_,
OBSWeakSource audioSource_, int volumeThreshold_,
bool usePreviousScene_, std::string audioSwitchStr_)
: scene(scene_),
transition(transition_),
audioSource(audioSource_),
volumeThreshold(volumeThreshold_),
usePreviousScene(usePreviousScene_),
audioSwitchStr(audioSwitchStr_)
{
volmeter = obs_volmeter_create(OBS_FADER_LOG);
obs_volmeter_add_callback(volmeter, setVolumeLevel, this);
obs_source_t *as = obs_weak_source_get_source(audioSource);
if (!obs_volmeter_attach_source(volmeter, as)) {
const char *name = obs_source_get_name(as);
blog(LOG_WARNING,
"failed to attach volmeter to source %s", name);
}
obs_source_release(as);
}
AudioSwitch(const AudioSwitch &other)
: scene(other.scene),
transition(other.transition),
audioSource(other.audioSource),
volumeThreshold(other.volumeThreshold),
usePreviousScene(other.usePreviousScene),
audioSwitchStr(other.audioSwitchStr)
{
volmeter = obs_volmeter_create(OBS_FADER_LOG);
obs_volmeter_add_callback(volmeter, setVolumeLevel, this);
obs_source_t *as =
obs_weak_source_get_source(other.audioSource);
if (!obs_volmeter_attach_source(volmeter, as)) {
const char *name = obs_source_get_name(as);
blog(LOG_WARNING,
"failed to attach volmeter to source %s", name);
}
obs_source_release(as);
}
AudioSwitch(AudioSwitch &&other)
: scene(other.scene),
transition(other.transition),
audioSource(other.audioSource),
volumeThreshold(other.volumeThreshold),
usePreviousScene(other.usePreviousScene),
audioSwitchStr(other.audioSwitchStr),
volmeter(other.volmeter)
{
other.volmeter = nullptr;
}
inline ~AudioSwitch()
{
obs_volmeter_remove_callback(volmeter, setVolumeLevel, this);
obs_volmeter_destroy(volmeter);
}
AudioSwitch &operator=(const AudioSwitch &other)
{
return *this = AudioSwitch(other);
}
AudioSwitch &operator=(AudioSwitch &&other) noexcept
{
if (this == &other) {
return *this;
}
obs_volmeter_destroy(volmeter);
volmeter = other.volmeter;
other.volmeter = nullptr;
return *this;
}
};
typedef enum { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 } NoMatch;
typedef enum { PERSIST = 0, START = 1, STOP = 2 } StartupBehavior;
typedef enum {
@@ -280,7 +382,7 @@ struct SwitcherData {
bool verbose = false;
bool tansitionOverrideOverride = false;
int interval = DEFAULT_INTERVAL;
int interval = default_interval;
obs_source_t *waitScene = NULL; //scene during which wait started
OBSWeakSource previousScene = NULL;
@@ -330,10 +432,12 @@ struct SwitcherData {
std::vector<TimeSwitch> timeSwitches;
QDateTime liveTime;
std::vector<AudioSwitch> audioSwitches;
std::vector<int> functionNamesByPriority = std::vector<int>{
DEFAULT_PRIORITY_0, DEFAULT_PRIORITY_1, DEFAULT_PRIORITY_2,
DEFAULT_PRIORITY_3, DEFAULT_PRIORITY_4, DEFAULT_PRIORITY_5,
DEFAULT_PRIORITY_6, DEFAULT_PRIORITY_7};
default_priority_0, default_priority_1, default_priority_2,
default_priority_3, default_priority_4, default_priority_5,
default_priority_6, default_priority_7, default_priority_8};
struct ThreadPrio {
std::string name;
@@ -396,6 +500,8 @@ struct SwitcherData {
OBSWeakSource &transition);
void checkTimeSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition);
void checkAudioSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition);
void saveWindowTitleSwitches(obs_data_t *obj);
void saveScreenRegionSwitches(obs_data_t *obj);
@@ -408,6 +514,7 @@ struct SwitcherData {
void saveFileSwitches(obs_data_t *obj);
void saveMediaSwitches(obs_data_t *obj);
void saveTimeSwitches(obs_data_t *obj);
void saveAudioSwitches(obs_data_t *obj);
void saveGeneralSettings(obs_data_t *obj);
void loadWindowTitleSwitches(obs_data_t *obj);
@@ -421,6 +528,7 @@ struct SwitcherData {
void loadFileSwitches(obs_data_t *obj);
void loadMediaSwitches(obs_data_t *obj);
void loadTimeSwitches(obs_data_t *obj);
void loadAudioSwitches(obs_data_t *obj);
void loadGeneralSettings(obs_data_t *obj);
void Prune()
@@ -531,6 +639,15 @@ struct SwitcherData {
mediaSwitches.erase(mediaSwitches.begin() +
i--);
}
for (size_t i = 0; i < audioSwitches.size(); i++) {
AudioSwitch &s = audioSwitches[i];
if ((!s.usePreviousScene &&
!WeakSourceValid(s.scene)) ||
!WeakSourceValid(s.transition))
audioSwitches.erase(audioSwitches.begin() +
i--);
}
}
inline ~SwitcherData() { Stop(); }
};

View File

@@ -224,6 +224,19 @@ static inline QString MakeTimeSwitchName(const QString &scene,
return switchName;
}
static inline QString MakeAudioSwitchName(const QString &scene,
const QString &transition,
const QString &audioSrouce,
const int &volume)
{
QString switchName = QStringLiteral("When volume of ") + audioSrouce +
QStringLiteral(" is above ") +
QString::number(volume) +
QStringLiteral("% switch to ") + scene +
QStringLiteral(" using ") + transition;
return switchName;
}
static inline std::string GetWeakSourceName(obs_weak_source_t *weak_source)
{
std::string name;

View File

@@ -0,0 +1,245 @@
#pragma once
#include <obs.hpp>
#include <QWidget>
#include <QPaintEvent>
#include <QSharedPointer>
#include <QTimer>
#include <QMutex>
#include <QList>
class QPushButton;
class VolumeMeterTimer;
class VolumeMeter : public QWidget {
Q_OBJECT
Q_PROPERTY(QColor backgroundNominalColor READ getBackgroundNominalColor
WRITE setBackgroundNominalColor DESIGNABLE true)
Q_PROPERTY(QColor backgroundWarningColor READ getBackgroundWarningColor
WRITE setBackgroundWarningColor DESIGNABLE true)
Q_PROPERTY(QColor backgroundErrorColor READ getBackgroundErrorColor
WRITE setBackgroundErrorColor DESIGNABLE true)
Q_PROPERTY(QColor foregroundNominalColor READ getForegroundNominalColor
WRITE setForegroundNominalColor DESIGNABLE true)
Q_PROPERTY(QColor foregroundWarningColor READ getForegroundWarningColor
WRITE setForegroundWarningColor DESIGNABLE true)
Q_PROPERTY(QColor foregroundErrorColor READ getForegroundErrorColor
WRITE setForegroundErrorColor DESIGNABLE true)
Q_PROPERTY(QColor clipColor READ getClipColor WRITE setClipColor
DESIGNABLE true)
Q_PROPERTY(QColor magnitudeColor READ getMagnitudeColor WRITE
setMagnitudeColor DESIGNABLE true)
Q_PROPERTY(QColor majorTickColor READ getMajorTickColor WRITE
setMajorTickColor DESIGNABLE true)
Q_PROPERTY(QColor minorTickColor READ getMinorTickColor WRITE
setMinorTickColor DESIGNABLE true)
// Levels are denoted in dBFS.
Q_PROPERTY(qreal minimumLevel READ getMinimumLevel WRITE setMinimumLevel
DESIGNABLE true)
Q_PROPERTY(qreal warningLevel READ getWarningLevel WRITE setWarningLevel
DESIGNABLE true)
Q_PROPERTY(qreal errorLevel READ getErrorLevel WRITE setErrorLevel
DESIGNABLE true)
Q_PROPERTY(qreal clipLevel READ getClipLevel WRITE setClipLevel
DESIGNABLE true)
Q_PROPERTY(qreal minimumInputLevel READ getMinimumInputLevel WRITE
setMinimumInputLevel DESIGNABLE true)
// Rates are denoted in dB/second.
Q_PROPERTY(qreal peakDecayRate READ getPeakDecayRate WRITE
setPeakDecayRate DESIGNABLE true)
// Time in seconds for the VU meter to integrate over.
Q_PROPERTY(
qreal magnitudeIntegrationTime READ getMagnitudeIntegrationTime
WRITE setMagnitudeIntegrationTime DESIGNABLE true)
// Duration is denoted in seconds.
Q_PROPERTY(qreal peakHoldDuration READ getPeakHoldDuration WRITE
setPeakHoldDuration DESIGNABLE true)
Q_PROPERTY(qreal inputPeakHoldDuration READ getInputPeakHoldDuration
WRITE setInputPeakHoldDuration DESIGNABLE true)
private slots:
void ClipEnding();
private:
obs_volmeter_t *obs_volmeter;
static QWeakPointer<VolumeMeterTimer> updateTimer;
QSharedPointer<VolumeMeterTimer> updateTimerRef;
inline void resetLevels();
inline void handleChannelCofigurationChange();
inline bool detectIdle(uint64_t ts);
inline void calculateBallistics(uint64_t ts,
qreal timeSinceLastRedraw = 0.0);
inline void calculateBallisticsForChannel(int channelNr, uint64_t ts,
qreal timeSinceLastRedraw);
void paintInputMeter(QPainter &painter, int x, int y, int width,
int height, float peakHold);
void paintHMeter(QPainter &painter, int x, int y, int width, int height,
float magnitude, float peak, float peakHold);
void paintHTicks(QPainter &painter, int x, int y, int width,
int height);
void paintVMeter(QPainter &painter, int x, int y, int width, int height,
float magnitude, float peak, float peakHold);
void paintVTicks(QPainter &painter, int x, int y, int height);
QMutex dataMutex;
uint64_t currentLastUpdateTime = 0;
float currentMagnitude[MAX_AUDIO_CHANNELS];
float currentPeak[MAX_AUDIO_CHANNELS];
float currentInputPeak[MAX_AUDIO_CHANNELS];
QPixmap *tickPaintCache = nullptr;
int displayNrAudioChannels = 0;
float displayMagnitude[MAX_AUDIO_CHANNELS];
float displayPeak[MAX_AUDIO_CHANNELS];
float displayPeakHold[MAX_AUDIO_CHANNELS];
uint64_t displayPeakHoldLastUpdateTime[MAX_AUDIO_CHANNELS];
float displayInputPeakHold[MAX_AUDIO_CHANNELS];
uint64_t displayInputPeakHoldLastUpdateTime[MAX_AUDIO_CHANNELS];
QFont tickFont;
QColor backgroundNominalColor;
QColor backgroundWarningColor;
QColor backgroundErrorColor;
QColor foregroundNominalColor;
QColor foregroundWarningColor;
QColor foregroundErrorColor;
QColor clipColor;
QColor magnitudeColor;
QColor majorTickColor;
QColor minorTickColor;
qreal minimumLevel;
qreal warningLevel;
qreal errorLevel;
qreal clipLevel;
qreal minimumInputLevel;
qreal peakDecayRate;
qreal magnitudeIntegrationTime;
qreal peakHoldDuration;
qreal inputPeakHoldDuration;
uint64_t lastRedrawTime = 0;
int channels = 0;
bool clipping = false;
bool vertical;
public:
explicit VolumeMeter(QWidget *parent = nullptr,
obs_volmeter_t *obs_volmeter = nullptr,
bool vertical = false);
~VolumeMeter();
void setLevels(const float magnitude[MAX_AUDIO_CHANNELS],
const float peak[MAX_AUDIO_CHANNELS],
const float inputPeak[MAX_AUDIO_CHANNELS]);
QColor getBackgroundNominalColor() const;
void setBackgroundNominalColor(QColor c);
QColor getBackgroundWarningColor() const;
void setBackgroundWarningColor(QColor c);
QColor getBackgroundErrorColor() const;
void setBackgroundErrorColor(QColor c);
QColor getForegroundNominalColor() const;
void setForegroundNominalColor(QColor c);
QColor getForegroundWarningColor() const;
void setForegroundWarningColor(QColor c);
QColor getForegroundErrorColor() const;
void setForegroundErrorColor(QColor c);
QColor getClipColor() const;
void setClipColor(QColor c);
QColor getMagnitudeColor() const;
void setMagnitudeColor(QColor c);
QColor getMajorTickColor() const;
void setMajorTickColor(QColor c);
QColor getMinorTickColor() const;
void setMinorTickColor(QColor c);
qreal getMinimumLevel() const;
void setMinimumLevel(qreal v);
qreal getWarningLevel() const;
void setWarningLevel(qreal v);
qreal getErrorLevel() const;
void setErrorLevel(qreal v);
qreal getClipLevel() const;
void setClipLevel(qreal v);
qreal getMinimumInputLevel() const;
void setMinimumInputLevel(qreal v);
qreal getPeakDecayRate() const;
void setPeakDecayRate(qreal v);
qreal getMagnitudeIntegrationTime() const;
void setMagnitudeIntegrationTime(qreal v);
qreal getPeakHoldDuration() const;
void setPeakHoldDuration(qreal v);
qreal getInputPeakHoldDuration() const;
void setInputPeakHoldDuration(qreal v);
void setPeakMeterType(enum obs_peak_meter_type peakMeterType);
virtual void mousePressEvent(QMouseEvent *event) override;
protected:
void paintEvent(QPaintEvent *event) override;
};
class VolumeMeterTimer : public QTimer {
Q_OBJECT
public:
inline VolumeMeterTimer() : QTimer() {}
void AddVolControl(VolumeMeter *meter);
void RemoveVolControl(VolumeMeter *meter);
protected:
void timerEvent(QTimerEvent *event) override;
QList<VolumeMeter *> volumeMeters;
};
class QLabel;
class QSlider;
class MuteCheckBox;
class VolControl : public QWidget {
Q_OBJECT
private:
OBSSource source;
QLabel *nameLabel;
QLabel *volLabel;
VolumeMeter *volMeter;
QSlider *slider;
float levelTotal;
float levelCount;
obs_fader_t *obs_fader;
obs_volmeter_t *obs_volmeter;
bool vertical;
static void OBSVolumeChanged(void *param, float db);
static void OBSVolumeLevel(void *data,
const float magnitude[MAX_AUDIO_CHANNELS],
const float peak[MAX_AUDIO_CHANNELS],
const float inputPeak[MAX_AUDIO_CHANNELS]);
private slots:
void SliderChanged(int vol);
void updateText();
public:
explicit VolControl(OBSSource source, bool vertical = false);
~VolControl();
inline obs_source_t *GetSource() const { return source; }
QString GetName() const;
void SetName(const QString &newName);
void SetMeterDecayRate(qreal q);
void setPeakMeterType(enum obs_peak_meter_type peakMeterType);
void EnableSlider(bool enable);
QSlider *GetSlider() const;
};

View File

@@ -17,7 +17,7 @@ void startHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
if (hotkeyData != NULL) {
char *path = obs_module_config_path("");
std::ofstream file;
file.open(std::string(path).append(START_HOTKEY_PATH),
file.open(std::string(path).append(start_hotkey_path),
std::ofstream::trunc);
if (file.is_open()) {
size_t num = obs_data_array_count(hotkeyData);
@@ -51,7 +51,7 @@ void stopHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
if (hotkeyData != NULL) {
char *path = obs_module_config_path("");
std::ofstream file;
file.open(std::string(path).append(STOP_HOTKEY_PATH),
file.open(std::string(path).append(stop_hotkey_path),
std::ofstream::trunc);
if (file.is_open()) {
size_t num = obs_data_array_count(hotkeyData);
@@ -87,7 +87,7 @@ void startStopToggleHotkeyFunc(void *data, obs_hotkey_id id,
if (hotkeyData != NULL) {
char *path = obs_module_config_path("");
std::ofstream file;
file.open(std::string(path).append(TOGGLE_HOTKEY_PATH),
file.open(std::string(path).append(toggle_hotkey_path),
std::ofstream::trunc);
if (file.is_open()) {
size_t num = obs_data_array_count(hotkeyData);

View File

@@ -80,7 +80,7 @@ void SceneSwitcher::UpdateIdleDataTransition(const QString &name)
void SceneSwitcher::UpdateIdleDataScene(const QString &name)
{
switcher->idleData.usePreviousScene = (name == PREVIOUS_SCENE_NAME);
switcher->idleData.usePreviousScene = (name == previous_scene_name);
obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData());
obs_weak_source_t *ws = obs_source_get_weak_source(scene);
@@ -221,7 +221,7 @@ void SwitcherData::saveIdleSwitches(obs_data_t *obj)
obs_data_set_bool(obj, "idleEnable", switcher->idleData.idleEnable);
obs_data_set_string(obj, "idleSceneName",
switcher->idleData.usePreviousScene
? PREVIOUS_SCENE_NAME
? previous_scene_name
: idleSceneName.c_str());
obs_data_set_string(obj, "idleTransitionName",
idleTransitionName.c_str());
@@ -256,10 +256,10 @@ void SwitcherData::loadIdleSwitches(obs_data_t *obj)
GetWeakTransitionByName(idleTransitionName.c_str());
obs_data_set_default_bool(obj, "idleEnable", false);
switcher->idleData.idleEnable = obs_data_get_bool(obj, "idleEnable");
obs_data_set_default_int(obj, "idleTime", DEFAULT_IDLE_TIME);
obs_data_set_default_int(obj, "idleTime", default_idle_time);
switcher->idleData.time = obs_data_get_int(obj, "idleTime");
switcher->idleData.usePreviousScene =
(idleSceneName == PREVIOUS_SCENE_NAME);
(idleSceneName == previous_scene_name);
}
void SceneSwitcher::setupIdleTab()
@@ -279,7 +279,7 @@ void SceneSwitcher::setupIdleTab()
ui->idleCheckBox->setChecked(switcher->idleData.idleEnable);
ui->idleScenes->setCurrentText(
switcher->idleData.usePreviousScene
? PREVIOUS_SCENE_NAME
? previous_scene_name
: GetWeakSourceName(switcher->idleData.scene).c_str());
ui->idleTransitions->setCurrentText(
GetWeakSourceName(switcher->idleData.transition).c_str());

View File

@@ -63,7 +63,7 @@ void SceneSwitcher::on_mediaAdd_clicked()
std::lock_guard<std::mutex> lock(switcher->m);
switcher->mediaSwitches.emplace_back(
scene, source, transition, state, restriction, time,
(sceneName == QString(PREVIOUS_SCENE_NAME)),
(sceneName == QString(previous_scene_name)),
switchText.toUtf8().constData());
}
@@ -195,7 +195,7 @@ void SwitcherData::saveMediaSwitches(obs_data_t *obj)
obs_data_set_string(array_obj, "source", sourceName);
obs_data_set_string(array_obj, "scene",
s.usePreviousScene
? PREVIOUS_SCENE_NAME
? previous_scene_name
: sceneName);
obs_data_set_string(array_obj, "transition",
transitionName);
@@ -244,7 +244,7 @@ void SwitcherData::loadMediaSwitches(obs_data_t *obj)
switcher->mediaSwitches.emplace_back(
GetWeakSourceByName(scene), GetWeakSourceByName(source),
GetWeakTransitionByName(transition), state, restriction,
time, (strcmp(scene, PREVIOUS_SCENE_NAME) == 0),
time, (strcmp(scene, previous_scene_name) == 0),
mediaStr);
obs_data_release(array_obj);
@@ -287,7 +287,7 @@ void SceneSwitcher::setupMediaTab()
for (auto &s : switcher->mediaSwitches) {
std::string sourceName = GetWeakSourceName(s.source);
std::string sceneName = (s.usePreviousScene)
? PREVIOUS_SCENE_NAME
? previous_scene_name
: GetWeakSourceName(s.scene);
std::string transitionName = GetWeakSourceName(s.transition);
QString listText = MakeMediaSwitchName(

View File

@@ -61,7 +61,7 @@ bool SwitcherData::prioFuncsValid()
return false;
for (int p : functionNamesByPriority) {
if (p < 0 || p > 7)
if (p < 0 || p > 8)
return false;
}
return true;

View File

@@ -78,7 +78,7 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked()
std::lock_guard<std::mutex> lock(switcher->m);
switcher->sceneRoundTripSwitches.emplace_back(
source1, source2, transition, delay,
(scene2Name == QString(PREVIOUS_SCENE_NAME)),
(scene2Name == QString(previous_scene_name)),
text.toUtf8().constData());
} else {
QListWidgetItem *item = ui->sceneRoundTrips->item(idx);
@@ -93,7 +93,7 @@ void SceneSwitcher::on_sceneRoundTripAdd_clicked()
s.transition = transition;
s.usePreviousScene =
(scene2Name ==
QString(PREVIOUS_SCENE_NAME));
QString(previous_scene_name));
s.sceneRoundTripStr =
text.toUtf8().constData();
break;
@@ -164,7 +164,7 @@ bool oldSceneRoundTripLoad(QFile *file)
GetWeakTransitionByQString(lines[4]);
if (WeakSourceValid(scene1) &&
((lines[1] == QString(PREVIOUS_SCENE_NAME)) ||
((lines[1] == QString(previous_scene_name)) ||
(WeakSourceValid(scene2))) &&
WeakSourceValid(transition)) {
newSceneRoundTripSwitch.emplace_back(
@@ -175,7 +175,7 @@ bool oldSceneRoundTripLoad(QFile *file)
lines[4]),
lines[2].toDouble() / 1000.,
(lines[1] ==
QString(PREVIOUS_SCENE_NAME)),
QString(previous_scene_name)),
lines[3].toStdString()));
}
lines.clear();
@@ -380,7 +380,7 @@ void SwitcherData::saveSceneRoundTripSwitches(obs_data_t *obj)
sceneName1);
obs_data_set_string(array_obj, "sceneRoundTripScene2",
s.usePreviousScene
? PREVIOUS_SCENE_NAME
? previous_scene_name
: sceneName2);
obs_data_set_string(array_obj, "transition",
transitionName);
@@ -444,7 +444,7 @@ void SwitcherData::loadSceneRoundTripSwitches(obs_data_t *obj)
GetWeakSourceByName(scene1),
GetWeakSourceByName(scene2),
GetWeakTransitionByName(transition), delay,
(strcmp(scene2, PREVIOUS_SCENE_NAME) == 0),
(strcmp(scene2, previous_scene_name) == 0),
sceneRoundTripStr);
obs_data_release(array_obj);
@@ -462,7 +462,7 @@ void SceneSwitcher::setupSequenceTab()
for (auto &s : switcher->sceneRoundTripSwitches) {
std::string sceneName1 = GetWeakSourceName(s.scene1);
std::string sceneName2 = (s.usePreviousScene)
? PREVIOUS_SCENE_NAME
? previous_scene_name
: GetWeakSourceName(s.scene2);
std::string transitionName = GetWeakSourceName(s.transition);
QString text = MakeSceneRoundTripSwitchName(

View File

@@ -85,7 +85,7 @@ void SceneSwitcher::on_timeAdd_clicked()
std::lock_guard<std::mutex> lock(switcher->m);
switcher->timeSwitches.emplace_back(
source, transition, trigger, time,
(sceneName == QString(PREVIOUS_SCENE_NAME)),
(sceneName == QString(previous_scene_name)),
text.toUtf8().constData());
QListWidgetItem *item =
@@ -104,7 +104,7 @@ void SceneSwitcher::on_timeAdd_clicked()
s.transition = transition;
s.usePreviousScene =
(sceneName ==
QString(PREVIOUS_SCENE_NAME));
QString(previous_scene_name));
s.timeSwitchStr =
text.toUtf8().constData();
break;
@@ -196,7 +196,6 @@ bool checkLiveTime(TimeSwitch &s, QDateTime &start, int &interval)
bool checkRegularTime(TimeSwitch &s, int &interval)
{
bool match = false;
if (s.trigger != ANY_DAY &&
s.trigger != QDate::currentDate().dayOfWeek())
return false;
@@ -248,7 +247,7 @@ void SwitcherData::saveTimeSwitches(obs_data_t *obj)
obs_source_get_name(transition);
obs_data_set_string(array_obj, "scene",
s.usePreviousScene
? PREVIOUS_SCENE_NAME
? previous_scene_name
: sceneName);
obs_data_set_string(array_obj, "transition",
transitionName);
@@ -293,7 +292,7 @@ void SwitcherData::loadTimeSwitches(obs_data_t *obj)
switcher->timeSwitches.emplace_back(
GetWeakSourceByName(scene),
GetWeakTransitionByName(transition), trigger, time,
(strcmp(scene, PREVIOUS_SCENE_NAME) == 0),
(strcmp(scene, previous_scene_name) == 0),
timeSwitchStr);
obs_data_release(array_obj);
@@ -318,7 +317,7 @@ void SceneSwitcher::setupTimeTab()
for (auto &s : switcher->timeSwitches) {
std::string sceneName = (s.usePreviousScene)
? PREVIOUS_SCENE_NAME
? previous_scene_name
: GetWeakSourceName(s.scene);
std::string transitionName = GetWeakSourceName(s.transition);
QString listText = MakeTimeSwitchName(sceneName.c_str(),

1002
src/volume-control.cpp Normal file

File diff suppressed because it is too large Load Diff