add linger variable instead of sleeping inside sequence match (#105)

This solves issues with the busy loop detection and adds the possibility of other switching methods to delay the scene switch
This commit is contained in:
WarmUpTill 2021-01-23 20:32:32 +01:00 committed by GitHub
parent d989c2b570
commit fe9457427f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 36 deletions

View File

@ -424,6 +424,7 @@ void SwitcherData::Thread()
{
blog(LOG_INFO, "started");
int sleep = 0;
int linger = 0;
std::chrono::milliseconds duration;
auto startTime = std::chrono::high_resolution_clock::now();
auto endTime = std::chrono::high_resolution_clock::now();
@ -447,8 +448,8 @@ void SwitcherData::Thread()
if (sleep) {
duration = std::chrono::milliseconds(sleep);
} else {
duration =
std::chrono::milliseconds(interval) - runTime;
duration = std::chrono::milliseconds(interval) +
std::chrono::milliseconds(linger) - runTime;
if (duration.count() < 1) {
blog(LOG_INFO,
"detected busy loop - refusing to sleep less than 1ms");
@ -463,6 +464,7 @@ void SwitcherData::Thread()
startTime = std::chrono::high_resolution_clock::now();
sleep = 0;
linger = 0;
switcher->Prune();
@ -507,7 +509,7 @@ void SwitcherData::Thread()
break;
case round_trip_func:
checkSceneSequence(match, scene, transition,
lock);
linger);
break;
case media_func:
checkMediaSwitch(match, scene, transition);
@ -532,6 +534,29 @@ void SwitcherData::Thread()
checkSwitchCooldown(match);
if (linger) {
duration = std::chrono::milliseconds(linger);
if (verbose)
blog(LOG_INFO,
"sleep for %ld before switching scene",
duration.count());
cv.wait_for(lock, duration);
if (switcher->stop) {
break;
}
if (sceneChangedDuringWait()) {
if (verbose)
blog(LOG_INFO,
"scene was changed manually - ignoring match",
duration.count());
match = false;
linger = 0;
}
}
// After this point we will call frontend functions
// obs_frontend_set_current_scene() and
// obs_frontend_set_current_transition()

View File

@ -21,7 +21,6 @@ struct SceneSequenceSwitch : SceneSwitcherEntry {
const char *getType() { return "sequence"; }
bool initialized();
bool valid();
void logSleep(int dur);
void save(obs_data_t *obj);
void load(obs_data_t *obj);
};

View File

@ -173,8 +173,7 @@ struct SwitcherData {
OBSWeakSource &transition);
void setCurrentDefTransition(OBSWeakSource &transition);
void checkSceneSequence(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition,
std::unique_lock<std::mutex> &lock);
OBSWeakSource &transition, int &linger);
void checkIdleSwitch(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition);
void checkWindowTitleSwitch(bool &match, OBSWeakSource &scene,

View File

@ -162,37 +162,20 @@ bool matchInterruptible(SwitcherData *switcher, SceneSequenceSwitch &s)
}
bool matchUninterruptible(SwitcherData *switcher, SceneSequenceSwitch &s,
obs_source_t *currentSource,
std::unique_lock<std::mutex> &lock)
obs_source_t *currentSource, int &linger)
{
bool ret = false;
// scene was already active for the previous cycle so remove this time
int dur = s.delay * 1000 - switcher->interval;
if (dur > 0) {
switcher->waitScene = currentSource;
if (switcher->verbose)
s.logSleep(dur);
switcher->cv.wait_for(lock, std::chrono::milliseconds(dur));
switcher->waitScene = nullptr;
}
obs_source_t *currentSource2 = obs_frontend_get_current_scene();
// only switch if user hasn't changed scene manually
if (currentSource == currentSource2) {
ret = true;
} else if (switcher->verbose) {
blog(LOG_INFO, "sequence canceled");
linger = dur;
}
obs_source_release(currentSource2);
return ret;
return true;
}
void SwitcherData::checkSceneSequence(bool &match, OBSWeakSource &scene,
OBSWeakSource &transition,
std::unique_lock<std::mutex> &lock)
OBSWeakSource &transition, int &linger)
{
if (SceneSequenceSwitch::pause)
return;
@ -211,13 +194,11 @@ void SwitcherData::checkSceneSequence(bool &match, OBSWeakSource &scene,
} else {
match = matchUninterruptible(
switcher, s, currentSource,
lock);
linger);
}
if (match) {
scene = (s.usePreviousScene)
? switcher->previousScene
: s.getScene();
scene = s.getScene();
transition = s.transition;
if (switcher->verbose)
s.logMatch();
@ -292,11 +273,6 @@ bool SceneSequenceSwitch::valid()
(SceneSwitcherEntry::valid() && WeakSourceValid(startScene));
}
void SceneSequenceSwitch::logSleep(int dur)
{
blog(LOG_INFO, "sequence sleep %d", dur);
}
void SceneSequenceSwitch::save(obs_data_t *obj)
{
SceneSwitcherEntry::save(obj);