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

@ -88,6 +88,7 @@ RequestResult RequestHandler::GetGroupSceneItemList(const Request& request)
* *
* @requestField sceneName | String | Name of the scene or group to search in * @requestField sceneName | String | Name of the scene or group to search in
* @requestField sourceName | String | Name of the source to find * @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 * @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"]; 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) 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; json responseData;
responseData["sceneItemId"] = obs_sceneitem_get_id(item); responseData["sceneItemId"] = obs_sceneitem_get_id(item);

View File

@ -205,7 +205,7 @@ namespace Utils {
namespace SearchHelper { namespace SearchHelper {
obs_hotkey_t *GetHotkeyByName(std::string name); obs_hotkey_t *GetHotkeyByName(std::string name);
obs_source_t *GetSceneTransitionByName(std::string name); // Increments source ref. Use OBSSourceAutoRelease 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 { namespace ActionHelper {

View File

@ -54,15 +54,42 @@ obs_source_t *Utils::Obs::SearchHelper::GetSceneTransitionByName(std::string nam
return ret; return ret;
} }
struct SceneItemSearchData {
std::string name;
int offset;
obs_sceneitem_t *ret = nullptr;
};
// Increments item ref. Use OBSSceneItemAutoRelease // 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()) if (name.empty())
return nullptr; return nullptr;
// Finds first matching scene item in scene, search starts at index 0 SceneItemSearchData enumData;
OBSSceneItem ret = obs_scene_find_source(scene, name.c_str()); enumData.name = name;
obs_sceneitem_addref(ret); 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;
} }