Compare commits

...

23 Commits

Author SHA1 Message Date
WarmUpTill
5d568683f7 Update obs-websocket-api.h 2025-07-06 11:06:25 +02:00
WarmUpTill
a26c37021d Fix crash on OBS shutdown 2025-07-06 11:06:22 +02:00
WarmUpTill
0cd7004f6a Setup MIDI device observers in parallel to avoid blocking OBS startup
Some checks failed
debian-build / build (push) Has been cancelled
Push to master / Check Formatting 🔍 (push) Has been cancelled
Push to master / Build Project 🧱 (push) Has been cancelled
Push to master / Create Release 🛫 (push) Has been cancelled
2025-06-25 13:56:40 +02:00
WarmUpTill
40c62ba700 CI: Add libremidi dependencies 2025-06-25 13:56:40 +02:00
Arimil
f2c7b532d9 Add support for kwin (wayland) (#1393)
Some checks failed
debian-build / build (push) Has been cancelled
Push to master / Check Formatting 🔍 (push) Has been cancelled
Push to master / Build Project 🧱 (push) Has been cancelled
Push to master / Create Release 🛫 (push) Has been cancelled
2025-06-21 19:51:25 +02:00
WarmUpTill
456a9c04c7 Add icon for windows installer
Some checks failed
debian-build / build (push) Waiting to run
Push to master / Check Formatting 🔍 (push) Waiting to run
Push to master / Build Project 🧱 (push) Waiting to run
Push to master / Create Release 🛫 (push) Blocked by required conditions
Check locale / ubuntu64 (push) Has been cancelled
2025-06-20 22:29:35 +02:00
WarmUpTill
3e1fdbde45 Add option to set and check list source settings by name
This makes it easier to select the intended settings value as the
underlying value often has no direct connection to the user facing name.

It also makes it possible to select list entries whos underlying value
changes frequently, but the user facing value does not.
(E.g. device IDs based on the input port compared to the device name)
2025-06-20 22:29:35 +02:00
WarmUpTill
874b9b86e2 Refactor locking of macro segments
This should avoid crashes when actions or conditions are performed in
parallel to the main macro loop and will improve the UI responsiveness
in some scenarios
2025-06-20 22:29:35 +02:00
WarmUpTill
98d1f83acc Cleanup 2025-06-20 22:29:35 +02:00
WarmUpTill
7e91f81957 Ease development with dirty dependency directory 2025-06-20 22:29:35 +02:00
WarmUpTill
20488afdd1 Fix tempvars being reset across macros for cached widgets
Some checks failed
debian-build / build (push) Has been cancelled
Check locale / ubuntu64 (push) Has been cancelled
Push to master / Check Formatting 🔍 (push) Has been cancelled
Push to master / Build Project 🧱 (push) Has been cancelled
Push to master / Create Release 🛫 (push) Has been cancelled
2025-06-12 21:29:07 +02:00
WarmUpTill
d9d387ad47 Fix crash when deleting cached macro widgets 2025-06-12 21:29:07 +02:00
WarmUpTill
0736d673e1 Add option to check if chat was cleared / message was removed 2025-06-12 21:29:07 +02:00
WarmUpTill
34151e4bc6 Fix "Get user info" only allowing small values for user ids 2025-06-12 21:29:07 +02:00
WarmUpTill
1346c19bec Fix crash when invalid token is used to connect to Twitch chat 2025-06-12 21:29:07 +02:00
WarmUpTill
be6bc48231 Fix macro selection resetting when any macro was removed 2025-06-12 18:33:24 +02:00
WarmUpTill
79a8ad57af Rework HTTP action URL input
The URL to be accessed can now be passed as a single URL instead of it
being split into a host and path component
2025-06-12 18:33:24 +02:00
WarmUpTill
daeb9275a3 Add support for inline scripts
* Script can be defined in the macro segment or loaded from a file
* Supports both LUA and Python
* Can be used for actions and conditions
* obs_script_create and obs_script_destroy are resolved at runtime
  (Let's hope the API remains stable)
2025-06-09 14:20:44 +02:00
WarmUpTill
73b542a4db Move scripting support to seperate project 2025-06-09 14:20:44 +02:00
WarmUpTill
e3471066e9 Export symbols 2025-06-09 14:20:44 +02:00
WarmUpTill
ec41c06b4d Update feature request description 2025-06-09 14:20:44 +02:00
WarmUpTill
201e45d058 Fix macro tree not resizing properly with OBS 31.1.0 2025-06-07 18:56:42 +02:00
WarmUpTill
b17aa30432 Fix attempting to cache widgets of about to be deleted macros 2025-06-06 19:14:46 +02:00
134 changed files with 2557 additions and 1464 deletions

View File

@@ -2,7 +2,7 @@
# https://github.com/obsproject/.github/tree/master/.github/ISSUE_TEMPLATE
name: Feature request
description: Suggest an idea for this projectReport a bug or crash
description: Suggest an idea for this project
body:
- type: markdown
id: md_welcome

View File

@@ -12,4 +12,7 @@ package 'libtesseract-dev'
package 'libproc2-dev'
package 'libusb-1.0-0-dev'
package 'libpaho-mqttpp-dev'
package 'libpaho-mqtt-dev'
package 'libpaho-mqtt-dev'
package 'libpaho-mqtt-dev'
package 'libasound2-dev'
package 'libpipewire-0.3-dev'

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.16...3.26)
cmake_minimum_required(VERSION 3.21...3.26)
project(advanced-scene-switcher VERSION 1.0.0)
@@ -103,8 +103,6 @@ target_sources(
lib/macro/macro-action-macro.hpp
lib/macro/macro-action-queue.cpp
lib/macro/macro-action-queue.hpp
lib/macro/macro-action-script.cpp
lib/macro/macro-action-script.hpp
lib/macro/macro-action-variable.cpp
lib/macro/macro-action-variable.hpp
lib/macro/macro-action.cpp
@@ -117,8 +115,6 @@ target_sources(
lib/macro/macro-condition-macro.hpp
lib/macro/macro-condition-queue.cpp
lib/macro/macro-condition-queue.hpp
lib/macro/macro-condition-script.cpp
lib/macro/macro-condition-script.hpp
lib/macro/macro-condition-tempvar.cpp
lib/macro/macro-condition-tempvar.hpp
lib/macro/macro-condition-variable.cpp
@@ -139,14 +135,10 @@ target_sources(
lib/macro/macro-ref.hpp
lib/macro/macro-run-button.cpp
lib/macro/macro-run-button.hpp
lib/macro/macro-script-handler.cpp
lib/macro/macro-script-handler.hpp
lib/macro/macro-segment-copy-paste.cpp
lib/macro/macro-segment-copy-paste.hpp
lib/macro/macro-segment-list.cpp
lib/macro/macro-segment-list.hpp
lib/macro/macro-segment-script.cpp
lib/macro/macro-segment-script.hpp
lib/macro/macro-segment-selection.cpp
lib/macro/macro-segment-selection.hpp
lib/macro/macro-segment.cpp
@@ -223,9 +215,6 @@ target_sources(
lib/utils/plugin-state-helpers.hpp
lib/utils/priority-helper.cpp
lib/utils/priority-helper.hpp
lib/utils/properties-view.cpp
lib/utils/properties-view.hpp
lib/utils/properties-view.moc.hpp
lib/utils/regex-config.cpp
lib/utils/regex-config.hpp
lib/utils/resizing-text-edit.cpp
@@ -426,6 +415,7 @@ else()
set_target_properties(${LIB_NAME} PROPERTIES PREFIX "")
set_target_properties(${LIB_NAME} PROPERTIES SOVERSION 1)
find_package(Qt6 REQUIRED COMPONENTS DBus)
find_package(X11 REQUIRED COMPONENTS Xss)
target_include_directories(${LIB_NAME} PRIVATE "${X11_INCLUDE_DIR}"
"${X11_Xss_INCLUDE_PATH}")
@@ -457,7 +447,8 @@ else()
)
endif()
target_include_directories(${LIB_NAME} PRIVATE "${PROC_INCLUDE_DIR}")
target_sources(${LIB_NAME} PRIVATE lib/linux/advanced-scene-switcher-nix.cpp)
target_sources(${LIB_NAME} PRIVATE lib/linux/advanced-scene-switcher-nix.cpp
lib/linux/kwin-helpers.cpp)
# Don't include irrelevant folders into sources archive
list(APPEND CPACK_SOURCE_IGNORE_FILES "\\.deps/.*")

View File

@@ -80,6 +80,8 @@ function(set_target_properties_plugin target)
configure_file(cmake/windows/resources/installer-Windows.iss.in
"${CMAKE_CURRENT_BINARY_DIR}/installer-Windows.generated.iss")
configure_file(data/res/images/logo.ico
"${CMAKE_CURRENT_BINARY_DIR}/installer.ico" COPYONLY)
configure_file(cmake/windows/resources/resource.rc.in
"${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}.rc")

View File

@@ -20,6 +20,8 @@ OutputBaseFilename={#MyAppName}-{#MyAppVersion}-Windows-Installer
Compression=lzma
SolidCompression=yes
DirExistsWarning=no
SetupIconFile=installer.ico
UninstallDisplayIcon={app}\data\obs-plugins\advanced-scene-switcher\res\images\logo.ico
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

View File

@@ -507,6 +507,7 @@ AdvSceneSwitcher.condition.source.type.showing="Is showing"
AdvSceneSwitcher.condition.source.type.settingsMatch="Settings match"
AdvSceneSwitcher.condition.source.type.settingsChanged="Settings changed"
AdvSceneSwitcher.condition.source.type.individualSettingMatches="Setting value matches"
AdvSceneSwitcher.condition.source.type.individualSettingListSelectionMatches="Settings value list selection matches"
AdvSceneSwitcher.condition.source.type.individualSettingChanged="Setting value changed"
AdvSceneSwitcher.condition.source.type.width="Width"
AdvSceneSwitcher.condition.source.type.height="Height"
@@ -530,6 +531,7 @@ AdvSceneSwitcher.condition.filter.type.showing="Is disabled"
AdvSceneSwitcher.condition.filter.type.settingsMatch="Settings match"
AdvSceneSwitcher.condition.filter.type.settingsChanged="Settings changed"
AdvSceneSwitcher.condition.filter.type.individualSettingMatches="Settings value matches"
AdvSceneSwitcher.condition.filter.type.individualSettingListSelectionMatches="Settings value list selection matches"
AdvSceneSwitcher.condition.filter.type.individualSettingChanged="Settings value changed"
AdvSceneSwitcher.condition.filter.refresh="Refresh"
AdvSceneSwitcher.condition.filter.refresh.tooltip="Repopulate the filter settings selection with the settings of the filter which's name matches the variable value."
@@ -730,6 +732,8 @@ AdvSceneSwitcher.condition.twitch.type.polling.channel.live="Stream is currently
AdvSceneSwitcher.condition.twitch.type.polling.channel.title="Current title matches"
AdvSceneSwitcher.condition.twitch.type.polling.channel.category="Current category is"
AdvSceneSwitcher.condition.twitch.type.chat.message="Chat message received"
AdvSceneSwitcher.condition.twitch.type.chat.messageRemoved="Single chat message removed"
AdvSceneSwitcher.condition.twitch.type.chat.cleared="All messages of user or channel cleared"
AdvSceneSwitcher.condition.twitch.type.chat.properties="Chat message properties:"
AdvSceneSwitcher.condition.twitch.type.chat.properties.select="Select chat message property:"
AdvSceneSwitcher.condition.twitch.type.chat.properties.firstMessage="Is first message"
@@ -801,6 +805,7 @@ AdvSceneSwitcher.condition.screenshot.entry="A screenshot was taken"
AdvSceneSwitcher.condition.mqtt="MQTT"
AdvSceneSwitcher.condition.mqtt.layout.match="Message was received from{{connection}} which matches{{regex}}:"
AdvSceneSwitcher.condition.mqtt.layout.listen="Set message selection to incoming message:{{listenButton}}"
AdvSceneSwitcher.condition.script="Script"
# Macro Actions
AdvSceneSwitcher.action.unknown="Unknown action"
@@ -884,6 +889,7 @@ AdvSceneSwitcher.action.filter.entry="On{{sources}}{{actions}}{{filters}}{{refre
AdvSceneSwitcher.action.filter.entry.settings="{{settings}}{{settingsInputMethod}}{{settingValue}}{{tempVar}}"
AdvSceneSwitcher.action.filter.getSettings="Get current settings"
AdvSceneSwitcher.action.filter.inputMethod.individualManual="Set to fixed value"
AdvSceneSwitcher.action.filter.inputMethod.individualListEntryManual="Set to list entry"
AdvSceneSwitcher.action.filter.inputMethod.individualTempvar="Set to macro property"
AdvSceneSwitcher.action.filter.inputMethod.json="Set setting JSON string"
AdvSceneSwitcher.action.source="Source"
@@ -914,6 +920,7 @@ AdvSceneSwitcher.action.source.deinterlaceMode.yadif2x="Yadif 2x"
AdvSceneSwitcher.action.source.deinterlaceOrder.topFieldFirst="Top Field First"
AdvSceneSwitcher.action.source.deinterlaceOrder.bottomFieldFirst="Bottom Field First"
AdvSceneSwitcher.action.source.inputMethod.individualManual="Set to fixed value"
AdvSceneSwitcher.action.source.inputMethod.individualListEntryManual="Set to list entry"
AdvSceneSwitcher.action.source.inputMethod.individualTempvar="Set to macro property"
AdvSceneSwitcher.action.source.inputMethod.json="Set setting JSON string"
AdvSceneSwitcher.action.source.refresh="Refresh"
@@ -1094,7 +1101,7 @@ AdvSceneSwitcher.action.http.type.post="POST"
AdvSceneSwitcher.action.http.type.put="PUT"
AdvSceneSwitcher.action.http.type.patch="PATCH"
AdvSceneSwitcher.action.http.type.delete="DELETE"
AdvSceneSwitcher.action.http.layout.method="Send{{method}}to URL{{url}}at path{{path}}"
AdvSceneSwitcher.action.http.layout.method="Send{{method}}to URL{{url}}"
AdvSceneSwitcher.action.http.layout.contentType="Content type:{{contentType}}"
AdvSceneSwitcher.action.http.layout.timeout="Timeout:{{timeout}}seconds"
AdvSceneSwitcher.action.http.entry.line1="Send{{method}}to{{url}}"
@@ -1250,6 +1257,7 @@ AdvSceneSwitcher.action.obsSetting.action.setOutputCanvasX="Set output resolutio
AdvSceneSwitcher.action.obsSetting.action.setOutputCanvasY="Set output resolution Y value"
AdvSceneSwitcher.action.obsSetting.getCurrentValue="Get current value"
AdvSceneSwitcher.action.obsSettings.layout="{{actions}}{{fpsType}}{{fpsIntValue}}{{fpsStringValue}}{{canvasSizeValue}}{{getCurrentValue}}"
AdvSceneSwitcher.action.script="Script"
# Hotkey
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Start the Advanced Scene Switcher"
@@ -1514,6 +1522,17 @@ AdvSceneSwitcher.twitch.selection.points.reward.tooltip.noPermission="Can't sele
AdvSceneSwitcher.twitch.selection.points.reward.tooltip.noChannel="Can't select points reward without entering a channel first!"
AdvSceneSwitcher.twitch.selection.points.reward.tooltip.error="Can't select points reward because Twitch responded with an error! Check OBS logs for more details."
AdvSceneSwitcher.script.type.inline="Inline"
AdvSceneSwitcher.script.type.file="File"
AdvSceneSwitcher.script.type.layout="Script type:{{scriptType}}"
AdvSceneSwitcher.script.language.python="Python"
AdvSceneSwitcher.script.language.lua="LUA"
AdvSceneSwitcher.script.language.select="--select language--"
AdvSceneSwitcher.script.language.layout="Script language:{{language}}"
AdvSceneSwitcher.script.file.open="Open"
AdvSceneSwitcher.script.file.open.failed="Could not open script file!"
AdvSceneSwitcher.script.file.layout="Script file:{{path}}{{open}}"
AdvSceneSwitcher.tempVar.select="--select value--"
AdvSceneSwitcher.tempVar.selectionInfo.lastValues="Last values:"
@@ -1907,6 +1926,24 @@ AdvSceneSwitcher.tempVar.twitch.is_turbo.chatReceive.description="'true' if the
AdvSceneSwitcher.tempVar.twitch.is_vip.chatReceive="Is chatter a VIP"
AdvSceneSwitcher.tempVar.twitch.is_vip.chatReceive.description="'true' if the chatter is a VIP in the channel, 'false' otherwise."
AdvSceneSwitcher.tempVar.twitch.login.chatRemove="User login"
AdvSceneSwitcher.tempVar.twitch.login.chatRemove.description="The name of the user who sent the message."
AdvSceneSwitcher.tempVar.twitch.message.chatRemove="Chat message"
AdvSceneSwitcher.tempVar.twitch.message_id.chatRemove.description="The chat message that was removed."
AdvSceneSwitcher.tempVar.twitch.message_id.chatRemove="Chat message ID"
AdvSceneSwitcher.tempVar.twitch.message_id.chatRemove.description="The ID of the message in UUID format."
AdvSceneSwitcher.tempVar.twitch.timestamp.chatRemove="Chat message timestamp"
AdvSceneSwitcher.tempVar.twitch.timestamp.chatRemove.description="The UNIX timestamp."
AdvSceneSwitcher.tempVar.twitch.login.chatClear="User login"
AdvSceneSwitcher.tempVar.twitch.login.chatClear.description="The login name of the user whose messages were removed from the chat room because they were banned or put in a timeout."
AdvSceneSwitcher.tempVar.twitch.user_id.chatClear="User ID"
AdvSceneSwitcher.tempVar.twitch.user_id.chatClear.description="Optional.\nThe User ID of the user that was banned or put in a timeout.\nEmpty in case the complete chat was cleared."
AdvSceneSwitcher.tempVar.twitch.ban_duration.chatClear="Ban duration"
AdvSceneSwitcher.tempVar.twitch.ban_duration.chatClear.description="Set to zero if the complete chat was cleared or a user was banned indefinitely.\nIs set to non-zero value, if a user was put in a timeout.\nWill contain the duration of the timeout in seconds."
AdvSceneSwitcher.tempVar.twitch.timestamp.chatClear="Timestamp"
AdvSceneSwitcher.tempVar.twitch.timestamp.chatClear.description="The UNIX timestamp."
AdvSceneSwitcher.tempVar.twitch.user_login.chatJoin="User login"
AdvSceneSwitcher.tempVar.twitch.user_login.chatJoin.description="The user login of the person who joined the chat room."

BIN
data/res/images/logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -22,7 +22,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include <obs.h>
#define OBS_WEBSOCKET_API_VERSION 2
#define OBS_WEBSOCKET_API_VERSION 3
#ifdef __cplusplus
extern "C" {
@@ -31,6 +31,8 @@ extern "C" {
typedef void *obs_websocket_vendor;
typedef void (*obs_websocket_request_callback_function)(obs_data_t *,
obs_data_t *, void *);
typedef void (*obs_websocket_event_callback_function)(uint64_t, const char *,
const char *, void *);
struct obs_websocket_request_response {
unsigned int status_code;
@@ -45,6 +47,11 @@ struct obs_websocket_request_callback {
void *priv_data;
};
struct obs_websocket_event_callback {
obs_websocket_event_callback_function callback;
void *priv_data;
};
static proc_handler_t *_ph;
/* ==================== INTERNAL API FUNCTIONS ==================== */
@@ -123,7 +130,6 @@ obs_websocket_call_request(const char *request_type, obs_data_t *request_data
request_data_string = obs_data_get_json(request_data);
calldata_t cd = {0, 0, 0, 0};
calldata_set_string(&cd, "request_type", request_type);
calldata_set_string(&cd, "request_data", request_data_string);
@@ -152,6 +158,48 @@ static inline void obs_websocket_request_response_free(
bfree(response);
}
// Register an event handler to receive obs-websocket events
static inline bool obs_websocket_register_event_callback(
obs_websocket_event_callback_function event_callback, void *priv_data)
{
if (!obs_websocket_ensure_ph())
return false;
struct obs_websocket_event_callback cb = {event_callback, priv_data};
calldata_t cd = {0, 0, 0, 0};
calldata_set_ptr(&cd, "callback", &cb);
proc_handler_call(_ph, "register_event_callback", &cd);
bool ret = calldata_bool(&cd, "success");
calldata_free(&cd);
return ret;
}
// Unregister an existing event handler
static inline bool obs_websocket_unregister_event_callback(
obs_websocket_event_callback_function event_callback, void *priv_data)
{
if (!obs_websocket_ensure_ph())
return false;
struct obs_websocket_event_callback cb = {event_callback, priv_data};
calldata_t cd = {0, 0, 0, 0};
calldata_set_ptr(&cd, "callback", &cb);
proc_handler_call(_ph, "unregister_event_callback", &cd);
bool ret = calldata_bool(&cd, "success");
calldata_free(&cd);
return ret;
}
/* ==================== VENDOR API FUNCTIONS ==================== */
// ALWAYS CALL ONLY VIA `obs_module_post_load()` CALLBACK!
@@ -163,7 +211,6 @@ obs_websocket_register_vendor(const char *vendor_name)
return NULL;
calldata_t cd = {0, 0, 0, 0};
calldata_set_string(&cd, "name", vendor_name);
proc_handler_call(_ph, "vendor_register", &cd);
@@ -179,11 +226,10 @@ static inline bool obs_websocket_vendor_register_request(
obs_websocket_request_callback_function request_callback,
void *priv_data)
{
calldata_t cd = {0, 0, 0, 0};
struct obs_websocket_request_callback cb = {request_callback,
priv_data};
calldata_t cd = {0, 0, 0, 0};
calldata_set_string(&cd, "type", request_type);
calldata_set_ptr(&cd, "callback", &cb);
@@ -200,7 +246,6 @@ obs_websocket_vendor_unregister_request(obs_websocket_vendor vendor,
const char *request_type)
{
calldata_t cd = {0, 0, 0, 0};
calldata_set_string(&cd, "type", request_type);
bool success = obs_websocket_vendor_run_simple_proc(
@@ -217,7 +262,6 @@ static inline bool obs_websocket_vendor_emit_event(obs_websocket_vendor vendor,
obs_data_t *event_data)
{
calldata_t cd = {0, 0, 0, 0};
calldata_set_string(&cd, "type", event_name);
calldata_set_ptr(&cd, "data", (void *)event_data);

View File

@@ -11,6 +11,7 @@ namespace advss {
class MacroActionEdit;
class MacroConditionEdit;
class MacroSegment;
class Duration;
class SequenceWidget;
struct SceneGroup;
@@ -192,7 +193,7 @@ signals:
void MacroRemoved(const QString &name);
void MacroRenamed(const QString &oldName, const QString &newName);
void MacroSegmentOrderChanged();
void SegmentTempVarsChanged();
void SegmentTempVarsChanged(MacroSegment *);
void HighlightMacrosChanged(bool value);
void ConnectionAdded(const QString &);

View File

@@ -32,6 +32,7 @@
#endif
#include <fstream>
#include <sstream>
#include "kwin-helpers.h"
namespace advss {
@@ -44,6 +45,10 @@ static XScreenSaverAllocInfoFunc allocSSFunc = nullptr;
static XScreenSaverQueryInfoFunc querySSFunc = nullptr;
bool canGetIdleTime = false;
static bool KWin = false;
static FocusNotifier notifier;
static QString KWinScriptObjectPath;
static QLibrary *libprocps = nullptr;
#ifdef PROCPS_AVAILABLE
typedef PROCTAB *(*openproc_func)(int flags);
@@ -275,6 +280,11 @@ int getActiveWindow(Window *&window)
void GetCurrentWindowTitle(std::string &title)
{
if (KWin) {
title = FocusNotifier::getActiveWindowTitle();
return;
}
Window *data = 0;
if (getActiveWindow(data) != Success || !data) {
return;
@@ -286,6 +296,7 @@ void GetCurrentWindowTitle(std::string &title)
auto name = getWindowName(data[0]);
XFree(data);
if (name.empty()) {
return;
}
@@ -412,6 +423,10 @@ void GetProcessList(QStringList &processes)
long getForegroundProcessPid()
{
if (KWin) {
return FocusNotifier::getActiveWindowPID();
}
Window *window;
if (getActiveWindow(window) != Success || !window || !*window) {
return -1;
@@ -437,6 +452,7 @@ long getForegroundProcessPid()
pid = *((long *)prop);
XFree(prop);
return pid;
}
@@ -562,6 +578,17 @@ void PlatformInit()
return;
}
KWin = isKWinAvailable();
if (!(KWin && startKWinScript(KWinScriptObjectPath) &&
registerKWinDBusListener(&notifier))) {
// something bad happened while trying to initialize
// the KWin script/dbus so disable it
KWin = false;
blog(LOG_INFO, "not using KWin compat");
} else {
blog(LOG_INFO, "using KWin compat");
}
initXss();
initProcps();
initProc2();
@@ -583,6 +610,8 @@ void PlatformCleanup()
cleanupHelper(libproc2);
cleanupDisplay();
XSetErrorHandler(NULL);
if (KWin && !KWinScriptObjectPath.isEmpty())
stopKWinScript(KWinScriptObjectPath);
}
} // namespace advss

166
lib/linux/kwin-helpers.cpp Normal file
View File

@@ -0,0 +1,166 @@
#include "kwin-helpers.h"
#include "log-helper.hpp"
#include <QDir>
#include <QFile>
#include <QFileDevice>
#include <QTextStream>
#include <QtDBus/QDBusConnectionInterface>
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusReply>
namespace advss {
int FocusNotifier::activePID = -1;
std::string FocusNotifier::activeTitle = {};
int FocusNotifier::getActiveWindowPID()
{
return activePID;
}
std::string FocusNotifier::getActiveWindowTitle()
{
return activeTitle;
}
void FocusNotifier::focusChanged(const int pid)
{
activePID = pid;
}
void FocusNotifier::focusTitle(const QString &title)
{
activeTitle = title.toStdString();
}
bool isKWinAvailable()
{
const QDBusConnectionInterface *interface =
QDBusConnection::sessionBus().interface();
if (!interface)
return false;
const QStringList services =
interface->registeredServiceNames().value();
return services.contains("org.kde.KWin");
}
bool startKWinScript(QString &scriptObjectPath)
{
const QString scriptPath =
"/tmp/AdvancedSceneSwitcher/KWinFocusNotifier.js";
const QString script =
R"(workspace.windowActivated.connect(function(client) {
if (!client) return;
if (!client.pid) return;
if (!client.caption) return;
callDBus(
"com.github.AdvancedSceneSwitcher",
"/com/github/AdvancedSceneSwitcher",
"com.github.AdvancedSceneSwitcher",
"focusChanged",
client.pid
);
callDBus(
"com.github.AdvancedSceneSwitcher",
"/com/github/AdvancedSceneSwitcher",
"com.github.AdvancedSceneSwitcher",
"focusTitle",
client.caption
);
}))";
if (const QDir dir; !dir.mkpath(QFileInfo(scriptPath).absolutePath())) {
blog(LOG_ERROR, "error creating /tmp/AdvancedSceneSwitcher");
return false;
}
QFile scriptFile(scriptPath);
if (!scriptFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
blog(LOG_ERROR,
"error opening KWinFocusNotifier.js for writing");
return false;
}
scriptFile.setPermissions(QFileDevice::ReadOwner |
QFileDevice::WriteOwner);
QTextStream outputStream(&scriptFile);
outputStream << script;
scriptFile.close();
const QDBusConnection bus = QDBusConnection::sessionBus();
QDBusInterface scriptingIface("org.kde.KWin", "/Scripting",
"org.kde.kwin.Scripting", bus);
if (!scriptingIface.isValid()) {
return false;
}
const QDBusReply<bool> scriptRunningReply =
scriptingIface.call("isScriptLoaded", scriptPath);
if (scriptRunningReply.isValid() && scriptRunningReply.value()) {
// script already registered and running, don't do it again
// this will leave the script running since we do not have
// a valid script id anymore, but at the very least this prevents
// it from running multiple times
return true;
}
const QDBusReply<int> scriptIdReply =
scriptingIface.call("loadScript", scriptPath);
if (!scriptIdReply.isValid()) {
return false;
}
const int scriptId = scriptIdReply.value();
scriptObjectPath =
QString("/Scripting/Script%1").arg(QString::number(scriptId));
QDBusInterface scriptRunner("org.kde.KWin", scriptObjectPath,
"org.kde.kwin.Script", bus);
if (!scriptRunner.isValid()) {
return false;
}
const QDBusReply<void> runReply = scriptRunner.call("run");
return runReply.isValid();
}
bool stopKWinScript(const QString &scriptObjectPath)
{
QDBusInterface scriptRunner("org.kde.KWin", scriptObjectPath,
"org.kde.kwin.Script",
QDBusConnection::sessionBus());
if (!scriptRunner.isValid()) {
return false;
}
const QDBusReply<void> stopReply = scriptRunner.call("stop");
return stopReply.isValid();
}
bool registerKWinDBusListener(FocusNotifier *notifier)
{
static const QString serviceName = "com.github.AdvancedSceneSwitcher";
static const QString objectPath = "/com/github/AdvancedSceneSwitcher";
auto bus = QDBusConnection::sessionBus();
if (bus.objectRegisteredAt(objectPath)) {
// already registered?
return true;
}
if (!bus.registerService(serviceName)) {
return false;
}
if (!bus.registerObject(objectPath, notifier,
QDBusConnection::ExportAllSlots)) {
return false;
}
return true;
}
} // namespace advss

33
lib/linux/kwin-helpers.h Normal file
View File

@@ -0,0 +1,33 @@
#pragma once
#include <QObject>
#include <QString>
#include <string>
namespace advss {
class FocusNotifier final : public QObject {
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "com.github.AdvancedSceneSwitcher")
static int activePID;
static std::string activeTitle;
public:
using QObject::QObject;
static int getActiveWindowPID();
static std::string getActiveWindowTitle();
public slots:
void focusChanged(const int pid);
void focusTitle(const QString &title);
};
bool isKWinAvailable();
bool startKWinScript(QString &scriptObjectPath);
bool stopKWinScript(const QString &scriptObjectPath);
bool registerKWinDBusListener(FocusNotifier *notifier);
void printDBusError();
} // namespace advss

View File

@@ -20,7 +20,7 @@ public:
MacroActionFactory() = delete;
EXPORT static bool Register(const std::string &id, MacroActionInfo);
static bool Deregister(const std::string &id);
EXPORT static bool Deregister(const std::string &id);
static std::shared_ptr<MacroAction> Create(const std::string &id,
Macro *m);
static QWidget *CreateWidget(const std::string &id, QWidget *parent,

View File

@@ -170,11 +170,7 @@ void MacroActionQueueEdit::UpdateEntryData()
void MacroActionQueueEdit::MacroChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_macro = text;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -182,11 +178,7 @@ void MacroActionQueueEdit::MacroChanged(const QString &text)
void MacroActionQueueEdit::QueueChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_queue = GetWeakActionQueueByQString(text);
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -194,11 +186,7 @@ void MacroActionQueueEdit::QueueChanged(const QString &text)
void MacroActionQueueEdit::ActionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_action = static_cast<MacroActionQueue::Action>(value);
SetWidgetVisibility();
emit HeaderInfoChanged(

View File

@@ -20,7 +20,7 @@ class MacroConditionFactory {
public:
MacroConditionFactory() = delete;
EXPORT static bool Register(const std::string &, MacroConditionInfo);
static bool Deregister(const std::string &);
EXPORT static bool Deregister(const std::string &);
static std::shared_ptr<MacroCondition> Create(const std::string &,
Macro *m);
static QWidget *CreateWidget(const std::string &id, QWidget *parent,

View File

@@ -538,11 +538,7 @@ void MacroConditionMacroEdit::UpdateEntryData()
void MacroConditionMacroEdit::MacroChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_macro = text;
_actionIndex->SetMacro(_entryData->_macro.GetMacro());
emit HeaderInfoChanged(
@@ -551,21 +547,13 @@ void MacroConditionMacroEdit::MacroChanged(const QString &text)
void MacroConditionMacroEdit::CountChanged(const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_count = value;
}
void MacroConditionMacroEdit::CountConditionChanged(int cond)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_counterCondition =
static_cast<MacroConditionMacro::CounterCondition>(cond);
}
@@ -590,11 +578,7 @@ void MacroConditionMacroEdit::MacroRemove(const QString &)
void MacroConditionMacroEdit::TypeChanged(int type)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->SetType(static_cast<MacroConditionMacro::Type>(type));
SetupWidgets();
}
@@ -640,11 +624,7 @@ void MacroConditionMacroEdit::UpdatePaused()
void MacroConditionMacroEdit::MultiStateConditionChanged(int cond)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_multiSateCondition =
static_cast<MacroConditionMacro::MultiStateCondition>(cond);
}
@@ -652,21 +632,13 @@ void MacroConditionMacroEdit::MultiStateConditionChanged(int cond)
void MacroConditionMacroEdit::MultiStateCountChanged(
const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_multiSateCount = value;
}
void MacroConditionMacroEdit::Add(const std::string &name)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
MacroRef macro(name);
_entryData->_macros.push_back(macro);
adjustSize();
@@ -675,11 +647,7 @@ void MacroConditionMacroEdit::Add(const std::string &name)
void MacroConditionMacroEdit::Remove(int idx)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_macros.erase(std::next(_entryData->_macros.begin(), idx));
adjustSize();
updateGeometry();
@@ -687,12 +655,8 @@ void MacroConditionMacroEdit::Remove(int idx)
void MacroConditionMacroEdit::Replace(int idx, const std::string &name)
{
if (_loading || !_entryData) {
return;
}
GUARD_LOADING_AND_LOCK();
MacroRef macro(name);
auto lock = LockContext();
_entryData->_macros[idx] = macro;
adjustSize();
updateGeometry();
@@ -700,11 +664,7 @@ void MacroConditionMacroEdit::Replace(int idx, const std::string &name)
void MacroConditionMacroEdit::ActionIndexChanged(const IntVariable &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_actionIndex = value;
}

View File

@@ -115,11 +115,7 @@ MacroConditionQueueEdit::MacroConditionQueueEdit(
void MacroConditionQueueEdit::ConditionChanged(int condition)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_condition =
static_cast<MacroConditionQueue::Condition>(condition);
emit HeaderInfoChanged(
@@ -129,11 +125,7 @@ void MacroConditionQueueEdit::ConditionChanged(int condition)
void MacroConditionQueueEdit::QueueChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_queue = GetWeakActionQueueByQString(text);
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -141,11 +133,7 @@ void MacroConditionQueueEdit::QueueChanged(const QString &text)
void MacroConditionQueueEdit::SizeChanged(const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_size = value;
}

View File

@@ -264,32 +264,19 @@ void MacroConditionTempVarEdit::UpdateEntryData()
void MacroConditionTempVarEdit::VariableChanged(const TempVariableRef &var)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_tempVar = var;
}
void MacroConditionTempVarEdit::Variable2Changed(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_variable2 = GetWeakVariableByQString(text);
}
void MacroConditionTempVarEdit::ConditionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_type =
static_cast<MacroConditionTempVar::Condition>(value);
SetWidgetVisibility();
@@ -297,11 +284,7 @@ void MacroConditionTempVarEdit::ConditionChanged(int value)
void MacroConditionTempVarEdit::StrValueChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_strValue = _strValue->toPlainText().toStdString();
adjustSize();
updateGeometry();
@@ -309,21 +292,13 @@ void MacroConditionTempVarEdit::StrValueChanged()
void MacroConditionTempVarEdit::NumValueChanged(double val)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_numValue = val;
}
void MacroConditionTempVarEdit::RegexChanged(const RegexConfig &conf)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_regex = conf;
adjustSize();
updateGeometry();

View File

@@ -236,11 +236,7 @@ void MacroConditionVariableEdit::UpdateEntryData()
void MacroConditionVariableEdit::VariableChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_variable = GetWeakVariableByQString(text);
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -248,22 +244,13 @@ void MacroConditionVariableEdit::VariableChanged(const QString &text)
void MacroConditionVariableEdit::Variable2Changed(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_variable2 = GetWeakVariableByQString(text);
}
void MacroConditionVariableEdit::ConditionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_type =
static_cast<MacroConditionVariable::Condition>(value);
SetWidgetVisibility();
@@ -271,11 +258,7 @@ void MacroConditionVariableEdit::ConditionChanged(int value)
void MacroConditionVariableEdit::StrValueChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_strValue = _strValue->toPlainText().toStdString();
adjustSize();
updateGeometry();
@@ -283,21 +266,13 @@ void MacroConditionVariableEdit::StrValueChanged()
void MacroConditionVariableEdit::NumValueChanged(double val)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_numValue = val;
}
void MacroConditionVariableEdit::RegexChanged(const RegexConfig &conf)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_regex = conf;
adjustSize();
updateGeometry();

View File

@@ -56,9 +56,7 @@ MacroSegmentList::~MacroSegmentList()
_autoScrollThread.join();
}
for (const auto &[_, widgets] : _widgetCache) {
clearWidgetVector(widgets);
}
ClearWidgetCache();
}
static bool posIsInScrollbar(const QScrollBar *scrollbar, const QPoint &pos)
@@ -146,7 +144,6 @@ void MacroSegmentList::SetCachingEnabled(bool enable)
void MacroSegmentList::CacheCurrentWidgetsFor(const Macro *macro)
{
if (!_useCache) {
_widgetCache.clear();
return;
}
@@ -168,7 +165,6 @@ void MacroSegmentList::CacheCurrentWidgetsFor(const Macro *macro)
bool MacroSegmentList::PopulateWidgetsFromCache(const Macro *macro)
{
if (!_useCache) {
_widgetCache.clear();
return false;
}
@@ -340,6 +336,13 @@ void MacroSegmentList::HideLastDropLine()
_dropLineIdx = -1;
}
void MacroSegmentList::ClearWidgetCache()
{
for (const auto &[_, widgets] : _widgetCache) {
clearWidgetVector(widgets);
}
}
static bool isInUpperHalfOf(const QPoint &pos, const QRect &rect)
{
return QRect(rect.topLeft(),

View File

@@ -61,6 +61,7 @@ private:
bool IsInListArea(const QPoint &) const;
QRect GetContentItemRectWithPadding(int idx) const;
void HideLastDropLine();
void ClearWidgetCache();
int _dragPosition = -1;
int _dropLineIdx = -1;

View File

@@ -107,7 +107,7 @@ void MacroSegment::SetupTempVars()
void MacroSegment::ClearAvailableTempvars()
{
_tempVariables.clear();
NotifyUIAboutTempVarChange();
NotifyUIAboutTempVarChange(this);
}
static std::shared_ptr<MacroSegment>
@@ -149,7 +149,7 @@ void MacroSegment::AddTempvar(const std::string &id, const std::string &name,
TempVariable var(id, name, description, sharedSegment);
_tempVariables.emplace_back(std::move(var));
NotifyUIAboutTempVarChange();
NotifyUIAboutTempVarChange(this);
}
void MacroSegment::SetTempVarValue(const std::string &id,

View File

@@ -19,7 +19,7 @@ namespace advss {
class Macro;
class EXPORT MacroSegment {
class EXPORT MacroSegment : public Lockable {
public:
MacroSegment(Macro *m, bool supportsVariableValue);
virtual ~MacroSegment() = default;

View File

@@ -76,12 +76,16 @@ void MacroSelection::ShowAllMacros()
void MacroSelection::MacroRemove(const QString &name)
{
const bool currentSelectionWasRemoved = name == currentText();
int idx = findText(name);
if (idx == -1) {
return;
}
removeItem(idx);
setCurrentIndex(-1);
if (currentSelectionWasRemoved) {
setCurrentIndex(-1);
}
}
void MacroSelection::MacroRename(const QString &oldName, const QString &newName)

View File

@@ -207,13 +207,11 @@ void AdvSceneSwitcher::RemoveMacro(std::shared_ptr<Macro> &macro)
clearWidgetCache(macro.get());
}
// Currently shown macro will always be part of the macros to be
// removed, so, we clear the widgets as they should not be cached
ui->conditionsList->Clear();
ui->actionsList->Clear();
ui->elseActionsList->Clear();
// Don't cache widgets for about to be deleted macros
MacroSegmentList::SetCachingEnabled(false);
ui->macros->Remove(macro);
MacroSegmentList::SetCachingEnabled(!switcher->disableMacroWidgetCache);
emit MacroRemoved(name);
}

View File

@@ -1301,10 +1301,10 @@ QSize MacroTreeDelegate::sizeHint(const QStyleOptionViewItem &option,
QWidget *item = tree->indexWidget(index);
if (!item) {
return (QSize(0, 0));
return QStyledItemDelegate::sizeHint(option, index);
}
return (QSize(option.widget->minimumWidth(), item->height()));
return QSize(item->sizeHint());
}
} // namespace advss

View File

@@ -173,7 +173,10 @@ static bool checkCondition(const std::shared_ptr<MacroCondition> &condition)
static constexpr auto perfLogThreshold = 300ms;
const auto startTime = std::chrono::high_resolution_clock::now();
const bool conditionMatched = condition->CheckCondition();
bool conditionMatched = false;
condition->WithLock([&condition, &conditionMatched]() {
conditionMatched = condition->CheckCondition();
});
const auto endTime = std::chrono::high_resolution_clock::now();
const auto timeSpent = endTime - startTime;
@@ -444,9 +447,12 @@ bool Macro::RunActionsHelper(
}
if (action->Enabled()) {
action->LogAction();
bool actionResult = false;
action->WithLock([&action, &actionResult]() {
actionResult = action->PerformAction();
});
actionsExecutedSuccessfully =
actionsExecutedSuccessfully &&
action->PerformAction();
actionsExecutedSuccessfully && actionResult;
} else {
vblog(LOG_INFO, "skipping disabled action %s",
action->GetId().c_str());
@@ -933,9 +939,12 @@ bool Macro::Load(obs_data_t *obj)
auto newEntry = MacroConditionFactory::Create(id, this);
if (newEntry) {
_conditions.emplace_back(newEntry);
auto c = _conditions.back().get();
c->Load(arrayObj);
c->ValidateLogicSelection(root, Name().c_str());
auto condition = _conditions.back().get();
condition->WithLock([&]() {
condition->Load(arrayObj);
condition->ValidateLogicSelection(
root, Name().c_str());
});
} else {
blog(LOG_WARNING,
"discarding condition entry with unknown id (%s) for macro %s",
@@ -948,12 +957,15 @@ bool Macro::Load(obs_data_t *obj)
OBSDataArrayAutoRelease actions = obs_data_get_array(obj, "actions");
count = obs_data_array_count(actions);
for (size_t i = 0; i < count; i++) {
OBSDataAutoRelease array_obj = obs_data_array_item(actions, i);
std::string id = obs_data_get_string(array_obj, "id");
OBSDataAutoRelease arrayObj = obs_data_array_item(actions, i);
std::string id = obs_data_get_string(arrayObj, "id");
auto newEntry = MacroActionFactory::Create(id, this);
if (newEntry) {
_actions.emplace_back(newEntry);
_actions.back()->Load(array_obj);
auto action = _actions.back().get();
action->WithLock([action, &arrayObj]() {
action->Load(arrayObj);
});
} else {
blog(LOG_WARNING,
"discarding action entry with unknown id (%s) for macro %s",
@@ -966,13 +978,16 @@ bool Macro::Load(obs_data_t *obj)
obs_data_get_array(obj, "elseActions");
count = obs_data_array_count(elseActions);
for (size_t i = 0; i < count; i++) {
OBSDataAutoRelease array_obj =
OBSDataAutoRelease arrayObj =
obs_data_array_item(elseActions, i);
std::string id = obs_data_get_string(array_obj, "id");
std::string id = obs_data_get_string(arrayObj, "id");
auto newEntry = MacroActionFactory::Create(id, this);
if (newEntry) {
_elseActions.emplace_back(newEntry);
_elseActions.back()->Load(array_obj);
auto action = _actions.back().get();
action->WithLock([action, &arrayObj]() {
action->Load(arrayObj);
});
} else {
blog(LOG_WARNING,
"discarding elseAction entry with unknown id (%s) for macro %s",
@@ -989,13 +1004,13 @@ bool Macro::Load(obs_data_t *obj)
bool Macro::PostLoad()
{
for (auto &c : _conditions) {
c->PostLoad();
c->WithLock([c]() { c->PostLoad(); });
}
for (auto &a : _actions) {
a->PostLoad();
a->WithLock([a]() { a->PostLoad(); });
}
for (auto &a : _elseActions) {
a->PostLoad();
a->WithLock([a]() { a->PostLoad(); });
}
return true;
}

View File

@@ -25,6 +25,14 @@ SwitcherData::SwitcherData(obs_module_t *m, translateFunc t)
_translate = t;
}
SwitcherData::~SwitcherData()
{
// Assume that OBS is shutting down, as the switcher object will only be
// destroyed when the plugin is unloaded
obsIsShuttingDown = true;
Stop();
}
const char *SwitcherData::Translate(const char *text)
{
return _translate(text);

View File

@@ -45,6 +45,9 @@ std::unique_lock<std::mutex> *GetSwitcherLoopLock();
class SwitcherData {
public:
SwitcherData(obs_module_t *modulePtr, translateFunc translate);
~SwitcherData();
void Thread();
void Start();
void Stop();
@@ -85,9 +88,6 @@ public:
/* --- End of saving / loading section --- */
SwitcherData(obs_module_t *m, translateFunc t);
inline ~SwitcherData() { Stop(); }
public:
SwitcherThread *th = nullptr;
std::mutex m;
@@ -102,7 +102,7 @@ public:
bool firstBoot = true;
bool transitionActive = false;
bool sceneColletionStop = false;
bool obsIsShuttingDown = false;
std::atomic_bool obsIsShuttingDown = {false};
bool firstInterval = true;
bool firstIntervalAfterStop = true;
bool startupLoadDone = false;

View File

@@ -7,7 +7,7 @@
namespace advss {
class SliderIgnoreScroll : public QSlider {
class ADVSS_EXPORT SliderIgnoreScroll : public QSlider {
Q_OBJECT
public:

View File

@@ -9,15 +9,14 @@
namespace advss {
class DurationSelection : public QWidget {
class ADVSS_EXPORT DurationSelection : public QWidget {
Q_OBJECT
public:
EXPORT DurationSelection(QWidget *parent = nullptr,
bool showUnitSelection = true,
double minValue = 0.0);
EXPORT void SetDuration(const Duration &);
DurationSelection(QWidget *parent = nullptr,
bool showUnitSelection = true, double minValue = 0.0);
void SetDuration(const Duration &);
Duration GetDuration() const { return _current; }
EXPORT QDoubleSpinBox *SpinBox() { return _duration->SpinBox(); }
QDoubleSpinBox *SpinBox() { return _duration->SpinBox(); }
private slots:
void _DurationChanged(const NumberVariable<double> &value);

View File

@@ -25,8 +25,8 @@ EXPORT void StopPlugin();
EXPORT void StartPlugin();
EXPORT bool PluginIsRunning();
EXPORT int GetIntervalValue();
void AddStartStep(std::function<void()>);
void AddStopStep(std::function<void()>);
EXPORT void AddStartStep(std::function<void()>);
EXPORT void AddStopStep(std::function<void()>);
void RunStartSteps();
void RunStopSteps();
void RunIntervalResetSteps();

View File

@@ -5,15 +5,15 @@
namespace advss {
class ResizingPlainTextEdit : public QPlainTextEdit {
class ADVSS_EXPORT ResizingPlainTextEdit : public QPlainTextEdit {
Q_OBJECT
public:
ResizingPlainTextEdit(QWidget *parent, const int scrollAt = 10,
const int minLines = 3,
const int paddingLines = 2);
virtual ~ResizingPlainTextEdit(){};
EXPORT int maxLength();
EXPORT void setMaxLength(int maxLength);
int maxLength();
void setMaxLength(int maxLength);
protected:
bool eventFilter(QObject *obj, QEvent *event) override;

View File

@@ -20,4 +20,36 @@ std::unique_lock<std::mutex> *GetLoopLock()
return GetSwitcherLoopLock();
}
PerInstanceMutex::PerInstanceMutex() {}
PerInstanceMutex::~PerInstanceMutex(){};
PerInstanceMutex::PerInstanceMutex(const PerInstanceMutex &) {}
PerInstanceMutex &PerInstanceMutex::operator=(const PerInstanceMutex &)
{
return *this;
}
PerInstanceMutex::operator std::mutex &()
{
return _mtx;
}
PerInstanceMutex::operator const std::mutex &() const
{
return _mtx;
}
std::lock_guard<std::mutex> Lockable::Lock()
{
return std::lock_guard<std::mutex>(_mtx);
}
void Lockable::WithLock(const std::function<void()> &func)
{
const auto lock = Lock();
func();
}
} // namespace advss

View File

@@ -1,6 +1,8 @@
#pragma once
#include "export-symbol-helper.hpp"
#include <functional>
#include <memory>
#include <mutex>
namespace advss {
@@ -10,10 +12,46 @@ namespace advss {
if (_loading || !_entryData) { \
return; \
} \
auto lock = LockContext();
auto lock = _entryData->Lock();
[[nodiscard]] EXPORT std::mutex *GetMutex();
[[nodiscard]] EXPORT std::lock_guard<std::mutex> LockContext();
[[nodiscard]] EXPORT std::unique_lock<std::mutex> *GetLoopLock();
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4251)
#endif
// std::mutex wrapper with no-op copy constructor and assignment operator
class EXPORT PerInstanceMutex {
public:
PerInstanceMutex();
~PerInstanceMutex();
PerInstanceMutex(const PerInstanceMutex &);
PerInstanceMutex &operator=(const PerInstanceMutex &);
operator std::mutex &();
operator const std::mutex &() const;
private:
std::mutex _mtx;
};
#ifdef _MSC_VER
#pragma warning(pop)
#endif
class EXPORT Lockable {
public:
Lockable() = default;
virtual ~Lockable() = default;
[[nodiscard]] std::lock_guard<std::mutex> Lock();
void WithLock(const std::function<void()> &func);
private:
PerInstanceMutex _mtx;
};
} // namespace advss

View File

@@ -274,8 +274,9 @@ TempVariableSelection::TempVariableSelection(QWidget *parent)
SLOT(HighlightChanged(int)));
QWidget::connect(window(), SIGNAL(MacroSegmentOrderChanged()), this,
SLOT(MacroSegmentsChanged()));
QWidget::connect(window(), SIGNAL(SegmentTempVarsChanged()), this,
SLOT(SegmentTempVarsChanged()));
QWidget::connect(window(),
SIGNAL(SegmentTempVarsChanged(MacroSegment *)), this,
SLOT(SegmentTempVarsChanged(MacroSegment *)));
auto layout = new QHBoxLayout();
layout->setContentsMargins(0, 0, 0, 0);
@@ -314,9 +315,15 @@ void TempVariableSelection::MacroSegmentsChanged()
SetVariable(currentSelection);
}
void TempVariableSelection::SegmentTempVarsChanged()
void TempVariableSelection::SegmentTempVarsChanged(MacroSegment *segment)
{
MacroSegmentsChanged();
const auto currentSegment = GetSegment();
const auto currentMacro = currentSegment ? currentSegment->GetMacro()
: nullptr;
const auto changeMacro = segment ? segment->GetMacro() : nullptr;
if (currentMacro == changeMacro) {
MacroSegmentsChanged();
}
}
void TempVariableSelection::HighlightChanged(int idx)
@@ -427,13 +434,11 @@ QString TempVariableSelection::SetupInfoLabel()
MacroSegment *TempVariableSelection::GetSegment() const
{
const QWidget *widget = this;
{
while (widget) {
if (qobject_cast<const MacroSegmentEdit *>(widget)) {
break;
}
widget = widget->parentWidget();
while (widget) {
if (qobject_cast<const MacroSegmentEdit *>(widget)) {
break;
}
widget = widget->parentWidget();
}
if (!widget) {
return nullptr;
@@ -442,17 +447,18 @@ MacroSegment *TempVariableSelection::GetSegment() const
return segmentWidget->Data().get();
}
void NotifyUIAboutTempVarChange()
void NotifyUIAboutTempVarChange(MacroSegment *segment)
{
obs_queue_task(
OBS_TASK_UI,
[](void *) {
[](void *segment) {
if (!SettingsWindowIsOpened()) {
return;
}
AdvSceneSwitcher::window->SegmentTempVarsChanged();
AdvSceneSwitcher::window->SegmentTempVarsChanged(
(MacroSegment *)segment);
},
nullptr, false);
segment, false);
}
} // namespace advss

View File

@@ -88,7 +88,7 @@ public:
private slots:
void SelectionIdxChanged(int);
void MacroSegmentsChanged();
void SegmentTempVarsChanged();
void SegmentTempVarsChanged(MacroSegment *);
void HighlightChanged(int);
signals:
@@ -104,6 +104,6 @@ private:
AutoUpdateTooltipLabel *_info;
};
void NotifyUIAboutTempVarChange();
void NotifyUIAboutTempVarChange(MacroSegment *);
} // namespace advss

View File

@@ -6,6 +6,7 @@
#include <obs-frontend-api.h>
#include <QGraphicsColorizeEffect>
#include <QListView>
#include <QMainWindow>
#include <QPropertyAnimation>
#include <QScrollBar>
@@ -104,6 +105,19 @@ int FindIdxInRagne(QComboBox *list, int start, int stop,
return foundIdx;
}
void SetRowVisibleByValue(QComboBox *list, const QString &value, bool show)
{
int index = list->findText(value);
if (index == -1) {
return;
}
auto view = qobject_cast<QListView *>(list->view());
if (view) {
view->setRowHidden(index, !show);
}
}
QWidget *GetSettingsWindow()
{
return SettingsWindowIsOpened() ? AdvSceneSwitcher::window : nullptr;

View File

@@ -20,9 +20,12 @@ EXPORT QObject *HighlightWidget(QWidget *widget, QColor startColor,
EXPORT void SetHeightToContentHeight(QListWidget *list);
EXPORT void SetButtonIcon(QAbstractButton *button, const char *path);
EXPORT int
FindIdxInRagne(QComboBox *list, int start, int stop, const std::string &value,
Qt::MatchFlags = Qt::MatchExactly | Qt::MatchCaseSensitive);
EXPORT void SetRowVisibleByValue(QComboBox *list, const QString &value,
bool show);
EXPORT bool DisplayMessage(const QString &msg, bool question = false,
bool modal = true);

View File

@@ -117,9 +117,25 @@ void RegisterWebsocketRequest(
});
}
static bool websocketModuleIsLoaded()
{
bool websocketModuleFound = false;
const auto checkModule = [](void *param, obs_module_t *module) {
bool *moduleFound = static_cast<bool *>(param);
auto name = obs_get_module_name(module);
if (name && strcmp(name, "obs-websocket") == 0) {
*moduleFound = true;
}
};
obs_enum_modules(checkModule, &websocketModuleFound);
return websocketModuleFound;
}
void SendWebsocketVendorEvent(const std::string &eventName, obs_data_t *data)
{
if (OBSIsShuttingDown()) {
// If obs-websocket was loaded, but was unloaded at some point any calls
// to obs_websocket_vendor_emit_event() will segfault
if (OBSIsShuttingDown() || !websocketModuleIsLoaded()) {
return;
}
obs_websocket_vendor_emit_event(vendor, eventName.c_str(), data);

View File

@@ -4,15 +4,15 @@
namespace advss {
class VariableTextEdit : public ResizingPlainTextEdit {
class ADVSS_EXPORT VariableTextEdit : public ResizingPlainTextEdit {
Q_OBJECT
public:
EXPORT VariableTextEdit(QWidget *parent, const int scrollAt = 10,
const int minLines = 3,
const int paddingLines = 2);
EXPORT void setPlainText(const QString &);
EXPORT void setPlainText(const StringVariable &);
EXPORT void setToolTip(const QString &string);
VariableTextEdit(QWidget *parent, const int scrollAt = 10,
const int minLines = 3, const int paddingLines = 2);
virtual ~VariableTextEdit(){};
void setPlainText(const QString &);
void setPlainText(const StringVariable &);
void setToolTip(const QString &string);
private:
};

View File

@@ -32,6 +32,7 @@ add_plugin(http)
add_plugin(midi)
add_plugin(mqtt)
add_plugin(openvr)
add_plugin(scripting)
add_plugin(stream-deck)
add_plugin(twitch)
add_plugin(usb)

View File

@@ -666,11 +666,7 @@ void MacroActionAudioEdit::UpdateEntryData()
void MacroActionAudioEdit::SourceChanged(const SourceSelection &source)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_audioSource = source;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -678,11 +674,7 @@ void MacroActionAudioEdit::SourceChanged(const SourceSelection &source)
void MacroActionAudioEdit::ActionChanged(int idx)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_action = static_cast<MacroActionAudio::Action>(
_actions->itemData(idx).toInt());
SetWidgetVisibility();
@@ -690,133 +682,81 @@ void MacroActionAudioEdit::ActionChanged(int idx)
void MacroActionAudioEdit::SyncOffsetChanged(const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_syncOffset = value;
}
void MacroActionAudioEdit::MonitorTypeChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_monitorType = static_cast<obs_monitoring_type>(value);
}
void MacroActionAudioEdit::BalanceChanged(const NumberVariable<double> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_balance = value;
}
void MacroActionAudioEdit::TrackChanged(const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_track = value;
}
void MacroActionAudioEdit::VolumeDBChanged(const NumberVariable<double> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_volumeDB = value;
}
void MacroActionAudioEdit::PercentDBClicked()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_useDb = !_entryData->_useDb;
SetWidgetVisibility();
}
void MacroActionAudioEdit::VolumeChanged(const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_volume = value;
}
void MacroActionAudioEdit::FadeChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_fade = value;
SetWidgetVisibility();
}
void MacroActionAudioEdit::DurationChanged(const Duration &dur)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_duration = dur;
}
void MacroActionAudioEdit::RateChanged(const NumberVariable<double> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_rate = value;
}
void MacroActionAudioEdit::WaitChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_wait = value;
}
void MacroActionAudioEdit::AbortActiveFadeChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_abortActiveFade = value;
}
void MacroActionAudioEdit::FadeTypeChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_fadeType = static_cast<MacroActionAudio::FadeType>(value);
SetWidgetVisibility();
}

View File

@@ -214,11 +214,7 @@ MacroActionClipboardEdit::MacroActionClipboardEdit(
void MacroActionClipboardEdit::ActionChanged(int index)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_action = static_cast<MacroActionClipboard::Action>(
_actions->itemData(index).toInt());
@@ -227,21 +223,13 @@ void MacroActionClipboardEdit::ActionChanged(int index)
void MacroActionClipboardEdit::TextChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_text = _text->text().toStdString();
}
void MacroActionClipboardEdit::UrlChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_url = _url->text().toStdString();
}

View File

@@ -153,11 +153,7 @@ void MacroActionFileEdit::UpdateEntryData()
void MacroActionFileEdit::PathChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_file = text.toUtf8().constData();
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -165,11 +161,7 @@ void MacroActionFileEdit::PathChanged(const QString &text)
void MacroActionFileEdit::TextChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_text = _text->toPlainText().toStdString();
adjustSize();
@@ -178,11 +170,7 @@ void MacroActionFileEdit::TextChanged()
void MacroActionFileEdit::ActionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_action = static_cast<MacroActionFile::Action>(value);
}

View File

@@ -3,6 +3,7 @@
#include "json-helpers.hpp"
#include "source-settings-helpers.hpp"
#include "selection-helpers.hpp"
#include "ui-helpers.hpp"
namespace advss {
@@ -26,10 +27,13 @@ const static std::map<MacroActionFilter::Action, std::string> actionTypes = {
"AdvSceneSwitcher.action.filter.type.pressSettingsButton"},
};
const static std::map<MacroActionFilter::SettingsInputMethod, std::string>
const static std::vector<
std::pair<MacroActionFilter::SettingsInputMethod, std::string>>
inputMethods = {
{MacroActionFilter::SettingsInputMethod::INDIVIDUAL_MANUAL,
"AdvSceneSwitcher.action.filter.inputMethod.individualManual"},
{MacroActionFilter::SettingsInputMethod::INDIVIDUAL_LIST_ENTRY,
"AdvSceneSwitcher.action.filter.inputMethod.individualListEntryManual"},
{MacroActionFilter::SettingsInputMethod::INDIVIDUAL_TEMPVAR,
"AdvSceneSwitcher.action.filter.inputMethod.individualTempvar"},
{MacroActionFilter::SettingsInputMethod::JSON_STRING,
@@ -59,6 +63,10 @@ static void performActionHelper(
case MacroActionFilter::SettingsInputMethod::INDIVIDUAL_MANUAL:
SetSourceSetting(source, setting, manualSettingValue);
break;
case MacroActionFilter::SettingsInputMethod::INDIVIDUAL_LIST_ENTRY:
SetSourceSettingListEntryValueByName(
source, setting, manualSettingValue);
break;
case MacroActionFilter::SettingsInputMethod::INDIVIDUAL_TEMPVAR: {
auto var = tempVar.GetTempVariable(macro);
if (!var) {
@@ -373,6 +381,16 @@ void MacroActionFilterEdit::GetSettingsClicked()
.value_or(""));
break;
}
case MacroActionFilter::SettingsInputMethod::INDIVIDUAL_LIST_ENTRY: {
const auto filters =
_entryData->_filter.GetFilters(_entryData->_source);
_manualSettingValue->setPlainText(
GetSourceSettingListEntryName(
filters.empty() ? nullptr : filters.at(0),
_entryData->_setting)
.value_or(""));
break;
}
case MacroActionFilter::SettingsInputMethod::INDIVIDUAL_TEMPVAR:
break;
case MacroActionFilter::SettingsInputMethod::JSON_STRING: {
@@ -415,6 +433,7 @@ void MacroActionFilterEdit::SelectionChanged(const SourceSetting &setting)
{
GUARD_LOADING_AND_LOCK();
_entryData->_setting = setting;
SetWidgetVisibility();
}
void MacroActionFilterEdit::ManualSettingsValueChanged()
@@ -440,6 +459,22 @@ void MacroActionFilterEdit::ButtonChanged(const SourceSettingButton &button)
_entryData->_button = button;
}
static QString GetIndividualListEntryName()
{
static const auto matchesInput =
[](const std::pair<MacroActionFilter::SettingsInputMethod,
std::string> &p) {
return p.first ==
MacroActionFilter::SettingsInputMethod::
INDIVIDUAL_LIST_ENTRY;
};
static const QString listValueText(
obs_module_text(std::find_if(inputMethods.begin(),
inputMethods.end(), matchesInput)
->second.c_str()));
return listValueText;
}
void MacroActionFilterEdit::SetWidgetVisibility()
{
SetLayoutVisible(_settingsLayout,
@@ -464,9 +499,16 @@ void MacroActionFilterEdit::SetWidgetVisibility()
MacroActionFilter::SettingsInputMethod::
INDIVIDUAL_TEMPVAR);
SetRowVisibleByValue(_settingsInputMethods,
GetIndividualListEntryName(),
_entryData->_setting.IsList());
if (_entryData->_action == MacroActionFilter::Action::SETTINGS &&
_entryData->_settingsInputMethod ==
MacroActionFilter::SettingsInputMethod::INDIVIDUAL_MANUAL) {
(_entryData->_settingsInputMethod ==
MacroActionFilter::SettingsInputMethod::INDIVIDUAL_MANUAL ||
_entryData->_settingsInputMethod ==
MacroActionFilter::SettingsInputMethod::
INDIVIDUAL_LIST_ENTRY)) {
RemoveStretchIfPresent(_settingsLayout);
_manualSettingValue->show();
} else {
@@ -475,8 +517,12 @@ void MacroActionFilterEdit::SetWidgetVisibility()
}
_refreshSettingSelection->setVisible(
_entryData->_settingsInputMethod ==
MacroActionFilter::SettingsInputMethod::INDIVIDUAL_MANUAL &&
(_entryData->_settingsInputMethod ==
MacroActionFilter::SettingsInputMethod::
INDIVIDUAL_MANUAL ||
_entryData->_settingsInputMethod ==
MacroActionFilter::SettingsInputMethod::
INDIVIDUAL_LIST_ENTRY) &&
(_entryData->_source.GetType() ==
SourceSelection::Type::VARIABLE ||
_entryData->_filter.GetType() ==

View File

@@ -36,6 +36,7 @@ public:
INDIVIDUAL_MANUAL,
INDIVIDUAL_TEMPVAR,
JSON_STRING,
INDIVIDUAL_LIST_ENTRY,
};
SettingsInputMethod _settingsInputMethod =
SettingsInputMethod::INDIVIDUAL_MANUAL;

View File

@@ -788,133 +788,82 @@ void MacroActionHotkeyEdit::UpdateEntryData()
void MacroActionHotkeyEdit::LShiftChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_leftShift = state;
}
void MacroActionHotkeyEdit::RShiftChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_rightShift = state;
}
void MacroActionHotkeyEdit::LCtrlChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_leftCtrl = state;
}
void MacroActionHotkeyEdit::RCtrlChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_rightCtrl = state;
}
void MacroActionHotkeyEdit::LAltChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_leftAlt = state;
}
void MacroActionHotkeyEdit::RAltChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_rightAlt = state;
}
void MacroActionHotkeyEdit::LMetaChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_leftMeta = state;
}
void MacroActionHotkeyEdit::RMetaChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_rightMeta = state;
}
void MacroActionHotkeyEdit::DurationChanged(const Duration &dur)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_duration = dur;
}
void MacroActionHotkeyEdit::OnlySendToOBSChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_onlySendToObs = state;
SetWidgetVisibility();
}
void MacroActionHotkeyEdit::KeyChanged(int key)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_key = static_cast<HotkeyType>(key);
}
void MacroActionHotkeyEdit::ActionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_action = static_cast<MacroActionHotkey::Action>(value);
SetWidgetVisibility();
}
void MacroActionHotkeyEdit::HotkeyTypeChanged(int value)
{
if (_loading || !_entryData) {
return;
}
{
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_hotkeyType =
static_cast<obs_hotkey_registerer_type>(value);
}
@@ -923,11 +872,7 @@ void MacroActionHotkeyEdit::HotkeyTypeChanged(int value)
void MacroActionHotkeyEdit::OBSHotkeyChanged(int idx)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
if (idx == -1) {
_entryData->_hotkeyName = "";
return;

View File

@@ -238,54 +238,34 @@ void MacroActionHttpEdit::UpdateEntryData()
void MacroActionHttpEdit::URLChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_url = _url->text().toStdString();
emit(HeaderInfoChanged(_url->text()));
}
void MacroActionHttpEdit::MethodChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_method = static_cast<MacroActionHttp::Method>(value);
SetWidgetVisibility();
}
void MacroActionHttpEdit::TimeoutChanged(const Duration &dur)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_timeout = dur;
}
void MacroActionHttpEdit::SetHeadersChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_setHeaders = value;
SetWidgetVisibility();
}
void MacroActionHttpEdit::HeadersChanged(const StringList &headers)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_headers = headers;
adjustSize();
updateGeometry();
@@ -302,11 +282,7 @@ void MacroActionHttpEdit::SetWidgetVisibility()
void MacroActionHttpEdit::DataChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_data = _data->toPlainText().toUtf8().constData();
adjustSize();

View File

@@ -75,11 +75,7 @@ void MacroActionLogEdit::UpdateEntryData()
void MacroActionLogEdit::LogMessageChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_logMessage = _logMessage->toPlainText().toStdString();
adjustSize();

View File

@@ -286,22 +286,14 @@ MacroActionMediaEdit::MacroActionMediaEdit(
void MacroActionMediaEdit::ActionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_action = static_cast<MacroActionMedia::Action>(value);
SetWidgetVisibility();
}
void MacroActionMediaEdit::SelectionTypeChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_selection =
static_cast<MacroActionMedia::SelectionType>(value);
SetWidgetVisibility();
@@ -309,32 +301,20 @@ void MacroActionMediaEdit::SelectionTypeChanged(int value)
void MacroActionMediaEdit::SeekDurationChanged(const Duration &seekDuration)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_seekDuration = seekDuration;
}
void MacroActionMediaEdit::SeekPercentageChanged(
const NumberVariable<double> &seekPercentage)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_seekPercentage = seekPercentage;
}
void MacroActionMediaEdit::SourceChanged(const SourceSelection &source)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_mediaSource = source;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -342,11 +322,7 @@ void MacroActionMediaEdit::SourceChanged(const SourceSelection &source)
void MacroActionMediaEdit::SourceChanged(const SceneItemSelection &item)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_sceneItem = item;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -356,11 +332,7 @@ void MacroActionMediaEdit::SourceChanged(const SceneItemSelection &item)
void MacroActionMediaEdit::SceneChanged(const SceneSelection &scene)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_scene = scene;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));

View File

@@ -296,41 +296,25 @@ void MacroActionOSCEdit::UpdateEntryData()
void MacroActionOSCEdit::IpChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->SetIP(_ip->text().toStdString());
}
void MacroActionOSCEdit::ProtocolChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->SetProtocol(static_cast<MacroActionOSC::Protocol>(value));
}
void MacroActionOSCEdit::PortChanged(const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->SetPortNr(value);
}
void MacroActionOSCEdit::MessageChanged(const OSCMessage &m)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_message = m;
adjustSize();

View File

@@ -300,12 +300,8 @@ void MacroActionPluginStateEdit::UpdateEntryData()
void MacroActionPluginStateEdit::ActionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
{
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_action = static_cast<PluginStateAction>(value);
SetWidgetVisibility();
}
@@ -316,32 +312,20 @@ void MacroActionPluginStateEdit::ActionChanged(int value)
void MacroActionPluginStateEdit::ValueChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_value = value;
SetWidgetVisibility();
}
void MacroActionPluginStateEdit::SceneChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_scene = GetWeakSourceByQString(text);
}
void MacroActionPluginStateEdit::PathChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_settingsPath = text.toStdString();
}

View File

@@ -157,11 +157,7 @@ void MacroActionRandomEdit::MacroRemove(const QString &)
void MacroActionRandomEdit::Add(const std::string &name)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
MacroRef macro(name);
_entryData->_macros.push_back(macro);
_allowRepeat->setVisible(ShouldShowAllowRepeat());
@@ -170,11 +166,7 @@ void MacroActionRandomEdit::Add(const std::string &name)
void MacroActionRandomEdit::Remove(int idx)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_macros.erase(std::next(_entryData->_macros.begin(), idx));
_allowRepeat->setVisible(ShouldShowAllowRepeat());
adjustSize();
@@ -182,23 +174,15 @@ void MacroActionRandomEdit::Remove(int idx)
void MacroActionRandomEdit::Replace(int idx, const std::string &name)
{
if (_loading || !_entryData) {
return;
}
GUARD_LOADING_AND_LOCK();
MacroRef macro(name);
auto lock = LockContext();
_entryData->_macros[idx] = macro;
adjustSize();
}
void MacroActionRandomEdit::AllowRepeatChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_allowRepeat = value;
}

View File

@@ -199,21 +199,13 @@ static bool isPauseAction(MacroActionRecord::Action a)
void MacroActionRecordEdit::FolderChanged(const QString &folder)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_folder = folder.toStdString();
}
void MacroActionRecordEdit::FormatStringChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_fileFormat = _recordFileFormat->text().toStdString();
}
@@ -230,11 +222,7 @@ void MacroActionRecordEdit::SetWidgetVisibility()
void MacroActionRecordEdit::ActionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_action = static_cast<MacroActionRecord::Action>(value);
SetWidgetVisibility();
}

View File

@@ -121,11 +121,7 @@ void MacroActionSceneCollectionEdit::UpdateEntryData()
void MacroActionSceneCollectionEdit::SceneCollectionChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_sceneCollection = text.toStdString();
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));

View File

@@ -156,21 +156,13 @@ void MacroActionSceneLockEdit::UpdateEntryData()
void MacroActionSceneLockEdit::SceneChanged(const SceneSelection &s)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_scene = s;
}
void MacroActionSceneLockEdit::SourceChanged(const SceneItemSelection &item)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_source = item;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -180,11 +172,7 @@ void MacroActionSceneLockEdit::SourceChanged(const SceneItemSelection &item)
void MacroActionSceneLockEdit::ActionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_action = static_cast<MacroActionSceneLock::Action>(value);
}

View File

@@ -273,31 +273,19 @@ MacroActionSwitchSceneEdit::MacroActionSwitchSceneEdit(
void MacroActionSwitchSceneEdit::DurationChanged(const Duration &dur)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_duration = dur;
}
void MacroActionSwitchSceneEdit::BlockUntilTransitionDoneChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_blockUntilTransitionDone = state;
}
void MacroActionSwitchSceneEdit::SceneTypeChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_sceneType =
static_cast<MacroActionSwitchScene::SceneType>(value);
SetWidgetVisibility();
@@ -351,11 +339,7 @@ void MacroActionSwitchSceneEdit::SetWidgetVisibility()
void MacroActionSwitchSceneEdit::SceneChanged(const SceneSelection &s)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_scene = s;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -363,11 +347,7 @@ void MacroActionSwitchSceneEdit::SceneChanged(const SceneSelection &s)
void MacroActionSwitchSceneEdit::TransitionChanged(const TransitionSelection &t)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_transition = t;
SetWidgetVisibility();
}

View File

@@ -170,22 +170,14 @@ void MacroActionSceneVisibilityEdit::UpdateEntryData()
void MacroActionSceneVisibilityEdit::SceneChanged(const SceneSelection &s)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_scene = s;
}
void MacroActionSceneVisibilityEdit::SourceChanged(
const SceneItemSelection &item)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_source = item;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -195,11 +187,7 @@ void MacroActionSceneVisibilityEdit::SourceChanged(
void MacroActionSceneVisibilityEdit::ActionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_action =
static_cast<MacroActionSceneVisibility::Action>(value);
}

View File

@@ -279,11 +279,7 @@ void MacroActionSequenceEdit::MacroRemove(const QString &)
void MacroActionSequenceEdit::Add(const std::string &name)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
MacroRef macro(name);
_entryData->_macros.push_back(macro);
adjustSize();
@@ -291,39 +287,27 @@ void MacroActionSequenceEdit::Add(const std::string &name)
void MacroActionSequenceEdit::Remove(int idx)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_macros.erase(std::next(_entryData->_macros.begin(), idx));
adjustSize();
}
void MacroActionSequenceEdit::Up(int idx)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
std::swap(_entryData->_macros[idx], _entryData->_macros[idx - 1]);
}
void MacroActionSequenceEdit::Down(int idx)
{
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
std::swap(_entryData->_macros[idx], _entryData->_macros[idx + 1]);
}
void MacroActionSequenceEdit::Replace(int idx, const std::string &name)
{
if (_loading || !_entryData) {
return;
}
GUARD_LOADING_AND_LOCK();
MacroRef macro(name);
auto lock = LockContext();
_entryData->_macros[idx] = macro;
adjustSize();
}
@@ -344,11 +328,7 @@ void MacroActionSequenceEdit::ContinueFromClicked()
void MacroActionSequenceEdit::RestartChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_restart = state;
}
@@ -377,32 +357,20 @@ void MacroActionSequenceEdit::UpdateStatusLine()
void MacroActionSequenceEdit::ActionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_action = static_cast<MacroActionSequence::Action>(value);
SetWidgetVisibility();
}
void MacroActionSequenceEdit::MacroChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_macro = text;
}
void MacroActionSequenceEdit::ResetIndexChanged(const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_resetIndex = value;
}

View File

@@ -3,6 +3,7 @@
#include "json-helpers.hpp"
#include "selection-helpers.hpp"
#include "source-settings-helpers.hpp"
#include "ui-helpers.hpp"
#include <obs-frontend-api.h>
@@ -67,10 +68,13 @@ const static std::map<obs_deinterlace_field_order, std::string>
"AdvSceneSwitcher.action.source.deinterlaceOrder.bottomFieldFirst"},
};
const static std::map<MacroActionSource::SettingsInputMethod, std::string>
static const std::vector<
std::pair<MacroActionSource::SettingsInputMethod, std::string>>
inputMethods = {
{MacroActionSource::SettingsInputMethod::INDIVIDUAL_MANUAL,
"AdvSceneSwitcher.action.source.inputMethod.individualManual"},
{MacroActionSource::SettingsInputMethod::INDIVIDUAL_LIST_ENTRY,
"AdvSceneSwitcher.action.source.inputMethod.individualListEntryManual"},
{MacroActionSource::SettingsInputMethod::INDIVIDUAL_TEMPVAR,
"AdvSceneSwitcher.action.source.inputMethod.individualTempvar"},
{MacroActionSource::SettingsInputMethod::JSON_STRING,
@@ -119,6 +123,10 @@ bool MacroActionSource::PerformAction()
case SettingsInputMethod::INDIVIDUAL_MANUAL:
SetSourceSetting(s, _setting, _manualSettingValue);
break;
case SettingsInputMethod::INDIVIDUAL_LIST_ENTRY:
SetSourceSettingListEntryValueByName(
s, _setting, _manualSettingValue);
break;
case SettingsInputMethod::INDIVIDUAL_TEMPVAR: {
auto var = _tempVar.GetTempVariable(GetMacro());
if (!var) {
@@ -263,9 +271,8 @@ static inline void populateActionSelection(QComboBox *list)
}
}
template<class T>
static inline void populateModeSelection(QComboBox *list,
const std::map<T, std::string> &modes)
template<typename T>
static inline void populateModeSelection(QComboBox *list, const T &modes)
{
list->clear();
for (const auto &[value, name] : modes) {
@@ -343,7 +350,7 @@ MacroActionSourceEdit::MacroActionSourceEdit(
auto entryLayout = new QHBoxLayout;
entryLayout->setContentsMargins(0, 0, 0, 0);
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
const std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{sources}}", _sources},
{"{{actions}}", _actions},
{"{{settings}}", _sourceSettings},
@@ -405,12 +412,8 @@ void MacroActionSourceEdit::UpdateEntryData()
void MacroActionSourceEdit::SourceChanged(const SourceSelection &source)
{
if (_loading || !_entryData) {
return;
}
{
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_source = source;
}
@@ -448,6 +451,13 @@ void MacroActionSourceEdit::GetSettingsClicked()
_entryData->_setting)
.value_or(""));
break;
case MacroActionSource::SettingsInputMethod::INDIVIDUAL_LIST_ENTRY:
_manualSettingValue->setPlainText(
GetSourceSettingListEntryName(
_entryData->_source.GetSource(),
_entryData->_setting)
.value_or(""));
break;
case MacroActionSource::SettingsInputMethod::INDIVIDUAL_TEMPVAR:
break;
case MacroActionSource::SettingsInputMethod::JSON_STRING:
@@ -501,6 +511,7 @@ void MacroActionSourceEdit::SelectionChanged(const SourceSetting &setting)
{
GUARD_LOADING_AND_LOCK();
_entryData->_setting = setting;
SetWidgetVisibility();
}
void MacroActionSourceEdit::ManualSettingsValueChanged()
@@ -518,6 +529,22 @@ void MacroActionSourceEdit::RefreshVariableSourceSelectionValue()
_sourceSettings->SetSource(_entryData->_source.GetSource());
}
static QString GetIndividualListEntryName()
{
static const auto matchesInput =
[](const std::pair<MacroActionSource::SettingsInputMethod,
std::string> &p) {
return p.first ==
MacroActionSource::SettingsInputMethod::
INDIVIDUAL_LIST_ENTRY;
};
static const QString listValueText(
obs_module_text(std::find_if(inputMethods.begin(),
inputMethods.end(), matchesInput)
->second.c_str()));
return listValueText;
}
void MacroActionSourceEdit::SetWidgetVisibility()
{
SetLayoutVisible(_settingsLayout,
@@ -536,6 +563,11 @@ void MacroActionSourceEdit::SetWidgetVisibility()
_entryData->_settingsInputMethod !=
MacroActionSource::SettingsInputMethod::
INDIVIDUAL_TEMPVAR);
SetRowVisibleByValue(_settingsInputMethods,
GetIndividualListEntryName(),
_entryData->_setting.IsList());
_tempVars->setVisible(_entryData->_action ==
MacroActionSource::Action::SETTINGS &&
_entryData->_settingsInputMethod ==
@@ -543,8 +575,11 @@ void MacroActionSourceEdit::SetWidgetVisibility()
INDIVIDUAL_TEMPVAR);
if (_entryData->_action == MacroActionSource::Action::SETTINGS &&
_entryData->_settingsInputMethod ==
MacroActionSource::SettingsInputMethod::INDIVIDUAL_MANUAL) {
(_entryData->_settingsInputMethod ==
MacroActionSource::SettingsInputMethod::INDIVIDUAL_MANUAL ||
_entryData->_settingsInputMethod ==
MacroActionSource::SettingsInputMethod::
INDIVIDUAL_LIST_ENTRY)) {
RemoveStretchIfPresent(_settingsLayout);
_manualSettingValue->show();
} else {
@@ -567,8 +602,12 @@ void MacroActionSourceEdit::SetWidgetVisibility()
MacroActionSource::Action::DEINTERLACE_FIELD_ORDER);
_refreshSettingSelection->setVisible(
_entryData->_settingsInputMethod ==
MacroActionSource::SettingsInputMethod::INDIVIDUAL_MANUAL &&
(_entryData->_settingsInputMethod ==
MacroActionSource::SettingsInputMethod::
INDIVIDUAL_MANUAL ||
_entryData->_settingsInputMethod ==
MacroActionSource::SettingsInputMethod::
INDIVIDUAL_LIST_ENTRY) &&
_entryData->_source.GetType() ==
SourceSelection::Type::VARIABLE);

View File

@@ -52,6 +52,7 @@ public:
INDIVIDUAL_MANUAL,
INDIVIDUAL_TEMPVAR,
JSON_STRING,
INDIVIDUAL_LIST_ENTRY,
};
SettingsInputMethod _settingsInputMethod =
SettingsInputMethod::INDIVIDUAL_MANUAL;

View File

@@ -236,21 +236,13 @@ void MacroActionStreamEdit::UpdateEntryData()
void MacroActionStreamEdit::KeyFrameIntervalChanged(
const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_keyFrameInterval = value;
}
void MacroActionStreamEdit::StringValueChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_stringValue = _stringValue->text().toStdString();
SetWidgetVisibility();
}
@@ -303,11 +295,8 @@ void MacroActionStreamEdit::SetWidgetVisibility()
void MacroActionStreamEdit::ActionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
{
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_action =
static_cast<MacroActionStream::Action>(value);
}

View File

@@ -164,11 +164,7 @@ void MacroActionSudioModeEdit::UpdateEntryData()
void MacroActionSudioModeEdit::SceneChanged(const SceneSelection &s)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_scene = s;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -187,11 +183,7 @@ void MacroActionSudioModeEdit::SetWidgetVisibility()
void MacroActionSudioModeEdit::ActionChanged(int index)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_action = static_cast<MacroActionSudioMode::Action>(
_actions->itemData(index).toInt());
SetWidgetVisibility();

View File

@@ -152,11 +152,7 @@ void MacroActionSystrayEdit::CheckIfTrayIsDisabled()
void MacroActionSystrayEdit::MessageChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_message = _message->text().toStdString();
}

View File

@@ -185,11 +185,7 @@ void MacroActionTimerEdit::UpdateEntryData()
void MacroActionTimerEdit::ActionTypeChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_actionType = static_cast<MacroActionTimer::Action>(value);
SetWidgetVisibility();
}
@@ -206,21 +202,13 @@ void MacroActionTimerEdit::SetWidgetVisibility()
void MacroActionTimerEdit::DurationChanged(const Duration &dur)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_duration = dur;
}
void MacroActionTimerEdit::MacroChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_macro = text;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));

View File

@@ -318,11 +318,7 @@ void MacroActionTransitionEdit::UpdateEntryData()
void MacroActionTransitionEdit::SourceChanged(const SceneItemSelection &item)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_source = item;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -332,11 +328,7 @@ void MacroActionTransitionEdit::SourceChanged(const SceneItemSelection &item)
void MacroActionTransitionEdit::ActionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_type = static_cast<MacroActionTransition::Type>(value);
SetWidgetVisibility();
emit HeaderInfoChanged(
@@ -345,11 +337,7 @@ void MacroActionTransitionEdit::ActionChanged(int value)
void MacroActionTransitionEdit::SceneChanged(const SceneSelection &s)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_scene = s;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -357,11 +345,7 @@ void MacroActionTransitionEdit::SceneChanged(const SceneSelection &s)
void MacroActionTransitionEdit::TransitionChanged(const TransitionSelection &t)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_transition = t;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -369,11 +353,7 @@ void MacroActionTransitionEdit::TransitionChanged(const TransitionSelection &t)
void MacroActionTransitionEdit::DurationChanged(const Duration &dur)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_duration = dur;
}
@@ -389,11 +369,7 @@ void MacroActionTransitionEdit::SetWidgetVisibility()
void MacroActionTransitionEdit::SetTransitionChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_setTransitionType = state;
_transitions->setEnabled(state);
if (state) {
@@ -406,11 +382,7 @@ void MacroActionTransitionEdit::SetTransitionChanged(int state)
void MacroActionTransitionEdit::SetDurationChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_setDuration = state;
_duration->setEnabled(state);
}

View File

@@ -117,11 +117,7 @@ void MacroActionVCamEdit::UpdateEntryData()
void MacroActionVCamEdit::ActionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_action = static_cast<MacroActionVCam::Action>(value);
}

View File

@@ -196,11 +196,7 @@ void MacroActionWaitEdit::SetupRandomDurationEdit()
void MacroActionWaitEdit::TypeChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
auto type = static_cast<MacroActionWait::Type>(value);
if (type == MacroActionWait::Type::FIXED) {
@@ -216,11 +212,7 @@ void MacroActionWaitEdit::TypeChanged(int value)
void MacroActionWaitEdit::DurationChanged(const Duration &dur)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_duration = dur;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -228,11 +220,7 @@ void MacroActionWaitEdit::DurationChanged(const Duration &dur)
void MacroActionWaitEdit::Duration2Changed(const Duration &dur)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_duration2 = dur;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));

View File

@@ -303,12 +303,8 @@ void MacroActionWebsocketEdit::UpdateEntryData()
void MacroActionWebsocketEdit::APITypeChanged(int index)
{
if (_loading || !_entryData) {
return;
}
{
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_api =
static_cast<MacroActionWebsocket::API>(index);
}
@@ -339,11 +335,7 @@ void MacroActionWebsocketEdit::APITypeChanged(int index)
void MacroActionWebsocketEdit::MessageTypeChanged(int index)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_type =
static_cast<MacroActionWebsocket::MessageType>(index);
SetWidgetVisibility();
@@ -353,11 +345,7 @@ void MacroActionWebsocketEdit::MessageTypeChanged(int index)
void MacroActionWebsocketEdit::MessageChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_message = _message->toPlainText().toUtf8().constData();
adjustSize();
@@ -367,11 +355,7 @@ void MacroActionWebsocketEdit::MessageChanged()
void MacroActionWebsocketEdit::ConnectionSelectionChanged(
const QString &connection)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_connection = GetWeakConnectionByQString(connection);
CheckForSettingsConflict();
emit(HeaderInfoChanged(connection));

View File

@@ -568,12 +568,8 @@ void MacroConditionAudioEdit::UpdateVolmeterSource()
void MacroConditionAudioEdit::SourceChanged(const SourceSelection &source)
{
if (_loading || !_entryData) {
return;
}
{
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_audioSource = source;
_entryData->ResetVolmeter();
}
@@ -586,11 +582,8 @@ void MacroConditionAudioEdit::SourceChanged(const SourceSelection &source)
void MacroConditionAudioEdit::VolumePercentChanged(
const NumberVariable<double> &vol)
{
if (_loading || !_entryData) {
return;
}
{
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_volumePercent = vol;
}
@@ -599,42 +592,27 @@ void MacroConditionAudioEdit::VolumePercentChanged(
void MacroConditionAudioEdit::SyncOffsetChanged(const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_syncOffset = value;
}
void MacroConditionAudioEdit::MonitorTypeChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_monitorType = static_cast<obs_monitoring_type>(value);
}
void MacroConditionAudioEdit::BalanceChanged(const NumberVariable<double> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_balance = value;
}
void MacroConditionAudioEdit::VolumeDBChanged(
const NumberVariable<double> &value)
{
if (_loading || !_entryData) {
return;
}
{
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_volumeDB = value;
}
SyncSliderAndValueSelection(false);
@@ -642,11 +620,7 @@ void MacroConditionAudioEdit::VolumeDBChanged(
void MacroConditionAudioEdit::PercentDBClicked()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_useDb = !_entryData->_useDb;
SetWidgetVisibility();
}
@@ -706,11 +680,7 @@ void MacroConditionAudioEdit::ConditionChanged(int cond)
void MacroConditionAudioEdit::CheckTypeChanged(int idx)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->SetType(static_cast<MacroConditionAudio::Type>(
_checkTypes->itemData(idx).toInt()));

View File

@@ -240,11 +240,7 @@ MacroConditionClipboardEdit::Create(QWidget *parent,
void MacroConditionClipboardEdit::ConditionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->SetCondition(
static_cast<MacroConditionClipboard::Condition>(value));
SetWidgetVisibility();
@@ -252,11 +248,7 @@ void MacroConditionClipboardEdit::ConditionChanged(int value)
void MacroConditionClipboardEdit::TextChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_text = _text->toPlainText().toStdString();
adjustSize();
updateGeometry();
@@ -264,11 +256,7 @@ void MacroConditionClipboardEdit::TextChanged()
void MacroConditionClipboardEdit::RegexChanged(const RegexConfig &conf)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_regex = conf;
adjustSize();
updateGeometry();

View File

@@ -225,11 +225,7 @@ MacroConditionCursorEdit::MacroConditionCursorEdit(
void MacroConditionCursorEdit::ConditionChanged(int index)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_condition = static_cast<MacroConditionCursor::Condition>(
_conditions->itemData(index).toInt());
SetWidgetVisibility();
@@ -237,55 +233,35 @@ void MacroConditionCursorEdit::ConditionChanged(int index)
void MacroConditionCursorEdit::ButtonChanged(int index)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_button = static_cast<MacroConditionCursor::Button>(
_buttons->itemData(index).toInt());
}
void MacroConditionCursorEdit::MinXChanged(const NumberVariable<int> &pos)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_minX = pos;
SetupFrame();
}
void MacroConditionCursorEdit::MinYChanged(const NumberVariable<int> &pos)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_minY = pos;
SetupFrame();
}
void MacroConditionCursorEdit::MaxXChanged(const NumberVariable<int> &pos)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_maxX = pos;
SetupFrame();
}
void MacroConditionCursorEdit::MaxYChanged(const NumberVariable<int> &pos)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_maxY = pos;
SetupFrame();
}

View File

@@ -517,11 +517,7 @@ MacroConditionDateEdit::MacroConditionDateEdit(
void MacroConditionDateEdit::DayOfWeekChanged(int day)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_dayOfWeek = static_cast<MacroConditionDate::Day>(day);
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -529,11 +525,7 @@ void MacroConditionDateEdit::DayOfWeekChanged(int day)
void MacroConditionDateEdit::ConditionChanged(int cond)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_condition =
static_cast<MacroConditionDate::Condition>(cond);
SetWidgetStatus();
@@ -543,11 +535,7 @@ void MacroConditionDateEdit::ConditionChanged(int cond)
void MacroConditionDateEdit::DateChanged(const QDate &date)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->SetDate1(date);
emit HeaderInfoChanged(
@@ -556,11 +544,7 @@ void MacroConditionDateEdit::DateChanged(const QDate &date)
void MacroConditionDateEdit::TimeChanged(const QTime &time)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->SetTime1(time);
emit HeaderInfoChanged(
@@ -569,53 +553,33 @@ void MacroConditionDateEdit::TimeChanged(const QTime &time)
void MacroConditionDateEdit::Date2Changed(const QDate &date)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->SetDate2(date);
}
void MacroConditionDateEdit::Time2Changed(const QTime &time)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->SetTime2(time);
}
void MacroConditionDateEdit::IgnoreDateChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_ignoreDate = !state;
SetWidgetStatus();
}
void MacroConditionDateEdit::IgnoreTimeChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_ignoreTime = !state;
SetWidgetStatus();
}
void MacroConditionDateEdit::RepeatChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_repeat = state;
_duration->setDisabled(!state);
SetWidgetStatus();
@@ -623,31 +587,20 @@ void MacroConditionDateEdit::RepeatChanged(int state)
void MacroConditionDateEdit::UpdateOnRepeatChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_updateOnRepeat = state;
}
void MacroConditionDateEdit::DurationChanged(const Duration &dur)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_duration = dur;
}
void MacroConditionDateEdit::AdvancedSettingsToggleClicked()
{
if (_loading || !_entryData) {
return;
}
{
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_dayOfWeekCheck = !_entryData->_dayOfWeekCheck;
}

View File

@@ -313,11 +313,7 @@ MacroConditionDisplayEdit::MacroConditionDisplayEdit(
void MacroConditionDisplayEdit::ConditionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->SetCondition(
static_cast<MacroConditionDisplay::Condition>(value));
SetWidgetVisibility();
@@ -325,32 +321,20 @@ void MacroConditionDisplayEdit::ConditionChanged(int value)
void MacroConditionDisplayEdit::CompareModeChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_compare =
static_cast<MacroConditionDisplay::CompareMode>(value);
}
void MacroConditionDisplayEdit::DisplayNameChanged(const QString &display)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_displayName = display.toStdString();
}
void MacroConditionDisplayEdit::RegexChanged(const RegexConfig &conf)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_regexConf = conf;
adjustSize();
@@ -360,43 +344,27 @@ void MacroConditionDisplayEdit::RegexChanged(const RegexConfig &conf)
void MacroConditionDisplayEdit::DisplayCountChanged(
const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_displayCount = value;
}
void MacroConditionDisplayEdit::DisplayWidthChanged(
const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_displayWidth = value;
}
void MacroConditionDisplayEdit::DisplayHeightChanged(
const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_displayHeight = value;
}
void MacroConditionDisplayEdit::UseDevicePixelRatioChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_useDevicePixelRatio = state;
}

View File

@@ -357,11 +357,7 @@ void MacroConditionFileEdit::FileTypeChanged(int index)
void MacroConditionFileEdit::ConditionChanged(int index)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->SetCondition(
static_cast<MacroConditionFile::Condition>(index));
SetWidgetVisibility();
@@ -369,11 +365,7 @@ void MacroConditionFileEdit::ConditionChanged(int index)
void MacroConditionFileEdit::PathChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_file = text.toUtf8().constData();
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -381,11 +373,7 @@ void MacroConditionFileEdit::PathChanged(const QString &text)
void MacroConditionFileEdit::MatchTextChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_text = _matchText->toPlainText().toUtf8().constData();
adjustSize();
@@ -394,11 +382,7 @@ void MacroConditionFileEdit::MatchTextChanged()
void MacroConditionFileEdit::RegexChanged(const RegexConfig &conf)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_regex = conf;
adjustSize();
updateGeometry();
@@ -406,21 +390,13 @@ void MacroConditionFileEdit::RegexChanged(const RegexConfig &conf)
void MacroConditionFileEdit::CheckModificationDateChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_useTime = state;
}
void MacroConditionFileEdit::OnlyMatchIfChangedChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_onlyMatchIfChanged = state;
}

View File

@@ -4,6 +4,7 @@
#include "text-helpers.hpp"
#include "source-settings-helpers.hpp"
#include "selection-helpers.hpp"
#include "ui-helpers.hpp"
#include <regex>
@@ -16,7 +17,7 @@ bool MacroConditionFilter::_registered = MacroConditionFactory::Register(
{MacroConditionFilter::Create, MacroConditionFilterEdit::Create,
"AdvSceneSwitcher.condition.filter"});
const static std::map<MacroConditionFilter::Condition, std::string>
static const std::vector<std::pair<MacroConditionFilter::Condition, std::string>>
filterConditionTypes = {
{MacroConditionFilter::Condition::ENABLED,
"AdvSceneSwitcher.condition.filter.type.active"},
@@ -30,6 +31,9 @@ const static std::map<MacroConditionFilter::Condition, std::string>
"AdvSceneSwitcher.condition.filter.type.individualSettingMatches"},
{MacroConditionFilter::Condition::INDIVIDUAL_SETTING_CHANGED,
"AdvSceneSwitcher.condition.filter.type.individualSettingChanged"},
{MacroConditionFilter::Condition::
INDIVIDUAL_SETTING_LIST_ENTRY_MATCH,
"AdvSceneSwitcher.condition.filter.type.individualSettingListSelectionMatches"},
};
bool MacroConditionFilter::CheckConditionHelper(const OBSWeakSource &filter)
@@ -73,6 +77,18 @@ bool MacroConditionFilter::CheckConditionHelper(const OBSWeakSource &filter)
SetTempVarValue("setting", *value);
break;
}
case Condition::INDIVIDUAL_SETTING_LIST_ENTRY_MATCH: {
const auto entryName =
GetSourceSettingListEntryName(filter, _setting);
if (!entryName) {
return false;
}
ret = _regex.Enabled() ? _regex.Matches(*entryName, _settings)
: entryName == std::string(_settings);
SetVariableValue(*entryName);
SetTempVarValue("setting", *entryName);
break;
}
case Condition::INDIVIDUAL_SETTING_CHANGED: {
auto value = GetSourceSettingValue(filter, _setting);
if (!value) {
@@ -168,6 +184,7 @@ void MacroConditionFilter::SetupTempVars()
"AdvSceneSwitcher.tempVar.filter.settings"));
break;
case Condition::INDIVIDUAL_SETTING_MATCH:
case Condition::INDIVIDUAL_SETTING_LIST_ENTRY_MATCH:
case Condition::INDIVIDUAL_SETTING_CHANGED:
AddTempvar("setting",
obs_module_text(
@@ -180,8 +197,9 @@ void MacroConditionFilter::SetupTempVars()
static inline void populateConditionSelection(QComboBox *list)
{
for (const auto &[_, name] : filterConditionTypes) {
list->addItem(obs_module_text(name.c_str()));
for (const auto &[value, name] : filterConditionTypes) {
list->addItem(obs_module_text(name.c_str()),
static_cast<int>(value));
}
}
@@ -232,7 +250,7 @@ MacroConditionFilterEdit::MacroConditionFilterEdit(
QWidget::connect(_refreshSettingSelection, SIGNAL(clicked()), this,
SLOT(RefreshVariableSourceSelectionValue()));
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
const std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{sources}}", _sources},
{"{{filters}}", _filters},
{"{{conditions}}", _conditions},
@@ -271,22 +289,14 @@ MacroConditionFilterEdit::MacroConditionFilterEdit(
void MacroConditionFilterEdit::SourceChanged(const SourceSelection &source)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_source = source;
}
void MacroConditionFilterEdit::FilterChanged(const FilterSelection &filter)
{
if (_loading || !_entryData) {
return;
}
{
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_filter = filter;
}
const auto filters =
@@ -299,13 +309,9 @@ void MacroConditionFilterEdit::FilterChanged(const FilterSelection &filter)
void MacroConditionFilterEdit::ConditionChanged(int index)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->SetCondition(
static_cast<MacroConditionFilter::Condition>(index));
GUARD_LOADING_AND_LOCK();
_entryData->SetCondition(static_cast<MacroConditionFilter::Condition>(
_conditions->itemData(index).toInt()));
SetWidgetVisibility();
}
@@ -327,6 +333,14 @@ void MacroConditionFilterEdit::GetSettingsClicked()
if (_entryData->GetCondition() ==
MacroConditionFilter::Condition::SETTINGS_MATCH) {
value = FormatJsonString(GetSourceSettings(filters.at(0)));
} else if (_entryData->GetCondition() ==
MacroConditionFilter::Condition::
INDIVIDUAL_SETTING_LIST_ENTRY_MATCH) {
value = QString::fromStdString(
GetSourceSettingListEntryName(
filters.empty() ? nullptr : filters.at(0),
_entryData->_setting)
.value_or(""));
} else {
value = QString::fromStdString(
GetSourceSettingValue(filters.at(0),
@@ -342,11 +356,7 @@ void MacroConditionFilterEdit::GetSettingsClicked()
void MacroConditionFilterEdit::SettingsChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_settings = _settings->toPlainText().toStdString();
adjustSize();
@@ -355,11 +365,7 @@ void MacroConditionFilterEdit::SettingsChanged()
void MacroConditionFilterEdit::RegexChanged(const RegexConfig &conf)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_regex = conf;
adjustSize();
@@ -369,12 +375,9 @@ void MacroConditionFilterEdit::RegexChanged(const RegexConfig &conf)
void MacroConditionFilterEdit::SettingSelectionChanged(
const SourceSetting &setting)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_setting = setting;
SetWidgetVisibility();
}
void MacroConditionFilterEdit::RefreshVariableSourceSelectionValue()
@@ -384,29 +387,59 @@ void MacroConditionFilterEdit::RefreshVariableSourceSelectionValue()
_settingSelection->SetSource(filters.empty() ? nullptr : filters.at(0));
}
static QString GetIndividualListEntryName()
{
static const auto matchesInput =
[](const std::pair<MacroConditionFilter::Condition, std::string>
&p) {
return p.first ==
MacroConditionFilter::Condition::
INDIVIDUAL_SETTING_LIST_ENTRY_MATCH;
};
static const QString listValueText(obs_module_text(
std::find_if(filterConditionTypes.begin(),
filterConditionTypes.end(), matchesInput)
->second.c_str()));
return listValueText;
}
void MacroConditionFilterEdit::SetWidgetVisibility()
{
const bool showSettingsControls =
_entryData->GetCondition() ==
MacroConditionFilter::Condition::SETTINGS_MATCH ||
_entryData->GetCondition() ==
MacroConditionFilter::Condition::INDIVIDUAL_SETTING_MATCH;
MacroConditionFilter::Condition::INDIVIDUAL_SETTING_MATCH ||
_entryData->GetCondition() ==
MacroConditionFilter::Condition::
INDIVIDUAL_SETTING_LIST_ENTRY_MATCH;
_settings->setVisible(showSettingsControls);
_getSettings->setVisible(showSettingsControls);
_regex->setVisible(showSettingsControls);
_settingSelection->setVisible(
_entryData->GetCondition() ==
MacroConditionFilter::Condition::INDIVIDUAL_SETTING_MATCH ||
_entryData->GetCondition() ==
MacroConditionFilter::Condition::
INDIVIDUAL_SETTING_LIST_ENTRY_MATCH ||
_entryData->GetCondition() ==
MacroConditionFilter::Condition::
INDIVIDUAL_SETTING_CHANGED);
_refreshSettingSelection->setVisible(
_entryData->GetCondition() ==
MacroConditionFilter::Condition::INDIVIDUAL_SETTING_MATCH &&
(_entryData->GetCondition() ==
MacroConditionFilter::Condition::
INDIVIDUAL_SETTING_MATCH ||
_entryData->GetCondition() ==
MacroConditionFilter::Condition::
INDIVIDUAL_SETTING_LIST_ENTRY_MATCH) &&
(_entryData->_source.GetType() ==
SourceSelection::Type::VARIABLE ||
_entryData->_filter.GetType() ==
FilterSelection::Type::VARIABLE));
SetRowVisibleByValue(_conditions, GetIndividualListEntryName(),
_entryData->_setting.IsList());
adjustSize();
updateGeometry();
}
@@ -419,8 +452,8 @@ void MacroConditionFilterEdit::UpdateEntryData()
_sources->SetSource(_entryData->_source);
_filters->SetFilter(_entryData->_source, _entryData->_filter);
_conditions->setCurrentIndex(
static_cast<int>(_entryData->GetCondition()));
_conditions->setCurrentIndex(_conditions->findData(
static_cast<int>(_entryData->GetCondition())));
_settings->setPlainText(_entryData->_settings);
_regex->SetRegexConfig(_entryData->_regex);
const auto filters =

View File

@@ -32,6 +32,7 @@ public:
SETTINGS_CHANGED,
INDIVIDUAL_SETTING_MATCH,
INDIVIDUAL_SETTING_CHANGED,
INDIVIDUAL_SETTING_LIST_ENTRY_MATCH,
};
void SetCondition(Condition);
Condition GetCondition() const { return _condition; }

View File

@@ -343,22 +343,14 @@ void MacroConditionFolderEdit::UpdateEntryData()
void MacroConditionFolderEdit::ConditionChanged(int index)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_condition = static_cast<MacroConditionFolder::Condition>(
_conditions->itemData(index).toInt());
}
void MacroConditionFolderEdit::PathChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->SetFolder(text.toStdString());
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -366,32 +358,20 @@ void MacroConditionFolderEdit::PathChanged(const QString &text)
void MacroConditionFolderEdit::RegexChanged(const RegexConfig &regex)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_regex = regex;
_entryData->_regex.SetEnabled(true);
}
void MacroConditionFolderEdit::FilterChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_filter = _filter->text().toStdString();
}
void MacroConditionFolderEdit::EnableFilterChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_enableFilter = value;
SetWidgetVisibility();
}

View File

@@ -107,11 +107,7 @@ MacroConditionHotkeyEdit::MacroConditionHotkeyEdit(
void MacroConditionHotkeyEdit::NameChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
const auto name = _name->text().toStdString();
// In case a hotkey is used by multiple conditions create a new hotkey
// with the new description or get an existing hotkey matching this
@@ -139,11 +135,7 @@ void MacroConditionHotkeyEdit::UpdateEntryData()
void MacroConditionHotkeyEdit::KeyStateChanged(int index)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_checkPressed = index == 0;
}

View File

@@ -56,11 +56,7 @@ MacroConditionIdleEdit::MacroConditionIdleEdit(
void MacroConditionIdleEdit::DurationChanged(const Duration &dur)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_duration = dur;
}

View File

@@ -761,11 +761,7 @@ void MacroConditionMediaEdit::TimeRestrictionChanged(int index)
void MacroConditionMediaEdit::TimeChanged(const Duration &dur)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_time = dur;
if (_entryData->GetSourceType() !=
MacroConditionMedia::SourceType::SOURCE) {

View File

@@ -152,11 +152,7 @@ MacroConditionPluginStateEdit::MacroConditionPluginStateEdit(
void MacroConditionPluginStateEdit::ConditionChanged(int idx)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->SetCondition(
static_cast<MacroConditionPluginState::Condition>(
_condition->itemData(idx).toInt()));

View File

@@ -122,11 +122,7 @@ MacroConditionRecordEdit::MacroConditionRecordEdit(
void MacroConditionRecordEdit::ConditionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->SetCondition(
static_cast<MacroConditionRecord::Condition>(value));
SetWidgetVisibility();
@@ -146,11 +142,7 @@ void MacroConditionRecordEdit::UpdateEntryData()
void MacroConditionRecordEdit::DurationChanged(const Duration &duration)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_duration = duration;
}

View File

@@ -114,11 +114,7 @@ MacroConditionReplayBufferEdit::MacroConditionReplayBufferEdit(
void MacroConditionReplayBufferEdit::StateChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_state =
static_cast<MacroConditionReplayBuffer::Condition>(value);
}

View File

@@ -193,41 +193,25 @@ void MacroConditionRunEdit::UpdateEntryData()
void MacroConditionRunEdit::TimeoutChanged(const Duration &dur)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_timeout = dur;
}
void MacroConditionRunEdit::CheckExitCodeChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_checkExitCode = state;
}
void MacroConditionRunEdit::ExitCodeChanged(int exitCode)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_exitCodeToCheck = exitCode;
}
void MacroConditionRunEdit::ProcessConfigChanged(const ProcessConfig &conf)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_procConfig = conf;
adjustSize();
updateGeometry();

View File

@@ -258,21 +258,13 @@ MacroConditionSceneOrderEdit::MacroConditionSceneOrderEdit(
void MacroConditionSceneOrderEdit::SceneChanged(const SceneSelection &s)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_scene = s;
}
void MacroConditionSceneOrderEdit::SourceChanged(const SceneItemSelection &item)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_source = item;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -282,11 +274,7 @@ void MacroConditionSceneOrderEdit::SourceChanged(const SceneItemSelection &item)
void MacroConditionSceneOrderEdit::Source2Changed(const SceneItemSelection &item)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_source2 = item;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -296,11 +284,8 @@ void MacroConditionSceneOrderEdit::Source2Changed(const SceneItemSelection &item
void MacroConditionSceneOrderEdit::ConditionChanged(int index)
{
if (_loading || !_entryData) {
return;
}
{
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_condition =
static_cast<MacroConditionSceneOrder::Condition>(index);
}
@@ -322,11 +307,7 @@ void MacroConditionSceneOrderEdit::ConditionChanged(int index)
void MacroConditionSceneOrderEdit::PositionChanged(
const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_position = value;
}

View File

@@ -170,11 +170,7 @@ MacroConditionSceneVisibilityEdit::MacroConditionSceneVisibilityEdit(
void MacroConditionSceneVisibilityEdit::SourceChanged(
const SceneItemSelection &item)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_source = item;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -184,11 +180,7 @@ void MacroConditionSceneVisibilityEdit::SourceChanged(
void MacroConditionSceneVisibilityEdit::SceneChanged(const SceneSelection &s)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_scene = s;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
@@ -196,11 +188,7 @@ void MacroConditionSceneVisibilityEdit::SceneChanged(const SceneSelection &s)
void MacroConditionSceneVisibilityEdit::ConditionChanged(int index)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_condition =
static_cast<MacroConditionSceneVisibility::Condition>(index);
if (_entryData->_condition ==

View File

@@ -4,6 +4,7 @@
#include "text-helpers.hpp"
#include "selection-helpers.hpp"
#include "source-settings-helpers.hpp"
#include "ui-helpers.hpp"
namespace advss {
@@ -14,7 +15,7 @@ bool MacroConditionSource::_registered = MacroConditionFactory::Register(
{MacroConditionSource::Create, MacroConditionSourceEdit::Create,
"AdvSceneSwitcher.condition.source"});
static const std::map<MacroConditionSource::Condition, std::string>
static const std::vector<std::pair<MacroConditionSource::Condition, std::string>>
sourceConditionTypes = {
{MacroConditionSource::Condition::ACTIVE,
"AdvSceneSwitcher.condition.source.type.active"},
@@ -26,6 +27,9 @@ static const std::map<MacroConditionSource::Condition, std::string>
"AdvSceneSwitcher.condition.source.type.settingsChanged"},
{MacroConditionSource::Condition::INDIVIDUAL_SETTING_MATCH,
"AdvSceneSwitcher.condition.source.type.individualSettingMatches"},
{MacroConditionSource::Condition::
INDIVIDUAL_SETTING_LIST_ENTRY_MATCH,
"AdvSceneSwitcher.condition.source.type.individualSettingListSelectionMatches"},
{MacroConditionSource::Condition::INDIVIDUAL_SETTING_CHANGED,
"AdvSceneSwitcher.condition.source.type.individualSettingChanged"},
{MacroConditionSource::Condition::HEIGHT,
@@ -105,6 +109,18 @@ bool MacroConditionSource::CheckCondition()
SetTempVarValue("setting", *value);
break;
}
case Condition::INDIVIDUAL_SETTING_LIST_ENTRY_MATCH: {
const auto entryName = GetSourceSettingListEntryName(
_source.GetSource(), _setting);
if (!entryName) {
return false;
}
ret = _regex.Enabled() ? _regex.Matches(*entryName, _settings)
: entryName == std::string(_settings);
SetVariableValue(*entryName);
SetTempVarValue("setting", *entryName);
break;
}
case Condition::INDIVIDUAL_SETTING_CHANGED: {
const auto value =
GetSourceSettingValue(_source.GetSource(), _setting);
@@ -200,6 +216,7 @@ void MacroConditionSource::SetupTempVars()
"AdvSceneSwitcher.tempVar.source.settings"));
break;
case Condition::INDIVIDUAL_SETTING_MATCH:
case Condition::INDIVIDUAL_SETTING_LIST_ENTRY_MATCH:
case Condition::INDIVIDUAL_SETTING_CHANGED:
AddTempvar("setting",
obs_module_text(
@@ -221,11 +238,11 @@ void MacroConditionSource::SetupTempVars()
}
template<class T>
static inline void populateSelection(QComboBox *list,
const std::map<T, std::string> &map)
static inline void populateSelection(QComboBox *list, const T &map)
{
for (const auto &[_, name] : map) {
list->addItem(obs_module_text(name.c_str()));
for (const auto &[value, name] : map) {
list->addItem(obs_module_text(name.c_str()),
static_cast<int>(value));
}
}
@@ -320,12 +337,8 @@ MacroConditionSourceEdit::MacroConditionSourceEdit(
void MacroConditionSourceEdit::SourceChanged(const SourceSelection &source)
{
if (_loading || !_entryData) {
return;
}
{
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_source = source;
}
_settingSelection->SetSource(_entryData->_source.GetSource());
@@ -336,13 +349,9 @@ void MacroConditionSourceEdit::SourceChanged(const SourceSelection &source)
void MacroConditionSourceEdit::ConditionChanged(int index)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->SetCondition(
static_cast<MacroConditionSource::Condition>(index));
GUARD_LOADING_AND_LOCK();
_entryData->SetCondition(static_cast<MacroConditionSource::Condition>(
_conditions->itemData(index).toInt()));
SetWidgetVisibility();
}
@@ -357,6 +366,14 @@ void MacroConditionSourceEdit::GetSettingsClicked()
MacroConditionSource::Condition::ALL_SETTINGS_MATCH) {
value = FormatJsonString(
GetSourceSettings(_entryData->_source.GetSource()));
} else if (_entryData->GetCondition() ==
MacroConditionSource::Condition::
INDIVIDUAL_SETTING_LIST_ENTRY_MATCH) {
value = QString::fromStdString(
GetSourceSettingListEntryName(
_entryData->_source.GetSource(),
_entryData->_setting)
.value_or(""));
} else {
value = QString::fromStdString(
GetSourceSettingValue(_entryData->_source.GetSource(),
@@ -372,11 +389,7 @@ void MacroConditionSourceEdit::GetSettingsClicked()
void MacroConditionSourceEdit::SettingsChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_settings = _settings->toPlainText().toStdString();
adjustSize();
@@ -385,11 +398,7 @@ void MacroConditionSourceEdit::SettingsChanged()
void MacroConditionSourceEdit::RegexChanged(const RegexConfig &conf)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_regex = conf;
adjustSize();
@@ -399,12 +408,9 @@ void MacroConditionSourceEdit::RegexChanged(const RegexConfig &conf)
void MacroConditionSourceEdit::SettingSelectionChanged(
const SourceSetting &setting)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_setting = setting;
SetWidgetVisibility();
}
void MacroConditionSourceEdit::RefreshVariableSourceSelectionValue()
@@ -414,38 +420,52 @@ void MacroConditionSourceEdit::RefreshVariableSourceSelectionValue()
void MacroConditionSourceEdit::SizeChanged(const NumberVariable<int> &value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_size = value;
}
void MacroConditionSourceEdit::CompareMethodChanged(int index)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_comparision =
static_cast<MacroConditionSource::SizeComparision>(index);
}
static QString GetIndividualListEntryName()
{
static const auto matchesInput =
[](const std::pair<MacroConditionSource::Condition, std::string>
&p) {
return p.first ==
MacroConditionSource::Condition::
INDIVIDUAL_SETTING_LIST_ENTRY_MATCH;
};
static const QString listValueText(obs_module_text(
std::find_if(sourceConditionTypes.begin(),
sourceConditionTypes.end(), matchesInput)
->second.c_str()));
return listValueText;
}
void MacroConditionSourceEdit::SetWidgetVisibility()
{
const bool settingsMatch =
_entryData->GetCondition() ==
MacroConditionSource::Condition::ALL_SETTINGS_MATCH ||
_entryData->GetCondition() ==
MacroConditionSource::Condition::INDIVIDUAL_SETTING_MATCH;
MacroConditionSource::Condition::INDIVIDUAL_SETTING_MATCH ||
_entryData->GetCondition() ==
MacroConditionSource::Condition::
INDIVIDUAL_SETTING_LIST_ENTRY_MATCH;
_settings->setVisible(settingsMatch);
_getSettings->setVisible(settingsMatch);
_regex->setVisible(settingsMatch);
_settingSelection->setVisible(
_entryData->GetCondition() ==
MacroConditionSource::Condition::INDIVIDUAL_SETTING_MATCH ||
_entryData->GetCondition() ==
MacroConditionSource::Condition::
INDIVIDUAL_SETTING_LIST_ENTRY_MATCH ||
_entryData->GetCondition() ==
MacroConditionSource::Condition::
INDIVIDUAL_SETTING_CHANGED);
@@ -460,8 +480,12 @@ void MacroConditionSourceEdit::SetWidgetVisibility()
: "");
_refreshSettingSelection->setVisible(
_entryData->GetCondition() ==
MacroConditionSource::Condition::INDIVIDUAL_SETTING_MATCH &&
(_entryData->GetCondition() ==
MacroConditionSource::Condition::
INDIVIDUAL_SETTING_MATCH ||
_entryData->GetCondition() ==
MacroConditionSource::Condition::
INDIVIDUAL_SETTING_LIST_ENTRY_MATCH) &&
_entryData->_source.GetType() ==
SourceSelection::Type::VARIABLE);
@@ -473,6 +497,9 @@ void MacroConditionSourceEdit::SetWidgetVisibility()
_size->setVisible(isSizeCheck);
_sizeCompareMethods->setVisible(isSizeCheck);
SetRowVisibleByValue(_conditions, GetIndividualListEntryName(),
_entryData->_setting.IsList());
adjustSize();
updateGeometry();
}
@@ -484,8 +511,8 @@ void MacroConditionSourceEdit::UpdateEntryData()
}
_sources->SetSource(_entryData->_source);
_conditions->setCurrentIndex(
static_cast<int>(_entryData->GetCondition()));
_conditions->setCurrentIndex(_conditions->findData(
static_cast<int>(_entryData->GetCondition())));
_settings->setPlainText(_entryData->_settings);
_regex->SetRegexConfig(_entryData->_regex);
_settingSelection->SetSelection(_entryData->_source.GetSource(),

View File

@@ -33,6 +33,7 @@ public:
INDIVIDUAL_SETTING_CHANGED,
HEIGHT,
WIDTH,
INDIVIDUAL_SETTING_LIST_ENTRY_MATCH,
};
void SetCondition(Condition);
Condition GetCondition() const { return _condition; }

View File

@@ -116,11 +116,7 @@ MacroConditionStudioModeEdit::MacroConditionStudioModeEdit(
void MacroConditionStudioModeEdit::ConditionChanged(int cond)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_condition = static_cast<StudioModeCondition>(cond);
SetWidgetVisibility();
emit HeaderInfoChanged(
@@ -129,11 +125,7 @@ void MacroConditionStudioModeEdit::ConditionChanged(int cond)
void MacroConditionStudioModeEdit::SceneChanged(const SceneSelection &s)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_scene = s;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));

View File

@@ -228,62 +228,38 @@ MacroConditionTimerEdit::MacroConditionTimerEdit(
void MacroConditionTimerEdit::TimerTypeChanged(int type)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_type = static_cast<MacroConditionTimer::TimerType>(type);
SetWidgetVisibility();
}
void MacroConditionTimerEdit::DurationChanged(const Duration &dur)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_duration = dur;
}
void MacroConditionTimerEdit::Duration2Changed(const Duration &dur)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_duration2 = dur;
}
void MacroConditionTimerEdit::SaveRemainingChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_saveRemaining = state;
}
void MacroConditionTimerEdit::AutoResetChanged(int state)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_oneshot = !state;
}
void MacroConditionTimerEdit::PauseContinueClicked()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
if (_entryData->_paused) {
timer.start(1000);
_entryData->Continue();
@@ -296,11 +272,7 @@ void MacroConditionTimerEdit::PauseContinueClicked()
void MacroConditionTimerEdit::ResetClicked()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->Reset();
}

View File

@@ -332,12 +332,8 @@ MacroConditionTransitionEdit::MacroConditionTransitionEdit(
void MacroConditionTransitionEdit::ConditionChanged(int index)
{
if (_loading || !_entryData) {
return;
}
{
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_condition =
static_cast<MacroConditionTransition::Condition>(
_conditions->itemData(index).toInt());
@@ -350,11 +346,7 @@ void MacroConditionTransitionEdit::ConditionChanged(int index)
void MacroConditionTransitionEdit::TransitionChanged(
const TransitionSelection &t)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_transition = t;
_entryData->ConnectToTransitionSignals();
emit HeaderInfoChanged(
@@ -363,21 +355,13 @@ void MacroConditionTransitionEdit::TransitionChanged(
void MacroConditionTransitionEdit::SceneChanged(const SceneSelection &s)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_scene = s;
}
void MacroConditionTransitionEdit::DurationChanged(const Duration &dur)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_duration = dur;
}

View File

@@ -87,11 +87,7 @@ MacroConditionVCamEdit::MacroConditionVCamEdit(
void MacroConditionVCamEdit::StateChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_state = static_cast<VCamState>(value);
}

View File

@@ -9,12 +9,16 @@
Q_DECLARE_METATYPE(advss::SourceSetting);
using properties_delete_t = decltype(&obs_properties_destroy);
using properties_t = std::unique_ptr<obs_properties_t, properties_delete_t>;
namespace advss {
SourceSetting::SourceSetting(const std::string &id,
SourceSetting::SourceSetting(const std::string &id, obs_property_type type,
const std::string &description,
const std::string &longDescription)
: _id(id),
_type(type),
_description(description),
_longDescription(longDescription)
{
@@ -24,6 +28,7 @@ bool SourceSetting::Save(obs_data_t *obj) const
{
OBSDataAutoRelease data = obs_data_create();
obs_data_set_string(data, "id", _id.c_str());
obs_data_set_int(data, "type", _type);
obs_data_set_string(data, "description", _description.c_str());
obs_data_set_obj(obj, "sourceSetting", data);
return true;
@@ -33,10 +38,21 @@ bool SourceSetting::Load(obs_data_t *obj)
{
OBSDataAutoRelease data = obs_data_get_obj(obj, "sourceSetting");
_id = obs_data_get_string(data, "id");
_type = static_cast<obs_property_type>(obs_data_get_int(data, "type"));
_description = obs_data_get_string(data, "description");
return true;
}
static bool isListType(obs_property_type type)
{
return type == OBS_PROPERTY_LIST || type == OBS_PROPERTY_EDITABLE_LIST;
}
bool SourceSetting::IsList() const
{
return isListType(_type);
}
bool SourceSetting::operator==(const SourceSetting &other) const
{
return _id == other._id;
@@ -85,7 +101,7 @@ static void addSettingsHelper(obs_property_t *property,
if (!property) {
continue;
}
auto type = obs_property_get_type(property);
const auto type = obs_property_get_type(property);
if (type == OBS_PROPERTY_GROUP) {
auto group = obs_property_group_content(property);
auto description = obs_property_description(property);
@@ -110,7 +126,8 @@ static void addSettingsHelper(obs_property_t *property,
prefix + description +
obs_module_text(getPropertySuffix(type));
auto longDescription = obs_property_long_description(property);
SourceSetting setting(name, descriptionWithPrefixAndSuffix,
SourceSetting setting(name, type,
descriptionWithPrefixAndSuffix,
longDescription ? longDescription : "");
settings.emplace_back(setting);
} while (obs_property_next(&property));
@@ -118,19 +135,20 @@ static void addSettingsHelper(obs_property_t *property,
std::vector<SourceSetting> GetSoruceSettings(obs_source_t *source)
{
auto properties = obs_source_properties(source);
properties_t properties(obs_source_properties(source),
obs_properties_destroy);
if (!properties) {
return {};
}
std::vector<SourceSetting> settings;
auto it = obs_properties_first(properties);
auto it = obs_properties_first(properties.get());
addSettingsHelper(it, settings);
obs_properties_destroy(properties);
return settings;
}
std::optional<std::string> GetSourceSettingValue(const OBSWeakSource &ws,
const SourceSetting &setting)
static std::optional<std::string>
getDataJsonWithDefaults(const OBSWeakSource &ws)
{
OBSSourceAutoRelease source = obs_weak_source_get_source(ws);
OBSDataAutoRelease data = obs_source_get_settings(source);
@@ -143,10 +161,139 @@ std::optional<std::string> GetSourceSettingValue(const OBSWeakSource &ws,
if (!json) {
return {};
}
auto value = GetJsonField(json, setting.GetID());
return json;
}
std::optional<std::string> GetSourceSettingValue(const OBSWeakSource &source,
const SourceSetting &setting)
{
const auto json = getDataJsonWithDefaults(source);
if (!json) {
return {};
}
auto value = GetJsonField(*json, setting.GetID());
return value;
}
static obs_property_t *findListPropertyByIdHelper(obs_property_t *property,
const std::string &id)
{
do {
if (!property) {
continue;
}
const auto type = obs_property_get_type(property);
if (type == OBS_PROPERTY_GROUP) {
auto group = obs_property_group_content(property);
findListPropertyByIdHelper(obs_properties_first(group),
id);
continue;
}
if (!isListType(type)) {
continue;
}
auto name = obs_property_name(property);
if (name != id) {
continue;
}
return property;
} while (obs_property_next(&property));
return nullptr;
}
static std::pair<obs_property_t *, properties_t>
findListPropertyById(const obs_source_t *source, const std::string &id)
{
// Note:
// Using obs_source_properties() here might cause flickering for some
// sources, as this will call obs_properties_apply_settings()
// implicitly.
// So, we use obs_get_source_properties() instead.
//
// 20250617: This might cause issues with the move plugin as it doesn't
// handle obs_get_source_properties() properly in the move filter
auto properties = obs_get_source_properties(obs_source_get_id(source));
if (!properties) {
return {nullptr, properties_t(nullptr, obs_properties_destroy)};
}
auto property = obs_properties_first(properties);
return {findListPropertyByIdHelper(property, id),
properties_t(nullptr, obs_properties_destroy)};
}
static std::pair<obs_property_t *, properties_t>
findListPropertyById(const OBSWeakSource &ws, const std::string &id)
{
OBSSourceAutoRelease source = obs_weak_source_get_source(ws);
return findListPropertyById(source.Get(), id);
}
std::optional<std::string>
GetSourceSettingListEntryName(const OBSWeakSource &source,
const SourceSetting &setting)
{
if (!setting.IsList()) {
return {};
}
const auto json = getDataJsonWithDefaults(source);
if (!json) {
return {};
}
const auto &[property, properties] =
findListPropertyById(source, setting.GetID());
if (!property) {
return {};
}
const auto type = obs_property_list_format(property);
if (type == OBS_COMBO_FORMAT_INVALID) {
return {};
}
auto currentValue = GetJsonField(*json, setting.GetID());
if (!currentValue) {
return {};
}
const auto count = obs_property_list_item_count(property);
for (size_t i = 0; i < count; i++) {
std::string value;
switch (type) {
case OBS_COMBO_FORMAT_INT:
value = std::to_string(
obs_property_list_item_int(property, i));
break;
case OBS_COMBO_FORMAT_FLOAT:
value = std::to_string(
obs_property_list_item_float(property, i));
break;
case OBS_COMBO_FORMAT_STRING:
value = obs_property_list_item_string(property, i);
break;
case OBS_COMBO_FORMAT_BOOL:
value = std::to_string(
obs_property_list_item_bool(property, i));
break;
default:
break;
}
if (value == currentValue) {
return obs_property_list_item_name(property, i);
}
}
return {};
}
void SetSourceSetting(obs_source_t *source, const SourceSetting &setting,
const std::string &value)
{
@@ -233,6 +380,63 @@ void SetSourceSetting(obs_source_t *source, const SourceSetting &setting,
obs_source_update(source, data);
}
void SetSourceSettingListEntryValueByName(obs_source_t *source,
const SourceSetting &setting,
const std::string &name)
{
if (!setting.IsList()) {
return;
}
const auto &[property, properties] =
findListPropertyById(source, setting.GetID());
if (!property) {
return;
}
const auto type = obs_property_list_format(property);
if (type == OBS_COMBO_FORMAT_INVALID) {
return;
}
const auto count = obs_property_list_item_count(property);
bool found = false;
size_t idx = 0;
for (; idx < count; idx++) {
if (obs_property_list_item_name(property, idx) == name) {
found = true;
break;
}
}
if (!found) {
return;
}
std::string value;
switch (type) {
case OBS_COMBO_FORMAT_INT:
value = std::to_string(
obs_property_list_item_int(property, idx));
break;
case OBS_COMBO_FORMAT_FLOAT:
value = std::to_string(
obs_property_list_item_float(property, idx));
break;
case OBS_COMBO_FORMAT_STRING:
value = obs_property_list_item_string(property, idx);
break;
case OBS_COMBO_FORMAT_BOOL:
value = std::to_string(
obs_property_list_item_bool(property, idx));
break;
default:
break;
}
SetSourceSetting(source, setting, value);
}
SourceSettingSelection::SourceSettingSelection(QWidget *parent)
: QWidget(parent),
_settings(new FilterComboBox(

View File

@@ -14,15 +14,18 @@ namespace advss {
class SourceSetting {
public:
SourceSetting() = default;
SourceSetting(const std::string &id, const std::string &description,
SourceSetting(const std::string &id, obs_property_type type,
const std::string &description,
const std::string &longDescription = "");
bool Save(obs_data_t *obj) const;
bool Load(obs_data_t *obj);
std::string GetID() const { return _id; }
EXPORT bool operator==(const SourceSetting &other) const;
bool IsList() const;
bool operator==(const SourceSetting &other) const;
private:
std::string _id = "";
obs_property_type _type = OBS_PROPERTY_INVALID;
std::string _description = "";
std::string _longDescription = "";
@@ -32,8 +35,14 @@ private:
std::vector<SourceSetting> GetSoruceSettings(obs_source_t *source);
std::optional<std::string> GetSourceSettingValue(const OBSWeakSource &source,
const SourceSetting &setting);
std::optional<std::string>
GetSourceSettingListEntryName(const OBSWeakSource &source,
const SourceSetting &setting);
void SetSourceSetting(obs_source_t *source, const SourceSetting &setting,
const std::string &value);
void SetSourceSettingListEntryValueByName(obs_source_t *source,
const SourceSetting &setting,
const std::string &name);
class SourceSettingSelection : public QWidget {
Q_OBJECT

View File

@@ -40,6 +40,10 @@ if(OS_MACOS)
target_link_libraries(${PROJECT_NAME} PRIVATE "-framework Security")
endif()
if(MSVC)
target_compile_options(${PROJECT_NAME} PRIVATE /wd4834)
endif()
target_sources(
${PROJECT_NAME} PRIVATE macro-action-http.cpp macro-action-http.hpp
key-value-list.cpp key-value-list.hpp)

View File

@@ -65,20 +65,47 @@ void MacroActionHttp::SetupTempVars()
"AdvSceneSwitcher.tempVar.http.error.description"));
}
struct URLInfo {
std::string host;
std::string path;
};
static URLInfo getURLInfo(const std::string &input)
{
if (input.empty()) {
return {};
}
QString urlInput = QString::fromStdString(input);
if (!urlInput.contains("://")) {
urlInput = "http://" + urlInput;
}
const QUrl url(urlInput);
auto host =
url.scheme().toStdString() + "://" + url.host().toStdString();
int port = url.port();
if (port != -1) {
host += ":" + std::to_string(port);
}
auto path = url.path().toStdString();
if (path.empty()) {
path = "/";
}
return {host, path};
}
bool MacroActionHttp::PerformAction()
{
httplib::Client cli(_url);
const auto [host, path] = getURLInfo(_url);
httplib::Client cli(host);
setTimeout(cli, _timeout);
const auto params = _setParams ? getParams(_params) : httplib::Params();
const auto headers = _setHeaders ? getHeaders(_headers)
: httplib::Headers();
// This copy is necessary for some reason for MacOS but not Linux or
// Windows.
// Without it all requests fail with "Invalid argument" or
// "Failed to write connection" when sending out the data.
std::string path = _path;
httplib::Result response;
switch (_method) {
case MacroActionHttp::Method::GET:
@@ -167,13 +194,12 @@ void MacroActionHttp::LogAction() const
ablog(LOG_INFO,
"sent HTTP request (%s) "
"to URL \"%s\" "
"to path \"%s\" "
"with content type \"%s\" "
"with body \"%s\" "
"with headers \"%s\" "
"with parameters \"%s\" "
"with timeout \"%s\"",
methodToString(_method).data(), _url.c_str(), _path.c_str(),
methodToString(_method).data(), _url.c_str(),
_contentType.c_str(), _body.c_str(),
_setHeaders ? stringListToString(_headers).c_str() : "-",
_setParams ? stringListToString(_params).c_str() : "-",
@@ -184,7 +210,6 @@ bool MacroActionHttp::Save(obs_data_t *obj) const
{
MacroAction::Save(obj);
_url.Save(obj, "url");
_path.Save(obj, "path");
_contentType.Save(obj, "contentType");
_body.Save(obj, "body");
obs_data_set_bool(obj, "setHeaders", _setHeaders);
@@ -200,7 +225,11 @@ bool MacroActionHttp::Load(obs_data_t *obj)
{
MacroAction::Load(obj);
_url.Load(obj, "url");
_path.Load(obj, "path");
if (obs_data_has_user_value(obj, "path")) {
std::string url = _url.UnresolvedValue();
url += obs_data_get_string(obj, "path");
_url = url;
}
_contentType.Load(obj, "contentType");
_body.Load(obj, "body");
_setHeaders = obs_data_get_bool(obj, "setHeaders");
@@ -230,7 +259,6 @@ std::shared_ptr<MacroAction> MacroActionHttp::Copy() const
void MacroActionHttp::ResolveVariablesToFixedValues()
{
_url.ResolveVariables();
_path.ResolveVariables();
_contentType.ResolveVariables();
_body.ResolveVariables();
_headers.ResolveVariables();
@@ -263,7 +291,6 @@ MacroActionHttpEdit::MacroActionHttpEdit(
QWidget *parent, std::shared_ptr<MacroActionHttp> entryData)
: QWidget(parent),
_url(new VariableLineEdit(this)),
_path(new VariableLineEdit(this)),
_contentType(new VariableLineEdit(this)),
_contentTypeLayout(new QHBoxLayout()),
_methods(new QComboBox()),
@@ -306,7 +333,6 @@ void MacroActionHttpEdit::UpdateEntryData()
}
_url->setText(_entryData->_url);
_path->setText(_entryData->_path);
_contentType->setText(_entryData->_contentType);
_body->setPlainText(_entryData->_body);
_setHeaders->setChecked(_entryData->_setHeaders);
@@ -326,12 +352,6 @@ void MacroActionHttpEdit::URLChanged()
emit(HeaderInfoChanged(_url->text()));
}
void MacroActionHttpEdit::PathChanged()
{
GUARD_LOADING_AND_LOCK();
_entryData->_path = _path->text().toStdString();
}
void MacroActionHttpEdit::ContentTypeChanged()
{
GUARD_LOADING_AND_LOCK();
@@ -395,8 +415,6 @@ void MacroActionHttpEdit::SetWidgetSignalConnections()
{
QWidget::connect(_url, SIGNAL(editingFinished()), this,
SLOT(URLChanged()));
QWidget::connect(_path, SIGNAL(editingFinished()), this,
SLOT(PathChanged()));
QWidget::connect(_contentType, SIGNAL(editingFinished()), this,
SLOT(ContentTypeChanged()));
QWidget::connect(_body, SIGNAL(textChanged()), this,
@@ -420,18 +438,15 @@ void MacroActionHttpEdit::SetWidgetSignalConnections()
void MacroActionHttpEdit::SetWidgetLayout()
{
const std::unordered_map<std::string, QWidget *> widgets = {
{"{{url}}", _url},
{"{{path}}", _path},
{"{{contentType}}", _contentType},
{"{{method}}", _methods},
{"{{body}}", _body},
{"{{url}}", _url}, {"{{contentType}}", _contentType},
{"{{method}}", _methods}, {"{{body}}", _body},
{"{{timeout}}", _timeout},
};
auto actionLayout = new QHBoxLayout;
PlaceWidgets(
obs_module_text("AdvSceneSwitcher.action.http.layout.method"),
actionLayout, widgets);
actionLayout, widgets, false);
PlaceWidgets(obs_module_text(
"AdvSceneSwitcher.action.http.layout.contentType"),

View File

@@ -33,7 +33,6 @@ public:
};
StringVariable _url = "127.0.0.1:8080";
StringVariable _path = "/";
StringVariable _body = obs_module_text("AdvSceneSwitcher.enterText");
StringVariable _contentType = "application/json";
bool _setHeaders = false;
@@ -68,7 +67,6 @@ public:
private slots:
void URLChanged();
void PathChanged();
void BodyChanged();
void ContentTypeChanged();
void MethodChanged(int);
@@ -86,7 +84,6 @@ private:
void SetWidgetVisibility();
VariableLineEdit *_url;
VariableLineEdit *_path;
VariableLineEdit *_contentType;
QHBoxLayout *_contentTypeLayout;
QComboBox *_methods;

View File

@@ -136,12 +136,8 @@ void MacroActionMidiEdit::UpdateEntryData()
void MacroActionMidiEdit::DeviceSelectionChanged(const MidiDevice &device)
{
if (_loading || !_entryData) {
return;
}
{
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_device = device;
}
emit HeaderInfoChanged(
@@ -158,11 +154,7 @@ void MacroActionMidiEdit::ListenDeviceSelectionChanged(const MidiDevice &dev)
void MacroActionMidiEdit::MidiMessageChanged(const MidiMessage &message)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_message = message;
}

Some files were not shown because too many files have changed in this diff Show More