From c21afa4ddcfde65c09a2d42b3961a8b4a4a7a87a Mon Sep 17 00:00:00 2001 From: duncte123 Date: Thu, 8 Aug 2024 09:24:28 +0200 Subject: [PATCH] Events: Add from and to scene names to transition events These scene names are missing to make these events useful for anything other than monitoring --- CMakeLists.txt | 4 +- cmake/legacy.cmake | 2 +- data/locale/be-BY.ini | 4 +- data/locale/ro-RO.ini | 2 +- data/locale/ru-RU.ini | 2 +- data/locale/sv-SE.ini | 4 +- data/locale/tt-RU.ini | 9 ++ docs/generated/protocol.json | 112 +++++++++++++----- docs/generated/protocol.md | 63 +++++++--- src/Config.cpp | 25 ++-- src/eventhandler/EventHandler.cpp | 30 ++--- src/eventhandler/EventHandler.h | 4 + src/eventhandler/EventHandler_Outputs.cpp | 22 ++++ src/eventhandler/EventHandler_Transitions.cpp | 50 +++++++- src/requesthandler/RequestHandler.cpp | 2 + src/requesthandler/RequestHandler.h | 2 + src/requesthandler/RequestHandler_General.cpp | 1 + src/requesthandler/RequestHandler_Outputs.cpp | 7 +- src/requesthandler/RequestHandler_Record.cpp | 57 +++++++++ .../RequestHandler_SceneItems.cpp | 7 ++ src/requesthandler/RequestHandler_Sources.cpp | 4 +- src/utils/Obs.h | 32 ++--- src/utils/Obs_ObjectHelper.cpp | 2 + 23 files changed, 339 insertions(+), 108 deletions(-) create mode 100644 data/locale/tt-RU.ini diff --git a/CMakeLists.txt b/CMakeLists.txt index 1affd0911..9fd515e02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16...3.25) legacy_check() -set(obs-websocket_VERSION 5.4.2) +set(obs-websocket_VERSION 5.5.2) set(OBS_WEBSOCKET_RPC_VERSION 1) include(cmake/obs-websocket-api.cmake) @@ -138,12 +138,14 @@ target_compile_definitions( target_compile_options( obs-websocket PRIVATE $<$:/wd4267> + $<$:/wd4996> $<$:-Wall> $<$:-Wno-error=float-conversion> $<$:-Wno-error=shadow> $<$:-Wno-error=format-overflow> $<$:-Wno-error=int-conversion> $<$:-Wno-error=comment> + $<$:-Wno-error=deprecated-declarations> $<$:-Wno-error=null-pointer-subtraction> $<$:-Wno-error=deprecated-declarations> $<$:-Wno-error=implicit-int-conversion> diff --git a/cmake/legacy.cmake b/cmake/legacy.cmake index 2cd327ebb..ef87160f2 100644 --- a/cmake/legacy.cmake +++ b/cmake/legacy.cmake @@ -1,4 +1,4 @@ -project(obs-websocket VERSION 5.4.2) +project(obs-websocket VERSION 5.5.2) set(OBS_WEBSOCKET_RPC_VERSION 1) option(ENABLE_WEBSOCKET "Enable building OBS with websocket plugin" ON) diff --git a/data/locale/be-BY.ini b/data/locale/be-BY.ini index ff34586af..01c4b8117 100644 --- a/data/locale/be-BY.ini +++ b/data/locale/be-BY.ini @@ -13,10 +13,10 @@ OBSWebSocket.Settings.ServerPort="Порт сервера" OBSWebSocket.Settings.ShowConnectInfo="Паказаць звесткі пра злучэнне" OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Увага: ідзе трансляцыя" OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Выглядае, што ў бягучы момант ідзе вывад (стрым, запіс і г. д.)." -OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Вы ўпэўненыя, што хочаце паказаць вашы звесткі пра злучэнне?" +OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Ці вы ўпэўненыя, што хочаце паказаць вашы звесткі пра злучэнне?" OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Увага: магчымая небяспека" OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket захоўвае пароль сервера ў выглядзе звычайнага тэксту. Настойліва рэкамендуецца выкарыстоўваць пароль, які згенеруе obs-websocket." -OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Вы ўпэўненыя, што хочаце карыстацца сваім паролем?" +OBSWebSocket.Settings.Save.UserPasswordWarningInfoText="Ці вы ўпэўненыя, што хочаце карыстацца сваім паролем?" OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle="Увага: памылковая канфігурацыя" OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage="Пароль павінен утрымліваць 6 або больш сімвалаў." OBSWebSocket.SessionTable.Title="Злучаныя сеансы WebSocket" diff --git a/data/locale/ro-RO.ini b/data/locale/ro-RO.ini index c5a7a69f4..73ec3f69e 100644 --- a/data/locale/ro-RO.ini +++ b/data/locale/ro-RO.ini @@ -12,7 +12,7 @@ OBSWebSocket.Settings.GeneratePassword="Generează parola" OBSWebSocket.Settings.ServerPort="Portul serverului" OBSWebSocket.Settings.ShowConnectInfo="Afișează informațiile conexiunii" OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Avertisment: În prezent în direct" -OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Se pare că un output (transmisiune, înregistrare etc.) este activ în prezent." +OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Se pare că un output (stream, înregistrare etc.) este activ în prezent." OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Sigur vrei să afișezi informațiile de conectare?" OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Avertisment: Potențială problemă de securitate" OBSWebSocket.Settings.Save.UserPasswordWarningMessage="obs-websocket stochează parola serverului ca text simplu. Este foarte recomandat să folosiți o parolă generată de obs-websocket." diff --git a/data/locale/ru-RU.ini b/data/locale/ru-RU.ini index 3978a38e5..0c01a73ef 100644 --- a/data/locale/ru-RU.ini +++ b/data/locale/ru-RU.ini @@ -28,7 +28,7 @@ OBSWebSocket.SessionTable.KickButtonColumnTitle="Выгнать?" OBSWebSocket.SessionTable.KickButtonText="Выгнать" OBSWebSocket.ConnectInfo.DialogTitle="Сведения о подключении WebSocket" OBSWebSocket.ConnectInfo.CopyText="Копировать" -OBSWebSocket.ConnectInfo.ServerIp="IP сервера (лучшая догадка)" +OBSWebSocket.ConnectInfo.ServerIp="IP сервера (вероятный)" OBSWebSocket.ConnectInfo.ServerPort="Порт сервера" OBSWebSocket.ConnectInfo.ServerPassword="Пароль сервера" OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText="[Вход отключён]" diff --git a/data/locale/sv-SE.ini b/data/locale/sv-SE.ini index 48ad3beae..a45140543 100644 --- a/data/locale/sv-SE.ini +++ b/data/locale/sv-SE.ini @@ -1,6 +1,6 @@ OBSWebSocket.Plugin.Description="Fjärrkontroll av OBS Studio via WebSocket" OBSWebSocket.Settings.DialogTitle="WebSocket-serverinställningar" -OBSWebSocket.Settings.PluginSettingsTitle="Insticksmodulsinställningar" +OBSWebSocket.Settings.PluginSettingsTitle="Insticksprogramsinställningar" OBSWebSocket.Settings.ServerEnable="Aktivera WebSocket-server" OBSWebSocket.Settings.AlertsEnable="Aktivera systemfältsmeddelanden" OBSWebSocket.Settings.DebugEnable="Aktivera felsökningsloggning" @@ -11,7 +11,7 @@ OBSWebSocket.Settings.Password="Serverlösenord" OBSWebSocket.Settings.GeneratePassword="Generera lösenord" OBSWebSocket.Settings.ServerPort="Serverport" OBSWebSocket.Settings.ShowConnectInfo="Visa anslutningsinformation" -OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Varning: Sänder för närvarande" +OBSWebSocket.Settings.ShowConnectInfoWarningTitle="Varning: Direktsändning pågår" OBSWebSocket.Settings.ShowConnectInfoWarningMessage="Det verkar som om en utmatning (ström, inspelning, etc.) är för närvarande aktiv." OBSWebSocket.Settings.ShowConnectInfoWarningInfoText="Är du säker på att du vill visa din anslutningsinformation?" OBSWebSocket.Settings.Save.UserPasswordWarningTitle="Varning: Potentiellt säkerhetsproblem" diff --git a/data/locale/tt-RU.ini b/data/locale/tt-RU.ini new file mode 100644 index 000000000..e7ad03c2b --- /dev/null +++ b/data/locale/tt-RU.ini @@ -0,0 +1,9 @@ +OBSWebSocket.Settings.ServerSettingsTitle="Сервер көйләүләре" +OBSWebSocket.Settings.Password="Сервер серсүзе" +OBSWebSocket.Settings.GeneratePassword="Серсүзне ясау" +OBSWebSocket.Settings.ServerPort="Сервер порты" +OBSWebSocket.SessionTable.KickButtonColumnTitle="Чыгарыргамы?" +OBSWebSocket.SessionTable.KickButtonText="Чыгару" +OBSWebSocket.ConnectInfo.CopyText="Күчермә алу" +OBSWebSocket.ConnectInfo.ServerPort="Сервер порты" +OBSWebSocket.ConnectInfo.ServerPassword="Сервер серсүзе" diff --git a/docs/generated/protocol.json b/docs/generated/protocol.json index aacbe235a..674562020 100644 --- a/docs/generated/protocol.json +++ b/docs/generated/protocol.json @@ -461,72 +461,72 @@ { "description": "Unknown state.", "enumIdentifier": "OBS_WEBSOCKET_OUTPUT_UNKNOWN", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.0.0", "enumValue": "OBS_WEBSOCKET_OUTPUT_UNKNOWN" }, { "description": "The output is starting.", "enumIdentifier": "OBS_WEBSOCKET_OUTPUT_STARTING", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.0.0", "enumValue": "OBS_WEBSOCKET_OUTPUT_STARTING" }, { "description": "The input has started.", "enumIdentifier": "OBS_WEBSOCKET_OUTPUT_STARTED", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.0.0", "enumValue": "OBS_WEBSOCKET_OUTPUT_STARTED" }, { "description": "The output is stopping.", "enumIdentifier": "OBS_WEBSOCKET_OUTPUT_STOPPING", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.0.0", "enumValue": "OBS_WEBSOCKET_OUTPUT_STOPPING" }, { "description": "The output has stopped.", "enumIdentifier": "OBS_WEBSOCKET_OUTPUT_STOPPED", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.0.0", "enumValue": "OBS_WEBSOCKET_OUTPUT_STOPPED" }, { "description": "The output has disconnected and is reconnecting.", "enumIdentifier": "OBS_WEBSOCKET_OUTPUT_RECONNECTING", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.0.0", "enumValue": "OBS_WEBSOCKET_OUTPUT_RECONNECTING" }, { "description": "The output has reconnected successfully.", "enumIdentifier": "OBS_WEBSOCKET_OUTPUT_RECONNECTED", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.1.0", "enumValue": "OBS_WEBSOCKET_OUTPUT_RECONNECTED" }, { "description": "The output is now paused.", "enumIdentifier": "OBS_WEBSOCKET_OUTPUT_PAUSED", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.1.0", "enumValue": "OBS_WEBSOCKET_OUTPUT_PAUSED" }, { "description": "The output has been resumed (unpaused).", "enumIdentifier": "OBS_WEBSOCKET_OUTPUT_RESUMED", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.0.0", "enumValue": "OBS_WEBSOCKET_OUTPUT_RESUMED" } @@ -538,56 +538,56 @@ { "description": "No action.", "enumIdentifier": "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NONE", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.0.0", "enumValue": "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NONE" }, { "description": "Play the media input.", "enumIdentifier": "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.0.0", "enumValue": "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY" }, { "description": "Pause the media input.", "enumIdentifier": "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.0.0", "enumValue": "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE" }, { "description": "Stop the media input.", "enumIdentifier": "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.0.0", "enumValue": "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP" }, { "description": "Restart the media input.", "enumIdentifier": "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.0.0", "enumValue": "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART" }, { "description": "Go to the next playlist item.", "enumIdentifier": "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.0.0", "enumValue": "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT" }, { "description": "Go to the previous playlist item.", "enumIdentifier": "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS", - "rpcVersion": 1, - "deprecated": true, + "rpcVersion": "1", + "deprecated": false, "initialVersion": "5.0.0", "enumValue": "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS" } @@ -3472,6 +3472,37 @@ "requestFields": [], "responseFields": [] }, + { + "description": "Splits the current file being recorded into a new file.", + "requestType": "SplitRecordFile", + "complexity": 2, + "rpcVersion": "1", + "deprecated": false, + "initialVersion": "5.5.0", + "category": "record", + "requestFields": [], + "responseFields": [] + }, + { + "description": "Adds a new chapter marker to the file currently being recorded.\n\nNote: As of OBS 30.2.0, the only file format supporting this feature is Hybrid MP4.", + "requestType": "CreateRecordChapter", + "complexity": 2, + "rpcVersion": "1", + "deprecated": false, + "initialVersion": "5.5.0", + "category": "record", + "requestFields": [ + { + "valueName": "chapterName", + "valueType": "String", + "valueDescription": "Name of the new chapter", + "valueRestrictions": null, + "valueOptional": true, + "valueOptionalBehavior": "Unknown" + } + ], + "responseFields": [] + }, { "description": "Gets a list of all scene items in a scene.\n\nScenes only", "requestType": "GetSceneItemList", @@ -6046,6 +6077,23 @@ } ] }, + { + "description": "The record output has started writing to a new file. For example, when a file split happens.", + "eventType": "RecordFileChanged", + "eventSubscription": "Outputs", + "complexity": 2, + "rpcVersion": "1", + "deprecated": false, + "initialVersion": "5.5.0", + "category": "outputs", + "dataFields": [ + { + "valueName": "newOutputPath", + "valueType": "String", + "valueDescription": "File name that the output has begun writing to" + } + ] + }, { "description": "The state of the replay buffer output has changed.", "eventType": "ReplayBufferStateChanged", diff --git a/docs/generated/protocol.md b/docs/generated/protocol.md index 06f8a929f..52b18f1ae 100644 --- a/docs/generated/protocol.md +++ b/docs/generated/protocol.md @@ -1336,7 +1336,6 @@ No action. - Identifier Value: `OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NONE` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.0.0 --- @@ -1347,7 +1346,6 @@ Play the media input. - Identifier Value: `OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.0.0 --- @@ -1358,7 +1356,6 @@ Pause the media input. - Identifier Value: `OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.0.0 --- @@ -1369,7 +1366,6 @@ Stop the media input. - Identifier Value: `OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.0.0 --- @@ -1380,7 +1376,6 @@ Restart the media input. - Identifier Value: `OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.0.0 --- @@ -1391,7 +1386,6 @@ Go to the next playlist item. - Identifier Value: `OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.0.0 --- @@ -1402,7 +1396,6 @@ Go to the previous playlist item. - Identifier Value: `OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.0.0 ## ObsOutputState @@ -1413,7 +1406,6 @@ Unknown state. - Identifier Value: `OBS_WEBSOCKET_OUTPUT_UNKNOWN` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.0.0 --- @@ -1424,7 +1416,6 @@ The output is starting. - Identifier Value: `OBS_WEBSOCKET_OUTPUT_STARTING` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.0.0 --- @@ -1435,7 +1426,6 @@ The input has started. - Identifier Value: `OBS_WEBSOCKET_OUTPUT_STARTED` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.0.0 --- @@ -1446,7 +1436,6 @@ The output is stopping. - Identifier Value: `OBS_WEBSOCKET_OUTPUT_STOPPING` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.0.0 --- @@ -1457,7 +1446,6 @@ The output has stopped. - Identifier Value: `OBS_WEBSOCKET_OUTPUT_STOPPED` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.0.0 --- @@ -1468,7 +1456,6 @@ The output has disconnected and is reconnecting. - Identifier Value: `OBS_WEBSOCKET_OUTPUT_RECONNECTING` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.0.0 --- @@ -1479,7 +1466,6 @@ The output has reconnected successfully. - Identifier Value: `OBS_WEBSOCKET_OUTPUT_RECONNECTED` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.1.0 --- @@ -1490,7 +1476,6 @@ The output is now paused. - Identifier Value: `OBS_WEBSOCKET_OUTPUT_PAUSED` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.1.0 --- @@ -1501,7 +1486,6 @@ The output has been resumed (unpaused). - Identifier Value: `OBS_WEBSOCKET_OUTPUT_RESUMED` - Latest Supported RPC Version: `1` -- **⚠️ Deprecated. ⚠️** - Added in v5.0.0 # Events @@ -1564,6 +1548,7 @@ The output has been resumed (unpaused). - [Outputs Events](#outputs-events) - [StreamStateChanged](#streamstatechanged) - [RecordStateChanged](#recordstatechanged) + - [RecordFileChanged](#recordfilechanged) - [ReplayBufferStateChanged](#replaybufferstatechanged) - [VirtualcamStateChanged](#virtualcamstatechanged) - [ReplayBufferSaved](#replaybuffersaved) @@ -2449,6 +2434,22 @@ The state of the record output has changed. --- +### RecordFileChanged + +The record output has started writing to a new file. For example, when a file split happens. + +- Complexity Rating: `2/5` +- Latest Supported RPC Version: `1` +- Added in v5.5.0 + +**Data Fields:** + +| Name | Type | Description | +| ---- | :---: | ----------- | +| newOutputPath | String | File name that the output has begun writing to | + +--- + ### ReplayBufferStateChanged The state of the replay buffer output has changed. @@ -2728,6 +2729,8 @@ communication is desired. - [ToggleRecordPause](#togglerecordpause) - [PauseRecord](#pauserecord) - [ResumeRecord](#resumerecord) + - [SplitRecordFile](#splitrecordfile) + - [CreateRecordChapter](#createrecordchapter) - [Media Inputs Requests](#media-inputs-1-requests) - [GetMediaInputStatus](#getmediainputstatus) - [SetMediaInputCursor](#setmediainputcursor) @@ -5281,6 +5284,34 @@ Resumes the record output. - Latest Supported RPC Version: `1` - Added in v5.0.0 +--- + +### SplitRecordFile + +Splits the current file being recorded into a new file. + +- Complexity Rating: `2/5` +- Latest Supported RPC Version: `1` +- Added in v5.5.0 + +--- + +### CreateRecordChapter + +Adds a new chapter marker to the file currently being recorded. + +Note: As of OBS 30.2.0, the only file format supporting this feature is Hybrid MP4. + +- Complexity Rating: `2/5` +- Latest Supported RPC Version: `1` +- Added in v5.5.0 + +**Request Fields:** + +| Name | Type | Description | Value Restrictions | ?Default Behavior | +| ---- | :---: | ----------- | :----------------: | ----------------- | +| ?chapterName | String | Name of the new chapter | None | Unknown | + ## Media Inputs Requests ### GetMediaInputStatus diff --git a/src/Config.cpp b/src/Config.cpp index 7af55b434..aaeb32c38 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -49,14 +49,16 @@ with this program. If not, see void Config::Load(json config) { + // Only load from plugin config directory if there hasn't been a migration if (config.is_null()) { std::string configFilePath = Utils::Obs::StringHelper::GetModuleConfigPath(CONFIG_FILE_NAME); Utils::Json::GetJsonFileContent(configFilePath, config); // Fetch the existing config, which may not exist } - // Should never happen, but just in case - if (!config.is_object()) - return; + if (!config.is_object()) { + blog(LOG_INFO, "[Config::Load] Existing configuration not found, using defaults."); + config = json::object(); + } if (config.contains(PARAM_FIRSTLOAD) && config[PARAM_FIRSTLOAD].is_boolean()) FirstLoad = config[PARAM_FIRSTLOAD]; @@ -85,6 +87,10 @@ void Config::Load(json config) Save(); } + // If there are migrated settings, write them to disk before processing arguments. + if (!config.empty()) + Save(); + // Process `--websocket_port` override QString portArgument = Utils::Platform::GetCommandLineArgument(CMDLINE_WEBSOCKET_PORT); if (portArgument != "") { @@ -139,7 +145,9 @@ void Config::Save() config[PARAM_PASSWORD] = ServerPassword; } - if (!Utils::Json::SetJsonFileContent(configFilePath, config)) + if (Utils::Json::SetJsonFileContent(configFilePath, config)) + blog(LOG_DEBUG, "[Config::Save] Saved config."); + else blog(LOG_ERROR, "[Config::Save] Failed to write config file!"); } @@ -191,7 +199,7 @@ bool MigratePersistentData() std::error_code ec; // Ensure module config directory exists - std::string moduleConfigDirectory = Utils::Obs::StringHelper::GetModuleConfigPath(""); + auto moduleConfigDirectory = std::filesystem::u8path(Utils::Obs::StringHelper::GetModuleConfigPath("")); if (!std::filesystem::exists(moduleConfigDirectory, ec)) std::filesystem::create_directories(moduleConfigDirectory, ec); if (ec) { @@ -201,10 +209,11 @@ bool MigratePersistentData() } // Move any existing persistent data to module config directory, then delete old file - std::string oldPersistentDataPath = - Utils::Obs::StringHelper::GetCurrentProfilePath() + "/../../../obsWebSocketPersistentData.json"; + auto oldPersistentDataPath = std::filesystem::u8path(Utils::Obs::StringHelper::GetCurrentProfilePath() + + "/../../../obsWebSocketPersistentData.json"); if (std::filesystem::exists(oldPersistentDataPath, ec)) { - std::string persistentDataPath = Utils::Obs::StringHelper::GetModuleConfigPath("persistent_data.json"); + auto persistentDataPath = + std::filesystem::u8path(Utils::Obs::StringHelper::GetModuleConfigPath("persistent_data.json")); std::filesystem::copy_file(oldPersistentDataPath, persistentDataPath, ec); std::filesystem::remove(oldPersistentDataPath, ec); blog(LOG_INFO, "[MigratePersistentData] Persistent data migrated to new path"); diff --git a/src/eventhandler/EventHandler.cpp b/src/eventhandler/EventHandler.cpp index cf862b629..05e46ab6f 100644 --- a/src/eventhandler/EventHandler.cpp +++ b/src/eventhandler/EventHandler.cpp @@ -27,11 +27,11 @@ EventHandler::EventHandler() signal_handler_t *coreSignalHandler = obs_get_signal_handler(); if (coreSignalHandler) { - signal_handler_connect(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this); - signal_handler_connect(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this); - signal_handler_connect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this); - signal_handler_connect(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this); - signal_handler_connect(coreSignalHandler, "source_update", SourceUpdatedMultiHandler, this); + coreSignals.emplace_back(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this); + coreSignals.emplace_back(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this); + coreSignals.emplace_back(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this); + coreSignals.emplace_back(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this); + coreSignals.emplace_back(coreSignalHandler, "source_update", SourceUpdatedMultiHandler, this); } else { blog(LOG_ERROR, "[EventHandler::EventHandler] Unable to get libobs signal handler!"); } @@ -45,16 +45,7 @@ EventHandler::~EventHandler() obs_frontend_remove_event_callback(OnFrontendEvent, this); - signal_handler_t *coreSignalHandler = obs_get_signal_handler(); - if (coreSignalHandler) { - signal_handler_disconnect(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this); - signal_handler_disconnect(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this); - signal_handler_disconnect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this); - signal_handler_disconnect(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this); - signal_handler_disconnect(coreSignalHandler, "source_update", SourceUpdatedMultiHandler, this); - } else { - blog(LOG_ERROR, "[EventHandler::~EventHandler] Unable to get libobs signal handler!"); - } + coreSignals.clear(); // Revoke callbacks of all inputs and scenes, in case some still have our callbacks attached auto enumInputs = [](void *param, obs_source_t *source) { @@ -378,12 +369,21 @@ void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_ break; case OBS_FRONTEND_EVENT_RECORDING_STARTED: eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STARTED); + { + OBSOutputAutoRelease recordOutput = obs_frontend_get_recording_output(); + if (recordOutput) { + signal_handler_t *sh = obs_output_get_signal_handler(recordOutput); + eventHandler->recordFileChangedSignal.Connect(sh, "file_changed", HandleRecordFileChanged, + private_data); + } + } break; case OBS_FRONTEND_EVENT_RECORDING_STOPPING: eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPING); break; case OBS_FRONTEND_EVENT_RECORDING_STOPPED: eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED); + eventHandler->recordFileChangedSignal.Disconnect(); break; case OBS_FRONTEND_EVENT_RECORDING_PAUSED: eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_PAUSED); diff --git a/src/eventhandler/EventHandler.h b/src/eventhandler/EventHandler.h index e9094428d..b52d38799 100644 --- a/src/eventhandler/EventHandler.h +++ b/src/eventhandler/EventHandler.h @@ -51,6 +51,9 @@ class EventHandler { std::atomic _obsReady = false; + std::vector coreSignals; + OBSSignal recordFileChangedSignal; + std::unique_ptr _inputVolumeMetersHandler; std::atomic _inputVolumeMetersRef = 0; std::atomic _inputActiveStateChangedRef = 0; @@ -155,6 +158,7 @@ class EventHandler { // Outputs void HandleStreamStateChanged(ObsOutputState state); void HandleRecordStateChanged(ObsOutputState state); + static void HandleRecordFileChanged(void *param, calldata_t *data); // Direct callback void HandleReplayBufferStateChanged(ObsOutputState state); void HandleVirtualcamStateChanged(ObsOutputState state); void HandleReplayBufferSaved(); diff --git a/src/eventhandler/EventHandler_Outputs.cpp b/src/eventhandler/EventHandler_Outputs.cpp index 186ebaf2b..918469133 100644 --- a/src/eventhandler/EventHandler_Outputs.cpp +++ b/src/eventhandler/EventHandler_Outputs.cpp @@ -87,6 +87,28 @@ void EventHandler::HandleRecordStateChanged(ObsOutputState state) BroadcastEvent(EventSubscription::Outputs, "RecordStateChanged", eventData); } +/** + * The record output has started writing to a new file. For example, when a file split happens. + * + * @dataField newOutputPath | String | File name that the output has begun writing to + * + * @eventType RecordFileChanged + * @eventSubscription Outputs + * @complexity 2 + * @rpcVersion -1 + * @initialVersion 5.5.0 + * @api events + * @category outputs + */ +void EventHandler::HandleRecordFileChanged(void *param, calldata_t *data) +{ + auto eventHandler = static_cast(param); + + json eventData; + eventData["newOutputPath"] = calldata_string(data, "next_file"); + eventHandler->BroadcastEvent(EventSubscription::Outputs, "RecordFileChanged", eventData); +} + /** * The state of the replay buffer output has changed. * diff --git a/src/eventhandler/EventHandler_Transitions.cpp b/src/eventhandler/EventHandler_Transitions.cpp index eefb38873..5b6730c89 100644 --- a/src/eventhandler/EventHandler_Transitions.cpp +++ b/src/eventhandler/EventHandler_Transitions.cpp @@ -63,11 +63,32 @@ void EventHandler::HandleCurrentSceneTransitionDurationChanged() BroadcastEvent(EventSubscription::Transitions, "CurrentSceneTransitionDurationChanged", eventData); } +void SetFromAndToScene(json &eventData, obs_source_t *transition) +{ + OBSSourceAutoRelease sourceScene = obs_transition_get_source(transition, OBS_TRANSITION_SOURCE_A); + OBSSourceAutoRelease destinationScene = obs_transition_get_source(transition, OBS_TRANSITION_SOURCE_B); + + eventData["fromScene"] = obs_source_get_name(sourceScene); + eventData["toScene"] = obs_source_get_name(destinationScene); +} + +// FIXME: OBS bug causes source B to be null for transition end but not video transition end. +// Needs to be fixed in obs itself +void SetToScene(json &eventData, obs_source_t *transition) +{ + OBSSourceAutoRelease sourceScene = obs_transition_get_source(transition, OBS_TRANSITION_SOURCE_A); + + eventData["toScene"] = obs_source_get_name(sourceScene); +} + /** * A scene transition has started. * - * @dataField transitionName | String | Scene transition name - * @dataField transitionUuid | String | Scene transition UUID + * @dataField transitionName | String | Scene transition name + * @dataField transitionUuid | String | Scene transition UUID + * @dataField transitionDuration | Number | Transition duration in milliseconds + * @dataField toScene | String | Scene that we transitioned to + * @dataField fromScene | String | Scene that we transitioned away from * * @eventType SceneTransitionStarted * @eventSubscription Transitions @@ -88,6 +109,10 @@ void EventHandler::HandleSceneTransitionStarted(void *param, calldata_t *data) json eventData; eventData["transitionName"] = obs_source_get_name(source); eventData["transitionUuid"] = obs_source_get_uuid(source); + eventData["transitionDuration"] = obs_frontend_get_transition_duration(); + + SetFromAndToScene(eventData, source); + eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionStarted", eventData); } @@ -96,8 +121,10 @@ void EventHandler::HandleSceneTransitionStarted(void *param, calldata_t *data) * * Note: Does not appear to trigger when the transition is interrupted by the user. * - * @dataField transitionName | String | Scene transition name - * @dataField transitionUuid | String | Scene transition UUID + * @dataField transitionName | String | Scene transition name + * @dataField transitionUuid | String | Scene transition UUID + * @dataField transitionDuration | Number | Transition duration in milliseconds + * @dataField toScene | String | Scene that we transitioned to * * @eventType SceneTransitionEnded * @eventSubscription Transitions @@ -118,6 +145,10 @@ void EventHandler::HandleSceneTransitionEnded(void *param, calldata_t *data) json eventData; eventData["transitionName"] = obs_source_get_name(source); eventData["transitionUuid"] = obs_source_get_uuid(source); + eventData["transitionDuration"] = obs_frontend_get_transition_duration(); + + SetToScene(eventData, source); + eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionEnded", eventData); } @@ -129,8 +160,11 @@ void EventHandler::HandleSceneTransitionEnded(void *param, calldata_t *data) * * Note: Appears to be called by every transition, regardless of relevance. * - * @dataField transitionName | String | Scene transition name - * @dataField transitionUuid | String | Scene transition UUID + * @dataField transitionName | String | Scene transition name + * @dataField transitionUuid | String | Scene transition UUID + * @dataField transitionDuration | Number | Transition duration in milliseconds + * @dataField toScene | String | Scene that we transitioned to + * @dataField fromScene | String | Scene that we transitioned away from * * @eventType SceneTransitionVideoEnded * @eventSubscription Transitions @@ -151,5 +185,9 @@ void EventHandler::HandleSceneTransitionVideoEnded(void *param, calldata_t *data json eventData; eventData["transitionName"] = obs_source_get_name(source); eventData["transitionUuid"] = obs_source_get_uuid(source); + eventData["transitionDuration"] = obs_frontend_get_transition_duration(); + + SetFromAndToScene(eventData, source); + eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionVideoEnded", eventData); } diff --git a/src/requesthandler/RequestHandler.cpp b/src/requesthandler/RequestHandler.cpp index a5be2d780..d8ef94efb 100644 --- a/src/requesthandler/RequestHandler.cpp +++ b/src/requesthandler/RequestHandler.cpp @@ -177,6 +177,8 @@ const std::unordered_map RequestHandler::_han {"ToggleRecordPause", &RequestHandler::ToggleRecordPause}, {"PauseRecord", &RequestHandler::PauseRecord}, {"ResumeRecord", &RequestHandler::ResumeRecord}, + {"SplitRecordFile", &RequestHandler::SplitRecordFile}, + {"CreateRecordChapter", &RequestHandler::CreateRecordChapter}, // Media Inputs {"GetMediaInputStatus", &RequestHandler::GetMediaInputStatus}, diff --git a/src/requesthandler/RequestHandler.h b/src/requesthandler/RequestHandler.h index 610fb465f..ea023afde 100644 --- a/src/requesthandler/RequestHandler.h +++ b/src/requesthandler/RequestHandler.h @@ -196,6 +196,8 @@ class RequestHandler { RequestResult ToggleRecordPause(const Request &); RequestResult PauseRecord(const Request &); RequestResult ResumeRecord(const Request &); + RequestResult SplitRecordFile(const Request &); + RequestResult CreateRecordChapter(const Request &); // Media Inputs RequestResult GetMediaInputStatus(const Request &); diff --git a/src/requesthandler/RequestHandler_General.cpp b/src/requesthandler/RequestHandler_General.cpp index a43d2af7e..0bd5436d9 100644 --- a/src/requesthandler/RequestHandler_General.cpp +++ b/src/requesthandler/RequestHandler_General.cpp @@ -266,6 +266,7 @@ RequestResult RequestHandler::TriggerHotkeyByName(const Request &request) return RequestResult::Error(RequestStatus::ResourceNotFound, "No hotkeys were found by that name."); obs_hotkey_trigger_routed_callback(obs_hotkey_get_id(hotkey), true); + obs_hotkey_trigger_routed_callback(obs_hotkey_get_id(hotkey), false); return RequestResult::Success(); } diff --git a/src/requesthandler/RequestHandler_Outputs.cpp b/src/requesthandler/RequestHandler_Outputs.cpp index 45bca638e..d2b0526b2 100644 --- a/src/requesthandler/RequestHandler_Outputs.cpp +++ b/src/requesthandler/RequestHandler_Outputs.cpp @@ -21,11 +21,8 @@ with this program. If not, see static bool VirtualCamAvailable() { - OBSDataAutoRelease privateData = obs_get_private_data(); - if (!privateData) - return false; - - return obs_data_get_bool(privateData, "vcamEnabled"); + OBSOutputAutoRelease output = obs_frontend_get_virtualcam_output(); + return output != nullptr; } static bool ReplayBufferAvailable() diff --git a/src/requesthandler/RequestHandler_Record.cpp b/src/requesthandler/RequestHandler_Record.cpp index e7310588e..e2ad3e2c4 100644 --- a/src/requesthandler/RequestHandler_Record.cpp +++ b/src/requesthandler/RequestHandler_Record.cpp @@ -189,3 +189,60 @@ RequestResult RequestHandler::ResumeRecord(const Request &) return RequestResult::Success(); } + +/** + * Splits the current file being recorded into a new file. + * + * @requestType SplitRecordFile + * @complexity 2 + * @rpcVersion -1 + * @initialVersion 5.5.0 + * @api requests + * @category record + */ +RequestResult RequestHandler::SplitRecordFile(const Request &) +{ + if (!obs_frontend_recording_active()) + return RequestResult::Error(RequestStatus::OutputNotRunning); + + if (!obs_frontend_recording_split_file()) + return RequestResult::Error(RequestStatus::RequestProcessingFailed, + "Verify that file splitting is enabled in the output settings."); + + return RequestResult::Success(); +} + +/** + * Adds a new chapter marker to the file currently being recorded. + * + * Note: As of OBS 30.2.0, the only file format supporting this feature is Hybrid MP4. + * + * @requestField ?chapterName | String | Name of the new chapter + * + * @requestType CreateRecordChapter + * @complexity 2 + * @rpcVersion -1 + * @initialVersion 5.5.0 + * @api requests + * @category record + */ +RequestResult RequestHandler::CreateRecordChapter(const Request &request) +{ + std::string chapterName; + if (request.Contains("chapterName")) { + RequestStatus::RequestStatus statusCode; + std::string comment; + if (!request.ValidateOptionalString("chapterName", statusCode, comment)) + return RequestResult::Error(statusCode, comment); + chapterName = request.RequestData["chapterName"]; + } + + if (!obs_frontend_recording_active()) + return RequestResult::Error(RequestStatus::OutputNotRunning); + + if (!obs_frontend_recording_add_chapter(chapterName.empty() ? nullptr : chapterName.c_str())) + return RequestResult::Error(RequestStatus::RequestProcessingFailed, + "Verify that the output being used supports chapter markers."); + + return RequestResult::Success(); +} diff --git a/src/requesthandler/RequestHandler_SceneItems.cpp b/src/requesthandler/RequestHandler_SceneItems.cpp index 67c5333ac..146fb6546 100644 --- a/src/requesthandler/RequestHandler_SceneItems.cpp +++ b/src/requesthandler/RequestHandler_SceneItems.cpp @@ -502,6 +502,13 @@ RequestResult RequestHandler::SetSceneItemTransform(const Request &request) cropChanged = true; } + if (r.Contains("cropToBounds")) { + if (!r.ValidateOptionalBoolean("cropToBounds", statusCode, comment)) + return RequestResult::Error(statusCode, comment); + sceneItemTransform.crop_to_bounds = r.RequestData["cropToBounds"]; + transformChanged = true; + } + if (!transformChanged && !cropChanged) return RequestResult::Error(RequestStatus::CannotAct, "You have not provided any valid transform changes."); diff --git a/src/requesthandler/RequestHandler_Sources.cpp b/src/requesthandler/RequestHandler_Sources.cpp index 459901ced..bc246a8f1 100644 --- a/src/requesthandler/RequestHandler_Sources.cpp +++ b/src/requesthandler/RequestHandler_Sources.cpp @@ -28,8 +28,8 @@ with this program. If not, see QImage TakeSourceScreenshot(obs_source_t *source, bool &success, uint32_t requestedWidth = 0, uint32_t requestedHeight = 0) { // Get info about the requested source - const uint32_t sourceWidth = obs_source_get_base_width(source); - const uint32_t sourceHeight = obs_source_get_base_height(source); + const uint32_t sourceWidth = obs_source_get_width(source); + const uint32_t sourceHeight = obs_source_get_height(source); const double sourceAspectRatio = ((double)sourceWidth / (double)sourceHeight); uint32_t imgWidth = sourceWidth; diff --git a/src/utils/Obs.h b/src/utils/Obs.h index 3a0e88b84..47fe214c5 100644 --- a/src/utils/Obs.h +++ b/src/utils/Obs.h @@ -42,7 +42,7 @@ enum ObsOutputState { * * @enumIdentifier OBS_WEBSOCKET_OUTPUT_UNKNOWN * @enumType ObsOutputState - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.0.0 * @api enums */ @@ -52,7 +52,7 @@ enum ObsOutputState { * * @enumIdentifier OBS_WEBSOCKET_OUTPUT_STARTING * @enumType ObsOutputState - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.0.0 * @api enums */ @@ -62,7 +62,7 @@ enum ObsOutputState { * * @enumIdentifier OBS_WEBSOCKET_OUTPUT_STARTED * @enumType ObsOutputState - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.0.0 * @api enums */ @@ -72,7 +72,7 @@ enum ObsOutputState { * * @enumIdentifier OBS_WEBSOCKET_OUTPUT_STOPPING * @enumType ObsOutputState - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.0.0 * @api enums */ @@ -82,7 +82,7 @@ enum ObsOutputState { * * @enumIdentifier OBS_WEBSOCKET_OUTPUT_STOPPED * @enumType ObsOutputState - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.0.0 * @api enums */ @@ -92,7 +92,7 @@ enum ObsOutputState { * * @enumIdentifier OBS_WEBSOCKET_OUTPUT_RECONNECTING * @enumType ObsOutputState - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.0.0 * @api enums */ @@ -102,7 +102,7 @@ enum ObsOutputState { * * @enumIdentifier OBS_WEBSOCKET_OUTPUT_RECONNECTED * @enumType ObsOutputState - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.1.0 * @api enums */ @@ -112,7 +112,7 @@ enum ObsOutputState { * * @enumIdentifier OBS_WEBSOCKET_OUTPUT_PAUSED * @enumType ObsOutputState - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.1.0 * @api enums */ @@ -122,7 +122,7 @@ enum ObsOutputState { * * @enumIdentifier OBS_WEBSOCKET_OUTPUT_RESUMED * @enumType ObsOutputState - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.0.0 * @api enums */ @@ -146,7 +146,7 @@ enum ObsMediaInputAction { * * @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NONE * @enumType ObsMediaInputAction - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.0.0 * @api enums */ @@ -156,7 +156,7 @@ enum ObsMediaInputAction { * * @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY * @enumType ObsMediaInputAction - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.0.0 * @api enums */ @@ -166,7 +166,7 @@ enum ObsMediaInputAction { * * @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE * @enumType ObsMediaInputAction - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.0.0 * @api enums */ @@ -176,7 +176,7 @@ enum ObsMediaInputAction { * * @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP * @enumType ObsMediaInputAction - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.0.0 * @api enums */ @@ -186,7 +186,7 @@ enum ObsMediaInputAction { * * @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART * @enumType ObsMediaInputAction - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.0.0 * @api enums */ @@ -196,7 +196,7 @@ enum ObsMediaInputAction { * * @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT * @enumType ObsMediaInputAction - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.0.0 * @api enums */ @@ -206,7 +206,7 @@ enum ObsMediaInputAction { * * @enumIdentifier OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS * @enumType ObsMediaInputAction - * @rpcVersion 1 + * @rpcVersion -1 * @initialVersion 5.0.0 * @api enums */ diff --git a/src/utils/Obs_ObjectHelper.cpp b/src/utils/Obs_ObjectHelper.cpp index e35c28bf5..10f207e55 100644 --- a/src/utils/Obs_ObjectHelper.cpp +++ b/src/utils/Obs_ObjectHelper.cpp @@ -83,5 +83,7 @@ json Utils::Obs::ObjectHelper::GetSceneItemTransform(obs_sceneitem_t *item) ret["cropTop"] = (int)crop.top; ret["cropBottom"] = (int)crop.bottom; + ret["cropToBounds"] = osi.crop_to_bounds; + return ret; }