From dca385ae876c039a53572c2257fa961de1d156c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Sat, 31 Aug 2019 01:33:33 +0200 Subject: [PATCH 1/5] requests(ReorderSceneItems): refactor --- src/WSRequestHandler_Scenes.cpp | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/WSRequestHandler_Scenes.cpp b/src/WSRequestHandler_Scenes.cpp index 6e8429c8..90211a14 100644 --- a/src/WSRequestHandler_Scenes.cpp +++ b/src/WSRequestHandler_Scenes.cpp @@ -94,8 +94,8 @@ HandlerResponse WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) { */ HandlerResponse WSRequestHandler::HandleReorderSceneItems(WSRequestHandler* req) { QString sceneName = obs_data_get_string(req->data, "scene"); - OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); - if (!scene) { + OBSSourceAutoRelease sceneSource = Utils::GetSceneFromNameOrCurrent(sceneName); + if (!sceneSource) { return req->SendErrorResponse("requested scene doesn't exist"); } @@ -104,38 +104,29 @@ HandlerResponse WSRequestHandler::HandleReorderSceneItems(WSRequestHandler* req) return req->SendErrorResponse("sceneItem order not specified"); } - size_t count = obs_data_array_count(items); + OBSScene scene = obs_scene_from_source(sceneSource); - std::vector newOrder; - newOrder.reserve(count); + QVector orderList; + struct obs_sceneitem_order_info info; - for (size_t i = 0; i < count; ++i) { + size_t itemCount = obs_data_array_count(items); + for (int i = 0; i < itemCount; i++) { OBSDataAutoRelease item = obs_data_array_item(items, i); - OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromItem(scene, item); - obs_sceneitem_release(sceneItem); // ref dec - + OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromItem(sceneSource, item); if (!sceneItem) { return req->SendErrorResponse("Invalid sceneItem id or name specified"); } - - for (size_t j = 0; j <= i; ++j) { - if (sceneItem == newOrder[j]) { - return req->SendErrorResponse("Duplicate sceneItem in specified order"); - } - } - newOrder.push_back(sceneItem); + info.group = nullptr; + info.item = sceneItem; + orderList.insert(0, info); } - bool success = obs_scene_reorder_items(obs_scene_from_source(scene), newOrder.data(), count); + bool success = obs_scene_reorder_items2(scene, orderList.data(), orderList.size()); if (!success) { return req->SendErrorResponse("Invalid sceneItem order"); } - for (auto const& item: newOrder) { - obs_sceneitem_release(item); - } - return req->SendOKResponse(); } From 9723147429b221a8076505dbd33c74691fa086ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Sat, 31 Aug 2019 02:04:42 +0200 Subject: [PATCH 2/5] Utils: refactor GetSceneItemFromItem and get rid of GetSceneItemFromId --- src/Utils.cpp | 81 ++++++++++++++------------------------------------- src/Utils.h | 3 +- 2 files changed, 23 insertions(+), 61 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index c08b5416..21caed27 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -173,20 +173,28 @@ obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) { return data; } -obs_sceneitem_t* Utils::GetSceneItemFromItem(obs_source_t* source, obs_data_t* item) { - OBSSceneItem sceneItem; - if (obs_data_has_user_value(item, "id")) { - sceneItem = GetSceneItemFromId(source, obs_data_get_int(item, "id")); - if (obs_data_has_user_value(item, "name") && - (QString)obs_source_get_name(obs_sceneitem_get_source(sceneItem)) != - (QString)obs_data_get_string(item, "name")) { - return nullptr; - } - } - else if (obs_data_has_user_value(item, "name")) { - sceneItem = GetSceneItemFromName(source, obs_data_get_string(item, "name")); - } - return sceneItem; +obs_sceneitem_t* Utils::GetSceneItemFromItem(obs_source_t* scene, obs_data_t* itemInfo) { + obs_data_item_t* idInfoItem = obs_data_item_byname(itemInfo, "id"); // TODO fix memory leak + int id = obs_data_item_get_int(idInfoItem); + + obs_data_item_t* nameInfoItem = obs_data_item_byname(itemInfo, "name"); // TODO fix memory leak + const char* name = obs_data_item_get_string(nameInfoItem); + + if (idInfoItem) { + obs_sceneitem_t* sceneItem = obs_scene_find_sceneitem_by_id(obs_scene_from_source(scene), id); + obs_source_t* sceneItemSource = obs_sceneitem_get_source(sceneItem); + + QString sceneItemName = obs_source_get_name(sceneItemSource); + if (nameInfoItem && (QString(name) != sceneItemName)) { + return nullptr; + } + + return sceneItem; + } else if (nameInfoItem) { + return GetSceneItemFromName(scene, name); + } + + return nullptr; } obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, QString name) { @@ -236,51 +244,6 @@ obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, QString name) return search.result; } -// TODO refactor this to unify it with GetSceneItemFromName -obs_sceneitem_t* Utils::GetSceneItemFromId(obs_source_t* source, size_t id) { - struct current_search { - size_t query; - obs_sceneitem_t* result; - bool (*enumCallback)(obs_scene_t*, obs_sceneitem_t*, void*); - }; - - current_search search; - search.query = id; - search.result = nullptr; - search.enumCallback = nullptr; - - OBSScene scene = obs_scene_from_source(source); - if (!scene) - return nullptr; - - search.enumCallback = []( - obs_scene_t* scene, - obs_sceneitem_t* currentItem, - void* param) - { - current_search* search = reinterpret_cast(param); - - if (obs_sceneitem_is_group(currentItem)) { - obs_sceneitem_group_enum_items(currentItem, search->enumCallback, param); - if (search->result) { - return false; - } - } - - if (obs_sceneitem_get_id(currentItem) == search->query) { - search->result = currentItem; - obs_sceneitem_addref(search->result); - return false; - } - - return true; - }; - - obs_scene_enum_items(scene, search.enumCallback, &search); - - return search.result; -} - bool Utils::IsValidAlignment(const uint32_t alignment) { switch (alignment) { case OBS_ALIGN_CENTER: diff --git a/src/Utils.h b/src/Utils.h index 8e2d410d..41eea124 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -38,8 +38,7 @@ class Utils { static obs_data_t* GetSceneItemData(obs_sceneitem_t* item); static obs_sceneitem_t* GetSceneItemFromName( obs_source_t* source, QString name); - static obs_sceneitem_t* GetSceneItemFromId(obs_source_t* source, size_t id); - static obs_sceneitem_t* GetSceneItemFromItem(obs_source_t* source, obs_data_t* item); + static obs_sceneitem_t* GetSceneItemFromItem(obs_source_t* scene, obs_data_t* item); static obs_source_t* GetTransitionFromName(QString transitionName); static obs_source_t* GetSceneFromNameOrCurrent(QString sceneName); static obs_data_t* GetSceneItemPropertiesData(obs_sceneitem_t* item); From cee0cbebc2c9ce5eafe50b8118dfcb801ad34303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Sat, 31 Aug 2019 02:17:58 +0200 Subject: [PATCH 3/5] Utils: use obs_scene_t* directly for scene-related helpers --- src/Utils.cpp | 36 +++++++++++++++++------------ src/Utils.h | 14 +++++------ src/WSRequestHandler_SceneItems.cpp | 27 +++++++++++----------- src/WSRequestHandler_Scenes.cpp | 8 +++---- src/WSRequestHandler_StudioMode.cpp | 4 ++-- 5 files changed, 46 insertions(+), 43 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index 21caed27..062e707c 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -173,7 +173,11 @@ obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) { return data; } -obs_sceneitem_t* Utils::GetSceneItemFromItem(obs_source_t* scene, obs_data_t* itemInfo) { +obs_sceneitem_t* Utils::GetSceneItemFromItem(obs_scene_t* scene, obs_data_t* itemInfo) { + if (!scene) { + return nullptr; + } + obs_data_item_t* idInfoItem = obs_data_item_byname(itemInfo, "id"); // TODO fix memory leak int id = obs_data_item_get_int(idInfoItem); @@ -181,7 +185,7 @@ obs_sceneitem_t* Utils::GetSceneItemFromItem(obs_source_t* scene, obs_data_t* it const char* name = obs_data_item_get_string(nameInfoItem); if (idInfoItem) { - obs_sceneitem_t* sceneItem = obs_scene_find_sceneitem_by_id(obs_scene_from_source(scene), id); + obs_sceneitem_t* sceneItem = obs_scene_find_sceneitem_by_id(scene, id); obs_source_t* sceneItemSource = obs_sceneitem_get_source(sceneItem); QString sceneItemName = obs_source_get_name(sceneItemSource); @@ -197,7 +201,11 @@ obs_sceneitem_t* Utils::GetSceneItemFromItem(obs_source_t* scene, obs_data_t* it return nullptr; } -obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, QString name) { +obs_sceneitem_t* Utils::GetSceneItemFromName(obs_scene_t* scene, QString name) { + if (!scene) { + return nullptr; + } + struct current_search { QString query; obs_sceneitem_t* result; @@ -209,10 +217,6 @@ obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, QString name) search.result = nullptr; search.enumCallback = nullptr; - OBSScene scene = obs_scene_from_source(source); - if (!scene) - return nullptr; - search.enumCallback = []( obs_scene_t* scene, obs_sceneitem_t* currentItem, @@ -282,17 +286,19 @@ obs_source_t* Utils::GetTransitionFromName(QString searchName) { return foundTransition; } -obs_source_t* Utils::GetSceneFromNameOrCurrent(QString sceneName) { +obs_scene_t* Utils::GetSceneFromNameOrCurrent(QString sceneName) { // Both obs_frontend_get_current_scene() and obs_get_source_by_name() - // do addref on the return source, so no need to use an OBSSource helper - obs_source_t* scene = nullptr; + // increase the returned source's refcount + OBSSourceAutoRelease sceneSource = nullptr; - if (sceneName.isEmpty() || sceneName.isNull()) - scene = obs_frontend_get_current_scene(); - else - scene = obs_get_source_by_name(sceneName.toUtf8()); + if (sceneName.isEmpty() || sceneName.isNull()) { + sceneSource = obs_frontend_get_current_scene(); + } + else { + sceneSource = obs_get_source_by_name(sceneName.toUtf8()); + } - return scene; + return obs_scene_from_source(sceneSource); } obs_data_array_t* Utils::GetScenes() { diff --git a/src/Utils.h b/src/Utils.h index 41eea124..3a8da207 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -36,11 +36,10 @@ class Utils { static obs_data_array_t* StringListToArray(char** strings, const char* key); static obs_data_array_t* GetSceneItems(obs_source_t* source); static obs_data_t* GetSceneItemData(obs_sceneitem_t* item); - static obs_sceneitem_t* GetSceneItemFromName( - obs_source_t* source, QString name); - static obs_sceneitem_t* GetSceneItemFromItem(obs_source_t* scene, obs_data_t* item); - static obs_source_t* GetTransitionFromName(QString transitionName); - static obs_source_t* GetSceneFromNameOrCurrent(QString sceneName); + + static obs_sceneitem_t* GetSceneItemFromName(obs_scene_t* scene, QString name); + static obs_sceneitem_t* GetSceneItemFromItem(obs_scene_t* scene, obs_data_t* item); + static obs_scene_t* GetSceneFromNameOrCurrent(QString sceneName); static obs_data_t* GetSceneItemPropertiesData(obs_sceneitem_t* item); static obs_data_array_t* GetSourceFiltersList(obs_source_t* source, bool includeSettings); @@ -52,9 +51,8 @@ class Utils { // TODO contribute a proper frontend API method for this to OBS and remove this hack static QSpinBox* GetTransitionDurationControl(); - static int GetTransitionDuration(obs_source_t* transition); - + static obs_source_t* GetTransitionFromName(QString transitionName); static bool SetTransitionByName(QString transitionName); static QString OBSVersionString(); @@ -70,9 +68,11 @@ class Utils { static QString ParseDataToQueryString(obs_data_t* data); static obs_hotkey_t* FindHotkeyByName(QString name); + static bool ReplayBufferEnabled(); static void StartReplayBuffer(); static bool IsRPHotkeySet(); + static const char* GetFilenameFormatting(); static bool SetFilenameFormatting(const char* filenameFormatting); }; diff --git a/src/WSRequestHandler_SceneItems.cpp b/src/WSRequestHandler_SceneItems.cpp index fd5c138f..e2e6d188 100644 --- a/src/WSRequestHandler_SceneItems.cpp +++ b/src/WSRequestHandler_SceneItems.cpp @@ -49,13 +49,12 @@ HandlerResponse WSRequestHandler::HandleGetSceneItemProperties(WSRequestHandler* } QString sceneName = obs_data_get_string(req->data, "scene-name"); - OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); + OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { return req->SendErrorResponse("requested scene doesn't exist"); } - OBSSceneItemAutoRelease sceneItem = - Utils::GetSceneItemFromName(scene, itemName); + OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName); if (!sceneItem) { return req->SendErrorResponse("specified scene item doesn't exist"); } @@ -105,7 +104,7 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemProperties(WSRequestHandler* } QString sceneName = obs_data_get_string(req->data, "scene-name"); - OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); + OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { return req->SendErrorResponse("requested scene doesn't exist"); } @@ -283,7 +282,7 @@ HandlerResponse WSRequestHandler::HandleResetSceneItem(WSRequestHandler* req) { } const char* sceneName = obs_data_get_string(req->data, "scene-name"); - OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); + OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { return req->SendErrorResponse("requested scene doesn't exist"); } @@ -329,7 +328,7 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemRender(WSRequestHandler* req } const char* sceneName = obs_data_get_string(req->data, "scene-name"); - OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); + OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { return req->SendErrorResponse("requested scene doesn't exist"); } @@ -371,7 +370,7 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemPosition(WSRequestHandler* r } QString sceneName = obs_data_get_string(req->data, "scene-name"); - OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); + OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { return req->SendErrorResponse("requested scene could not be found"); } @@ -419,7 +418,7 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemTransform(WSRequestHandler* } QString sceneName = obs_data_get_string(req->data, "scene-name"); - OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); + OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { return req->SendErrorResponse("requested scene doesn't exist"); } @@ -471,7 +470,7 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemCrop(WSRequestHandler* req) } QString sceneName = obs_data_get_string(req->data, "scene-name"); - OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); + OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { return req->SendErrorResponse("requested scene doesn't exist"); } @@ -511,7 +510,7 @@ HandlerResponse WSRequestHandler::HandleDeleteSceneItem(WSRequestHandler* req) { } const char* sceneName = obs_data_get_string(req->data, "scene"); - OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); + OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { return req->SendErrorResponse("requested scene doesn't exist"); } @@ -564,13 +563,13 @@ HandlerResponse WSRequestHandler::HandleDuplicateSceneItem(WSRequestHandler* req } const char* fromSceneName = obs_data_get_string(req->data, "fromScene"); - OBSSourceAutoRelease fromScene = Utils::GetSceneFromNameOrCurrent(fromSceneName); + OBSScene fromScene = Utils::GetSceneFromNameOrCurrent(fromSceneName); if (!fromScene) { return req->SendErrorResponse("requested fromScene doesn't exist"); } const char* toSceneName = obs_data_get_string(req->data, "toScene"); - OBSSourceAutoRelease toScene = Utils::GetSceneFromNameOrCurrent(toSceneName); + OBSScene toScene = Utils::GetSceneFromNameOrCurrent(toSceneName); if (!toScene) { return req->SendErrorResponse("requested toScene doesn't exist"); } @@ -586,7 +585,7 @@ HandlerResponse WSRequestHandler::HandleDuplicateSceneItem(WSRequestHandler* req data.referenceItem = referenceItem; obs_enter_graphics(); - obs_scene_atomic_update(obs_scene_from_source(toScene), DuplicateSceneItem, &data); + obs_scene_atomic_update(toScene, DuplicateSceneItem, &data); obs_leave_graphics(); obs_sceneitem_t *newItem = data.newItem; @@ -600,7 +599,7 @@ HandlerResponse WSRequestHandler::HandleDuplicateSceneItem(WSRequestHandler* req OBSDataAutoRelease responseData = obs_data_create(); obs_data_set_obj(responseData, "item", itemData); - obs_data_set_string(responseData, "scene", obs_source_get_name(toScene)); + obs_data_set_string(responseData, "scene", obs_source_get_name(obs_scene_get_source(toScene))); return req->SendOKResponse(responseData); } diff --git a/src/WSRequestHandler_Scenes.cpp b/src/WSRequestHandler_Scenes.cpp index 90211a14..cd7f8c25 100644 --- a/src/WSRequestHandler_Scenes.cpp +++ b/src/WSRequestHandler_Scenes.cpp @@ -94,8 +94,8 @@ HandlerResponse WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) { */ HandlerResponse WSRequestHandler::HandleReorderSceneItems(WSRequestHandler* req) { QString sceneName = obs_data_get_string(req->data, "scene"); - OBSSourceAutoRelease sceneSource = Utils::GetSceneFromNameOrCurrent(sceneName); - if (!sceneSource) { + OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName); + if (!scene) { return req->SendErrorResponse("requested scene doesn't exist"); } @@ -104,8 +104,6 @@ HandlerResponse WSRequestHandler::HandleReorderSceneItems(WSRequestHandler* req) return req->SendErrorResponse("sceneItem order not specified"); } - OBSScene scene = obs_scene_from_source(sceneSource); - QVector orderList; struct obs_sceneitem_order_info info; @@ -113,7 +111,7 @@ HandlerResponse WSRequestHandler::HandleReorderSceneItems(WSRequestHandler* req) for (int i = 0; i < itemCount; i++) { OBSDataAutoRelease item = obs_data_array_item(items, i); - OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromItem(sceneSource, item); + OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromItem(scene, item); if (!sceneItem) { return req->SendErrorResponse("Invalid sceneItem id or name specified"); } diff --git a/src/WSRequestHandler_StudioMode.cpp b/src/WSRequestHandler_StudioMode.cpp index 738b5bcc..bfcdae4e 100644 --- a/src/WSRequestHandler_StudioMode.cpp +++ b/src/WSRequestHandler_StudioMode.cpp @@ -69,12 +69,12 @@ HandlerResponse WSRequestHandler::HandleSetPreviewScene(WSRequestHandler* req) { } const char* scene_name = obs_data_get_string(req->data, "scene-name"); - OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(scene_name); + OBSScene scene = Utils::GetSceneFromNameOrCurrent(scene_name); if (!scene) { return req->SendErrorResponse("specified scene doesn't exist"); } - obs_frontend_set_current_preview_scene(scene); + obs_frontend_set_current_preview_scene(obs_scene_get_source(scene)); return req->SendOKResponse(); } From 73b5261c491f81b45d0fb326bc7d2759d4844fd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Sat, 31 Aug 2019 02:38:20 +0200 Subject: [PATCH 4/5] requests(ReorderSceneItems): atomic reorder + bring back GetSceneItemFromId --- src/Utils.cpp | 46 ++++++++++++++++++++++++++++-- src/Utils.h | 3 ++ src/WSRequestHandler_Scenes.cpp | 50 +++++++++++++++++++++++---------- 3 files changed, 82 insertions(+), 17 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index 062e707c..43abf217 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -185,7 +185,7 @@ obs_sceneitem_t* Utils::GetSceneItemFromItem(obs_scene_t* scene, obs_data_t* ite const char* name = obs_data_item_get_string(nameInfoItem); if (idInfoItem) { - obs_sceneitem_t* sceneItem = obs_scene_find_sceneitem_by_id(scene, id); + obs_sceneitem_t* sceneItem = GetSceneItemFromId(scene, id); obs_source_t* sceneItemSource = obs_sceneitem_get_source(sceneItem); QString sceneItemName = obs_source_get_name(sceneItemSource); @@ -215,7 +215,6 @@ obs_sceneitem_t* Utils::GetSceneItemFromName(obs_scene_t* scene, QString name) { current_search search; search.query = name; search.result = nullptr; - search.enumCallback = nullptr; search.enumCallback = []( obs_scene_t* scene, @@ -248,6 +247,49 @@ obs_sceneitem_t* Utils::GetSceneItemFromName(obs_scene_t* scene, QString name) { return search.result; } +obs_sceneitem_t* Utils::GetSceneItemFromId(obs_scene_t* scene, int64_t id) { + if (!scene) { + return nullptr; + } + + struct current_search { + int query; + obs_sceneitem_t* result; + bool (*enumCallback)(obs_scene_t*, obs_sceneitem_t*, void*); + }; + + current_search search; + search.query = id; + search.result = nullptr; + + search.enumCallback = []( + obs_scene_t* scene, + obs_sceneitem_t* currentItem, + void* param) + { + current_search* search = reinterpret_cast(param); + + if (obs_sceneitem_is_group(currentItem)) { + obs_sceneitem_group_enum_items(currentItem, search->enumCallback, search); + if (search->result) { + return false; + } + } + + if (obs_sceneitem_get_id(currentItem) == search->query) { + search->result = currentItem; + obs_sceneitem_addref(search->result); + return false; + } + + return true; + }; + + obs_scene_enum_items(scene, search.enumCallback, &search); + + return search.result; +} + bool Utils::IsValidAlignment(const uint32_t alignment) { switch (alignment) { case OBS_ALIGN_CENTER: diff --git a/src/Utils.h b/src/Utils.h index 3a8da207..6a446a7c 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -37,7 +37,10 @@ class Utils { static obs_data_array_t* GetSceneItems(obs_source_t* source); static obs_data_t* GetSceneItemData(obs_sceneitem_t* item); + // These two functions support nested lookup into groups static obs_sceneitem_t* GetSceneItemFromName(obs_scene_t* scene, QString name); + static obs_sceneitem_t* GetSceneItemFromId(obs_scene_t* scene, int64_t id); + static obs_sceneitem_t* GetSceneItemFromItem(obs_scene_t* scene, obs_data_t* item); static obs_scene_t* GetSceneFromNameOrCurrent(QString sceneName); static obs_data_t* GetSceneItemPropertiesData(obs_sceneitem_t* item); diff --git a/src/WSRequestHandler_Scenes.cpp b/src/WSRequestHandler_Scenes.cpp index cd7f8c25..3a8754b4 100644 --- a/src/WSRequestHandler_Scenes.cpp +++ b/src/WSRequestHandler_Scenes.cpp @@ -104,26 +104,46 @@ HandlerResponse WSRequestHandler::HandleReorderSceneItems(WSRequestHandler* req) return req->SendErrorResponse("sceneItem order not specified"); } - QVector orderList; - struct obs_sceneitem_order_info info; + struct reorder_context { + obs_data_array_t* items; + bool success; + QString errorMessage; + }; - size_t itemCount = obs_data_array_count(items); - for (int i = 0; i < itemCount; i++) { - OBSDataAutoRelease item = obs_data_array_item(items, i); + struct reorder_context ctx; + ctx.success = false; + ctx.items = items; - OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromItem(scene, item); - if (!sceneItem) { - return req->SendErrorResponse("Invalid sceneItem id or name specified"); + obs_scene_atomic_update(scene, [](void* param, obs_scene_t* scene) { + auto ctx = reinterpret_cast(param); + + QVector orderList; + struct obs_sceneitem_order_info info; + + size_t itemCount = obs_data_array_count(ctx->items); + for (int i = 0; i < itemCount; i++) { + OBSDataAutoRelease item = obs_data_array_item(ctx->items, i); + + OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromItem(scene, item); + if (!sceneItem) { + ctx->success = false; + ctx->errorMessage = "Invalid sceneItem id or name specified"; + return; + } + + info.group = nullptr; + info.item = sceneItem; + orderList.insert(0, info); } - info.group = nullptr; - info.item = sceneItem; - orderList.insert(0, info); - } + ctx->success = obs_scene_reorder_items2(scene, orderList.data(), orderList.size()); + if (!ctx->success) { + ctx->errorMessage = "Invalid sceneItem order"; + } + }, &ctx); - bool success = obs_scene_reorder_items2(scene, orderList.data(), orderList.size()); - if (!success) { - return req->SendErrorResponse("Invalid sceneItem order"); + if (!ctx.success) { + return req->SendErrorResponse(ctx.errorMessage); } return req->SendOKResponse(); From a034fbba8306e372acfc0c753c825ad41c511899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Sat, 31 Aug 2019 02:50:05 +0200 Subject: [PATCH 5/5] utils(GetSceneItemFromItem): fix memory leaks with obs_data_item_t uses --- src/Utils.cpp | 4 ++-- src/obs-websocket.cpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index 43abf217..5bd2823d 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -178,10 +178,10 @@ obs_sceneitem_t* Utils::GetSceneItemFromItem(obs_scene_t* scene, obs_data_t* ite return nullptr; } - obs_data_item_t* idInfoItem = obs_data_item_byname(itemInfo, "id"); // TODO fix memory leak + OBSDataItemAutoRelease idInfoItem = obs_data_item_byname(itemInfo, "id"); int id = obs_data_item_get_int(idInfoItem); - obs_data_item_t* nameInfoItem = obs_data_item_byname(itemInfo, "name"); // TODO fix memory leak + OBSDataItemAutoRelease nameInfoItem = obs_data_item_byname(itemInfo, "name"); const char* name = obs_data_item_get_string(nameInfoItem); if (idInfoItem) { diff --git a/src/obs-websocket.cpp b/src/obs-websocket.cpp index 7ec92245..2f066ac0 100644 --- a/src/obs-websocket.cpp +++ b/src/obs-websocket.cpp @@ -18,6 +18,7 @@ with this program. If not, see #include #include +#include #include #include