diff --git a/CMakeLists.txt b/CMakeLists.txt index 54057727..72790cae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,6 +80,7 @@ target_sources( src/requesthandler/RequestBatchHandler.h src/requesthandler/RequestHandler.cpp src/requesthandler/RequestHandler.h + src/requesthandler/RequestHandler_Canvases.cpp src/requesthandler/RequestHandler_Config.cpp src/requesthandler/RequestHandler_Filters.cpp src/requesthandler/RequestHandler_General.cpp diff --git a/src/requesthandler/RequestHandler.cpp b/src/requesthandler/RequestHandler.cpp index c077215e..02a750f1 100644 --- a/src/requesthandler/RequestHandler.cpp +++ b/src/requesthandler/RequestHandler.cpp @@ -53,6 +53,9 @@ const std::unordered_map RequestHandler::_han {"GetRecordDirectory", &RequestHandler::GetRecordDirectory}, {"SetRecordDirectory", &RequestHandler::SetRecordDirectory}, + // Canvases + {"GetCanvasList", &RequestHandler::GetCanvasList}, + // Sources {"GetSourceActive", &RequestHandler::GetSourceActive}, {"GetSourceScreenshot", &RequestHandler::GetSourceScreenshot}, diff --git a/src/requesthandler/RequestHandler.h b/src/requesthandler/RequestHandler.h index 082a6a1b..49898aeb 100644 --- a/src/requesthandler/RequestHandler.h +++ b/src/requesthandler/RequestHandler.h @@ -72,6 +72,9 @@ class RequestHandler { RequestResult GetRecordDirectory(const Request &); RequestResult SetRecordDirectory(const Request &); + // Canvases + RequestResult GetCanvasList(const Request &); + // Sources RequestResult GetSourceActive(const Request &); RequestResult GetSourceScreenshot(const Request &); diff --git a/src/requesthandler/RequestHandler_Canvases.cpp b/src/requesthandler/RequestHandler_Canvases.cpp new file mode 100644 index 00000000..1d289e7b --- /dev/null +++ b/src/requesthandler/RequestHandler_Canvases.cpp @@ -0,0 +1,61 @@ +/* +obs-websocket +Copyright (C) 2016-2021 Stephane Lepin +Copyright (C) 2020-2021 Kyle Manning + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see +*/ + +#include "RequestHandler.h" + +/** + * Gets an array of canvases in OBS. + * + * @responseField canvases | Array | Array of canvases + * + * @requestType GetCanvasList + * @complexity 2 + * @rpcVersion -1 + * @initialVersion 5.0.0 + * @api requests + * @category scenes + */ +RequestResult RequestHandler::GetCanvasList(const Request &request) +{ + json responseData; + std::vector ret; + + obs_enum_canvases( + [](void *param, obs_canvas_t *canvas) { + auto ret = static_cast *>(param); + json canvasJson; + canvasJson["canvasName"] = obs_canvas_get_name(canvas); + canvasJson["canvasUuid"] = obs_canvas_get_uuid(canvas); + struct obs_video_info ovi; + if (obs_canvas_get_video_info(canvas, &ovi)) { + canvasJson["fpsNumerator"] = ovi.fps_num; + canvasJson["fpsDenominator"] = ovi.fps_den; + canvasJson["baseWidth"] = ovi.base_width; + canvasJson["baseHeight"] = ovi.base_height; + canvasJson["outputWidth"] = ovi.output_width; + canvasJson["outputHeight"] = ovi.output_height; + } + ret->push_back(canvasJson); + return true; + }, + &ret); + responseData["canvases"] = ret; + + return RequestResult::Success(responseData); +} diff --git a/src/requesthandler/RequestHandler_Filters.cpp b/src/requesthandler/RequestHandler_Filters.cpp index bbdaac5a..59d7d9aa 100644 --- a/src/requesthandler/RequestHandler_Filters.cpp +++ b/src/requesthandler/RequestHandler_Filters.cpp @@ -43,6 +43,8 @@ RequestResult RequestHandler::GetSourceFilterKindList(const Request &) /** * Gets an array of all of a source's filters. * + * @requestField ?canvasName | String | Name of the canvas the source is in + * @requestField ?canvasUuid | String | UUID of the canvas the source is in * @requestField ?sourceName | String | Name of the source * @requestField ?sourceUuid | String | UUID of the source * @@ -107,6 +109,8 @@ RequestResult RequestHandler::GetSourceFilterDefaultSettings(const Request &requ /** * Creates a new filter, adding it to the specified source. * + * @requestField ?canvasName | String | Name of the canvas the source is in + * @requestField ?canvasUuid | String | UUID of the canvas the source is in * @requestField ?sourceName | String | Name of the source to add the filter to * @requestField ?sourceUuid | String | UUID of the source to add the filter to * @requestField filterName | String | Name of the new filter to be created @@ -161,6 +165,8 @@ RequestResult RequestHandler::CreateSourceFilter(const Request &request) /** * Removes a filter from a source. * + * @requestField ?canvasName | String | Name of the canvas the source is in + * @requestField ?canvasUuid | String | UUID of the canvas the source is in * @requestField ?sourceName | String | Name of the source the filter is on * @requestField ?sourceUuid | String | UUID of the source the filter is on * @requestField filterName | String | Name of the filter to remove @@ -188,6 +194,8 @@ RequestResult RequestHandler::RemoveSourceFilter(const Request &request) /** * Sets the name of a source filter (rename). * + * @requestField ?canvasName | String | Name of the canvas the source is in + * @requestField ?canvasUuid | String | UUID of the canvas the source is in * @requestField ?sourceName | String | Name of the source the filter is on * @requestField ?sourceUuid | String | UUID of the source the filter is on * @requestField filterName | String | Current name of the filter @@ -222,6 +230,8 @@ RequestResult RequestHandler::SetSourceFilterName(const Request &request) /** * Gets the info for a specific source filter. * + * @requestField ?canvasName | String | Name of the canvas the source is in + * @requestField ?canvasUuid | String | UUID of the canvas the source is in * @requestField ?sourceName | String | Name of the source * @requestField ?sourceUuid | String | UUID of the source * @requestField filterName | String | Name of the filter @@ -262,6 +272,8 @@ RequestResult RequestHandler::GetSourceFilter(const Request &request) /** * Sets the index position of a filter on a source. * + * @requestField ?canvasName | String | Name of the canvas the source is in + * @requestField ?canvasUuid | String | UUID of the canvas the source is in * @requestField ?sourceName | String | Name of the source the filter is on * @requestField ?sourceUuid | String | UUID of the source the filter is on * @requestField filterName | String | Name of the filter @@ -292,6 +304,8 @@ RequestResult RequestHandler::SetSourceFilterIndex(const Request &request) /** * Sets the settings of a source filter. * + * @requestField ?canvasName | String | Name of the canvas the source is in + * @requestField ?canvasUuid | String | UUID of the canvas the source is in * @requestField ?sourceName | String | Name of the source the filter is on * @requestField ?sourceUuid | String | UUID of the source the filter is on * @requestField filterName | String | Name of the filter to set the settings of @@ -341,6 +355,8 @@ RequestResult RequestHandler::SetSourceFilterSettings(const Request &request) /** * Sets the enable state of a source filter. * + * @requestField ?canvasName | String | Name of the canvas the source is in + * @requestField ?canvasUuid | String | UUID of the canvas the source is in * @requestField ?sourceName | String | Name of the source the filter is on * @requestField ?sourceUuid | String | UUID of the source the filter is on * @requestField filterName | String | Name of the filter diff --git a/src/requesthandler/RequestHandler_Inputs.cpp b/src/requesthandler/RequestHandler_Inputs.cpp index bdd88177..38fc7f79 100644 --- a/src/requesthandler/RequestHandler_Inputs.cpp +++ b/src/requesthandler/RequestHandler_Inputs.cpp @@ -123,6 +123,8 @@ RequestResult RequestHandler::GetSpecialInputs(const Request &) /** * Creates a new input, adding it as a scene item to the specified scene. * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene to add the input to as a scene item * @requestField ?sceneUuid | String | UUID of the scene to add the input to as a scene item * @requestField inputName | String | Name of the new input to created diff --git a/src/requesthandler/RequestHandler_SceneItems.cpp b/src/requesthandler/RequestHandler_SceneItems.cpp index 146fb654..d39faded 100644 --- a/src/requesthandler/RequestHandler_SceneItems.cpp +++ b/src/requesthandler/RequestHandler_SceneItems.cpp @@ -24,8 +24,10 @@ with this program. If not, see * * Scenes only * - * @requestField ?sceneName | String | Name of the scene to get the items of - * @requestField ?sceneUuid | String | UUID of the scene to get the items of + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in + * @requestField ?sceneName | String | Name of the scene to get the items of + * @requestField ?sceneUuid | String | UUID of the scene to get the items of * * @responseField sceneItems | Array | Array of scene items in the scene * @@ -57,8 +59,10 @@ RequestResult RequestHandler::GetSceneItemList(const Request &request) * * Groups only * - * @requestField ?sceneName | String | Name of the group to get the items of - * @requestField ?sceneUuid | String | UUID of the group to get the items of + * @requestField ?canvasName | String | Name of the canvas the group is in + * @requestField ?canvasUuid | String | UUID of the canvas the group is in + * @requestField ?sceneName | String | Name of the group to get the items of + * @requestField ?sceneUuid | String | UUID of the group to get the items of * * @responseField sceneItems | Array | Array of scene items in the group * @@ -88,6 +92,8 @@ RequestResult RequestHandler::GetGroupSceneItemList(const Request &request) * * Scenes and Groups * + * @requestField ?canvasName | String | Name of the canvas the scene or group is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene or group is in * @requestField ?sceneName | String | Name of the scene or group to search in * @requestField ?sceneUuid | String | UUID of the scene or group to search in * @requestField sourceName | String | Name of the source to find @@ -133,6 +139,8 @@ RequestResult RequestHandler::GetSceneItemId(const Request &request) /** * Gets the source associated with a scene item. * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene the item is in * @requestField ?sceneUuid | String | UUID of the scene the item is in * @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0 @@ -169,6 +177,8 @@ RequestResult RequestHandler::GetSceneItemSource(const Request &request) * * Scenes only * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene to create the new item in * @requestField ?sceneUuid | String | UUID of the scene to create the new item in * @requestField ?sourceName | String | Name of the source to add to the scene @@ -223,6 +233,8 @@ RequestResult RequestHandler::CreateSceneItem(const Request &request) * * Scenes only * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene the item is in * @requestField ?sceneUuid | String | UUID of the scene the item is in * @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0 @@ -253,6 +265,8 @@ RequestResult RequestHandler::RemoveSceneItem(const Request &request) * * Scenes only * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene the item is in * @requestField ?sceneUuid | String | UUID of the scene the item is in * @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0 @@ -330,6 +344,8 @@ RequestResult RequestHandler::DuplicateSceneItem(const Request &request) * * Scenes and Groups * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene the item is in * @requestField ?sceneUuid | String | UUID of the scene the item is in * @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0 @@ -361,6 +377,8 @@ RequestResult RequestHandler::GetSceneItemTransform(const Request &request) /** * Sets the transform and crop info of a scene item. * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene the item is in * @requestField ?sceneUuid | String | UUID of the scene the item is in * @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0 @@ -526,6 +544,8 @@ RequestResult RequestHandler::SetSceneItemTransform(const Request &request) * * Scenes and Groups * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene the item is in * @requestField ?sceneUuid | String | UUID of the scene the item is in * @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0 @@ -559,6 +579,8 @@ RequestResult RequestHandler::GetSceneItemEnabled(const Request &request) * * Scenes and Groups * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene the item is in * @requestField ?sceneUuid | String | UUID of the scene the item is in * @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0 @@ -592,6 +614,8 @@ RequestResult RequestHandler::SetSceneItemEnabled(const Request &request) * * Scenes and Groups * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene the item is in * @requestField ?sceneUuid | String | UUID of the scene the item is in * @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0 @@ -625,6 +649,8 @@ RequestResult RequestHandler::GetSceneItemLocked(const Request &request) * * Scenes and Group * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene the item is in * @requestField ?sceneUuid | String | UUID of the scene the item is in * @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0 @@ -660,6 +686,8 @@ RequestResult RequestHandler::SetSceneItemLocked(const Request &request) * * Scenes and Groups * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene the item is in * @requestField ?sceneUuid | String | UUID of the scene the item is in * @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0 @@ -693,6 +721,8 @@ RequestResult RequestHandler::GetSceneItemIndex(const Request &request) * * Scenes and Groups * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene the item is in * @requestField ?sceneUuid | String | UUID of the scene the item is in * @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0 @@ -736,6 +766,8 @@ RequestResult RequestHandler::SetSceneItemIndex(const Request &request) * * Scenes and Groups * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene the item is in * @requestField ?sceneUuid | String | UUID of the scene the item is in * @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0 @@ -771,6 +803,8 @@ RequestResult RequestHandler::GetSceneItemBlendMode(const Request &request) * * Scenes and Groups * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene the item is in * @requestField ?sceneUuid | String | UUID of the scene the item is in * @requestField sceneItemId | Number | Numeric ID of the scene item | >= 0 diff --git a/src/requesthandler/RequestHandler_Scenes.cpp b/src/requesthandler/RequestHandler_Scenes.cpp index 47ede5dd..942022fb 100644 --- a/src/requesthandler/RequestHandler_Scenes.cpp +++ b/src/requesthandler/RequestHandler_Scenes.cpp @@ -20,8 +20,11 @@ with this program. If not, see #include "RequestHandler.h" /** - * Gets an array of all scenes in OBS. + * Gets an array of scenes in OBS. * + * @requestField ?canvasName | String | Name of the canvas the scenes are in + * @requestField ?canvasUuid | String | UUID of the canvas the scenes are in + * * @responseField currentProgramSceneName | String | Current program scene name. Can be `null` if internal state desync * @responseField currentProgramSceneUuid | String | Current program scene UUID. Can be `null` if internal state desync * @responseField currentPreviewSceneName | String | Current preview scene name. `null` if not in studio mode @@ -35,29 +38,53 @@ with this program. If not, see * @api requests * @category scenes */ -RequestResult RequestHandler::GetSceneList(const Request &) +RequestResult RequestHandler::GetSceneList(const Request &request) { json responseData; - - OBSSourceAutoRelease currentProgramScene = obs_frontend_get_current_scene(); - if (currentProgramScene) { - responseData["currentProgramSceneName"] = obs_source_get_name(currentProgramScene); - responseData["currentProgramSceneUuid"] = obs_source_get_uuid(currentProgramScene); + RequestStatus::RequestStatus statusCode; + std::string comment; + OBSCanvasAutoRelease canvas = request.ValidateCanvas("canvasName", "canvasUuid", statusCode, comment); + if (statusCode == RequestStatus::ResourceNotFound) + return RequestResult::Error(statusCode, comment); + if (canvas) { + OBSSourceAutoRelease programSource = obs_canvas_get_channel(canvas, 0); + if (programSource && obs_source_get_type(programSource) == OBS_SOURCE_TYPE_TRANSITION) { + OBSSourceAutoRelease activeSource = obs_transition_get_active_source(programSource); + if (activeSource) { + responseData["currentProgramSceneName"] = obs_source_get_name(activeSource); + responseData["currentProgramSceneUuid"] = obs_source_get_uuid(activeSource); + } else { + responseData["currentProgramSceneName"] = nullptr; + responseData["currentProgramSceneUuid"] = nullptr; + } + } else if (programSource && obs_source_is_scene(programSource)) { + responseData["currentProgramSceneName"] = obs_source_get_name(programSource); + responseData["currentProgramSceneUuid"] = obs_source_get_uuid(programSource); + } else { + responseData["currentProgramSceneName"] = nullptr; + responseData["currentProgramSceneUuid"] = nullptr; + } } else { - responseData["currentProgramSceneName"] = nullptr; - responseData["currentProgramSceneUuid"] = nullptr; - } + OBSSourceAutoRelease currentProgramScene = obs_frontend_get_current_scene(); + if (currentProgramScene) { + responseData["currentProgramSceneName"] = obs_source_get_name(currentProgramScene); + responseData["currentProgramSceneUuid"] = obs_source_get_uuid(currentProgramScene); + } else { + responseData["currentProgramSceneName"] = nullptr; + responseData["currentProgramSceneUuid"] = nullptr; + } - OBSSourceAutoRelease currentPreviewScene = obs_frontend_get_current_preview_scene(); - if (currentPreviewScene) { - responseData["currentPreviewSceneName"] = obs_source_get_name(currentPreviewScene); - responseData["currentPreviewSceneUuid"] = obs_source_get_uuid(currentPreviewScene); - } else { - responseData["currentPreviewSceneName"] = nullptr; - responseData["currentPreviewSceneUuid"] = nullptr; + OBSSourceAutoRelease currentPreviewScene = obs_frontend_get_current_preview_scene(); + if (currentPreviewScene) { + responseData["currentPreviewSceneName"] = obs_source_get_name(currentPreviewScene); + responseData["currentPreviewSceneUuid"] = obs_source_get_uuid(currentPreviewScene); + } else { + responseData["currentPreviewSceneName"] = nullptr; + responseData["currentPreviewSceneUuid"] = nullptr; + } } - responseData["scenes"] = Utils::Obs::ArrayHelper::GetSceneList(); + responseData["scenes"] = Utils::Obs::ArrayHelper::GetSceneList(canvas); return RequestResult::Success(responseData); } @@ -76,11 +103,16 @@ RequestResult RequestHandler::GetSceneList(const Request &) * @api requests * @category scenes */ -RequestResult RequestHandler::GetGroupList(const Request &) +RequestResult RequestHandler::GetGroupList(const Request &request) { json responseData; + RequestStatus::RequestStatus statusCode; + std::string comment; + OBSCanvasAutoRelease canvas = request.ValidateCanvas("canvasName", "canvasUuid", statusCode, comment); + if (statusCode == RequestStatus::ResourceNotFound) + return RequestResult::Error(statusCode, comment); - responseData["groups"] = Utils::Obs::ArrayHelper::GetGroupList(); + responseData["groups"] = Utils::Obs::ArrayHelper::GetGroupList(canvas); return RequestResult::Success(responseData); } @@ -115,8 +147,10 @@ RequestResult RequestHandler::GetCurrentProgramScene(const Request &) /** * Sets the current program scene. * - * @requestField ?sceneName | String | Scene name to set as the current program scene - * @requestField ?sceneUuid | String | Scene UUID to set as the current program scene + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in + * @requestField ?sceneName | String | Scene name to set as the current program scene + * @requestField ?sceneUuid | String | Scene UUID to set as the current program scene * * @requestType SetCurrentProgramScene * @complexity 1 @@ -176,8 +210,10 @@ RequestResult RequestHandler::GetCurrentPreviewScene(const Request &) * * Only available when studio mode is enabled. * - * @requestField ?sceneName | String | Scene name to set as the current preview scene - * @requestField ?sceneUuid | String | Scene UUID to set as the current preview scene + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in + * @requestField ?sceneName | String | Scene name to set as the current preview scene + * @requestField ?sceneUuid | String | Scene UUID to set as the current preview scene * * @requestType SetCurrentPreviewScene * @complexity 1 @@ -242,6 +278,8 @@ RequestResult RequestHandler::CreateScene(const Request &request) /** * Removes a scene from OBS. * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene to remove * @requestField ?sceneUuid | String | UUID of the scene to remove * @@ -256,11 +294,15 @@ RequestResult RequestHandler::RemoveScene(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; + OBSCanvasAutoRelease canvas = request.ValidateCanvas("canvasName", "canvasUuid", statusCode, comment); + if (statusCode == RequestStatus::ResourceNotFound) + return RequestResult::Error(statusCode, comment); + OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment); if (!scene) return RequestResult::Error(statusCode, comment); - if (Utils::Obs::NumberHelper::GetSceneCount() < 2) + if (Utils::Obs::NumberHelper::GetSceneCount(canvas) < 2) return RequestResult::Error(RequestStatus::NotEnoughResources, "You cannot remove the last scene in the collection."); @@ -272,6 +314,8 @@ RequestResult RequestHandler::RemoveScene(const Request &request) /** * Sets the name of a scene (rename). * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene to be renamed * @requestField ?sceneUuid | String | UUID of the scene to be renamed * @requestField newSceneName | String | New name for the scene @@ -287,13 +331,18 @@ RequestResult RequestHandler::SetSceneName(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; + OBSCanvasAutoRelease canvas = request.ValidateCanvas("canvasName", "canvasUuid", statusCode, comment); + if (statusCode == RequestStatus::ResourceNotFound) + return RequestResult::Error(statusCode, comment); + OBSSourceAutoRelease scene = request.ValidateScene(statusCode, comment); if (!(scene && request.ValidateString("newSceneName", statusCode, comment))) return RequestResult::Error(statusCode, comment); std::string newSceneName = request.RequestData["newSceneName"]; - OBSSourceAutoRelease existingSource = obs_get_source_by_name(newSceneName.c_str()); + OBSSourceAutoRelease existingSource = canvas ? obs_canvas_get_source_by_name(canvas, newSceneName.c_str()) + : obs_get_source_by_name(newSceneName.c_str()); if (existingSource) return RequestResult::Error(RequestStatus::ResourceAlreadyExists, "A source already exists by that new scene name."); @@ -308,8 +357,10 @@ RequestResult RequestHandler::SetSceneName(const Request &request) * * Note: A transition UUID response field is not currently able to be implemented as of 2024-1-18. * - * @requestField ?sceneName | String | Name of the scene - * @requestField ?sceneUuid | String | UUID of the scene + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in + * @requestField ?sceneName | String | Name of the scene + * @requestField ?sceneUuid | String | UUID of the scene * * @responseField transitionName | String | Name of the overridden scene transition, else `null` * @responseField transitionDuration | Number | Duration of the overridden scene transition, else `null` @@ -349,6 +400,8 @@ RequestResult RequestHandler::GetSceneSceneTransitionOverride(const Request &req /** * Sets the scene transition overridden for a scene. * + * @requestField ?canvasName | String | Name of the canvas the scene is in + * @requestField ?canvasUuid | String | UUID of the canvas the scene is in * @requestField ?sceneName | String | Name of the scene * @requestField ?sceneUuid | String | UUID of the scene * @requestField ?transitionName | String | Name of the scene transition to use as override. Specify `null` to remove | Unchanged diff --git a/src/requesthandler/RequestHandler_Sources.cpp b/src/requesthandler/RequestHandler_Sources.cpp index bc246a8f..11ff0627 100644 --- a/src/requesthandler/RequestHandler_Sources.cpp +++ b/src/requesthandler/RequestHandler_Sources.cpp @@ -114,6 +114,8 @@ bool IsImageFormatValid(std::string format) * * **Compatible with inputs and scenes.** * + * @requestField ?canvasName | String | Name of the canvas the source is in + * @requestField ?canvasUuid | String | UUID of the canvas the source is in * @requestField ?sourceName | String | Name of the source to get the active state of * @requestField ?sourceUuid | String | UUID of the source to get the active state of * @@ -152,6 +154,8 @@ RequestResult RequestHandler::GetSourceActive(const Request &request) * * **Compatible with inputs and scenes.** * + * @requestField ?canvasName | String | Name of the canvas the source is in + * @requestField ?canvasUuid | String | UUID of the canvas the source is in * @requestField ?sourceName | String | Name of the source to take a screenshot of * @requestField ?sourceUuid | String | UUID of the source to take a screenshot of * @requestField imageFormat | String | Image compression format to use. Use `GetVersion` to get compatible image formats @@ -240,6 +244,8 @@ RequestResult RequestHandler::GetSourceScreenshot(const Request &request) * * **Compatible with inputs and scenes.** * + * @requestField ?canvasName | String | Name of the canvas the source is in + * @requestField ?canvasUuid | String | UUID of the canvas the source is in * @requestField ?sourceName | String | Name of the source to take a screenshot of * @requestField ?sourceUuid | String | UUID of the source to take a screenshot of * @requestField imageFormat | String | Image compression format to use. Use `GetVersion` to get compatible image formats diff --git a/src/requesthandler/RequestHandler_Ui.cpp b/src/requesthandler/RequestHandler_Ui.cpp index 29896bda..c586ae71 100644 --- a/src/requesthandler/RequestHandler_Ui.cpp +++ b/src/requesthandler/RequestHandler_Ui.cpp @@ -265,6 +265,8 @@ RequestResult RequestHandler::OpenVideoMixProjector(const Request &request) * * Note: This request serves to provide feature parity with 4.x. It is very likely to be changed/deprecated in a future release. * + * @requestField ?canvasName | String | Name of the canvas the source is in + * @requestField ?canvasUuid | String | UUID of the canvas the source is in * @requestField ?sourceName | String | Name of the source to open a projector for * @requestField ?sourceUuid | String | UUID of the source to open a projector for * @requestField ?monitorIndex | Number | Monitor index, use `GetMonitorList` to obtain index | None | -1: Opens projector in windowed mode diff --git a/src/requesthandler/rpc/Request.cpp b/src/requesthandler/rpc/Request.cpp index dc9320a9..1fdd963a 100644 --- a/src/requesthandler/rpc/Request.cpp +++ b/src/requesthandler/rpc/Request.cpp @@ -214,9 +214,14 @@ bool Request::ValidateArray(const std::string &keyName, RequestStatus::RequestSt obs_source_t *Request::ValidateSource(const std::string &nameKeyName, const std::string &uuidKeyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const { + OBSCanvasAutoRelease canvas = ValidateCanvas("canvasName", "canvasUuid", statusCode, comment); + if (statusCode == RequestStatus::ResourceNotFound) + return nullptr; + if (ValidateString(nameKeyName, statusCode, comment)) { std::string sourceName = RequestData[nameKeyName]; - obs_source_t *ret = obs_get_source_by_name(sourceName.c_str()); + obs_source_t *ret = canvas ? obs_canvas_get_source_by_name(canvas, sourceName.c_str()) + : obs_get_source_by_name(sourceName.c_str()); if (!ret) { statusCode = RequestStatus::ResourceNotFound; comment = std::string("No source was found by the name of `") + sourceName + "`."; @@ -383,3 +388,31 @@ obs_output_t *Request::ValidateOutput(const std::string &keyName, RequestStatus: return ret; } + +obs_canvas_t *Request::ValidateCanvas(const std::string &nameKeyName, const std::string &uuidKeyName, + RequestStatus::RequestStatus &statusCode, std::string &comment) const +{ + if (ValidateString(nameKeyName, statusCode, comment)) { + std::string canvasName = RequestData[nameKeyName]; + obs_canvas_t *ret = obs_get_canvas_by_name(canvasName.c_str()); + if (!ret) { + statusCode = RequestStatus::ResourceNotFound; + comment = std::string("No canvas was found by the name of `") + canvasName + "`."; + return nullptr; + } + return ret; + } + + if (ValidateString(uuidKeyName, statusCode, comment)) { + std::string canvasUuid = RequestData[uuidKeyName]; + obs_canvas_t *ret = obs_get_canvas_by_uuid(canvasUuid.c_str()); + if (!ret) { + statusCode = RequestStatus::ResourceNotFound; + comment = std::string("No source was found by the UUID of `") + canvasUuid + "`."; + return nullptr; + } + return ret; + } + + return nullptr; +} diff --git a/src/requesthandler/rpc/Request.h b/src/requesthandler/rpc/Request.h index 77eb2c5c..ebe539dd 100644 --- a/src/requesthandler/rpc/Request.h +++ b/src/requesthandler/rpc/Request.h @@ -76,6 +76,9 @@ struct Request { const ObsWebSocketSceneFilter filter = OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const; obs_output_t *ValidateOutput(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; + obs_canvas_t *ValidateCanvas(const std::string &nameKeyName, const std::string &uuidKeyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment) const; std::string RequestType; bool HasRequestData; diff --git a/src/utils/Obs.h b/src/utils/Obs.h index 47fe214c..1eb13da0 100644 --- a/src/utils/Obs.h +++ b/src/utils/Obs.h @@ -240,7 +240,7 @@ namespace Utils { namespace NumberHelper { uint64_t GetOutputDuration(obs_output_t *output); - size_t GetSceneCount(); + size_t GetSceneCount(obs_canvas_t* canvas = nullptr); size_t GetSourceFilterIndex(obs_source_t *source, obs_source_t *filter); } @@ -249,8 +249,8 @@ namespace Utils { std::vector GetProfileList(); std::vector GetHotkeyList(); std::vector GetHotkeyNameList(); - std::vector GetSceneList(); - std::vector GetGroupList(); + std::vector GetSceneList(obs_canvas_t* canvas = NULL); + std::vector GetGroupList(obs_canvas_t *canvas = NULL); std::vector GetSceneItemList(obs_scene_t *scene, bool basic = false); std::vector GetInputList(std::string inputKind = ""); std::vector GetInputKindList(bool unversioned = false, bool includeDisabled = false); diff --git a/src/utils/Obs_ArrayHelper.cpp b/src/utils/Obs_ArrayHelper.cpp index 0ed224a5..d23399bb 100644 --- a/src/utils/Obs_ArrayHelper.cpp +++ b/src/utils/Obs_ArrayHelper.cpp @@ -84,33 +84,50 @@ std::vector Utils::Obs::ArrayHelper::GetHotkeyNameList() return ret; } -std::vector Utils::Obs::ArrayHelper::GetSceneList() +std::vector Utils::Obs::ArrayHelper::GetSceneList(obs_canvas_t *canvas) { - obs_frontend_source_list sceneList = {}; - obs_frontend_get_scenes(&sceneList); - std::vector ret; - ret.reserve(sceneList.sources.num); - for (size_t i = 0; i < sceneList.sources.num; i++) { - obs_source_t *scene = sceneList.sources.array[i]; + if (canvas) { + obs_canvas_enum_scenes( + canvas, + [](void *param, obs_source_t *scene) { + auto ret = static_cast *>(param); + json sceneJson; + sceneJson["sceneName"] = obs_source_get_name(scene); + sceneJson["sceneUuid"] = obs_source_get_uuid(scene); + ret->push_back(sceneJson); + return true; + }, + &ret); + for (size_t i = 0; i < ret.size(); i++) { + ret[i]["sceneIndex"] = i + 1; + } + } else { - json sceneJson; - sceneJson["sceneName"] = obs_source_get_name(scene); - sceneJson["sceneUuid"] = obs_source_get_uuid(scene); - sceneJson["sceneIndex"] = sceneList.sources.num - i - 1; + obs_frontend_source_list sceneList = {}; + obs_frontend_get_scenes(&sceneList); - ret.push_back(sceneJson); - } + ret.reserve(sceneList.sources.num); + for (size_t i = 0; i < sceneList.sources.num; i++) { + obs_source_t *scene = sceneList.sources.array[i]; - obs_frontend_source_list_free(&sceneList); + json sceneJson; + sceneJson["sceneName"] = obs_source_get_name(scene); + sceneJson["sceneUuid"] = obs_source_get_uuid(scene); + sceneJson["sceneIndex"] = sceneList.sources.num - i - 1; - // Reverse the vector order to match other array returns - std::reverse(ret.begin(), ret.end()); + ret.push_back(sceneJson); + } + obs_frontend_source_list_free(&sceneList); + + // Reverse the vector order to match other array returns + std::reverse(ret.begin(), ret.end()); + } return ret; } -std::vector Utils::Obs::ArrayHelper::GetGroupList() +std::vector Utils::Obs::ArrayHelper::GetGroupList(obs_canvas_t *canvas) { std::vector ret; @@ -125,7 +142,11 @@ std::vector Utils::Obs::ArrayHelper::GetGroupList() return true; }; - obs_enum_scenes(cb, &ret); + if (canvas) { + obs_canvas_enum_scenes(canvas, cb, &ret); + } else { + obs_enum_scenes(cb, &ret); + } return ret; } diff --git a/src/utils/Obs_NumberHelper.cpp b/src/utils/Obs_NumberHelper.cpp index 74b032be..543c2e7b 100644 --- a/src/utils/Obs_NumberHelper.cpp +++ b/src/utils/Obs_NumberHelper.cpp @@ -35,7 +35,7 @@ uint64_t Utils::Obs::NumberHelper::GetOutputDuration(obs_output_t *output) return util_mul_div64(totalFrames, frameTimeNs, 1000000ULL); } -size_t Utils::Obs::NumberHelper::GetSceneCount() +size_t Utils::Obs::NumberHelper::GetSceneCount(obs_canvas_t *canvas) { size_t ret; auto sceneEnumProc = [](void *param, obs_source_t *scene) { @@ -48,7 +48,10 @@ size_t Utils::Obs::NumberHelper::GetSceneCount() return true; }; - obs_enum_scenes(sceneEnumProc, &ret); + if (canvas) + obs_canvas_enum_scenes(canvas, sceneEnumProc, &ret); + else + obs_enum_scenes(sceneEnumProc, &ret); return ret; }