mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-22 01:44:49 -05:00
Merge remote-tracking branch 'WarmUpTill/master'
This commit is contained in:
commit
8fd263f44a
|
|
@ -365,7 +365,7 @@
|
|||
<item>
|
||||
<widget class="QLabel" name="label_56">
|
||||
<property name="text">
|
||||
<string>Use thread priority (experimental)</string>
|
||||
<string>Use thread priority</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -385,6 +385,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_57">
|
||||
<property name="text">
|
||||
<string>(raising the priority higher than "Normal" is usually not recommended)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_41">
|
||||
<property name="orientation">
|
||||
|
|
|
|||
|
|
@ -64,8 +64,7 @@ SceneSwitcher::SceneSwitcher(QWidget *parent)
|
|||
auto sourceEnum = [](void *data, obs_source_t *source) -> bool /* -- */
|
||||
{
|
||||
QComboBox *combo = reinterpret_cast<QComboBox *>(data);
|
||||
if (obs_source_media_get_state(source) !=
|
||||
OBS_MEDIA_STATE_NONE) {
|
||||
if (strcmp(obs_source_get_id(source), "ffmpeg_source") == 0) {
|
||||
const char *name = obs_source_get_name(source);
|
||||
combo->addItem(name);
|
||||
}
|
||||
|
|
@ -354,7 +353,7 @@ SceneSwitcher::SceneSwitcher(QWidget *parent)
|
|||
ui->readPathLineEdit->setDisabled(true);
|
||||
}
|
||||
|
||||
if (switcher->th.joinable())
|
||||
if (switcher->th && switcher->th->isRunning())
|
||||
SetStarted();
|
||||
else
|
||||
SetStopped();
|
||||
|
|
@ -401,8 +400,17 @@ SceneSwitcher::SceneSwitcher(QWidget *parent)
|
|||
item->setData(Qt::UserRole, text);
|
||||
}
|
||||
|
||||
for (std::string p : switcher->threadPrioritiesNamesOrderdByPrio) {
|
||||
ui->threadPriority->addItem(p.c_str());
|
||||
for (int i = 0; i < switcher->threadPriorities.size(); ++i) {
|
||||
ui->threadPriority->addItem(
|
||||
switcher->threadPriorities[i].name.c_str());
|
||||
ui->threadPriority->setItemData(
|
||||
i, switcher->threadPriorities[i].description.c_str(),
|
||||
Qt::ToolTipRole);
|
||||
if (switcher->threadPriority ==
|
||||
switcher->threadPriorities[i].value) {
|
||||
ui->threadPriority->setCurrentText(
|
||||
switcher->threadPriorities[i].name.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -885,6 +893,9 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||
obs_data_set_int(obj, "priority7",
|
||||
switcher->functionNamesByPriority[7]);
|
||||
|
||||
obs_data_set_int(obj, "threadPriority",
|
||||
switcher->threadPriority);
|
||||
|
||||
obs_data_set_obj(save_data, "advanced-scene-switcher", obj);
|
||||
|
||||
obs_data_array_release(array);
|
||||
|
|
@ -1246,12 +1257,19 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||
array_obj, "restriction");
|
||||
uint64_t time = obs_data_get_int(array_obj, "time");
|
||||
|
||||
string mediaStr = MakeMediaSwitchName(source, scene,
|
||||
transition, state,
|
||||
restriction, time)
|
||||
.toUtf8()
|
||||
.constData();
|
||||
|
||||
switcher->mediaSwitches.emplace_back(
|
||||
GetWeakSourceByName(scene),
|
||||
GetWeakSourceByName(source),
|
||||
GetWeakTransitionByName(transition), state,
|
||||
restriction, time,
|
||||
(strcmp(scene, PREVIOUS_SCENE_NAME) == 0));
|
||||
(strcmp(scene, PREVIOUS_SCENE_NAME) == 0),
|
||||
mediaStr);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
|
|
@ -1362,6 +1380,11 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||
(DEFAULT_PRIORITY_7);
|
||||
}
|
||||
|
||||
obs_data_set_default_int(obj, "threadPriority",
|
||||
QThread::NormalPriority);
|
||||
switcher->threadPriority =
|
||||
obs_data_get_int(obj, "threadPriority");
|
||||
|
||||
obs_data_array_release(array);
|
||||
obs_data_array_release(screenRegionArray);
|
||||
obs_data_array_release(pauseScenesArray);
|
||||
|
|
@ -1392,6 +1415,7 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||
********************************************************************************/
|
||||
void SwitcherData::Thread()
|
||||
{
|
||||
blog(LOG_INFO, "Advanced Scene Switcher started");
|
||||
//to avoid scene duplication when rapidly switching scene collection
|
||||
this_thread::sleep_for(chrono::seconds(2));
|
||||
|
||||
|
|
@ -1483,7 +1507,8 @@ void SwitcherData::Thread()
|
|||
switchScene(scene, transition, lock);
|
||||
}
|
||||
}
|
||||
endLoop:;
|
||||
endLoop:
|
||||
blog(LOG_INFO, "Advanced Scene Switcher stopped");
|
||||
}
|
||||
|
||||
void switchScene(OBSWeakSource &scene, OBSWeakSource &transition,
|
||||
|
|
@ -1542,19 +1567,23 @@ bool SwitcherData::sceneChangedDuringWait()
|
|||
|
||||
void SwitcherData::Start()
|
||||
{
|
||||
if (!th.joinable()) {
|
||||
if (!(th && th->isRunning())) {
|
||||
stop = false;
|
||||
switcher->th = thread([]() { switcher->Thread(); });
|
||||
switcher->th = new SwitcherThread();
|
||||
switcher->th->start((QThread::Priority)switcher->threadPriority);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SwitcherData::Stop()
|
||||
{
|
||||
if (th.joinable()) {
|
||||
if (th && th->isRunning()) {
|
||||
switcher->stop = true;
|
||||
transitionCv.notify_one();
|
||||
cv.notify_one();
|
||||
th.join();
|
||||
th->wait();
|
||||
delete th;
|
||||
th = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ void SceneSwitcher::SetStopped()
|
|||
|
||||
void SceneSwitcher::on_toggleStartButton_clicked()
|
||||
{
|
||||
if (switcher->th.joinable())
|
||||
if (switcher->th && switcher->th->isRunning())
|
||||
{
|
||||
switcher->Stop();
|
||||
SetStopped();
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ public slots:
|
|||
void on_fileScenesList_currentRowChanged(int idx);
|
||||
void on_browseButton_3_clicked();
|
||||
|
||||
void on_mediaSwitches_currentRowChanged(int idx);
|
||||
void on_mediaAdd_clicked();
|
||||
void on_mediaRemove_clicked();
|
||||
|
||||
|
|
@ -129,6 +130,7 @@ public slots:
|
|||
|
||||
void on_priorityUp_clicked();
|
||||
void on_priorityDown_clicked();
|
||||
void on_threadPriority_currentTextChanged(const QString &text);
|
||||
|
||||
void updateScreenRegionCursorPos();
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
#include <chrono>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <regex>
|
||||
#include <mutex>
|
||||
#include <fstream>
|
||||
|
|
@ -214,18 +213,20 @@ struct MediaSwitch {
|
|||
time_restriction restriction;
|
||||
bool matched;
|
||||
bool usePreviousScene;
|
||||
std::string mediaSwitchStr;
|
||||
|
||||
inline MediaSwitch(OBSWeakSource scene_, OBSWeakSource source_,
|
||||
OBSWeakSource transition_, obs_media_state state_,
|
||||
time_restriction restriction_, uint64_t time_,
|
||||
bool usePreviousScene_)
|
||||
bool usePreviousScene_, std::string mediaSwitchStr_)
|
||||
: scene(scene_),
|
||||
source(source_),
|
||||
transition(transition_),
|
||||
state(state_),
|
||||
restriction(restriction_),
|
||||
time(time_),
|
||||
usePreviousScene(usePreviousScene_)
|
||||
usePreviousScene(usePreviousScene_),
|
||||
mediaSwitchStr(mediaSwitchStr_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
@ -252,11 +253,14 @@ struct TimeSwitch {
|
|||
|
||||
typedef enum { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 } NoMatch;
|
||||
|
||||
class SwitcherThread;
|
||||
|
||||
/********************************************************************************
|
||||
* SwitcherData
|
||||
********************************************************************************/
|
||||
struct SwitcherData {
|
||||
thread th;
|
||||
SwitcherThread *th;
|
||||
|
||||
condition_variable cv;
|
||||
mutex m;
|
||||
bool transitionActive = false;
|
||||
|
|
@ -311,18 +315,33 @@ struct SwitcherData {
|
|||
DEFAULT_PRIORITY_3, DEFAULT_PRIORITY_4, DEFAULT_PRIORITY_5,
|
||||
DEFAULT_PRIORITY_6, DEFAULT_PRIORITY_7};
|
||||
|
||||
std::vector<std::string> threadPrioritiesNamesOrderdByPrio{
|
||||
"Lowest", "Low", "Normal", "High", "Highest", "Time critical",
|
||||
struct ThreadPrio {
|
||||
std::string name;
|
||||
std::string description;
|
||||
uint32_t value;
|
||||
};
|
||||
std::map<std::string, int> threadPriorities = {
|
||||
{"Lowest", QThread::LowestPriority},
|
||||
{"Low", QThread::LowPriority},
|
||||
{"Normal", QThread::NormalPriority},
|
||||
{"High", QThread::HighPriority},
|
||||
{"Highest", QThread::HighestPriority},
|
||||
{"Time critical", QThread::TimeCriticalPriority},
|
||||
|
||||
std::vector<ThreadPrio> threadPriorities{
|
||||
{"Idle",
|
||||
"scheduled only when no other threads are running (lowest CPU load)",
|
||||
QThread::IdlePriority},
|
||||
{"Lowest", "scheduled less often than LowPriority",
|
||||
QThread::LowestPriority},
|
||||
{"Low", "scheduled less often than NormalPriority",
|
||||
QThread::LowPriority},
|
||||
{"Normal", "the default priority of the operating system",
|
||||
QThread::NormalPriority},
|
||||
{"High", "scheduled more often than NormalPriority",
|
||||
QThread::HighPriority},
|
||||
{"Highest", "scheduled more often than HighPriority",
|
||||
QThread::HighestPriority},
|
||||
{"Time critical",
|
||||
"scheduled as often as possible (highest CPU load)",
|
||||
QThread::TimeCriticalPriority},
|
||||
};
|
||||
|
||||
uint32_t threadPriority = QThread::NormalPriority;
|
||||
|
||||
void Thread();
|
||||
void Start();
|
||||
void Stop();
|
||||
|
|
@ -442,7 +461,8 @@ struct SwitcherData {
|
|||
|
||||
for (size_t i = 0; i < timeSwitches.size(); i++) {
|
||||
TimeSwitch &s = timeSwitches[i];
|
||||
if (!WeakSourceValid(s.scene) ||
|
||||
if ((!s.usePreviousScene &&
|
||||
!WeakSourceValid(s.scene)) ||
|
||||
!WeakSourceValid(s.transition))
|
||||
timeSwitches.erase(timeSwitches.begin() + i--);
|
||||
}
|
||||
|
|
@ -452,6 +472,23 @@ struct SwitcherData {
|
|||
!WeakSourceValid(idleData.transition)) {
|
||||
idleData.idleEnable = false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mediaSwitches.size(); i++) {
|
||||
MediaSwitch &s = mediaSwitches[i];
|
||||
if ((!s.usePreviousScene &&
|
||||
!WeakSourceValid(s.scene)) ||
|
||||
!WeakSourceValid(s.source) ||
|
||||
!WeakSourceValid(s.transition))
|
||||
mediaSwitches.erase(mediaSwitches.begin() +
|
||||
i--);
|
||||
}
|
||||
}
|
||||
inline ~SwitcherData() { Stop(); }
|
||||
};
|
||||
|
||||
extern SwitcherData *switcher;
|
||||
class SwitcherThread : public QThread {
|
||||
public:
|
||||
explicit SwitcherThread(){};
|
||||
void run() { switcher->Thread(); };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ void startHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pr
|
|||
|
||||
if (pressed)
|
||||
{
|
||||
if (!switcher->th.joinable())
|
||||
if (!(switcher->th && switcher->th->isRunning()))
|
||||
switcher->Start();
|
||||
}
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ void stopHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pre
|
|||
|
||||
if (pressed)
|
||||
{
|
||||
if (switcher->th.joinable())
|
||||
if (switcher->th && switcher->th->isRunning())
|
||||
switcher->Stop();
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ void startStopToggleHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotke
|
|||
|
||||
if (pressed)
|
||||
{
|
||||
if (switcher->th.joinable())
|
||||
if (switcher->th && switcher->th->isRunning())
|
||||
switcher->Stop();
|
||||
else
|
||||
switcher->Start();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,37 @@
|
|||
#include <obs-module.h>
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
void SceneSwitcher::on_mediaSwitches_currentRowChanged(int idx)
|
||||
{
|
||||
if (loading)
|
||||
return;
|
||||
if (idx == -1)
|
||||
return;
|
||||
|
||||
QListWidgetItem *item = ui->mediaSwitches->item(idx);
|
||||
|
||||
QString mediaSceneStr = item->data(Qt::UserRole).toString();
|
||||
|
||||
lock_guard<mutex> lock(switcher->m);
|
||||
for (auto &s : switcher->mediaSwitches) {
|
||||
if (mediaSceneStr.compare(s.mediaSwitchStr.c_str()) == 0) {
|
||||
QString sceneName = GetWeakSourceName(s.scene).c_str();
|
||||
QString sourceName =
|
||||
GetWeakSourceName(s.source).c_str();
|
||||
QString transitionName =
|
||||
GetWeakSourceName(s.transition).c_str();
|
||||
ui->mediaScenes->setCurrentText(sceneName);
|
||||
ui->mediaSources->setCurrentText(sourceName);
|
||||
ui->mediaTransitions->setCurrentText(transitionName);
|
||||
ui->mediaStates->setCurrentIndex(s.state);
|
||||
ui->mediaTimeRestrictions->setCurrentIndex(
|
||||
s.restriction);
|
||||
ui->mediaTime->setValue(s.time);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_mediaAdd_clicked()
|
||||
{
|
||||
QString sourceName = ui->mediaSources->currentText();
|
||||
|
|
@ -32,7 +63,8 @@ void SceneSwitcher::on_mediaAdd_clicked()
|
|||
lock_guard<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());
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_mediaRemove_clicked()
|
||||
|
|
@ -41,17 +73,23 @@ void SceneSwitcher::on_mediaRemove_clicked()
|
|||
if (!item)
|
||||
return;
|
||||
|
||||
int idx = ui->mediaSwitches->currentRow();
|
||||
if (idx == -1)
|
||||
return;
|
||||
|
||||
string mediaStr =
|
||||
item->data(Qt::UserRole).toString().toUtf8().constData();
|
||||
{
|
||||
lock_guard<mutex> lock(switcher->m);
|
||||
|
||||
auto &switches = switcher->mediaSwitches;
|
||||
switches.erase(switches.begin() + idx);
|
||||
|
||||
for (auto it = switches.begin(); it != switches.end(); ++it) {
|
||||
auto &s = *it;
|
||||
|
||||
if (s.mediaSwitchStr == mediaStr) {
|
||||
switches.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
qDeleteAll(ui->mediaSwitches->selectedItems());
|
||||
|
||||
delete item;
|
||||
}
|
||||
|
||||
void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene,
|
||||
|
|
@ -86,5 +124,6 @@ void SwitcherData::checkMediaSwitch(bool &match, OBSWeakSource &scene,
|
|||
transition = mediaSwitch.transition;
|
||||
}
|
||||
mediaSwitch.matched = matched;
|
||||
obs_source_release(source);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,44 +1,68 @@
|
|||
#include <algorithm>
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
void SceneSwitcher::on_threadPriority_currentTextChanged(const QString &text)
|
||||
{
|
||||
if (loading || ui->threadPriority->count() != switcher->threadPriorities.size())
|
||||
return;
|
||||
|
||||
lock_guard<mutex> lock(switcher->m);
|
||||
|
||||
for (auto p : switcher->threadPriorities) {
|
||||
if (p.name == text.toUtf8()
|
||||
.constData()) {
|
||||
switcher->threadPriority = p.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_priorityUp_clicked()
|
||||
{
|
||||
int currentIndex = ui->priorityList->currentRow();
|
||||
if (currentIndex != -1 && currentIndex != 0)
|
||||
{
|
||||
ui->priorityList->insertItem(currentIndex - 1 ,ui->priorityList->takeItem(currentIndex));
|
||||
ui->priorityList->setCurrentRow(currentIndex -1);
|
||||
if (currentIndex != -1 && currentIndex != 0) {
|
||||
ui->priorityList->insertItem(
|
||||
currentIndex - 1,
|
||||
ui->priorityList->takeItem(currentIndex));
|
||||
ui->priorityList->setCurrentRow(currentIndex - 1);
|
||||
lock_guard<mutex> lock(switcher->m);
|
||||
|
||||
iter_swap(switcher->functionNamesByPriority.begin() + currentIndex, switcher->functionNamesByPriority.begin() + currentIndex - 1);
|
||||
iter_swap(switcher->functionNamesByPriority.begin() +
|
||||
currentIndex,
|
||||
switcher->functionNamesByPriority.begin() +
|
||||
currentIndex - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_priorityDown_clicked()
|
||||
{
|
||||
int currentIndex = ui->priorityList->currentRow();
|
||||
if (currentIndex != -1 && currentIndex != ui->priorityList->count() - 1)
|
||||
{
|
||||
ui->priorityList->insertItem(currentIndex + 1, ui->priorityList->takeItem(currentIndex));
|
||||
if (currentIndex != -1 &&
|
||||
currentIndex != ui->priorityList->count() - 1) {
|
||||
ui->priorityList->insertItem(
|
||||
currentIndex + 1,
|
||||
ui->priorityList->takeItem(currentIndex));
|
||||
ui->priorityList->setCurrentRow(currentIndex + 1);
|
||||
lock_guard<mutex> lock(switcher->m);
|
||||
|
||||
iter_swap(switcher->functionNamesByPriority.begin() + currentIndex, switcher->functionNamesByPriority.begin() + currentIndex + 1);
|
||||
iter_swap(switcher->functionNamesByPriority.begin() +
|
||||
currentIndex,
|
||||
switcher->functionNamesByPriority.begin() +
|
||||
currentIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
bool SwitcherData::prioFuncsValid()
|
||||
{
|
||||
auto it = std::unique(functionNamesByPriority.begin(), functionNamesByPriority.end());
|
||||
auto it = std::unique(functionNamesByPriority.begin(),
|
||||
functionNamesByPriority.end());
|
||||
bool wasUnique = (it == functionNamesByPriority.end());
|
||||
if (!wasUnique)
|
||||
return false;
|
||||
|
||||
for (int p : functionNamesByPriority)
|
||||
{
|
||||
for (int p : functionNamesByPriority) {
|
||||
if (p < 0 || p > 7)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user