Compare commits

..

4 Commits

Author SHA1 Message Date
WarmUpTill
267855fded Cleanup
* Use OBSSourceAutoRelease
* Do not return true if source selection is invalid
2023-12-17 10:40:29 +01:00
WarmUpTill
4bdebb7feb Fix crash when asking for settings backup
This dialog cannot be modal since other plugins might attempt to display
content which might result in a deadlock.
2023-12-16 19:02:38 +01:00
Michael Kirsch
ab5f69d2ef Decrease the minimal interval time to 10ms 2023-12-13 19:29:14 +01:00
Michael Kirsch
63ee36ddfe Enable Area Selection in ScreenshotHelper class 2023-12-13 14:19:17 +01:00
8 changed files with 90 additions and 67 deletions

View File

@@ -119,7 +119,7 @@
<string notr="true">ms</string> <string notr="true">ms</string>
</property> </property>
<property name="minimum"> <property name="minimum">
<number>50</number> <number>10</number>
</property> </property>
<property name="maximum"> <property name="maximum">
<number>20000</number> <number>20000</number>

View File

@@ -10,6 +10,7 @@
#include <QMainWindow> #include <QMainWindow>
#include <QAction> #include <QAction>
#include <QFileDialog> #include <QFileDialog>
#include <QTextStream>
#include <QDirIterator> #include <QDirIterator>
#include <regex> #include <regex>
#include <filesystem> #include <filesystem>
@@ -135,7 +136,7 @@ bool AdvSceneSwitcher::eventFilter(QObject *obj, QEvent *event)
/****************************************************************************** /******************************************************************************
* Saving and loading * Saving and loading
******************************************************************************/ ******************************************************************************/
static void AskForBackup(obs_data_t *obj); static void AskForBackup(const QString &json);
static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *) static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
{ {
@@ -156,16 +157,25 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
switcher->Stop(); switcher->Stop();
switcher->m.lock(); switcher->m.lock();
obs_data_t *obj = OBSDataAutoRelease obj =
obs_data_get_obj(save_data, "advanced-scene-switcher"); obs_data_get_obj(save_data, "advanced-scene-switcher");
if (!obj) { if (!obj) {
obj = obs_data_create(); obj = obs_data_create();
} }
if (switcher->VersionChanged(obj, g_GIT_SHA1)) { if (switcher->VersionChanged(obj, g_GIT_SHA1)) {
AskForBackup(obj); auto json = obs_data_get_json(obj);
static QString jsonQString = json ? json : "";
std::thread t([]() {
obs_queue_task(
OBS_TASK_UI,
[](void *) {
AskForBackup(jsonQString);
},
nullptr, false);
});
t.detach();
} }
switcher->LoadSettings(obj); switcher->LoadSettings(obj);
obs_data_release(obj);
switcher->m.unlock(); switcher->m.unlock();
if (!switcher->stop) { if (!switcher->stop) {
@@ -174,12 +184,12 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
} }
} }
static void AskForBackup(obs_data_t *obj) static void AskForBackup(const QString &json)
{ {
bool backupSettings = DisplayMessage( const bool backupWasConfirmed = DisplayMessage(
obs_module_text("AdvSceneSwitcher.askBackup"), true); obs_module_text("AdvSceneSwitcher.askBackup"), true, false);
if (!backupSettings) { if (!backupWasConfirmed) {
return; return;
} }
@@ -198,8 +208,8 @@ static void AskForBackup(obs_data_t *obj)
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
return; return;
} }
auto out = QTextStream(&file);
obs_data_save_json(obj, file.fileName().toUtf8().constData()); out << json;
} }
/****************************************************************************** /******************************************************************************

View File

@@ -32,7 +32,7 @@ void MacroActionScreenshot::CustomScreenshot(OBSWeakSource &source)
} }
auto s = obs_weak_source_get_source(source); auto s = obs_weak_source_get_source(source);
_screenshot.~ScreenshotHelper(); _screenshot.~ScreenshotHelper();
new (&_screenshot) ScreenshotHelper(s, false, 0, true, _path); new (&_screenshot) ScreenshotHelper(s, QRect(), false, 0, true, _path);
obs_source_release(s); obs_source_release(s);
} }

View File

@@ -62,17 +62,17 @@ MacroConditionAudio::~MacroConditionAudio()
bool MacroConditionAudio::CheckOutputCondition() bool MacroConditionAudio::CheckOutputCondition()
{ {
bool ret = false; bool ret = false;
auto s = obs_weak_source_get_source(_audioSource.GetSource()); OBSSourceAutoRelease source =
obs_weak_source_get_source(_audioSource.GetSource());
// peak will have a value from -60 db to 0 db so we need to scale it
double curVolume = ((double)_peak + 60) * 1.7; double curVolume = ((double)_peak + 60) * 1.7;
switch (_outputCondition) { switch (_outputCondition) {
case OutputCondition::ABOVE: case OutputCondition::ABOVE:
// peak will have a value from -60 db to 0 db
ret = curVolume > _volume; ret = curVolume > _volume;
break; break;
case OutputCondition::BELOW: case OutputCondition::BELOW:
// peak will have a value from -60 db to 0 db
ret = curVolume < _volume; ret = curVolume < _volume;
break; break;
default: default:
@@ -84,21 +84,21 @@ bool MacroConditionAudio::CheckOutputCondition()
// Reset for next check // Reset for next check
_peak = -std::numeric_limits<float>::infinity(); _peak = -std::numeric_limits<float>::infinity();
obs_source_release(s);
if (_audioSource.GetType() == SourceSelection::Type::VARIABLE) { if (_audioSource.GetType() == SourceSelection::Type::VARIABLE) {
ResetVolmeter(); ResetVolmeter();
} }
return ret; return ret && source;
} }
bool MacroConditionAudio::CheckVolumeCondition() bool MacroConditionAudio::CheckVolumeCondition()
{ {
bool ret = false; bool ret = false;
auto s = obs_weak_source_get_source(_audioSource.GetSource()); OBSSourceAutoRelease source =
obs_weak_source_get_source(_audioSource.GetSource());
float curVolume = obs_source_get_volume(s); float curVolume = obs_source_get_volume(source);
bool muted = obs_source_muted(s); bool muted = obs_source_muted(source);
switch (_volumeCondition) { switch (_volumeCondition) {
case VolumeCondition::ABOVE: case VolumeCondition::ABOVE:
@@ -126,10 +126,9 @@ bool MacroConditionAudio::CheckVolumeCondition()
} }
SetTempVarValue("configured_volume", std::to_string(curVolume)); SetTempVarValue("configured_volume", std::to_string(curVolume));
SetTempVarValue("muted", muted ? "true" : "false"); SetTempVarValue("muted", (source && muted) ? "true" : "false");
obs_source_release(s); return ret && source;
return ret;
} }
bool MacroConditionAudio::CheckSyncOffset() bool MacroConditionAudio::CheckSyncOffset()
@@ -139,8 +138,9 @@ bool MacroConditionAudio::CheckSyncOffset()
} }
bool ret = false; bool ret = false;
auto s = obs_weak_source_get_source(_audioSource.GetSource()); OBSSourceAutoRelease source =
auto curOffset = obs_source_get_sync_offset(s) / nsPerMs; obs_weak_source_get_source(_audioSource.GetSource());
auto curOffset = obs_source_get_sync_offset(source) / nsPerMs;
if (_outputCondition == OutputCondition::ABOVE) { if (_outputCondition == OutputCondition::ABOVE) {
ret = curOffset > _syncOffset; ret = curOffset > _syncOffset;
} else { } else {
@@ -148,8 +148,7 @@ bool MacroConditionAudio::CheckSyncOffset()
} }
SetVariableValue(std::to_string(curOffset)); SetVariableValue(std::to_string(curOffset));
SetTempVarValue("sync_offset", std::to_string(curOffset)); SetTempVarValue("sync_offset", std::to_string(curOffset));
obs_source_release(s); return ret && source;
return ret;
} }
bool MacroConditionAudio::CheckMonitor() bool MacroConditionAudio::CheckMonitor()
@@ -159,13 +158,13 @@ bool MacroConditionAudio::CheckMonitor()
} }
bool ret = false; bool ret = false;
auto s = obs_weak_source_get_source(_audioSource.GetSource()); OBSSourceAutoRelease source =
ret = obs_source_get_monitoring_type(s) == _monitorType; obs_weak_source_get_source(_audioSource.GetSource());
ret = obs_source_get_monitoring_type(source) == _monitorType;
SetVariableValue(""); SetVariableValue("");
SetTempVarValue("monitor", SetTempVarValue("monitor",
std::to_string(obs_source_get_monitoring_type(s))); std::to_string(obs_source_get_monitoring_type(source)));
obs_source_release(s); return ret && source;
return ret;
} }
bool MacroConditionAudio::CheckBalance() bool MacroConditionAudio::CheckBalance()
@@ -175,8 +174,9 @@ bool MacroConditionAudio::CheckBalance()
} }
bool ret = false; bool ret = false;
auto s = obs_weak_source_get_source(_audioSource.GetSource()); OBSSourceAutoRelease source =
auto curBalance = obs_source_get_balance_value(s); obs_weak_source_get_source(_audioSource.GetSource());
auto curBalance = obs_source_get_balance_value(source);
if (_outputCondition == OutputCondition::ABOVE) { if (_outputCondition == OutputCondition::ABOVE) {
ret = curBalance > _balance; ret = curBalance > _balance;
} else { } else {
@@ -184,8 +184,7 @@ bool MacroConditionAudio::CheckBalance()
} }
SetVariableValue(std::to_string(curBalance)); SetVariableValue(std::to_string(curBalance));
SetTempVarValue("balance", std::to_string(curBalance)); SetTempVarValue("balance", std::to_string(curBalance));
obs_source_release(s); return ret && source;
return ret;
} }
bool MacroConditionAudio::CheckCondition() bool MacroConditionAudio::CheckCondition()
@@ -239,13 +238,12 @@ obs_volmeter_t *AddVolmeterToSource(MacroConditionAudio *entry,
obs_volmeter_t *volmeter = obs_volmeter_create(OBS_FADER_LOG); obs_volmeter_t *volmeter = obs_volmeter_create(OBS_FADER_LOG);
obs_volmeter_add_callback(volmeter, MacroConditionAudio::SetVolumeLevel, obs_volmeter_add_callback(volmeter, MacroConditionAudio::SetVolumeLevel,
entry); entry);
obs_source_t *as = obs_weak_source_get_source(source); OBSSourceAutoRelease audioSource = obs_weak_source_get_source(source);
if (!obs_volmeter_attach_source(volmeter, as)) { if (!obs_volmeter_attach_source(volmeter, audioSource)) {
const char *name = obs_source_get_name(as); const char *name = obs_source_get_name(audioSource);
blog(LOG_WARNING, "failed to attach volmeter to source %s", blog(LOG_WARNING, "failed to attach volmeter to source %s",
name); name);
} }
obs_source_release(as);
return volmeter; return volmeter;
} }
@@ -455,10 +453,9 @@ MacroConditionAudioEdit::MacroConditionAudioEdit(
void MacroConditionAudioEdit::UpdateVolmeterSource() void MacroConditionAudioEdit::UpdateVolmeterSource()
{ {
delete _volMeter; delete _volMeter;
obs_source_t *soruce = obs_weak_source_get_source( OBSSourceAutoRelease soruce = obs_weak_source_get_source(
_entryData->_audioSource.GetSource()); _entryData->_audioSource.GetSource());
_volMeter = new VolControl(soruce); _volMeter = new VolControl(soruce.Get());
obs_source_release(soruce);
QLayout *layout = this->layout(); QLayout *layout = this->layout();
layout->addWidget(_volMeter); layout->addWidget(_volMeter);

View File

@@ -215,8 +215,15 @@ void MacroConditionVideo::GetScreenshot(bool blocking)
{ {
auto source = obs_weak_source_get_source(_video.GetVideo()); auto source = obs_weak_source_get_source(_video.GetVideo());
_screenshotData.~ScreenshotHelper(); _screenshotData.~ScreenshotHelper();
new (&_screenshotData) QRect screenshotArea;
ScreenshotHelper(source, blocking, GetSwitcher()->interval); if (_areaParameters.enable && _condition != VideoCondition::NO_IMAGE) {
screenshotArea.setRect(_areaParameters.area.x,
_areaParameters.area.y,
_areaParameters.area.width,
_areaParameters.area.height);
}
new (&_screenshotData) ScreenshotHelper(
source, screenshotArea, blocking, GetSwitcher()->interval);
obs_source_release(source); obs_source_release(source);
_getNextScreenshot = false; _getNextScreenshot = false;
} }
@@ -361,13 +368,6 @@ bool MacroConditionVideo::CheckColor()
bool MacroConditionVideo::Compare() bool MacroConditionVideo::Compare()
{ {
if (_areaParameters.enable && _condition != VideoCondition::NO_IMAGE) {
_screenshotData.image = _screenshotData.image.copy(
_areaParameters.area.x, _areaParameters.area.y,
_areaParameters.area.width,
_areaParameters.area.height);
}
if (_condition != VideoCondition::OCR) { if (_condition != VideoCondition::OCR) {
SetVariableValue(""); SetVariableValue("");
} }

View File

@@ -255,7 +255,13 @@ void PreviewImage::CreateImage(const VideoInput &video, PreviewType type,
VideoCondition condition) VideoCondition condition)
{ {
auto source = obs_weak_source_get_source(video.GetVideo()); auto source = obs_weak_source_get_source(video.GetVideo());
ScreenshotHelper screenshot(source, true); QRect screenshotArea;
if (areaParams.enable && type == PreviewType::SHOW_MATCH) {
screenshotArea.setRect(areaParams.area.x, areaParams.area.y,
areaParams.area.width,
areaParams.area.height);
}
ScreenshotHelper screenshot(source, screenshotArea, true);
obs_source_release(source); obs_source_release(source);
if (!video.ValidSelection() || !screenshot.done) { if (!video.ValidSelection() || !screenshot.done) {
@@ -274,11 +280,6 @@ void PreviewImage::CreateImage(const VideoInput &video, PreviewType type,
if (type == PreviewType::SHOW_MATCH) { if (type == PreviewType::SHOW_MATCH) {
std::unique_lock<std::mutex> lock(_mtx); std::unique_lock<std::mutex> lock(_mtx);
if (areaParams.enable) {
screenshot.image = screenshot.image.copy(
areaParams.area.x, areaParams.area.y,
areaParams.area.width, areaParams.area.height);
}
// Will emit status label update // Will emit status label update
MarkMatch(screenshot.image, patternMatchParams, MarkMatch(screenshot.image, patternMatchParams,
patternImageData, objDetectParams, ocrParams, patternImageData, objDetectParams, ocrParams,

View File

@@ -7,10 +7,11 @@ namespace advss {
static void ScreenshotTick(void *param, float); static void ScreenshotTick(void *param, float);
ScreenshotHelper::ScreenshotHelper(obs_source_t *source, bool blocking, ScreenshotHelper::ScreenshotHelper(obs_source_t *source, const QRect &subarea,
int timeout, bool saveToFile, bool blocking, int timeout, bool saveToFile,
std::string path) std::string path)
: weakSource(OBSGetWeakRef(source)), : weakSource(OBSGetWeakRef(source)),
_subarea(subarea),
_blocking(blocking), _blocking(blocking),
_saveToFile(saveToFile), _saveToFile(saveToFile),
_path(path) _path(path)
@@ -62,7 +63,12 @@ void ScreenshotHelper::Screenshot()
cy = ovi.base_height; cy = ovi.base_height;
} }
if (!cx || !cy) { QRect renderArea(0, 0, cx, cy);
if (!_subarea.isEmpty()) {
renderArea &= _subarea;
}
if (renderArea.isEmpty()) {
vblog(LOG_WARNING, vblog(LOG_WARNING,
"Cannot screenshot \"%s\", invalid target size", "Cannot screenshot \"%s\", invalid target size",
obs_source_get_name(source)); obs_source_get_name(source));
@@ -71,16 +77,24 @@ void ScreenshotHelper::Screenshot()
return; return;
} }
cx = renderArea.width();
cy = renderArea.height();
texrender = gs_texrender_create(GS_RGBA, GS_ZS_NONE); texrender = gs_texrender_create(GS_RGBA, GS_ZS_NONE);
stagesurf = gs_stagesurface_create(cx, cy, GS_RGBA); stagesurf = gs_stagesurface_create(renderArea.width(),
renderArea.height(), GS_RGBA);
gs_texrender_reset(texrender); gs_texrender_reset(texrender);
if (gs_texrender_begin(texrender, cx, cy)) { if (gs_texrender_begin(texrender, renderArea.width(),
renderArea.height())) {
vec4 zero; vec4 zero;
vec4_zero(&zero); vec4_zero(&zero);
gs_clear(GS_CLEAR_COLOR, &zero, 0.0f, 0); gs_clear(GS_CLEAR_COLOR, &zero, 0.0f, 0);
gs_ortho(0.0f, (float)cx, 0.0f, (float)cy, -100.0f, 100.0f); gs_ortho((float)(renderArea.left()),
(float)(renderArea.right() + 1),
(float)(renderArea.top()),
(float)(renderArea.bottom() + 1), -100.0f, 100.0f);
gs_blend_state_push(); gs_blend_state_push();
gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO); gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO);

View File

@@ -12,9 +12,9 @@ namespace advss {
class ScreenshotHelper { class ScreenshotHelper {
public: public:
ScreenshotHelper() = default; ScreenshotHelper() = default;
ScreenshotHelper(obs_source_t *source, bool blocking = false, ScreenshotHelper(obs_source_t *source, const QRect &subarea = QRect(),
int timeout = 1000, bool saveToFile = false, bool blocking = false, int timeout = 1000,
std::string path = ""); bool saveToFile = false, std::string path = "");
ScreenshotHelper &operator=(const ScreenshotHelper &) = delete; ScreenshotHelper &operator=(const ScreenshotHelper &) = delete;
ScreenshotHelper(const ScreenshotHelper &) = delete; ScreenshotHelper(const ScreenshotHelper &) = delete;
~ScreenshotHelper(); ~ScreenshotHelper();
@@ -39,6 +39,7 @@ public:
private: private:
std::atomic_bool _initDone = false; std::atomic_bool _initDone = false;
QRect _subarea = QRect();
bool _blocking = false; bool _blocking = false;
std::thread _saveThread; std::thread _saveThread;
bool _saveToFile = false; bool _saveToFile = false;