requesthandler, utils: Add search offset to GetSceneItemId

Allows you to select a specific match by offset, or select the
last (top) scene item by specifying `-1`.
This commit is contained in:
tt2468 2022-04-13 02:01:40 -07:00
parent e6c48990d6
commit c355c72f4b
3 changed files with 45 additions and 10 deletions

View File

@ -86,8 +86,9 @@ RequestResult RequestHandler::GetGroupSceneItemList(const Request& request)
*
* Scenes and Groups
*
* @requestField sceneName | String | Name of the scene or group to search in
* @requestField sourceName | String | Name of the source to find
* @requestField sceneName | String | Name of the scene or group to search in
* @requestField sourceName | String | Name of the source to find
* @requestField ?searchOffset | Number | Number of matches to skip during search. >= 0 means first forward. -1 means last (top) item | >= -1 | 0
*
* @responseField sceneItemId | Number | Numeric ID of the scene item
*
@ -108,9 +109,16 @@ RequestResult RequestHandler::GetSceneItemId(const Request& request)
std::string sourceName = request.RequestData["sourceName"];
OBSSceneItemAutoRelease item = Utils::Obs::SearchHelper::GetSceneItemByName(scene, sourceName);
int offset = 0;
if (request.Contains("searchOffset")) {
if (!request.ValidateOptionalNumber("searchOffset", statusCode, comment, -1))
return RequestResult::Error(statusCode, comment);
offset = request.RequestData["searchOffset"];
}
OBSSceneItemAutoRelease item = Utils::Obs::SearchHelper::GetSceneItemByName(scene, sourceName, offset);
if (!item)
return RequestResult::Error(RequestStatus::ResourceNotFound, "No scene items were found in the specified scene by that name.");
return RequestResult::Error(RequestStatus::ResourceNotFound, "No scene items were found in the specified scene by that name or offset.");
json responseData;
responseData["sceneItemId"] = obs_sceneitem_get_id(item);

View File

@ -205,7 +205,7 @@ namespace Utils {
namespace SearchHelper {
obs_hotkey_t *GetHotkeyByName(std::string name);
obs_source_t *GetSceneTransitionByName(std::string name); // Increments source ref. Use OBSSourceAutoRelease
obs_sceneitem_t *GetSceneItemByName(obs_scene_t *scene, std::string name); // Increments ref. Use OBSSceneItemAutoRelease
obs_sceneitem_t *GetSceneItemByName(obs_scene_t *scene, std::string name, int offset = 0); // Increments ref. Use OBSSceneItemAutoRelease
}
namespace ActionHelper {

View File

@ -54,15 +54,42 @@ obs_source_t *Utils::Obs::SearchHelper::GetSceneTransitionByName(std::string nam
return ret;
}
struct SceneItemSearchData {
std::string name;
int offset;
obs_sceneitem_t *ret = nullptr;
};
// Increments item ref. Use OBSSceneItemAutoRelease
obs_sceneitem_t *Utils::Obs::SearchHelper::GetSceneItemByName(obs_scene_t *scene, std::string name)
obs_sceneitem_t *Utils::Obs::SearchHelper::GetSceneItemByName(obs_scene_t *scene, std::string name, int offset)
{
if (name.empty())
return nullptr;
// Finds first matching scene item in scene, search starts at index 0
OBSSceneItem ret = obs_scene_find_source(scene, name.c_str());
obs_sceneitem_addref(ret);
SceneItemSearchData enumData;
enumData.name = name;
enumData.offset = offset;
return ret;
obs_scene_enum_items(scene, [](obs_scene_t*, obs_sceneitem_t* sceneItem, void* param) {
auto enumData = static_cast<SceneItemSearchData*>(param);
OBSSource itemSource = obs_sceneitem_get_source(sceneItem);
std::string sourceName = obs_source_get_name(itemSource);
if (sourceName == enumData->name) {
if (enumData->offset > 0) {
enumData->offset--;
} else {
if (enumData->ret) // Release existing selection in the case of last match selection
obs_sceneitem_release(enumData->ret);
obs_sceneitem_addref(sceneItem);
enumData->ret = sceneItem;
if (enumData->offset == 0) // Only break if in normal selection mode (not offset == -1)
return false;
}
}
return true;
}, &enumData);
return enumData.ret;
}