From c377bf3f910a43b5d166315b2083c94dc33f4d1b Mon Sep 17 00:00:00 2001 From: Mike Blouin Date: Fri, 8 Jun 2018 18:07:01 -0700 Subject: [PATCH 1/8] feat(batch): Initial commit for batch operations Exposing a new batch operations API that allows you to batch updates to multiple objects (e.g. controls, participants) and multiple property updates on a single object. This API also allows for the use of custom data including nested objects and arrays. Current only exposes batch methods for `controls` - other objects will come in a subsequent commit. Tests are not yet complete as we have yet to expose handlers for control update events and the current implementation does not update internal state on all events so it is not testable. We also need to invest in proper teardown methods to kill interactive connection when using asserts. --- Tests/Tests.cpp | 95 ++++++ .../Interactivity.UWP.Cpp.vcxproj | 2 + .../Interactivity.UWP.Cpp.vcxproj.filters | 6 + .../Interactivity.Win32.Cpp.vcxproj | 2 + .../Interactivity.Win32.Cpp.vcxproj.filters | 4 + .../Interactivity.Xbox.Cpp.vcxproj | 2 + .../Interactivity.Xbox.Cpp.vcxproj.filters | 6 + source/interactivity.cpp | 1 + source/interactivity.h | 60 ++++ source/internal/interactive_batch.cpp | 275 ++++++++++++++++++ source/internal/interactive_batch.h | 50 ++++ source/internal/interactive_control.cpp | 51 ++++ source/internal/interactive_participant.cpp | 74 +++++ source/internal/interactive_session.cpp | 13 +- source/internal/interactive_session.h | 3 + 15 files changed, 642 insertions(+), 2 deletions(-) create mode 100644 source/internal/interactive_batch.cpp create mode 100644 source/internal/interactive_batch.h diff --git a/Tests/Tests.cpp b/Tests/Tests.cpp index 2e3218d..dc425f0 100644 --- a/Tests/Tests.cpp +++ b/Tests/Tests.cpp @@ -930,5 +930,100 @@ TEST_CLASS(Tests) Logger::WriteMessage("Disconnecting..."); interactive_close_session(session); } + + TEST_METHOD(ControlBatchTest) + { + g_start = std::chrono::high_resolution_clock::now(); + interactive_config_debug(interactive_debug_trace, handle_debug_message); + + int err = 0; + std::string clientId = CLIENT_ID; + std::string versionId = VERSION_ID; + std::string shareCode = SHARE_CODE; + std::string auth; + + ASSERT_NOERR(do_auth(clientId, "", auth)); + + interactive_session session; + Logger::WriteMessage("Connecting..."); + ASSERT_NOERR(interactive_open_session(&session)); + ASSERT_NOERR(interactive_set_error_handler(session, handle_error_assert)); + ASSERT_NOERR(interactive_connect(session, auth.c_str(), versionId.c_str(), shareCode.c_str(), true)); + ASSERT_NOERR(interactive_set_participants_changed_handler(session, handle_participants_changed)); + + // Simulate 60 frames/sec for 1 second. + const int fps = 60; + const int seconds = 1; + for (int i = 0; i < fps * seconds; ++i) + { + ASSERT_NOERR(interactive_run(session, 1)); + std::this_thread::sleep_for(std::chrono::milliseconds(1000 / fps)); + } + + interactive_batch batch; + Assert::AreEqual((int)MIXER_OK, interactive_control_batch_begin(session, &batch, "default")); + + interactive_batch_entry entry; + Assert::AreEqual((int)MIXER_OK, interactive_control_batch_add(batch, &entry, "GiveHealth")); + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(batch, entry, "foo", "bar")); + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(batch, entry, "number", 42)); + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_array(batch, entry, "array", [](interactive_batch batch, interactive_batch_array arrayItem) + { + Assert::AreEqual((int)MIXER_OK, interactive_batch_array_push_object(batch, arrayItem, [](interactive_batch batch, interactive_batch_entry objectEntry) + { + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(batch, objectEntry, "foo", "bar")); + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(batch, objectEntry, "number", 42)); + })); + Assert::AreEqual((int)MIXER_OK, interactive_batch_array_push_str(batch, arrayItem, "bar")); + Assert::AreEqual((int)MIXER_OK, interactive_batch_array_push_uint(batch, arrayItem, 42)); + })); + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_object(batch, entry, "object", [](interactive_batch batch, interactive_batch_entry objectEntry) + { + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(batch, objectEntry, "foo", "bar")); + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(batch, objectEntry, "number", 42)); + })); + Assert::AreEqual((int)MIXER_OK, interactive_control_batch_end(batch)); + + // Simulate 60 frames/sec for 1 second. + for (int i = 0; i < fps * seconds; ++i) + { + ASSERT_NOERR(interactive_run(session, 1)); + std::this_thread::sleep_for(std::chrono::milliseconds(1000 / fps)); + } + + Logger::WriteMessage("Enumerating scenes."); + ASSERT_NOERR(interactive_get_scenes(session, [](void* context, interactive_session session, interactive_scene* scene) + { + std::stringstream s; + s << "[Scene] '" << std::string(scene->id, scene->idLength) << "'"; + Logger::WriteMessage(s.str().c_str()); + + Logger::WriteMessage("Controls:"); + interactive_scene_get_controls(session, scene->id, [](void* context, interactive_session session, interactive_control* control) + { + if (0 == strcmp(control->id, "GiveHealth")) { + char foo[4]; + size_t nameLength = 4; + int number; + print_control_properties(session, control->id); + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_string(session, "GiveHealth", "foo", foo, &nameLength)); + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_int(session, "GiveHealth", "number", &number)); + Assert::AreEqual("bar", foo); + } + }); + })); + + for (int i = 0; i < fps * seconds; ++i) + { + ASSERT_NOERR(interactive_run(session, 1)); + std::this_thread::sleep_for(std::chrono::milliseconds(1000 / fps)); + } + + Logger::WriteMessage("Disconnecting..."); + interactive_close_session(session); + + Assert::IsTrue(0 == err); + } + }; } \ No newline at end of file diff --git a/builds/Interactivity.UWP.Cpp/Interactivity.UWP.Cpp.vcxproj b/builds/Interactivity.UWP.Cpp/Interactivity.UWP.Cpp.vcxproj index 4603de2..59e7938 100644 --- a/builds/Interactivity.UWP.Cpp/Interactivity.UWP.Cpp.vcxproj +++ b/builds/Interactivity.UWP.Cpp/Interactivity.UWP.Cpp.vcxproj @@ -71,6 +71,7 @@ true true + true true @@ -125,6 +126,7 @@ + diff --git a/builds/Interactivity.UWP.Cpp/Interactivity.UWP.Cpp.vcxproj.filters b/builds/Interactivity.UWP.Cpp/Interactivity.UWP.Cpp.vcxproj.filters index 5caadba..71e7aaf 100644 --- a/builds/Interactivity.UWP.Cpp/Interactivity.UWP.Cpp.vcxproj.filters +++ b/builds/Interactivity.UWP.Cpp/Interactivity.UWP.Cpp.vcxproj.filters @@ -45,6 +45,9 @@ C++ Source + + C++ Source + @@ -68,5 +71,8 @@ Includes + + Includes + \ No newline at end of file diff --git a/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj b/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj index 954b4b1..161c8f4 100644 --- a/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj +++ b/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj @@ -67,6 +67,7 @@ true true + true true @@ -121,6 +122,7 @@ + diff --git a/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj.filters b/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj.filters index 4372f6e..1c79560 100644 --- a/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj.filters +++ b/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj.filters @@ -45,6 +45,7 @@ C++ Source + @@ -71,5 +72,8 @@ Includes + + Includes + \ No newline at end of file diff --git a/builds/Interactivity.Xbox.Cpp/Interactivity.Xbox.Cpp.vcxproj b/builds/Interactivity.Xbox.Cpp/Interactivity.Xbox.Cpp.vcxproj index 6350480..05ba815 100644 --- a/builds/Interactivity.Xbox.Cpp/Interactivity.Xbox.Cpp.vcxproj +++ b/builds/Interactivity.Xbox.Cpp/Interactivity.Xbox.Cpp.vcxproj @@ -65,6 +65,7 @@ true true + true true @@ -98,6 +99,7 @@ + diff --git a/builds/Interactivity.Xbox.Cpp/Interactivity.Xbox.Cpp.vcxproj.filters b/builds/Interactivity.Xbox.Cpp/Interactivity.Xbox.Cpp.vcxproj.filters index b345173..70e2a87 100644 --- a/builds/Interactivity.Xbox.Cpp/Interactivity.Xbox.Cpp.vcxproj.filters +++ b/builds/Interactivity.Xbox.Cpp/Interactivity.Xbox.Cpp.vcxproj.filters @@ -42,6 +42,9 @@ C++ Source + + C++ Source + @@ -59,5 +62,8 @@ Includes + + Includes + \ No newline at end of file diff --git a/source/interactivity.cpp b/source/interactivity.cpp index 9f2e805..1264f6e 100644 --- a/source/interactivity.cpp +++ b/source/interactivity.cpp @@ -1,6 +1,7 @@ #include "internal/common.cpp" #include "internal/http_client.cpp" #include "internal/interactive_auth.cpp" +#include "internal/interactive_batch.cpp" #include "internal/interactive_control.cpp" #include "internal/interactive_group.cpp" #include "internal/interactive_participant.cpp" diff --git a/source/interactivity.h b/source/interactivity.h index e6b9fc6..1b09c13 100644 --- a/source/interactivity.h +++ b/source/interactivity.h @@ -173,6 +173,49 @@ extern "C" { void interactive_close_session(interactive_session session); /** @} */ + /** @name Batch Requests + * @{ + */ + struct interactive_batch_public {}; + struct interactive_batch_entry_public {}; + struct interactive_batch_array_public {}; + + typedef interactive_batch_public* interactive_batch; + + typedef interactive_batch_entry_public* interactive_batch_entry; + + typedef interactive_batch_array_public* interactive_batch_array; + + typedef void(*interactive_batch_object_callback)(interactive_batch, interactive_batch_entry); + + typedef void(*interactive_batch_array_callback)(interactive_batch, interactive_batch_array); + + int interactive_batch_add_param_null(interactive_batch batch, interactive_batch_entry entry, const char* name); + + int interactive_batch_add_param_str(interactive_batch batch, interactive_batch_entry entry, const char* name, const char* value); + + int interactive_batch_add_param_uint(interactive_batch batch, interactive_batch_entry entry, const char* name, unsigned int value); + + int interactive_batch_add_param_bool(interactive_batch batch, interactive_batch_entry entry, const char* name, bool value); + + int interactive_batch_add_param_object(interactive_batch batch, interactive_batch_entry entry, const char* name, interactive_batch_object_callback callback); + + int interactive_batch_add_param_array(interactive_batch batch, interactive_batch_entry entry, const char* name, interactive_batch_array_callback callback); + + int interactive_batch_array_push_null(interactive_batch batch, interactive_batch_array arrayItem); + + int interactive_batch_array_push_str(interactive_batch batch, interactive_batch_array arrayItem, const char* value); + + int interactive_batch_array_push_uint(interactive_batch batch, interactive_batch_array arrayItem, unsigned int value); + + int interactive_batch_array_push_bool(interactive_batch batch, interactive_batch_array arrayItem, bool value); + + int interactive_batch_array_push_object(interactive_batch batch, interactive_batch_array arrayItem, interactive_batch_object_callback callback); + + int interactive_batch_array_push_array(interactive_batch batch, interactive_batch_array arrayItem, interactive_batch_array_callback callback); + + /** @} */ + /** @name Controls * @{ */ @@ -286,6 +329,12 @@ extern "C" { /// Get a char* meta property value by name. /// int interactive_control_get_meta_property_string(interactive_session session, const char* controlId, const char* key, char* property, size_t* propertyLength); + + int interactive_control_batch_begin(interactive_session session, interactive_batch* batchPtr, const char* sceneId); + + int interactive_control_batch_add(interactive_batch batch, interactive_batch_entry* entry, const char* controlId); + + int interactive_control_batch_end(interactive_batch batch); /** @} */ /** @name Groups @@ -531,6 +580,17 @@ extern "C" { /// Get the participant's group name. /// int interactive_participant_get_group(interactive_session session, const char* participantId, char* group, size_t* groupLength); + + int interactive_participant_batch_begin(interactive_session session, interactive_batch* batchPtr); + + int interactive_participant_batch_add(interactive_batch batch, interactive_batch_entry* entry, const char* participantId); + + int interactive_participant_batch_end(interactive_batch batch); + + /// + /// Reads a string value from the participant object. + /// + int interactive_participant_get_param_string(interactive_session session, const char * participantId, const char *paramName, char* value, size_t* valueLength); /** @} */ /** @name Manual Protocol Integration diff --git a/source/internal/interactive_batch.cpp b/source/internal/interactive_batch.cpp new file mode 100644 index 0000000..cbb2b0c --- /dev/null +++ b/source/internal/interactive_batch.cpp @@ -0,0 +1,275 @@ +#include "interactive_batch.h" +#include "interactive_session.h" +#include "common.h" + +#include + +namespace mixer_internal +{ + +interactive_batch_entry_internal::interactive_batch_entry_internal() + : next(nullptr), value(rapidjson::kObjectType) +{ +} + +interactive_batch_array_internal::interactive_batch_array_internal() + : value(rapidjson::kArrayType) +{ +} + +int interactive_batch_begin(interactive_session session, interactive_batch* batchPtr, char *methodName, on_get_batch_params getParams) +{ + if (nullptr == session || nullptr == batchPtr || nullptr == methodName || nullptr == getParams) + { + return MIXER_ERROR_INVALID_POINTER; + } + + std::auto_ptr batchInternal(new interactive_batch_internal()); + batchInternal->session = reinterpret_cast(session); + batchInternal->priority = RPC_PRIORITY_DEFAULT; + batchInternal->method = methodName; + batchInternal->getParams = getParams; + batchInternal->firstEntry = nullptr; + batchInternal->lastEntry = nullptr; + batchInternal->document = std::make_shared(); + *batchPtr = reinterpret_cast(batchInternal.release()); + + return MIXER_OK; +} + +int interactive_batch_add_entry(interactive_batch batch, interactive_batch_entry* entry) +{ + if (nullptr == batch || nullptr == entry) + { + return MIXER_ERROR_INVALID_POINTER; + } + + interactive_batch_internal* batchInternal = reinterpret_cast(batch); + interactive_batch_entry_internal* entryInternal = new interactive_batch_entry_internal(); + if (nullptr == batchInternal->firstEntry) + { + batchInternal->firstEntry = entryInternal; + batchInternal->lastEntry = entryInternal; + } + else + { + batchInternal->lastEntry->next = entryInternal; + batchInternal->lastEntry = entryInternal; + } + + *entry = reinterpret_cast(entryInternal); + + return MIXER_OK; +} + +int interactive_batch_iterate_entries(interactive_batch_internal* batch, on_get_entry_params getParams) +{ + if (nullptr == getParams) + { + return MIXER_ERROR_INVALID_POINTER; + } + + interactive_batch_entry_internal* freePtr = nullptr; + interactive_batch_entry_internal* next = batch->firstEntry; + while (nullptr != next) { + getParams(next); + freePtr = next; + next = next->next; + delete freePtr; + } + + batch->firstEntry = nullptr; + batch->lastEntry = nullptr; + + return MIXER_OK; +} + +int interactive_batch_free(interactive_batch_internal* batch) +{ + if (nullptr == batch) + { + return MIXER_ERROR_INVALID_POINTER; + } + + interactive_batch_entry_internal* freePtr = nullptr; + interactive_batch_entry_internal* next = batch->firstEntry; + while (nullptr != next) { + freePtr = next; + next = next->next; + delete freePtr; + } + + delete batch; + + return MIXER_OK; +} + +int interactive_batch_end(interactive_batch_internal* batch) +{ + if (nullptr == batch) + { + return MIXER_ERROR_INVALID_POINTER; + } + + int result = queue_method(*batch->session, batch->method, [&](rapidjson::Document::AllocatorType& allocator, rapidjson::Value& params) + { + params.AddMember(RPC_PRIORITY, batch->priority, allocator); + batch->getParams(batch, allocator, params); + }, nullptr, batch->document); + + interactive_batch_free(batch); + + return result; +} + +int interactive_batch_add_param(interactive_batch batch, interactive_batch_entry entry, const char* name, rapidjson::Value& value) +{ + if (nullptr == batch || nullptr == entry || nullptr == name) + { + return MIXER_ERROR_INVALID_POINTER; + } + + interactive_batch_internal* batchInternal = reinterpret_cast(batch); + interactive_batch_entry_internal* entryInternal = reinterpret_cast(entry); + entryInternal->value.AddMember( + rapidjson::Value(std::string(name), batchInternal->document->GetAllocator()), + value, + batchInternal->document->GetAllocator()); + + return MIXER_OK; +} + +int interactive_batch_array_push(interactive_batch batch, interactive_batch_array arrayItem, rapidjson::Value& value) +{ + if (nullptr == batch || nullptr == arrayItem) + { + return MIXER_ERROR_INVALID_POINTER; + } + + interactive_batch_internal* batchInternal = reinterpret_cast(batch); + interactive_batch_array_internal* arrayInternal = reinterpret_cast(arrayItem); + arrayInternal->value.PushBack(value, batchInternal->document->GetAllocator()); + + return MIXER_OK; +} + +} + +using namespace mixer_internal; + +int interactive_batch_set_priority(interactive_batch batch, int priority) +{ + if (nullptr == batch) + { + return MIXER_ERROR_INVALID_POINTER; + } + + interactive_batch_internal* batchInternal = reinterpret_cast(batch); + batchInternal->priority = priority; + return MIXER_OK; +} + +int interactive_batch_add_param_null(interactive_batch batch, interactive_batch_entry entry, const char* name) +{ + return interactive_batch_add_param(batch, entry, name, rapidjson::Value(rapidjson::kNullType)); +} + +int interactive_batch_add_param_str(interactive_batch batch, interactive_batch_entry entry, const char* name, const char* value) +{ + if (nullptr == value) + { + return MIXER_ERROR_INVALID_POINTER; + } + + interactive_batch_internal* batchInternal = reinterpret_cast(batch); + return interactive_batch_add_param(batch, entry, name, rapidjson::Value(std::string(value), batchInternal->document->GetAllocator())); +} + +int interactive_batch_add_param_uint(interactive_batch batch, interactive_batch_entry entry, const char* name, unsigned int value) +{ + return interactive_batch_add_param(batch, entry, name, rapidjson::Value(value)); +} + +int interactive_batch_add_param_bool(interactive_batch batch, interactive_batch_entry entry, const char* name, bool value) +{ + return interactive_batch_add_param(batch, entry, name, rapidjson::Value(value)); +} + +int interactive_batch_add_param_object(interactive_batch batch, interactive_batch_entry entry, const char* name, interactive_batch_object_callback callback) +{ + if (nullptr == batch || nullptr == entry) + { + return MIXER_ERROR_INVALID_POINTER; + } + + std::auto_ptr tempEntry(new interactive_batch_entry_internal()); + callback(batch, reinterpret_cast(tempEntry.get())); + + return interactive_batch_add_param(batch, entry, name, tempEntry->value); +} + +int interactive_batch_add_param_array(interactive_batch batch, interactive_batch_entry entry, const char* name, interactive_batch_array_callback callback) +{ + if (nullptr == batch || nullptr == entry) + { + return MIXER_ERROR_INVALID_POINTER; + } + + std::auto_ptr tempArray(new interactive_batch_array_internal()); + tempArray->value.SetArray(); + callback(batch, reinterpret_cast(tempArray.get())); + + return interactive_batch_add_param(batch, entry, name, tempArray->value); +} + +int interactive_batch_array_push_null(interactive_batch batch, interactive_batch_array arrayItem) +{ + return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(rapidjson::kNullType)); +} + +int interactive_batch_array_push_str(interactive_batch batch, interactive_batch_array arrayItem, const char* value) +{ + if (nullptr == value) + { + return MIXER_ERROR_INVALID_POINTER; + } + + interactive_batch_internal* batchInternal = reinterpret_cast(batch); + return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(std::string(value), batchInternal->document->GetAllocator())); +} + +int interactive_batch_array_push_uint(interactive_batch batch, interactive_batch_array arrayItem, unsigned int value) +{ + return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(value)); +} + +int interactive_batch_array_push_bool(interactive_batch batch, interactive_batch_array arrayItem, bool value) +{ + return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(value)); +} + +int interactive_batch_array_push_object(interactive_batch batch, interactive_batch_array arrayItem, interactive_batch_object_callback callback) +{ + if (nullptr == batch || nullptr == arrayItem) + { + return MIXER_ERROR_INVALID_POINTER; + } + + std::auto_ptr tempEntry(new interactive_batch_entry_internal()); + callback(batch, reinterpret_cast(tempEntry.get())); + + return interactive_batch_array_push(batch, arrayItem, tempEntry->value); +} + +int interactive_batch_array_push_array(interactive_batch batch, interactive_batch_array arrayItem, interactive_batch_array_callback callback) +{ + if (nullptr == batch || nullptr == arrayItem) + { + return MIXER_ERROR_INVALID_POINTER; + } + + std::auto_ptr tempArray(new interactive_batch_array_internal()); + callback(batch, reinterpret_cast(tempArray.get())); + + return interactive_batch_array_push(batch, arrayItem, tempArray->value); +} diff --git a/source/internal/interactive_batch.h b/source/internal/interactive_batch.h new file mode 100644 index 0000000..88c76de --- /dev/null +++ b/source/internal/interactive_batch.h @@ -0,0 +1,50 @@ +#pragma once +#include "interactivity.h" +#include "interactive_session.h" +#include "rapidjson\document.h" +#include + +namespace mixer_internal +{ + +struct interactive_batch_internal; +struct interactive_batch_entry_internal; +typedef std::function on_get_entry_params; +typedef std::function on_get_batch_params; + +struct interactive_batch_internal +{ + interactive_session_internal* session; + const char* method; + int priority; + on_get_batch_params getParams; + std::shared_ptr document; + interactive_batch_entry_internal* firstEntry; + interactive_batch_entry_internal* lastEntry; + const char *param; +}; + +struct interactive_batch_entry_internal +{ + interactive_batch_entry_internal(); + + interactive_batch_entry_internal* next; + rapidjson::Value value; +}; + +struct interactive_batch_array_internal +{ + interactive_batch_array_internal(); + + rapidjson::Value value; +}; + +int interactive_batch_begin(interactive_session session, interactive_batch* batchPtr, char *methodName, on_get_batch_params getParams); +int interactive_batch_add_entry(interactive_batch batch, interactive_batch_entry* entry); +int interactive_batch_iterate_entries(interactive_batch_internal* batch, on_get_entry_params getParams); +int interactive_batch_free(interactive_batch_internal* batch); +int interactive_batch_end(interactive_batch_internal* batch); +int interactive_batch_add_param(interactive_batch batch, interactive_batch_entry entry, char* name, rapidjson::Value& value); +int interactive_batch_array_push(interactive_batch batch, interactive_batch_array arrayItem, rapidjson::Value& value); + +} \ No newline at end of file diff --git a/source/internal/interactive_control.cpp b/source/internal/interactive_control.cpp index e63e7d6..caf1cae 100644 --- a/source/internal/interactive_control.cpp +++ b/source/internal/interactive_control.cpp @@ -1,4 +1,5 @@ #include "interactive_session.h" +#include "interactive_batch.h" #include "common.h" namespace mixer_internal @@ -538,4 +539,54 @@ int interactive_control_get_meta_property_string(interactive_session session, co property[*propertyLength - 1] = '\0'; return MIXER_OK; +} + +void interactive_control_batch_get_params(interactive_batch_internal* batchInternal, rapidjson::Document::AllocatorType& allocator, rapidjson::Value& params) +{ + rapidjson::Value controls(rapidjson::kArrayType); + interactive_batch_iterate_entries(batchInternal, [&](interactive_batch_entry_internal* entry) + { + controls.PushBack(entry->value, allocator); + }); + params.AddMember(RPC_PARAM_CONTROLS, controls, allocator); + params.AddMember(RPC_SCENE_ID, std::string(batchInternal->param), allocator); +} + +int interactive_control_batch_begin(interactive_session session, interactive_batch* batchPtr, const char* sceneId) +{ + if (nullptr == session || nullptr == batchPtr) + { + return MIXER_ERROR_INVALID_POINTER; + } + + RETURN_IF_FAILED(interactive_batch_begin(session, batchPtr, RPC_METHOD_UPDATE_CONTROLS, interactive_control_batch_get_params)); + + interactive_batch_internal* batchInternal = reinterpret_cast(*batchPtr); + batchInternal->param = sceneId; + + return MIXER_OK; +} + +int interactive_control_batch_add(interactive_batch batch, interactive_batch_entry* entry, const char* controlId) +{ + if (nullptr == batch) { + return MIXER_ERROR_INVALID_POINTER; + } + + RETURN_IF_FAILED(interactive_batch_add_entry(batch, entry)); + + RETURN_IF_FAILED(interactive_batch_add_param_str(batch, *entry, RPC_CONTROL_ID, controlId)); + + return MIXER_OK; +} + +int interactive_control_batch_end(interactive_batch batch) +{ + if (nullptr == batch) + { + return MIXER_ERROR_INVALID_POINTER; + } + + interactive_batch_internal* batchInternal = reinterpret_cast(batch); + return interactive_batch_end(batchInternal); } \ No newline at end of file diff --git a/source/internal/interactive_participant.cpp b/source/internal/interactive_participant.cpp index a4c4a42..ba2b259 100644 --- a/source/internal/interactive_participant.cpp +++ b/source/internal/interactive_participant.cpp @@ -1,4 +1,5 @@ #include "interactive_session.h" +#include "interactive_batch.h" #include "common.h" namespace mixer_internal @@ -262,4 +263,77 @@ int interactive_participant_get_group(interactive_session session, const char* p group[actualLength] = 0; *groupLength = actualLength + 1; return MIXER_OK; +} + +int interactive_participant_batch_begin(interactive_session session, interactive_batch* batchPtr) +{ + if (nullptr == session || nullptr == batchPtr) + { + return MIXER_ERROR_INVALID_POINTER; + } + + return interactive_batch_begin(session, batchPtr, RPC_METHOD_UPDATE_PARTICIPANTS, [](interactive_batch_internal* batchInternal, rapidjson::Document::AllocatorType& allocator, rapidjson::Value& params) + { + rapidjson::Value participants(rapidjson::kArrayType); + interactive_batch_iterate_entries(batchInternal, [&](interactive_batch_entry_internal* entry) + { + participants.PushBack(entry->value, allocator); + }); + params.AddMember(RPC_PARAM_PARTICIPANTS, participants, allocator); + }); +} + +int interactive_participant_batch_add(interactive_batch batch, interactive_batch_entry* entry, const char* participantId) +{ + RETURN_IF_FAILED(interactive_batch_add_entry(batch, entry)); + + RETURN_IF_FAILED(interactive_batch_add_param_str(batch, *entry, RPC_SESSION_ID, participantId)); + + return MIXER_OK; +} + +int interactive_participant_batch_end(interactive_batch batch) +{ + if (nullptr == batch) + { + return MIXER_ERROR_INVALID_POINTER; + } + + interactive_batch_internal* batchInternal = reinterpret_cast(batch); + return interactive_batch_end(batchInternal); +} + +int interactive_participant_get_param_string(interactive_session session, const char * participantId, const char *paramName, char* value, size_t* valueLength) +{ + if (nullptr == session || nullptr == participantId || nullptr == valueLength) + { + return MIXER_ERROR_INVALID_POINTER; + } + + interactive_session_internal* sessionInternal = reinterpret_cast(session); + // Validate connection state. + if (interactive_disconnected == sessionInternal->state) + { + return MIXER_ERROR_NOT_CONNECTED; + } + + auto participantItr = sessionInternal->participants.find(std::string(participantId)); + if (sessionInternal->participants.end() == participantItr) + { + return MIXER_ERROR_OBJECT_NOT_FOUND; + } + + std::shared_ptr participantDoc = participantItr->second; + + size_t actualLength = (*participantDoc)[paramName].GetStringLength(); + if (nullptr == value || *valueLength < actualLength + 1) + { + *valueLength = actualLength + 1; + return MIXER_ERROR_BUFFER_SIZE; + } + + memcpy(value, (*participantDoc)[paramName].GetString(), actualLength); + value[actualLength] = 0; + *valueLength = actualLength + 1; + return MIXER_OK; } \ No newline at end of file diff --git a/source/internal/interactive_session.cpp b/source/internal/interactive_session.cpp index daa5be3..2637a15 100644 --- a/source/internal/interactive_session.cpp +++ b/source/internal/interactive_session.cpp @@ -10,8 +10,11 @@ typedef std::function& methodDoc) { - std::shared_ptr doc(std::make_shared()); - doc->SetObject(); + std::shared_ptr doc(nullptr == methodDoc ? std::make_shared() : methodDoc); + if (!doc->IsObject()) { + doc->SetObject(); + } + rapidjson::Document::AllocatorType& allocator = doc->GetAllocator(); unsigned int packetID = session.packetId++; @@ -52,6 +55,12 @@ int send_method(interactive_session_internal& session, const std::string& method int queue_method(interactive_session_internal& session, const std::string& method, on_get_params getParams, method_handler onReply) { std::shared_ptr methodDoc; + return queue_method(session, method, getParams, onReply, methodDoc); +} + +int queue_method(interactive_session_internal& session, const std::string& method, on_get_params getParams, method_handler onReply, std::shared_ptr& methodDoc) +{ + std::shared_ptr doc(methodDoc); unsigned int packetId = 0; RETURN_IF_FAILED(create_method_json(session, method, getParams, nullptr == onReply, &packetId, methodDoc)); DEBUG_TRACE(std::string("Queueing method: ") + jsonStringify(*methodDoc)); diff --git a/source/internal/interactive_session.h b/source/internal/interactive_session.h index 308ce6a..e532183 100644 --- a/source/internal/interactive_session.h +++ b/source/internal/interactive_session.h @@ -127,6 +127,7 @@ typedef std::function& methodDoc); int receive_reply(interactive_session_internal& session, unsigned int id, std::shared_ptr& replyPtr, unsigned int timeoutMs = 5000); int cache_groups(interactive_session_internal& session); @@ -157,6 +158,8 @@ int check_reply_errors(interactive_session_internal& session, rapidjson::Documen #define RPC_ERROR_PATH "path" #define RPC_DISABLED "disabled" #define RPC_SEQUENCE "seq" +#define RPC_PRIORITY "priority" +#define RPC_PRIORITY_DEFAULT 0 // RPC methods and replies #define RPC_METHOD_HELLO "hello" From a8902534d6d98bb619d4d3e4181b76df2da71cb1 Mon Sep 17 00:00:00 2001 From: Mike Blouin Date: Fri, 15 Jun 2018 13:54:34 -0700 Subject: [PATCH 2/8] feat(batch): Control tests and build fixes Fix build issues and warnings and have working tests for control updates --- Tests/Tests.cpp | 53 ++++++++++++------- .../Interactivity.UWP.Cpp.vcxproj | 7 ++- .../Interactivity.Win32.Cpp.vcxproj | 7 ++- .../Interactivity.Win32.Cpp.vcxproj.filters | 4 +- .../Interactivity.Xbox.Cpp.vcxproj | 5 +- source/interactivity.h | 4 +- source/internal/interactive_batch.cpp | 18 +++---- source/internal/interactive_control.cpp | 2 +- source/internal/interactive_participant.cpp | 2 +- source/internal/interactive_session.cpp | 1 - 10 files changed, 66 insertions(+), 37 deletions(-) diff --git a/Tests/Tests.cpp b/Tests/Tests.cpp index dc425f0..4e92764 100644 --- a/Tests/Tests.cpp +++ b/Tests/Tests.cpp @@ -982,7 +982,7 @@ TEST_CLASS(Tests) Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(batch, objectEntry, "foo", "bar")); Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(batch, objectEntry, "number", 42)); })); - Assert::AreEqual((int)MIXER_OK, interactive_control_batch_end(batch)); + Assert::AreEqual((int)MIXER_OK, interactive_control_batch_commit(batch)); // Simulate 60 frames/sec for 1 second. for (int i = 0; i < fps * seconds; ++i) @@ -991,26 +991,41 @@ TEST_CLASS(Tests) std::this_thread::sleep_for(std::chrono::milliseconds(1000 / fps)); } - Logger::WriteMessage("Enumerating scenes."); + Logger::WriteMessage("Validating custom properties"); ASSERT_NOERR(interactive_get_scenes(session, [](void* context, interactive_session session, interactive_scene* scene) { - std::stringstream s; - s << "[Scene] '" << std::string(scene->id, scene->idLength) << "'"; - Logger::WriteMessage(s.str().c_str()); - - Logger::WriteMessage("Controls:"); - interactive_scene_get_controls(session, scene->id, [](void* context, interactive_session session, interactive_control* control) - { - if (0 == strcmp(control->id, "GiveHealth")) { - char foo[4]; - size_t nameLength = 4; - int number; - print_control_properties(session, control->id); - Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_string(session, "GiveHealth", "foo", foo, &nameLength)); - Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_int(session, "GiveHealth", "number", &number)); - Assert::AreEqual("bar", foo); - } - }); + char foo[4]; + size_t nameLength = 4; + int number = 0; + memset(foo, 0, sizeof(char[4])); + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_string(session, "GiveHealth", "foo", foo, &nameLength)); + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_int(session, "GiveHealth", "number", &number)); + Assert::AreEqual("bar", foo); + Assert::AreEqual(42, number); + memset(foo, 0, sizeof(char[4])); + number = 0; + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_string(session, "GiveHealth", "array/0/foo", foo, &nameLength)); + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_int(session, "GiveHealth", "array/0/number", &number)); + Assert::AreEqual("bar", foo); + Assert::AreEqual(42, number); + memset(foo, 0, sizeof(char[4])); + number = 0; + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_string(session, "GiveHealth", "array/1", foo, &nameLength)); + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_int(session, "GiveHealth", "array/2", &number)); + Assert::AreEqual("bar", foo); + Assert::AreEqual(42, number); + memset(foo, 0, sizeof(char[4])); + number = 0; + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_string(session, "GiveHealth", "array/1", foo, &nameLength)); + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_int(session, "GiveHealth", "array/2", &number)); + Assert::AreEqual("bar", foo); + Assert::AreEqual(42, number); + memset(foo, 0, sizeof(char[4])); + number = 0; + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_string(session, "GiveHealth", "object/foo", foo, &nameLength)); + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_int(session, "GiveHealth", "object/number", &number)); + Assert::AreEqual("bar", foo); + Assert::AreEqual(42, number); })); for (int i = 0; i < fps * seconds; ++i) diff --git a/builds/Interactivity.UWP.Cpp/Interactivity.UWP.Cpp.vcxproj b/builds/Interactivity.UWP.Cpp/Interactivity.UWP.Cpp.vcxproj index 59e7938..e91146c 100644 --- a/builds/Interactivity.UWP.Cpp/Interactivity.UWP.Cpp.vcxproj +++ b/builds/Interactivity.UWP.Cpp/Interactivity.UWP.Cpp.vcxproj @@ -71,7 +71,12 @@ true true - + + true + true + true + true + true true diff --git a/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj b/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj index 161c8f4..b32bbe8 100644 --- a/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj +++ b/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj @@ -67,7 +67,12 @@ true true - + + true + true + true + true + true true diff --git a/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj.filters b/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj.filters index 1c79560..cdd9f77 100644 --- a/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj.filters +++ b/builds/Interactivity.Win32.Cpp/Interactivity.Win32.Cpp.vcxproj.filters @@ -45,7 +45,9 @@ C++ Source - + + C++ Source + diff --git a/builds/Interactivity.Xbox.Cpp/Interactivity.Xbox.Cpp.vcxproj b/builds/Interactivity.Xbox.Cpp/Interactivity.Xbox.Cpp.vcxproj index 05ba815..1fcdccf 100644 --- a/builds/Interactivity.Xbox.Cpp/Interactivity.Xbox.Cpp.vcxproj +++ b/builds/Interactivity.Xbox.Cpp/Interactivity.Xbox.Cpp.vcxproj @@ -65,7 +65,10 @@ true true - + + true + true + true true diff --git a/source/interactivity.h b/source/interactivity.h index 1b09c13..d1b8a1e 100644 --- a/source/interactivity.h +++ b/source/interactivity.h @@ -334,7 +334,7 @@ extern "C" { int interactive_control_batch_add(interactive_batch batch, interactive_batch_entry* entry, const char* controlId); - int interactive_control_batch_end(interactive_batch batch); + int interactive_control_batch_commit(interactive_batch batch); /** @} */ /** @name Groups @@ -585,7 +585,7 @@ extern "C" { int interactive_participant_batch_add(interactive_batch batch, interactive_batch_entry* entry, const char* participantId); - int interactive_participant_batch_end(interactive_batch batch); + int interactive_participant_batch_commit(interactive_batch batch); /// /// Reads a string value from the participant object. diff --git a/source/internal/interactive_batch.cpp b/source/internal/interactive_batch.cpp index cbb2b0c..922645f 100644 --- a/source/internal/interactive_batch.cpp +++ b/source/internal/interactive_batch.cpp @@ -132,7 +132,7 @@ int interactive_batch_add_param(interactive_batch batch, interactive_batch_entry interactive_batch_internal* batchInternal = reinterpret_cast(batch); interactive_batch_entry_internal* entryInternal = reinterpret_cast(entry); entryInternal->value.AddMember( - rapidjson::Value(std::string(name), batchInternal->document->GetAllocator()), + rapidjson::Value(std::string(name).c_str(), batchInternal->document->GetAllocator()), value, batchInternal->document->GetAllocator()); @@ -171,7 +171,7 @@ int interactive_batch_set_priority(interactive_batch batch, int priority) int interactive_batch_add_param_null(interactive_batch batch, interactive_batch_entry entry, const char* name) { - return interactive_batch_add_param(batch, entry, name, rapidjson::Value(rapidjson::kNullType)); + return interactive_batch_add_param(batch, entry, name, rapidjson::Value(rapidjson::kNullType).Move()); } int interactive_batch_add_param_str(interactive_batch batch, interactive_batch_entry entry, const char* name, const char* value) @@ -182,17 +182,17 @@ int interactive_batch_add_param_str(interactive_batch batch, interactive_batch_e } interactive_batch_internal* batchInternal = reinterpret_cast(batch); - return interactive_batch_add_param(batch, entry, name, rapidjson::Value(std::string(value), batchInternal->document->GetAllocator())); + return interactive_batch_add_param(batch, entry, name, rapidjson::Value(std::string(value).c_str(), batchInternal->document->GetAllocator()).Move()); } int interactive_batch_add_param_uint(interactive_batch batch, interactive_batch_entry entry, const char* name, unsigned int value) { - return interactive_batch_add_param(batch, entry, name, rapidjson::Value(value)); + return interactive_batch_add_param(batch, entry, name, rapidjson::Value(value).Move()); } int interactive_batch_add_param_bool(interactive_batch batch, interactive_batch_entry entry, const char* name, bool value) { - return interactive_batch_add_param(batch, entry, name, rapidjson::Value(value)); + return interactive_batch_add_param(batch, entry, name, rapidjson::Value(value).Move()); } int interactive_batch_add_param_object(interactive_batch batch, interactive_batch_entry entry, const char* name, interactive_batch_object_callback callback) @@ -224,7 +224,7 @@ int interactive_batch_add_param_array(interactive_batch batch, interactive_batch int interactive_batch_array_push_null(interactive_batch batch, interactive_batch_array arrayItem) { - return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(rapidjson::kNullType)); + return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(rapidjson::kNullType).Move()); } int interactive_batch_array_push_str(interactive_batch batch, interactive_batch_array arrayItem, const char* value) @@ -235,17 +235,17 @@ int interactive_batch_array_push_str(interactive_batch batch, interactive_batch_ } interactive_batch_internal* batchInternal = reinterpret_cast(batch); - return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(std::string(value), batchInternal->document->GetAllocator())); + return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(std::string(value).c_str(), batchInternal->document->GetAllocator()).Move()); } int interactive_batch_array_push_uint(interactive_batch batch, interactive_batch_array arrayItem, unsigned int value) { - return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(value)); + return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(value).Move()); } int interactive_batch_array_push_bool(interactive_batch batch, interactive_batch_array arrayItem, bool value) { - return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(value)); + return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(value).Move()); } int interactive_batch_array_push_object(interactive_batch batch, interactive_batch_array arrayItem, interactive_batch_object_callback callback) diff --git a/source/internal/interactive_control.cpp b/source/internal/interactive_control.cpp index caf1cae..a0be0a4 100644 --- a/source/internal/interactive_control.cpp +++ b/source/internal/interactive_control.cpp @@ -580,7 +580,7 @@ int interactive_control_batch_add(interactive_batch batch, interactive_batch_ent return MIXER_OK; } -int interactive_control_batch_end(interactive_batch batch) +int interactive_control_batch_commit(interactive_batch batch) { if (nullptr == batch) { diff --git a/source/internal/interactive_participant.cpp b/source/internal/interactive_participant.cpp index ba2b259..03aafa6 100644 --- a/source/internal/interactive_participant.cpp +++ b/source/internal/interactive_participant.cpp @@ -292,7 +292,7 @@ int interactive_participant_batch_add(interactive_batch batch, interactive_batch return MIXER_OK; } -int interactive_participant_batch_end(interactive_batch batch) +int interactive_participant_batch_commit(interactive_batch batch) { if (nullptr == batch) { diff --git a/source/internal/interactive_session.cpp b/source/internal/interactive_session.cpp index 2637a15..99ffd9c 100644 --- a/source/internal/interactive_session.cpp +++ b/source/internal/interactive_session.cpp @@ -405,7 +405,6 @@ int handle_control_changed(interactive_session_internal& session, rapidjson::Doc return MIXER_ERROR_UNRECOGNIZED_DATA_FORMAT; } - const char * sceneId = doc[RPC_PARAMS][RPC_SCENE_ID].GetString(); rapidjson::Value& controls = doc[RPC_PARAMS][RPC_PARAM_CONTROLS]; for (auto itr = controls.Begin(); itr != controls.End(); ++itr) { From 2337d46dacb92bc2621421564b7f6a5988c80a61 Mon Sep 17 00:00:00 2001 From: Mike Blouin Date: Fri, 15 Jun 2018 14:23:41 -0700 Subject: [PATCH 3/8] feat(batch): Comment batch method declarations --- source/interactivity.h | 108 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/source/interactivity.h b/source/interactivity.h index d1b8a1e..74ad8f4 100644 --- a/source/interactivity.h +++ b/source/interactivity.h @@ -176,8 +176,19 @@ extern "C" { /** @name Batch Requests * @{ */ + /// + /// Opaque handle for a batch update object + /// struct interactive_batch_public {}; + + /// + /// Opqaque handle for a batch entry object + /// struct interactive_batch_entry_public {}; + + /// + /// Opqaque handle for a batch entry array + /// struct interactive_batch_array_public {}; typedef interactive_batch_public* interactive_batch; @@ -190,28 +201,93 @@ extern "C" { typedef void(*interactive_batch_array_callback)(interactive_batch, interactive_batch_array); + /// + /// Nullifies a field on a batch update object. + /// + /// The Mixer interactive protocol implements the JSON Merge Patch algorithm (RFC 7386) for updates on protocol objects - meaning that to delete an object property you need to set it to null rather than just omit it in an update. + /// + /// int interactive_batch_add_param_null(interactive_batch batch, interactive_batch_entry entry, const char* name); + /// + /// Adds a string field on a batch update object. + /// int interactive_batch_add_param_str(interactive_batch batch, interactive_batch_entry entry, const char* name, const char* value); + /// + /// Adds a uint field on a batch update object. + /// int interactive_batch_add_param_uint(interactive_batch batch, interactive_batch_entry entry, const char* name, unsigned int value); + /// + /// Adds a bool field on a batch update object. + /// int interactive_batch_add_param_bool(interactive_batch batch, interactive_batch_entry entry, const char* name, bool value); + /// + /// Adds an object field on a batch update object. + /// + /// Object properties must be added before the supplied callback returns using the `interactive_batch_add_param_*` family of methods. + /// + /// int interactive_batch_add_param_object(interactive_batch batch, interactive_batch_entry entry, const char* name, interactive_batch_object_callback callback); + /// + /// Adds an array field on a batch update object. + /// + /// Array items must be added before the supplied callback returns using the `interactive_batch_array_push_*` family of methods. + /// + /// int interactive_batch_add_param_array(interactive_batch batch, interactive_batch_entry entry, const char* name, interactive_batch_array_callback callback); + /// + /// Pushes a null item to a batch update array. + /// + /// Must be called within the callback from `interactive_batch_add_param_array` or `interactive_batch_array_push_object`. + /// + /// int interactive_batch_array_push_null(interactive_batch batch, interactive_batch_array arrayItem); + /// + /// Pushes a string item to a batch update array. + /// + /// Must be called within the callback from `interactive_batch_add_param_array` or `interactive_batch_array_push_object`. + /// + /// int interactive_batch_array_push_str(interactive_batch batch, interactive_batch_array arrayItem, const char* value); + /// + /// Pushes a uint item to a batch update array. + /// + /// Must be called within the callback from `interactive_batch_add_param_array` or `interactive_batch_array_push_object`. + /// + /// int interactive_batch_array_push_uint(interactive_batch batch, interactive_batch_array arrayItem, unsigned int value); + /// + /// Pushes a bool item to a batch update array. + /// + /// Must be called within the callback from `interactive_batch_add_param_array` or `interactive_batch_array_push_object`. + /// + /// int interactive_batch_array_push_bool(interactive_batch batch, interactive_batch_array arrayItem, bool value); + /// + /// Pushes an object on to a batch update array. + /// + /// Must be called within the callback from `interactive_batch_add_param_array` or `interactive_batch_array_push_object`. + /// Object properties must be added before the supplied callback returns using the `interactive_batch_add_param_*` family of methods. + /// + /// int interactive_batch_array_push_object(interactive_batch batch, interactive_batch_array arrayItem, interactive_batch_object_callback callback); + /// + /// Pushes an array on to a batch update array. + /// + /// Must be called within the callback from `interactive_batch_add_param_array` or `interactive_batch_array_push_object`. + /// Array items must be added before the supplied callback returns using the `interactive_batch_array_push_*` family of methods. + /// + /// int interactive_batch_array_push_array(interactive_batch batch, interactive_batch_array arrayItem, interactive_batch_array_callback callback); /** @} */ @@ -330,10 +406,26 @@ extern "C" { /// int interactive_control_get_meta_property_string(interactive_session session, const char* controlId, const char* key, char* property, size_t* propertyLength); + /// + /// Starts a batch update of interactive control objects. + /// + /// Note that batch requests created with this method will only support updates to control objects. + /// Batch requests are finalized with the `interactive_control_batch_commit` method after using `interactive_control_batch_add` to add the individual updates. + /// + /// int interactive_control_batch_begin(interactive_session session, interactive_batch* batchPtr, const char* sceneId); + /// + /// Adds an update to the control batch request for the control with the given id. + /// + /// Note that a batch request should only contain a single entry per control ID. + /// + /// int interactive_control_batch_add(interactive_batch batch, interactive_batch_entry* entry, const char* controlId); + /// + /// Commits an interactive control batch update against the interactive service. + /// int interactive_control_batch_commit(interactive_batch batch); /** @} */ @@ -581,10 +673,26 @@ extern "C" { /// int interactive_participant_get_group(interactive_session session, const char* participantId, char* group, size_t* groupLength); + /// + /// Starts a batch update of participant objects. + /// + /// Note that batch requests created with this method will only support updates to participant objects. + /// Batch requests are finalized with the `interactive_participant_batch_commit` method after using `interactive_participant_batch_add` to add the individual updates. + /// + /// int interactive_participant_batch_begin(interactive_session session, interactive_batch* batchPtr); + /// + /// Adds an update to the participant batch request for the participant with the given id. + /// + /// Note that a batch request should only contain a single entry per participant ID. + /// + /// int interactive_participant_batch_add(interactive_batch batch, interactive_batch_entry* entry, const char* participantId); + /// + /// Commits an interactive participant batch update against the interactive service. + /// int interactive_participant_batch_commit(interactive_batch batch); /// From dd2cec33fee8068ee4d3a3c09b84785ea2ff7976 Mon Sep 17 00:00:00 2001 From: Mobius5150 Date: Sat, 14 Jul 2018 14:45:01 -0700 Subject: [PATCH 4/8] feat(batch): Batch implementation w/o callback --- Tests/Tests.cpp | 97 +++++-- source/interactivity.h | 66 +++-- source/internal/interactive_batch.cpp | 276 ++++++++++++-------- source/internal/interactive_batch.h | 42 +-- source/internal/interactive_control.cpp | 31 +-- source/internal/interactive_participant.cpp | 24 +- source/internal/interactive_session.cpp | 42 ++- source/internal/interactive_session.h | 1 + 8 files changed, 336 insertions(+), 243 deletions(-) diff --git a/Tests/Tests.cpp b/Tests/Tests.cpp index 4e92764..f25a223 100644 --- a/Tests/Tests.cpp +++ b/Tests/Tests.cpp @@ -542,7 +542,6 @@ TEST_CLASS(Tests) ASSERT_NOERR(do_auth(clientId, "", auth)); - interactive_session session; Logger::WriteMessage("Connecting..."); ASSERT_NOERR(interactive_open_session(&session)); ASSERT_NOERR(interactive_set_error_handler(session, handle_error_assert)); @@ -559,6 +558,7 @@ TEST_CLASS(Tests) Logger::WriteMessage("Disconnecting..."); interactive_close_session(session); + session = nullptr; Assert::IsTrue(0 == err); } @@ -577,7 +577,6 @@ TEST_CLASS(Tests) ASSERT_NOERR(do_auth(clientId, clientSecret, auth)); - interactive_session session; Logger::WriteMessage("Connecting..."); ASSERT_NOERR(interactive_open_session(&session)); ASSERT_NOERR(interactive_set_error_handler(session, handle_error_assert)); @@ -594,6 +593,7 @@ TEST_CLASS(Tests) Logger::WriteMessage("Disconnecting..."); interactive_close_session(session); + session = nullptr; Assert::IsTrue(0 == err); } @@ -611,7 +611,6 @@ TEST_CLASS(Tests) ASSERT_NOERR(do_auth(clientId, "", auth)); - interactive_session session; ASSERT_NOERR(interactive_open_session(&session)); ASSERT_NOERR(interactive_set_error_handler(session, handle_error_assert)); ASSERT_NOERR(interactive_set_input_handler(session, handle_input)); @@ -637,6 +636,7 @@ TEST_CLASS(Tests) Logger::WriteMessage("Disconnecting..."); interactive_close_session(session); + session = nullptr; Assert::IsTrue(0 == err); } @@ -654,7 +654,6 @@ TEST_CLASS(Tests) ASSERT_NOERR(do_auth(clientId, "", auth)); - interactive_session session; ASSERT_NOERR(interactive_open_session(&session)); ASSERT_NOERR(interactive_set_error_handler(session, handle_error_assert)); interactive_set_state_changed_handler(session, [](void* context, interactive_session session, interactive_state prevState, interactive_state newState) @@ -691,6 +690,7 @@ TEST_CLASS(Tests) Logger::WriteMessage("Disconnecting..."); interactive_close_session(session); + session = nullptr; Assert::IsTrue(0 == err); } @@ -708,7 +708,6 @@ TEST_CLASS(Tests) ASSERT_NOERR(do_auth(clientId, "", auth)); - interactive_session session; Logger::WriteMessage("Connecting..."); ASSERT_NOERR(interactive_open_session(&session)); ASSERT_NOERR(interactive_set_error_handler(session, handle_error_assert)); @@ -795,6 +794,7 @@ TEST_CLASS(Tests) Logger::WriteMessage("Disconnecting..."); interactive_close_session(session); + session = nullptr; Assert::IsTrue(0 == err); } @@ -812,7 +812,6 @@ TEST_CLASS(Tests) ASSERT_NOERR(do_auth(clientId, "", auth)); - interactive_session session; Logger::WriteMessage("Connecting..."); ASSERT_NOERR(interactive_open_session(&session)); ASSERT_NOERR(interactive_set_error_handler(session, handle_error_assert)); @@ -857,6 +856,7 @@ TEST_CLASS(Tests) Logger::WriteMessage("Disconnecting..."); interactive_close_session(session); + session = nullptr; Assert::IsTrue(0 == err); } @@ -874,7 +874,6 @@ TEST_CLASS(Tests) ASSERT_NOERR(do_auth(clientId, "", auth)); - interactive_session session; ASSERT_NOERR(interactive_open_session(&session)); std::string controlId = "GiveHealth"; @@ -929,6 +928,7 @@ TEST_CLASS(Tests) Logger::WriteMessage("Disconnecting..."); interactive_close_session(session); + session = nullptr; } TEST_METHOD(ControlBatchTest) @@ -944,7 +944,6 @@ TEST_CLASS(Tests) ASSERT_NOERR(do_auth(clientId, "", auth)); - interactive_session session; Logger::WriteMessage("Connecting..."); ASSERT_NOERR(interactive_open_session(&session)); ASSERT_NOERR(interactive_set_error_handler(session, handle_error_assert)); @@ -965,24 +964,37 @@ TEST_CLASS(Tests) interactive_batch_entry entry; Assert::AreEqual((int)MIXER_OK, interactive_control_batch_add(batch, &entry, "GiveHealth")); - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(batch, entry, "foo", "bar")); - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(batch, entry, "number", 42)); - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_array(batch, entry, "array", [](interactive_batch batch, interactive_batch_array arrayItem) - { - Assert::AreEqual((int)MIXER_OK, interactive_batch_array_push_object(batch, arrayItem, [](interactive_batch batch, interactive_batch_entry objectEntry) - { - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(batch, objectEntry, "foo", "bar")); - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(batch, objectEntry, "number", 42)); - })); - Assert::AreEqual((int)MIXER_OK, interactive_batch_array_push_str(batch, arrayItem, "bar")); - Assert::AreEqual((int)MIXER_OK, interactive_batch_array_push_uint(batch, arrayItem, 42)); - })); - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_object(batch, entry, "object", [](interactive_batch batch, interactive_batch_entry objectEntry) - { - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(batch, objectEntry, "foo", "bar")); - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(batch, objectEntry, "number", 42)); - })); + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(&entry.obj, "foo", "bar")); + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(&entry.obj, "number", 42)); + + interactive_batch_array entryArray; + interactive_batch_add_param_array(&entry.obj, "array", &entryArray); + + interactive_batch_object entryArrayObject; + interactive_batch_array_push_object(&entryArray, &entryArrayObject); + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(&entryArrayObject, "foo", "bar")); + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(&entryArrayObject, "number", 42)); + + Assert::AreEqual((int)MIXER_OK, interactive_batch_array_push_str(&entryArray, "bar")); + Assert::AreEqual((int)MIXER_OK, interactive_batch_array_push_uint(&entryArray, 42)); + + interactive_batch_array entryArrayArray; + interactive_batch_array_push_array(&entryArray, &entryArrayArray); + + interactive_batch_object entryArrayArrayObject; + interactive_batch_array_push_object(&entryArrayArray, &entryArrayArrayObject); + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(&entryArrayArrayObject, "foo", "bar")); + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(&entryArrayArrayObject, "number", 42)); + + Assert::AreEqual((int)MIXER_OK, interactive_batch_array_push_str(&entryArrayArray, "bar")); + Assert::AreEqual((int)MIXER_OK, interactive_batch_array_push_uint(&entryArrayArray, 42)); + + interactive_batch_object entryObject; + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_object(&entry.obj, "object", &entryObject)); + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(&entryObject, "foo", "bar")); + Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(&entryObject, "number", 42)); Assert::AreEqual((int)MIXER_OK, interactive_control_batch_commit(batch)); + Assert::AreEqual((int)MIXER_OK, interactive_batch_close(batch)); // Simulate 60 frames/sec for 1 second. for (int i = 0; i < fps * seconds; ++i) @@ -1016,8 +1028,14 @@ TEST_CLASS(Tests) Assert::AreEqual(42, number); memset(foo, 0, sizeof(char[4])); number = 0; - Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_string(session, "GiveHealth", "array/1", foo, &nameLength)); - Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_int(session, "GiveHealth", "array/2", &number)); + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_string(session, "GiveHealth", "array/3/0/foo", foo, &nameLength)); + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_int(session, "GiveHealth", "array/3/0/number", &number)); + Assert::AreEqual("bar", foo); + Assert::AreEqual(42, number); + memset(foo, 0, sizeof(char[4])); + number = 0; + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_string(session, "GiveHealth", "array/3/1", foo, &nameLength)); + Assert::AreEqual((int)MIXER_OK, interactive_control_get_property_int(session, "GiveHealth", "array/3/2", &number)); Assert::AreEqual("bar", foo); Assert::AreEqual(42, number); memset(foo, 0, sizeof(char[4])); @@ -1036,9 +1054,34 @@ TEST_CLASS(Tests) Logger::WriteMessage("Disconnecting..."); interactive_close_session(session); + session = nullptr; Assert::IsTrue(0 == err); } + TEST_METHOD_CLEANUP(CleanupSession) { + if (nullptr != session) + { + try { + Logger::WriteMessage("Disconnecting in cleanup..."); + interactive_close_session(session); + } + catch (std::exception e) { + Logger::WriteMessage((std::string("Error in cleanup handler: ") + e.what()).c_str()); + } + catch (std::string e) { + Logger::WriteMessage(("Error in cleanup handler: " + e).c_str()); + } + catch (...) + { + Logger::WriteMessage("Unknown error in cleanup handler. You should debug this."); + } + } + + session = nullptr; + } + +private: + interactive_session session = nullptr; }; } \ No newline at end of file diff --git a/source/interactivity.h b/source/interactivity.h index 74ad8f4..dd1b68b 100644 --- a/source/interactivity.h +++ b/source/interactivity.h @@ -181,25 +181,38 @@ extern "C" { /// struct interactive_batch_public {}; + typedef interactive_batch_public* interactive_batch; + /// - /// Opqaque handle for a batch entry object + /// Opaque handle for a batch object /// - struct interactive_batch_entry_public {}; + struct interactive_batch_object + { + void* _a; + void* _b; + }; /// - /// Opqaque handle for a batch entry array + /// Opaque handle for a batch array /// - struct interactive_batch_array_public {}; - - typedef interactive_batch_public* interactive_batch; - - typedef interactive_batch_entry_public* interactive_batch_entry; - - typedef interactive_batch_array_public* interactive_batch_array; + struct interactive_batch_array + { + void* _a; + void* _b; + }; - typedef void(*interactive_batch_object_callback)(interactive_batch, interactive_batch_entry); + /// + /// Handle for a batch entry + /// + struct interactive_batch_entry + { + interactive_batch_object obj; + }; - typedef void(*interactive_batch_array_callback)(interactive_batch, interactive_batch_array); + /// + /// Closes an interactive batch request. Should be called after committing or aborting a batch request to free memory. + /// + int interactive_batch_close(interactive_batch batch); /// /// Nullifies a field on a batch update object. @@ -207,22 +220,22 @@ extern "C" { /// The Mixer interactive protocol implements the JSON Merge Patch algorithm (RFC 7386) for updates on protocol objects - meaning that to delete an object property you need to set it to null rather than just omit it in an update. /// /// - int interactive_batch_add_param_null(interactive_batch batch, interactive_batch_entry entry, const char* name); + int interactive_batch_add_param_null(interactive_batch_object* obj, const char* name); /// /// Adds a string field on a batch update object. /// - int interactive_batch_add_param_str(interactive_batch batch, interactive_batch_entry entry, const char* name, const char* value); + int interactive_batch_add_param_str(interactive_batch_object* obj, const char* name, const char* value); /// /// Adds a uint field on a batch update object. /// - int interactive_batch_add_param_uint(interactive_batch batch, interactive_batch_entry entry, const char* name, unsigned int value); + int interactive_batch_add_param_uint(interactive_batch_object* obj, const char* name, unsigned int value); /// /// Adds a bool field on a batch update object. /// - int interactive_batch_add_param_bool(interactive_batch batch, interactive_batch_entry entry, const char* name, bool value); + int interactive_batch_add_param_bool(interactive_batch_object* obj, const char* name, bool value); /// /// Adds an object field on a batch update object. @@ -230,7 +243,7 @@ extern "C" { /// Object properties must be added before the supplied callback returns using the `interactive_batch_add_param_*` family of methods. /// /// - int interactive_batch_add_param_object(interactive_batch batch, interactive_batch_entry entry, const char* name, interactive_batch_object_callback callback); + int interactive_batch_add_param_object(interactive_batch_object* obj, const char* name, interactive_batch_object* paramObj); /// /// Adds an array field on a batch update object. @@ -238,7 +251,7 @@ extern "C" { /// Array items must be added before the supplied callback returns using the `interactive_batch_array_push_*` family of methods. /// /// - int interactive_batch_add_param_array(interactive_batch batch, interactive_batch_entry entry, const char* name, interactive_batch_array_callback callback); + int interactive_batch_add_param_array(interactive_batch_object* obj, const char* name, interactive_batch_array* paramArr); /// /// Pushes a null item to a batch update array. @@ -246,7 +259,7 @@ extern "C" { /// Must be called within the callback from `interactive_batch_add_param_array` or `interactive_batch_array_push_object`. /// /// - int interactive_batch_array_push_null(interactive_batch batch, interactive_batch_array arrayItem); + int interactive_batch_array_push_null(interactive_batch_array* array); /// /// Pushes a string item to a batch update array. @@ -254,7 +267,7 @@ extern "C" { /// Must be called within the callback from `interactive_batch_add_param_array` or `interactive_batch_array_push_object`. /// /// - int interactive_batch_array_push_str(interactive_batch batch, interactive_batch_array arrayItem, const char* value); + int interactive_batch_array_push_str(interactive_batch_array* array, const char* value); /// /// Pushes a uint item to a batch update array. @@ -262,7 +275,7 @@ extern "C" { /// Must be called within the callback from `interactive_batch_add_param_array` or `interactive_batch_array_push_object`. /// /// - int interactive_batch_array_push_uint(interactive_batch batch, interactive_batch_array arrayItem, unsigned int value); + int interactive_batch_array_push_uint(interactive_batch_array* array, unsigned int value); /// /// Pushes a bool item to a batch update array. @@ -270,7 +283,7 @@ extern "C" { /// Must be called within the callback from `interactive_batch_add_param_array` or `interactive_batch_array_push_object`. /// /// - int interactive_batch_array_push_bool(interactive_batch batch, interactive_batch_array arrayItem, bool value); + int interactive_batch_array_push_bool(interactive_batch_array* array, bool value); /// /// Pushes an object on to a batch update array. @@ -279,7 +292,7 @@ extern "C" { /// Object properties must be added before the supplied callback returns using the `interactive_batch_add_param_*` family of methods. /// /// - int interactive_batch_array_push_object(interactive_batch batch, interactive_batch_array arrayItem, interactive_batch_object_callback callback); + int interactive_batch_array_push_object(interactive_batch_array* array, interactive_batch_object* pushObj); /// /// Pushes an array on to a batch update array. @@ -288,7 +301,12 @@ extern "C" { /// Array items must be added before the supplied callback returns using the `interactive_batch_array_push_*` family of methods. /// /// - int interactive_batch_array_push_array(interactive_batch batch, interactive_batch_array arrayItem, interactive_batch_array_callback callback); + int interactive_batch_array_push_array(interactive_batch_array* array, interactive_batch_array* pushArr); + + /// + /// Sets the update priority of this batch update. + /// + int interactive_batch_set_priority(interactive_batch batch, int priority); /** @} */ diff --git a/source/internal/interactive_batch.cpp b/source/internal/interactive_batch.cpp index 922645f..6e0f03b 100644 --- a/source/internal/interactive_batch.cpp +++ b/source/internal/interactive_batch.cpp @@ -3,152 +3,155 @@ #include "common.h" #include +#include + +#include "rapidjson/pointer.h" + +#define OBJECT_BATCH(o) ((o)->_a) +#define OBJECT_POINTER(o) ((o)->_b) namespace mixer_internal { -interactive_batch_entry_internal::interactive_batch_entry_internal() - : next(nullptr), value(rapidjson::kObjectType) +inline interactive_batch_internal* cast_batch(interactive_batch batch) +{ + return reinterpret_cast(batch); +} + +inline interactive_batch_internal* object_get_batch(interactive_batch_object* obj) +{ + return reinterpret_cast(OBJECT_BATCH(obj)); +} + +inline rapidjson::Value* object_get_value(interactive_batch_object* obj) { + return reinterpret_cast(OBJECT_POINTER(obj)); } -interactive_batch_array_internal::interactive_batch_array_internal() - : value(rapidjson::kArrayType) +inline interactive_batch_internal* array_get_batch(interactive_batch_array* obj) { + return reinterpret_cast(OBJECT_BATCH(obj)); } -int interactive_batch_begin(interactive_session session, interactive_batch* batchPtr, char *methodName, on_get_batch_params getParams) +inline rapidjson::Value* array_get_value(interactive_batch_array* obj) { - if (nullptr == session || nullptr == batchPtr || nullptr == methodName || nullptr == getParams) + return reinterpret_cast(OBJECT_POINTER(obj)); +} + +int interactive_batch_begin(interactive_session session, interactive_batch* batchPtr, char *methodName) +{ + if (nullptr == session || nullptr == batchPtr || nullptr == methodName) { return MIXER_ERROR_INVALID_POINTER; } std::auto_ptr batchInternal(new interactive_batch_internal()); batchInternal->session = reinterpret_cast(session); - batchInternal->priority = RPC_PRIORITY_DEFAULT; batchInternal->method = methodName; - batchInternal->getParams = getParams; - batchInternal->firstEntry = nullptr; - batchInternal->lastEntry = nullptr; batchInternal->document = std::make_shared(); *batchPtr = reinterpret_cast(batchInternal.release()); + interactive_batch_set_priority(*batchPtr, RPC_PRIORITY_DEFAULT); + return MIXER_OK; } -int interactive_batch_add_entry(interactive_batch batch, interactive_batch_entry* entry) +int interactive_batch_add_entry(interactive_batch batch, interactive_batch_entry* entry, const char * paramsKey) { if (nullptr == batch || nullptr == entry) { return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batchInternal = reinterpret_cast(batch); - interactive_batch_entry_internal* entryInternal = new interactive_batch_entry_internal(); - if (nullptr == batchInternal->firstEntry) + interactive_batch_internal* batchInternal = cast_batch(batch); + std::stringstream ss; + ss << "/" << RPC_PARAMS << "/" << paramsKey; + size_t pos = batchInternal->entries.size(); + if (0 == pos) { - batchInternal->firstEntry = entryInternal; - batchInternal->lastEntry = entryInternal; - } - else - { - batchInternal->lastEntry->next = entryInternal; - batchInternal->lastEntry = entryInternal; + rapidjson::Pointer(ss.str().c_str()) + .Set(*batchInternal->document, rapidjson::Value(rapidjson::kArrayType)); } - *entry = reinterpret_cast(entryInternal); + ss << "/" << pos; + OBJECT_BATCH(&entry->obj) = batchInternal; + OBJECT_POINTER(&entry->obj) = + &rapidjson::Pointer(ss.str().c_str()) + .Set(*batchInternal->document, rapidjson::Value(rapidjson::kObjectType)); return MIXER_OK; } -int interactive_batch_iterate_entries(interactive_batch_internal* batch, on_get_entry_params getParams) +int interactive_batch_free(interactive_batch_internal* batch) { - if (nullptr == getParams) + if (nullptr == batch) { return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_entry_internal* freePtr = nullptr; - interactive_batch_entry_internal* next = batch->firstEntry; - while (nullptr != next) { - getParams(next); - freePtr = next; - next = next->next; - delete freePtr; - } - - batch->firstEntry = nullptr; - batch->lastEntry = nullptr; + delete batch; return MIXER_OK; } -int interactive_batch_free(interactive_batch_internal* batch) +int interactive_batch_commit(interactive_batch_internal* batch) { if (nullptr == batch) { return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_entry_internal* freePtr = nullptr; - interactive_batch_entry_internal* next = batch->firstEntry; - while (nullptr != next) { - freePtr = next; - next = next->next; - delete freePtr; + return queue_method_prebuilt(*batch->session, batch->method.c_str(), nullptr, batch->document); +} + +int interactive_batch_add_param(interactive_batch_internal* batch, rapidjson::Pointer& ptr, rapidjson::Value& value) +{ + if (nullptr == batch) + { + return MIXER_ERROR_INVALID_POINTER; } - delete batch; + ptr.Set(*batch->document, value); return MIXER_OK; } -int interactive_batch_end(interactive_batch_internal* batch) +int interactive_batch_add_param(interactive_batch_object* obj, const char *paramName, rapidjson::Value& value) { - if (nullptr == batch) + if (nullptr == obj || nullptr == paramName) { return MIXER_ERROR_INVALID_POINTER; } - int result = queue_method(*batch->session, batch->method, [&](rapidjson::Document::AllocatorType& allocator, rapidjson::Value& params) - { - params.AddMember(RPC_PRIORITY, batch->priority, allocator); - batch->getParams(batch, allocator, params); - }, nullptr, batch->document); - - interactive_batch_free(batch); + object_get_value(obj)->AddMember( + rapidjson::Value(std::string(paramName).c_str(), object_get_batch(obj)->document->GetAllocator()), + value, + object_get_batch(obj)->document->GetAllocator()); - return result; + return MIXER_OK; } -int interactive_batch_add_param(interactive_batch batch, interactive_batch_entry entry, const char* name, rapidjson::Value& value) +int interactive_batch_array_push(interactive_batch_array* array, rapidjson::Value& value) { - if (nullptr == batch || nullptr == entry || nullptr == name) + if (nullptr == array) { return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batchInternal = reinterpret_cast(batch); - interactive_batch_entry_internal* entryInternal = reinterpret_cast(entry); - entryInternal->value.AddMember( - rapidjson::Value(std::string(name).c_str(), batchInternal->document->GetAllocator()), - value, - batchInternal->document->GetAllocator()); + array_get_value(array)->PushBack(value, array_get_batch(array)->document->GetAllocator()); return MIXER_OK; } -int interactive_batch_array_push(interactive_batch batch, interactive_batch_array arrayItem, rapidjson::Value& value) +int interactive_batch_array_push(interactive_batch_array* array, rapidjson::Pointer& ptr, rapidjson::Value& value) { - if (nullptr == batch || nullptr == arrayItem) + if (nullptr == array) { return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batchInternal = reinterpret_cast(batch); - interactive_batch_array_internal* arrayInternal = reinterpret_cast(arrayItem); - arrayInternal->value.PushBack(value, batchInternal->document->GetAllocator()); + interactive_batch_internal* batch = array_get_batch(array); + ptr.Set(*batch->document.get(), value); return MIXER_OK; } @@ -157,6 +160,16 @@ int interactive_batch_array_push(interactive_batch batch, interactive_batch_arra using namespace mixer_internal; +int interactive_batch_close(interactive_batch batch) +{ + if (nullptr == batch) + { + return MIXER_ERROR_INVALID_POINTER; + } + + return interactive_batch_free(cast_batch(batch)); +} + int interactive_batch_set_priority(interactive_batch batch, int priority) { if (nullptr == batch) @@ -164,112 +177,157 @@ int interactive_batch_set_priority(interactive_batch batch, int priority) return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batchInternal = reinterpret_cast(batch); - batchInternal->priority = priority; + interactive_batch_internal* batchInternal = cast_batch(batch); + std::stringstream ss; + ss << "/" << RPC_PARAMS << "/" << RPC_PRIORITY; + rapidjson::Pointer(ss.str().c_str()).Set(*batchInternal->document, priority); return MIXER_OK; } -int interactive_batch_add_param_null(interactive_batch batch, interactive_batch_entry entry, const char* name) +int interactive_batch_add_param_null(interactive_batch_object* obj, const char* name) { - return interactive_batch_add_param(batch, entry, name, rapidjson::Value(rapidjson::kNullType).Move()); + return interactive_batch_add_param( + obj, + name, + rapidjson::Value(rapidjson::kNullType).Move()); } -int interactive_batch_add_param_str(interactive_batch batch, interactive_batch_entry entry, const char* name, const char* value) +int interactive_batch_add_param_str(interactive_batch_object* obj, const char* name, const char* value) { - if (nullptr == value) + if (nullptr == obj || nullptr == value) { return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batchInternal = reinterpret_cast(batch); - return interactive_batch_add_param(batch, entry, name, rapidjson::Value(std::string(value).c_str(), batchInternal->document->GetAllocator()).Move()); + interactive_batch_internal* batch = object_get_batch(obj); + if (nullptr == batch) + { + return MIXER_ERROR_INVALID_POINTER; + } + + return interactive_batch_add_param( + obj, + name, + rapidjson::Value(std::string(value).c_str(), batch->document->GetAllocator()).Move()); } -int interactive_batch_add_param_uint(interactive_batch batch, interactive_batch_entry entry, const char* name, unsigned int value) +int interactive_batch_add_param_uint(interactive_batch_object* obj, const char* name, unsigned int value) { - return interactive_batch_add_param(batch, entry, name, rapidjson::Value(value).Move()); + return interactive_batch_add_param( + obj, + name, + rapidjson::Value(value).Move()); } -int interactive_batch_add_param_bool(interactive_batch batch, interactive_batch_entry entry, const char* name, bool value) +int interactive_batch_add_param_bool(interactive_batch_object* obj, const char* name, bool value) { - return interactive_batch_add_param(batch, entry, name, rapidjson::Value(value).Move()); + return interactive_batch_add_param( + obj, + name, + rapidjson::Value(value).Move()); } -int interactive_batch_add_param_object(interactive_batch batch, interactive_batch_entry entry, const char* name, interactive_batch_object_callback callback) +int interactive_batch_add_param_object(interactive_batch_object* obj, const char* name, interactive_batch_object* paramObj) { - if (nullptr == batch || nullptr == entry) + if (nullptr == obj || nullptr == name || nullptr == paramObj) { return MIXER_ERROR_INVALID_POINTER; } - - std::auto_ptr tempEntry(new interactive_batch_entry_internal()); - callback(batch, reinterpret_cast(tempEntry.get())); - return interactive_batch_add_param(batch, entry, name, tempEntry->value); + interactive_batch_internal* batch = object_get_batch(obj); + auto jsonObj = object_get_value(obj)->GetObject(); + jsonObj.AddMember( + rapidjson::Value(std::string(name).c_str(), object_get_batch(obj)->document->GetAllocator()).Move(), + rapidjson::Value(rapidjson::kObjectType).Move(), + object_get_batch(obj)->document->GetAllocator()); + OBJECT_BATCH(paramObj) = batch; + OBJECT_POINTER(paramObj) = &jsonObj.FindMember(name)->value; + + return MIXER_OK; } -int interactive_batch_add_param_array(interactive_batch batch, interactive_batch_entry entry, const char* name, interactive_batch_array_callback callback) +int interactive_batch_add_param_array(interactive_batch_object* obj, const char* name, interactive_batch_array* paramArr) { - if (nullptr == batch || nullptr == entry) + if (nullptr == obj || nullptr == name || nullptr == paramArr) { return MIXER_ERROR_INVALID_POINTER; } - std::auto_ptr tempArray(new interactive_batch_array_internal()); - tempArray->value.SetArray(); - callback(batch, reinterpret_cast(tempArray.get())); + interactive_batch_internal* batch = object_get_batch(obj); + auto jsonObj = object_get_value(obj)->GetObject(); + jsonObj.AddMember( + rapidjson::Value(std::string(name).c_str(), object_get_batch(obj)->document->GetAllocator()).Move(), + rapidjson::Value(rapidjson::kArrayType).Move(), + object_get_batch(obj)->document->GetAllocator()); + OBJECT_BATCH(paramArr) = batch; + OBJECT_POINTER(paramArr) = &jsonObj.FindMember(name)->value; - return interactive_batch_add_param(batch, entry, name, tempArray->value); + return MIXER_OK; } -int interactive_batch_array_push_null(interactive_batch batch, interactive_batch_array arrayItem) +int interactive_batch_array_push_null(interactive_batch_array* array) { - return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(rapidjson::kNullType).Move()); + return interactive_batch_array_push(array, rapidjson::Value(rapidjson::kNullType).Move()); } -int interactive_batch_array_push_str(interactive_batch batch, interactive_batch_array arrayItem, const char* value) +int interactive_batch_array_push_str(interactive_batch_array* array, const char* value) { if (nullptr == value) { return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batchInternal = reinterpret_cast(batch); - return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(std::string(value).c_str(), batchInternal->document->GetAllocator()).Move()); + interactive_batch_internal* batch = array_get_batch(array); + if (nullptr == batch) + { + return MIXER_ERROR_INVALID_POINTER; + } + + return interactive_batch_array_push(array, rapidjson::Value(std::string(value).c_str(), batch->document->GetAllocator()).Move()); } -int interactive_batch_array_push_uint(interactive_batch batch, interactive_batch_array arrayItem, unsigned int value) +int interactive_batch_array_push_uint(interactive_batch_array* array, unsigned int value) { - return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(value).Move()); + return interactive_batch_array_push(array, rapidjson::Value(value).Move()); } -int interactive_batch_array_push_bool(interactive_batch batch, interactive_batch_array arrayItem, bool value) +int interactive_batch_array_push_bool(interactive_batch_array* array, bool value) { - return interactive_batch_array_push(batch, arrayItem, rapidjson::Value(value).Move()); + return interactive_batch_array_push(array, rapidjson::Value(value).Move()); } -int interactive_batch_array_push_object(interactive_batch batch, interactive_batch_array arrayItem, interactive_batch_object_callback callback) +int interactive_batch_array_push_object(interactive_batch_array* array, interactive_batch_object* pushObj) { - if (nullptr == batch || nullptr == arrayItem) + if (nullptr == array || nullptr == pushObj) { return MIXER_ERROR_INVALID_POINTER; } - std::auto_ptr tempEntry(new interactive_batch_entry_internal()); - callback(batch, reinterpret_cast(tempEntry.get())); + interactive_batch_internal* batch = array_get_batch(array); + auto arr = array_get_value(array)->GetArray(); + arr.PushBack( + rapidjson::Value(rapidjson::kObjectType).Move(), + array_get_batch(array)->document->GetAllocator()); + OBJECT_BATCH(pushObj) = batch; + OBJECT_POINTER(pushObj) = &arr[arr.Size() - 1]; - return interactive_batch_array_push(batch, arrayItem, tempEntry->value); + return MIXER_OK; } -int interactive_batch_array_push_array(interactive_batch batch, interactive_batch_array arrayItem, interactive_batch_array_callback callback) +int interactive_batch_array_push_array(interactive_batch_array* array, interactive_batch_array* pushArr) { - if (nullptr == batch || nullptr == arrayItem) + if (nullptr == array || nullptr == pushArr) { return MIXER_ERROR_INVALID_POINTER; } - std::auto_ptr tempArray(new interactive_batch_array_internal()); - callback(batch, reinterpret_cast(tempArray.get())); + interactive_batch_internal* batch = array_get_batch(array); + auto arr = array_get_value(array)->GetArray(); + arr.PushBack( + rapidjson::Value(rapidjson::kArrayType).Move(), + array_get_batch(array)->document->GetAllocator()); + OBJECT_BATCH(pushArr) = batch; + OBJECT_POINTER(pushArr) = &arr[arr.Size() - 1]; - return interactive_batch_array_push(batch, arrayItem, tempArray->value); + return MIXER_OK; } diff --git a/source/internal/interactive_batch.h b/source/internal/interactive_batch.h index 88c76de..9d7d902 100644 --- a/source/internal/interactive_batch.h +++ b/source/internal/interactive_batch.h @@ -2,49 +2,27 @@ #include "interactivity.h" #include "interactive_session.h" #include "rapidjson\document.h" -#include + +#include namespace mixer_internal { struct interactive_batch_internal; -struct interactive_batch_entry_internal; -typedef std::function on_get_entry_params; -typedef std::function on_get_batch_params; - struct interactive_batch_internal { interactive_session_internal* session; - const char* method; - int priority; - on_get_batch_params getParams; + std::string method; std::shared_ptr document; - interactive_batch_entry_internal* firstEntry; - interactive_batch_entry_internal* lastEntry; - const char *param; -}; - -struct interactive_batch_entry_internal -{ - interactive_batch_entry_internal(); - - interactive_batch_entry_internal* next; - rapidjson::Value value; -}; - -struct interactive_batch_array_internal -{ - interactive_batch_array_internal(); - - rapidjson::Value value; + std::list entries; }; -int interactive_batch_begin(interactive_session session, interactive_batch* batchPtr, char *methodName, on_get_batch_params getParams); -int interactive_batch_add_entry(interactive_batch batch, interactive_batch_entry* entry); -int interactive_batch_iterate_entries(interactive_batch_internal* batch, on_get_entry_params getParams); +int interactive_batch_begin(interactive_session session, interactive_batch* batchPtr, char *methodName); +int interactive_batch_add_entry(interactive_batch batch, interactive_batch_entry* entry, const char * paramsKey); int interactive_batch_free(interactive_batch_internal* batch); -int interactive_batch_end(interactive_batch_internal* batch); -int interactive_batch_add_param(interactive_batch batch, interactive_batch_entry entry, char* name, rapidjson::Value& value); -int interactive_batch_array_push(interactive_batch batch, interactive_batch_array arrayItem, rapidjson::Value& value); +int interactive_batch_commit(interactive_batch_internal* batch); +int interactive_batch_add_param(interactive_batch_internal* batch, rapidjson::Pointer& ptr, rapidjson::Value& value); +int interactive_batch_array_push(interactive_batch_array* array, rapidjson::Value& value); +int interactive_batch_array_push(interactive_batch_array* array, rapidjson::Pointer& ptr, rapidjson::Value& value); } \ No newline at end of file diff --git a/source/internal/interactive_control.cpp b/source/internal/interactive_control.cpp index a0be0a4..07b4911 100644 --- a/source/internal/interactive_control.cpp +++ b/source/internal/interactive_control.cpp @@ -2,6 +2,8 @@ #include "interactive_batch.h" #include "common.h" +#include + namespace mixer_internal { @@ -541,17 +543,6 @@ int interactive_control_get_meta_property_string(interactive_session session, co return MIXER_OK; } -void interactive_control_batch_get_params(interactive_batch_internal* batchInternal, rapidjson::Document::AllocatorType& allocator, rapidjson::Value& params) -{ - rapidjson::Value controls(rapidjson::kArrayType); - interactive_batch_iterate_entries(batchInternal, [&](interactive_batch_entry_internal* entry) - { - controls.PushBack(entry->value, allocator); - }); - params.AddMember(RPC_PARAM_CONTROLS, controls, allocator); - params.AddMember(RPC_SCENE_ID, std::string(batchInternal->param), allocator); -} - int interactive_control_batch_begin(interactive_session session, interactive_batch* batchPtr, const char* sceneId) { if (nullptr == session || nullptr == batchPtr) @@ -559,10 +550,16 @@ int interactive_control_batch_begin(interactive_session session, interactive_bat return MIXER_ERROR_INVALID_POINTER; } - RETURN_IF_FAILED(interactive_batch_begin(session, batchPtr, RPC_METHOD_UPDATE_CONTROLS, interactive_control_batch_get_params)); - + RETURN_IF_FAILED(interactive_batch_begin(session, batchPtr, RPC_METHOD_UPDATE_CONTROLS)); + interactive_batch_internal* batchInternal = reinterpret_cast(*batchPtr); - batchInternal->param = sceneId; + std::stringstream ss; + ss << "/" << RPC_PARAMS << "/" RPC_SCENE_ID; + rapidjson::Pointer ptr(ss.str().c_str()); + interactive_batch_add_param( + batchInternal, + ptr, + rapidjson::Value(std::string(sceneId).c_str(), batchInternal->document->GetAllocator()).Move()); return MIXER_OK; } @@ -573,9 +570,9 @@ int interactive_control_batch_add(interactive_batch batch, interactive_batch_ent return MIXER_ERROR_INVALID_POINTER; } - RETURN_IF_FAILED(interactive_batch_add_entry(batch, entry)); + RETURN_IF_FAILED(interactive_batch_add_entry(batch, entry, RPC_PARAM_CONTROLS)); - RETURN_IF_FAILED(interactive_batch_add_param_str(batch, *entry, RPC_CONTROL_ID, controlId)); + RETURN_IF_FAILED(interactive_batch_add_param_str(&entry->obj, RPC_CONTROL_ID, controlId)); return MIXER_OK; } @@ -588,5 +585,5 @@ int interactive_control_batch_commit(interactive_batch batch) } interactive_batch_internal* batchInternal = reinterpret_cast(batch); - return interactive_batch_end(batchInternal); + return interactive_batch_commit(batchInternal); } \ No newline at end of file diff --git a/source/internal/interactive_participant.cpp b/source/internal/interactive_participant.cpp index 03aafa6..34b2383 100644 --- a/source/internal/interactive_participant.cpp +++ b/source/internal/interactive_participant.cpp @@ -265,29 +265,11 @@ int interactive_participant_get_group(interactive_session session, const char* p return MIXER_OK; } -int interactive_participant_batch_begin(interactive_session session, interactive_batch* batchPtr) -{ - if (nullptr == session || nullptr == batchPtr) - { - return MIXER_ERROR_INVALID_POINTER; - } - - return interactive_batch_begin(session, batchPtr, RPC_METHOD_UPDATE_PARTICIPANTS, [](interactive_batch_internal* batchInternal, rapidjson::Document::AllocatorType& allocator, rapidjson::Value& params) - { - rapidjson::Value participants(rapidjson::kArrayType); - interactive_batch_iterate_entries(batchInternal, [&](interactive_batch_entry_internal* entry) - { - participants.PushBack(entry->value, allocator); - }); - params.AddMember(RPC_PARAM_PARTICIPANTS, participants, allocator); - }); -} - int interactive_participant_batch_add(interactive_batch batch, interactive_batch_entry* entry, const char* participantId) { - RETURN_IF_FAILED(interactive_batch_add_entry(batch, entry)); + RETURN_IF_FAILED(interactive_batch_add_entry(batch, entry, RPC_PARAM_PARTICIPANTS)); - RETURN_IF_FAILED(interactive_batch_add_param_str(batch, *entry, RPC_SESSION_ID, participantId)); + RETURN_IF_FAILED(interactive_batch_add_param_str(&entry->obj, RPC_SESSION_ID, participantId)); return MIXER_OK; } @@ -300,7 +282,7 @@ int interactive_participant_batch_commit(interactive_batch batch) } interactive_batch_internal* batchInternal = reinterpret_cast(batch); - return interactive_batch_end(batchInternal); + return interactive_batch_commit(batchInternal); } int interactive_participant_get_param_string(interactive_session session, const char * participantId, const char *paramName, char* value, size_t* valueLength) diff --git a/source/internal/interactive_session.cpp b/source/internal/interactive_session.cpp index 99ffd9c..3240585 100644 --- a/source/internal/interactive_session.cpp +++ b/source/internal/interactive_session.cpp @@ -8,13 +8,8 @@ namespace mixer_internal typedef std::function on_get_params; -int create_method_json(interactive_session_internal& session, const std::string& method, on_get_params getParams, bool discard, unsigned int* id, std::shared_ptr& methodDoc) +int set_packet_info(interactive_session_internal& session, const std::string& method, bool discard, unsigned int* id, std::shared_ptr& doc) { - std::shared_ptr doc(nullptr == methodDoc ? std::make_shared() : methodDoc); - if (!doc->IsObject()) { - doc->SetObject(); - } - rapidjson::Document::AllocatorType& allocator = doc->GetAllocator(); unsigned int packetID = session.packetId++; @@ -23,6 +18,23 @@ int create_method_json(interactive_session_internal& session, const std::string& doc->AddMember(RPC_DISCARD, discard, allocator); doc->AddMember(RPC_SEQUENCE, session.sequenceId, allocator); + if (nullptr != id) + { + *id = packetID; + } + + return MIXER_OK; +} + +int create_method_json(on_get_params getParams, std::shared_ptr& methodDoc) +{ + std::shared_ptr doc(nullptr == methodDoc ? std::make_shared() : methodDoc); + if (!doc->IsObject()) { + doc->SetObject(); + } + + rapidjson::Document::AllocatorType& allocator = doc->GetAllocator(); + // Get the parameters from the caller. rapidjson::Value params(rapidjson::kObjectType); if (getParams) @@ -31,10 +43,6 @@ int create_method_json(interactive_session_internal& session, const std::string& } doc->AddMember(RPC_PARAMS, params, allocator); - if (nullptr != id) - { - *id = packetID; - } methodDoc = doc; return MIXER_OK; } @@ -42,7 +50,8 @@ int create_method_json(interactive_session_internal& session, const std::string& int send_method(interactive_session_internal& session, const std::string& method, on_get_params getParams, bool discard, unsigned int* id) { std::shared_ptr methodDoc; - RETURN_IF_FAILED(create_method_json(session, method, getParams, discard, id, methodDoc)); + RETURN_IF_FAILED(create_method_json(getParams, methodDoc)); + RETURN_IF_FAILED(set_packet_info(session, method, discard, id, methodDoc)); // Synchronize access to the websocket. std::string methodJson = jsonStringify(*methodDoc); @@ -54,15 +63,22 @@ int send_method(interactive_session_internal& session, const std::string& method int queue_method(interactive_session_internal& session, const std::string& method, on_get_params getParams, method_handler onReply) { - std::shared_ptr methodDoc; + std::shared_ptr methodDoc(std::make_shared()); return queue_method(session, method, getParams, onReply, methodDoc); } int queue_method(interactive_session_internal& session, const std::string& method, on_get_params getParams, method_handler onReply, std::shared_ptr& methodDoc) +{ + std::shared_ptr doc(methodDoc); + RETURN_IF_FAILED(create_method_json(getParams, methodDoc)); + return queue_method_prebuilt(session, method, onReply, doc); +} + +int queue_method_prebuilt(interactive_session_internal& session, const std::string& method, method_handler onReply, std::shared_ptr& methodDoc) { std::shared_ptr doc(methodDoc); unsigned int packetId = 0; - RETURN_IF_FAILED(create_method_json(session, method, getParams, nullptr == onReply, &packetId, methodDoc)); + RETURN_IF_FAILED(set_packet_info(session, method, nullptr == onReply, &packetId, methodDoc)); DEBUG_TRACE(std::string("Queueing method: ") + jsonStringify(*methodDoc)); if (onReply) { diff --git a/source/internal/interactive_session.h b/source/internal/interactive_session.h index e532183..f485790 100644 --- a/source/internal/interactive_session.h +++ b/source/internal/interactive_session.h @@ -128,6 +128,7 @@ typedef std::function& methodDoc); +int queue_method_prebuilt(interactive_session_internal& session, const std::string& method, method_handler onReply, std::shared_ptr& methodDoc); int receive_reply(interactive_session_internal& session, unsigned int id, std::shared_ptr& replyPtr, unsigned int timeoutMs = 5000); int cache_groups(interactive_session_internal& session); From 3f734bd8c93f3342075fc5240dac415417fb2088 Mon Sep 17 00:00:00 2001 From: Mobius5150 Date: Sat, 14 Jul 2018 16:08:16 -0700 Subject: [PATCH 5/8] fix(feedback): Apply PR feedback --- Tests/Tests.cpp | 4 +-- source/interactivity.h | 10 +++--- source/internal/interactive_batch.cpp | 13 ++++++-- source/internal/interactive_batch.h | 16 +++++++--- source/internal/interactive_control.cpp | 19 +++++++++--- source/internal/interactive_participant.cpp | 34 +++++++++++++++++++-- 6 files changed, 76 insertions(+), 20 deletions(-) diff --git a/Tests/Tests.cpp b/Tests/Tests.cpp index f25a223..2bac562 100644 --- a/Tests/Tests.cpp +++ b/Tests/Tests.cpp @@ -960,10 +960,10 @@ TEST_CLASS(Tests) } interactive_batch batch; - Assert::AreEqual((int)MIXER_OK, interactive_control_batch_begin(session, &batch, "default")); + Assert::AreEqual((int)MIXER_OK, interactive_control_batch_begin(session, "default", &batch)); interactive_batch_entry entry; - Assert::AreEqual((int)MIXER_OK, interactive_control_batch_add(batch, &entry, "GiveHealth")); + Assert::AreEqual((int)MIXER_OK, interactive_control_batch_add(batch, "GiveHealth", &entry)); Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(&entry.obj, "foo", "bar")); Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(&entry.obj, "number", 42)); diff --git a/source/interactivity.h b/source/interactivity.h index dd1b68b..f9a0646 100644 --- a/source/interactivity.h +++ b/source/interactivity.h @@ -431,7 +431,7 @@ extern "C" { /// Batch requests are finalized with the `interactive_control_batch_commit` method after using `interactive_control_batch_add` to add the individual updates. /// /// - int interactive_control_batch_begin(interactive_session session, interactive_batch* batchPtr, const char* sceneId); + int interactive_control_batch_begin(interactive_session session, const char* sceneId, interactive_batch* batchPtr); /// /// Adds an update to the control batch request for the control with the given id. @@ -439,7 +439,7 @@ extern "C" { /// Note that a batch request should only contain a single entry per control ID. /// /// - int interactive_control_batch_add(interactive_batch batch, interactive_batch_entry* entry, const char* controlId); + int interactive_control_batch_add(interactive_batch batch, const char* controlId, interactive_batch_entry* entry); /// /// Commits an interactive control batch update against the interactive service. @@ -706,7 +706,7 @@ extern "C" { /// Note that a batch request should only contain a single entry per participant ID. /// /// - int interactive_participant_batch_add(interactive_batch batch, interactive_batch_entry* entry, const char* participantId); + int interactive_participant_batch_add(interactive_batch batch, const char* sessionId, interactive_batch_entry* entry); /// /// Commits an interactive participant batch update against the interactive service. @@ -804,7 +804,9 @@ extern "C" { MIXER_ERROR_WS_READ_FAILED, MIXER_ERROR_WS_SEND_FAILED, MIXER_ERROR_NOT_CONNECTED, - MIXER_ERROR_OBJECT_EXISTS + MIXER_ERROR_OBJECT_EXISTS, + MIXER_ERROR_INVALID_BATCH_TYPE, + MIXER_ERROR_DUPLICATE_ENTRY, } mixer_result_code; /** @} */ diff --git a/source/internal/interactive_batch.cpp b/source/internal/interactive_batch.cpp index 6e0f03b..649be76 100644 --- a/source/internal/interactive_batch.cpp +++ b/source/internal/interactive_batch.cpp @@ -38,7 +38,7 @@ inline rapidjson::Value* array_get_value(interactive_batch_array* obj) return reinterpret_cast(OBJECT_POINTER(obj)); } -int interactive_batch_begin(interactive_session session, interactive_batch* batchPtr, char *methodName) +int interactive_batch_begin(interactive_session session, char *methodName, interactive_batch_type type, interactive_batch* batchPtr) { if (nullptr == session || nullptr == batchPtr || nullptr == methodName) { @@ -48,6 +48,7 @@ int interactive_batch_begin(interactive_session session, interactive_batch* batc std::auto_ptr batchInternal(new interactive_batch_internal()); batchInternal->session = reinterpret_cast(session); batchInternal->method = methodName; + batchInternal->type = type; batchInternal->document = std::make_shared(); *batchPtr = reinterpret_cast(batchInternal.release()); @@ -56,7 +57,7 @@ int interactive_batch_begin(interactive_session session, interactive_batch* batc return MIXER_OK; } -int interactive_batch_add_entry(interactive_batch batch, interactive_batch_entry* entry, const char * paramsKey) +int interactive_batch_add_entry(interactive_batch batch, const char * paramsKey, const char* entryId, interactive_batch_entry* entry) { if (nullptr == batch || nullptr == entry) { @@ -66,13 +67,19 @@ int interactive_batch_add_entry(interactive_batch batch, interactive_batch_entry interactive_batch_internal* batchInternal = cast_batch(batch); std::stringstream ss; ss << "/" << RPC_PARAMS << "/" << paramsKey; - size_t pos = batchInternal->entries.size(); + size_t pos = batchInternal->entryIds.size(); if (0 == pos) { rapidjson::Pointer(ss.str().c_str()) .Set(*batchInternal->document, rapidjson::Value(rapidjson::kArrayType)); } + auto result = batchInternal->entryIds.emplace(entryId); + if (!result.second) + { + return MIXER_ERROR_DUPLICATE_ENTRY; + } + ss << "/" << pos; OBJECT_BATCH(&entry->obj) = batchInternal; OBJECT_POINTER(&entry->obj) = diff --git a/source/internal/interactive_batch.h b/source/internal/interactive_batch.h index 9d7d902..e33a58d 100644 --- a/source/internal/interactive_batch.h +++ b/source/internal/interactive_batch.h @@ -3,22 +3,30 @@ #include "interactive_session.h" #include "rapidjson\document.h" -#include +#include namespace mixer_internal { +enum interactive_batch_type +{ + INTERACTIVE_BATCH_TYPE_CONTROL, + INTERACTIVE_BATCH_TYPE_PARTICIPANT, + INTERACTIVE_BATCH_TYPE_SCENE +}; + struct interactive_batch_internal; struct interactive_batch_internal { interactive_session_internal* session; std::string method; std::shared_ptr document; - std::list entries; + std::unordered_set entryIds; + interactive_batch_type type; }; -int interactive_batch_begin(interactive_session session, interactive_batch* batchPtr, char *methodName); -int interactive_batch_add_entry(interactive_batch batch, interactive_batch_entry* entry, const char * paramsKey); +int interactive_batch_begin(interactive_session session, char *methodName, interactive_batch_type type, interactive_batch* batchPtr); +int interactive_batch_add_entry(interactive_batch batch, const char * paramsKey, const char* entryId, interactive_batch_entry* entry); int interactive_batch_free(interactive_batch_internal* batch); int interactive_batch_commit(interactive_batch_internal* batch); int interactive_batch_add_param(interactive_batch_internal* batch, rapidjson::Pointer& ptr, rapidjson::Value& value); diff --git a/source/internal/interactive_control.cpp b/source/internal/interactive_control.cpp index 07b4911..cb493f6 100644 --- a/source/internal/interactive_control.cpp +++ b/source/internal/interactive_control.cpp @@ -543,14 +543,14 @@ int interactive_control_get_meta_property_string(interactive_session session, co return MIXER_OK; } -int interactive_control_batch_begin(interactive_session session, interactive_batch* batchPtr, const char* sceneId) +int interactive_control_batch_begin(interactive_session session, const char* sceneId, interactive_batch* batchPtr) { if (nullptr == session || nullptr == batchPtr) { return MIXER_ERROR_INVALID_POINTER; } - RETURN_IF_FAILED(interactive_batch_begin(session, batchPtr, RPC_METHOD_UPDATE_CONTROLS)); + RETURN_IF_FAILED(interactive_batch_begin(session, RPC_METHOD_UPDATE_CONTROLS, INTERACTIVE_BATCH_TYPE_CONTROL, batchPtr)); interactive_batch_internal* batchInternal = reinterpret_cast(*batchPtr); std::stringstream ss; @@ -564,13 +564,19 @@ int interactive_control_batch_begin(interactive_session session, interactive_bat return MIXER_OK; } -int interactive_control_batch_add(interactive_batch batch, interactive_batch_entry* entry, const char* controlId) +int interactive_control_batch_add(interactive_batch batch, const char* controlId, interactive_batch_entry* entry) { if (nullptr == batch) { return MIXER_ERROR_INVALID_POINTER; } - RETURN_IF_FAILED(interactive_batch_add_entry(batch, entry, RPC_PARAM_CONTROLS)); + interactive_batch_internal* batchInternal = reinterpret_cast(batch); + if (batchInternal->type != INTERACTIVE_BATCH_TYPE_CONTROL) + { + return MIXER_ERROR_INVALID_BATCH_TYPE; + } + + RETURN_IF_FAILED(interactive_batch_add_entry(batch, RPC_PARAM_CONTROLS, controlId, entry)); RETURN_IF_FAILED(interactive_batch_add_param_str(&entry->obj, RPC_CONTROL_ID, controlId)); @@ -585,5 +591,10 @@ int interactive_control_batch_commit(interactive_batch batch) } interactive_batch_internal* batchInternal = reinterpret_cast(batch); + if (batchInternal->type != INTERACTIVE_BATCH_TYPE_CONTROL) + { + return MIXER_ERROR_INVALID_BATCH_TYPE; + } + return interactive_batch_commit(batchInternal); } \ No newline at end of file diff --git a/source/internal/interactive_participant.cpp b/source/internal/interactive_participant.cpp index 34b2383..ab409f6 100644 --- a/source/internal/interactive_participant.cpp +++ b/source/internal/interactive_participant.cpp @@ -265,11 +265,34 @@ int interactive_participant_get_group(interactive_session session, const char* p return MIXER_OK; } -int interactive_participant_batch_add(interactive_batch batch, interactive_batch_entry* entry, const char* participantId) +int interactive_participant_batch_begin(interactive_session session, interactive_batch* batchPtr) { - RETURN_IF_FAILED(interactive_batch_add_entry(batch, entry, RPC_PARAM_PARTICIPANTS)); + if (nullptr == session || nullptr == batchPtr) + { + return MIXER_ERROR_INVALID_POINTER; + } - RETURN_IF_FAILED(interactive_batch_add_param_str(&entry->obj, RPC_SESSION_ID, participantId)); + RETURN_IF_FAILED(interactive_batch_begin(session, RPC_METHOD_UPDATE_PARTICIPANTS, INTERACTIVE_BATCH_TYPE_PARTICIPANT, batchPtr)); + + return MIXER_OK; +} + +int interactive_participant_batch_add(interactive_batch batch, const char* sessionId, interactive_batch_entry* entry) +{ + if (nullptr == batch) + { + return MIXER_ERROR_INVALID_POINTER; + } + + interactive_batch_internal* batchInternal = reinterpret_cast(batch); + if (batchInternal->type != INTERACTIVE_BATCH_TYPE_PARTICIPANT) + { + return MIXER_ERROR_INVALID_BATCH_TYPE; + } + + RETURN_IF_FAILED(interactive_batch_add_entry(batch, RPC_PARAM_PARTICIPANTS, sessionId, entry)); + + RETURN_IF_FAILED(interactive_batch_add_param_str(&entry->obj, RPC_SESSION_ID, sessionId)); return MIXER_OK; } @@ -282,6 +305,11 @@ int interactive_participant_batch_commit(interactive_batch batch) } interactive_batch_internal* batchInternal = reinterpret_cast(batch); + if (batchInternal->type != INTERACTIVE_BATCH_TYPE_PARTICIPANT) + { + return MIXER_ERROR_INVALID_BATCH_TYPE; + } + return interactive_batch_commit(batchInternal); } From 1d2c92833a4983ac85d1b4dc16090e0d770c4472 Mon Sep 17 00:00:00 2001 From: Mobius5150 Date: Sat, 14 Jul 2018 16:17:22 -0700 Subject: [PATCH 6/8] feat(batch): Improve tests for control batch ops --- Tests/Tests.cpp | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/Tests/Tests.cpp b/Tests/Tests.cpp index 2bac562..f3703ba 100644 --- a/Tests/Tests.cpp +++ b/Tests/Tests.cpp @@ -960,41 +960,48 @@ TEST_CLASS(Tests) } interactive_batch batch; - Assert::AreEqual((int)MIXER_OK, interactive_control_batch_begin(session, "default", &batch)); + ASSERT_NOERR(interactive_control_batch_begin(session, "default", &batch)); interactive_batch_entry entry; - Assert::AreEqual((int)MIXER_OK, interactive_control_batch_add(batch, "GiveHealth", &entry)); - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(&entry.obj, "foo", "bar")); - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(&entry.obj, "number", 42)); + ASSERT_NOERR(interactive_control_batch_add(batch, "GiveHealth", &entry)); + ASSERT_NOERR(interactive_batch_add_param_str(&entry.obj, "foo", "bar")); + ASSERT_NOERR(interactive_batch_add_param_uint(&entry.obj, "number", 42)); + { + // Invalid Entry + interactive_batch_entry entryDupe; + ASSERT_ERR(MIXER_ERROR_DUPLICATE_ENTRY, interactive_control_batch_add(batch, "GiveHealth", &entryDupe)); + ASSERT_ERR(MIXER_ERROR_INVALID_BATCH_TYPE, interactive_participant_batch_add(batch, "GiveHealth", &entryDupe)); + } + interactive_batch_array entryArray; interactive_batch_add_param_array(&entry.obj, "array", &entryArray); interactive_batch_object entryArrayObject; interactive_batch_array_push_object(&entryArray, &entryArrayObject); - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(&entryArrayObject, "foo", "bar")); - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(&entryArrayObject, "number", 42)); + ASSERT_NOERR(interactive_batch_add_param_str(&entryArrayObject, "foo", "bar")); + ASSERT_NOERR(interactive_batch_add_param_uint(&entryArrayObject, "number", 42)); - Assert::AreEqual((int)MIXER_OK, interactive_batch_array_push_str(&entryArray, "bar")); - Assert::AreEqual((int)MIXER_OK, interactive_batch_array_push_uint(&entryArray, 42)); + ASSERT_NOERR(interactive_batch_array_push_str(&entryArray, "bar")); + ASSERT_NOERR(interactive_batch_array_push_uint(&entryArray, 42)); interactive_batch_array entryArrayArray; interactive_batch_array_push_array(&entryArray, &entryArrayArray); interactive_batch_object entryArrayArrayObject; interactive_batch_array_push_object(&entryArrayArray, &entryArrayArrayObject); - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(&entryArrayArrayObject, "foo", "bar")); - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(&entryArrayArrayObject, "number", 42)); + ASSERT_NOERR(interactive_batch_add_param_str(&entryArrayArrayObject, "foo", "bar")); + ASSERT_NOERR(interactive_batch_add_param_uint(&entryArrayArrayObject, "number", 42)); - Assert::AreEqual((int)MIXER_OK, interactive_batch_array_push_str(&entryArrayArray, "bar")); - Assert::AreEqual((int)MIXER_OK, interactive_batch_array_push_uint(&entryArrayArray, 42)); + ASSERT_NOERR(interactive_batch_array_push_str(&entryArrayArray, "bar")); + ASSERT_NOERR(interactive_batch_array_push_uint(&entryArrayArray, 42)); interactive_batch_object entryObject; - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_object(&entry.obj, "object", &entryObject)); - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_str(&entryObject, "foo", "bar")); - Assert::AreEqual((int)MIXER_OK, interactive_batch_add_param_uint(&entryObject, "number", 42)); - Assert::AreEqual((int)MIXER_OK, interactive_control_batch_commit(batch)); - Assert::AreEqual((int)MIXER_OK, interactive_batch_close(batch)); + ASSERT_NOERR(interactive_batch_add_param_object(&entry.obj, "object", &entryObject)); + ASSERT_NOERR(interactive_batch_add_param_str(&entryObject, "foo", "bar")); + ASSERT_NOERR(interactive_batch_add_param_uint(&entryObject, "number", 42)); + ASSERT_NOERR(interactive_control_batch_commit(batch)); + ASSERT_NOERR(interactive_batch_close(batch)); // Simulate 60 frames/sec for 1 second. for (int i = 0; i < fps * seconds; ++i) From f2de22070667df880ec04b43a09c069022e64544 Mon Sep 17 00:00:00 2001 From: Mobius5150 Date: Sat, 14 Jul 2018 16:21:42 -0700 Subject: [PATCH 7/8] fix(batch): PR feedback on naming --- Tests/Tests.cpp | 2 +- source/interactivity.h | 20 ++++----- source/internal/interactive_batch.cpp | 48 ++++++++++----------- source/internal/interactive_batch.h | 14 +++--- source/internal/interactive_control.cpp | 12 +++--- source/internal/interactive_participant.cpp | 10 ++--- 6 files changed, 53 insertions(+), 53 deletions(-) diff --git a/Tests/Tests.cpp b/Tests/Tests.cpp index f3703ba..6841b6c 100644 --- a/Tests/Tests.cpp +++ b/Tests/Tests.cpp @@ -959,7 +959,7 @@ TEST_CLASS(Tests) std::this_thread::sleep_for(std::chrono::milliseconds(1000 / fps)); } - interactive_batch batch; + interactive_batch_op batch; ASSERT_NOERR(interactive_control_batch_begin(session, "default", &batch)); interactive_batch_entry entry; diff --git a/source/interactivity.h b/source/interactivity.h index f9a0646..fa7349c 100644 --- a/source/interactivity.h +++ b/source/interactivity.h @@ -179,9 +179,9 @@ extern "C" { /// /// Opaque handle for a batch update object /// - struct interactive_batch_public {}; + struct interactive_batch_op_public {}; - typedef interactive_batch_public* interactive_batch; + typedef interactive_batch_op_public* interactive_batch_op; /// /// Opaque handle for a batch object @@ -212,7 +212,7 @@ extern "C" { /// /// Closes an interactive batch request. Should be called after committing or aborting a batch request to free memory. /// - int interactive_batch_close(interactive_batch batch); + int interactive_batch_close(interactive_batch_op batch); /// /// Nullifies a field on a batch update object. @@ -306,7 +306,7 @@ extern "C" { /// /// Sets the update priority of this batch update. /// - int interactive_batch_set_priority(interactive_batch batch, int priority); + int interactive_batch_set_priority(interactive_batch_op batch, int priority); /** @} */ @@ -431,7 +431,7 @@ extern "C" { /// Batch requests are finalized with the `interactive_control_batch_commit` method after using `interactive_control_batch_add` to add the individual updates. /// /// - int interactive_control_batch_begin(interactive_session session, const char* sceneId, interactive_batch* batchPtr); + int interactive_control_batch_begin(interactive_session session, const char* sceneId, interactive_batch_op* batchPtr); /// /// Adds an update to the control batch request for the control with the given id. @@ -439,12 +439,12 @@ extern "C" { /// Note that a batch request should only contain a single entry per control ID. /// /// - int interactive_control_batch_add(interactive_batch batch, const char* controlId, interactive_batch_entry* entry); + int interactive_control_batch_add(interactive_batch_op batch, const char* controlId, interactive_batch_entry* entry); /// /// Commits an interactive control batch update against the interactive service. /// - int interactive_control_batch_commit(interactive_batch batch); + int interactive_control_batch_commit(interactive_batch_op batch); /** @} */ /** @name Groups @@ -698,7 +698,7 @@ extern "C" { /// Batch requests are finalized with the `interactive_participant_batch_commit` method after using `interactive_participant_batch_add` to add the individual updates. /// /// - int interactive_participant_batch_begin(interactive_session session, interactive_batch* batchPtr); + int interactive_participant_batch_begin(interactive_session session, interactive_batch_op* batchPtr); /// /// Adds an update to the participant batch request for the participant with the given id. @@ -706,12 +706,12 @@ extern "C" { /// Note that a batch request should only contain a single entry per participant ID. /// /// - int interactive_participant_batch_add(interactive_batch batch, const char* sessionId, interactive_batch_entry* entry); + int interactive_participant_batch_add(interactive_batch_op batch, const char* sessionId, interactive_batch_entry* entry); /// /// Commits an interactive participant batch update against the interactive service. /// - int interactive_participant_batch_commit(interactive_batch batch); + int interactive_participant_batch_commit(interactive_batch_op batch); /// /// Reads a string value from the participant object. diff --git a/source/internal/interactive_batch.cpp b/source/internal/interactive_batch.cpp index 649be76..e23410c 100644 --- a/source/internal/interactive_batch.cpp +++ b/source/internal/interactive_batch.cpp @@ -13,14 +13,14 @@ namespace mixer_internal { -inline interactive_batch_internal* cast_batch(interactive_batch batch) +inline interactive_batch_op_internal* cast_batch(interactive_batch_op batch) { - return reinterpret_cast(batch); + return reinterpret_cast(batch); } -inline interactive_batch_internal* object_get_batch(interactive_batch_object* obj) +inline interactive_batch_op_internal* object_get_batch(interactive_batch_object* obj) { - return reinterpret_cast(OBJECT_BATCH(obj)); + return reinterpret_cast(OBJECT_BATCH(obj)); } inline rapidjson::Value* object_get_value(interactive_batch_object* obj) @@ -28,9 +28,9 @@ inline rapidjson::Value* object_get_value(interactive_batch_object* obj) return reinterpret_cast(OBJECT_POINTER(obj)); } -inline interactive_batch_internal* array_get_batch(interactive_batch_array* obj) +inline interactive_batch_op_internal* array_get_batch(interactive_batch_array* obj) { - return reinterpret_cast(OBJECT_BATCH(obj)); + return reinterpret_cast(OBJECT_BATCH(obj)); } inline rapidjson::Value* array_get_value(interactive_batch_array* obj) @@ -38,33 +38,33 @@ inline rapidjson::Value* array_get_value(interactive_batch_array* obj) return reinterpret_cast(OBJECT_POINTER(obj)); } -int interactive_batch_begin(interactive_session session, char *methodName, interactive_batch_type type, interactive_batch* batchPtr) +int interactive_batch_begin(interactive_session session, char *methodName, interactive_batch_type type, interactive_batch_op* batchPtr) { if (nullptr == session || nullptr == batchPtr || nullptr == methodName) { return MIXER_ERROR_INVALID_POINTER; } - std::auto_ptr batchInternal(new interactive_batch_internal()); + std::auto_ptr batchInternal(new interactive_batch_op_internal()); batchInternal->session = reinterpret_cast(session); batchInternal->method = methodName; batchInternal->type = type; batchInternal->document = std::make_shared(); - *batchPtr = reinterpret_cast(batchInternal.release()); + *batchPtr = reinterpret_cast(batchInternal.release()); interactive_batch_set_priority(*batchPtr, RPC_PRIORITY_DEFAULT); return MIXER_OK; } -int interactive_batch_add_entry(interactive_batch batch, const char * paramsKey, const char* entryId, interactive_batch_entry* entry) +int interactive_batch_add_entry(interactive_batch_op batch, const char * paramsKey, const char* entryId, interactive_batch_entry* entry) { if (nullptr == batch || nullptr == entry) { return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batchInternal = cast_batch(batch); + interactive_batch_op_internal* batchInternal = cast_batch(batch); std::stringstream ss; ss << "/" << RPC_PARAMS << "/" << paramsKey; size_t pos = batchInternal->entryIds.size(); @@ -89,7 +89,7 @@ int interactive_batch_add_entry(interactive_batch batch, const char * paramsKey, return MIXER_OK; } -int interactive_batch_free(interactive_batch_internal* batch) +int interactive_batch_free(interactive_batch_op_internal* batch) { if (nullptr == batch) { @@ -101,7 +101,7 @@ int interactive_batch_free(interactive_batch_internal* batch) return MIXER_OK; } -int interactive_batch_commit(interactive_batch_internal* batch) +int interactive_batch_commit(interactive_batch_op_internal* batch) { if (nullptr == batch) { @@ -111,7 +111,7 @@ int interactive_batch_commit(interactive_batch_internal* batch) return queue_method_prebuilt(*batch->session, batch->method.c_str(), nullptr, batch->document); } -int interactive_batch_add_param(interactive_batch_internal* batch, rapidjson::Pointer& ptr, rapidjson::Value& value) +int interactive_batch_add_param(interactive_batch_op_internal* batch, rapidjson::Pointer& ptr, rapidjson::Value& value) { if (nullptr == batch) { @@ -157,7 +157,7 @@ int interactive_batch_array_push(interactive_batch_array* array, rapidjson::Poin return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batch = array_get_batch(array); + interactive_batch_op_internal* batch = array_get_batch(array); ptr.Set(*batch->document.get(), value); return MIXER_OK; @@ -167,7 +167,7 @@ int interactive_batch_array_push(interactive_batch_array* array, rapidjson::Poin using namespace mixer_internal; -int interactive_batch_close(interactive_batch batch) +int interactive_batch_close(interactive_batch_op batch) { if (nullptr == batch) { @@ -177,14 +177,14 @@ int interactive_batch_close(interactive_batch batch) return interactive_batch_free(cast_batch(batch)); } -int interactive_batch_set_priority(interactive_batch batch, int priority) +int interactive_batch_set_priority(interactive_batch_op batch, int priority) { if (nullptr == batch) { return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batchInternal = cast_batch(batch); + interactive_batch_op_internal* batchInternal = cast_batch(batch); std::stringstream ss; ss << "/" << RPC_PARAMS << "/" << RPC_PRIORITY; rapidjson::Pointer(ss.str().c_str()).Set(*batchInternal->document, priority); @@ -206,7 +206,7 @@ int interactive_batch_add_param_str(interactive_batch_object* obj, const char* n return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batch = object_get_batch(obj); + interactive_batch_op_internal* batch = object_get_batch(obj); if (nullptr == batch) { return MIXER_ERROR_INVALID_POINTER; @@ -241,7 +241,7 @@ int interactive_batch_add_param_object(interactive_batch_object* obj, const char return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batch = object_get_batch(obj); + interactive_batch_op_internal* batch = object_get_batch(obj); auto jsonObj = object_get_value(obj)->GetObject(); jsonObj.AddMember( rapidjson::Value(std::string(name).c_str(), object_get_batch(obj)->document->GetAllocator()).Move(), @@ -260,7 +260,7 @@ int interactive_batch_add_param_array(interactive_batch_object* obj, const char* return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batch = object_get_batch(obj); + interactive_batch_op_internal* batch = object_get_batch(obj); auto jsonObj = object_get_value(obj)->GetObject(); jsonObj.AddMember( rapidjson::Value(std::string(name).c_str(), object_get_batch(obj)->document->GetAllocator()).Move(), @@ -284,7 +284,7 @@ int interactive_batch_array_push_str(interactive_batch_array* array, const char* return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batch = array_get_batch(array); + interactive_batch_op_internal* batch = array_get_batch(array); if (nullptr == batch) { return MIXER_ERROR_INVALID_POINTER; @@ -310,7 +310,7 @@ int interactive_batch_array_push_object(interactive_batch_array* array, interact return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batch = array_get_batch(array); + interactive_batch_op_internal* batch = array_get_batch(array); auto arr = array_get_value(array)->GetArray(); arr.PushBack( rapidjson::Value(rapidjson::kObjectType).Move(), @@ -328,7 +328,7 @@ int interactive_batch_array_push_array(interactive_batch_array* array, interacti return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batch = array_get_batch(array); + interactive_batch_op_internal* batch = array_get_batch(array); auto arr = array_get_value(array)->GetArray(); arr.PushBack( rapidjson::Value(rapidjson::kArrayType).Move(), diff --git a/source/internal/interactive_batch.h b/source/internal/interactive_batch.h index e33a58d..80d5b59 100644 --- a/source/internal/interactive_batch.h +++ b/source/internal/interactive_batch.h @@ -15,8 +15,8 @@ enum interactive_batch_type INTERACTIVE_BATCH_TYPE_SCENE }; -struct interactive_batch_internal; -struct interactive_batch_internal +struct interactive_batch_op_internal; +struct interactive_batch_op_internal { interactive_session_internal* session; std::string method; @@ -25,11 +25,11 @@ struct interactive_batch_internal interactive_batch_type type; }; -int interactive_batch_begin(interactive_session session, char *methodName, interactive_batch_type type, interactive_batch* batchPtr); -int interactive_batch_add_entry(interactive_batch batch, const char * paramsKey, const char* entryId, interactive_batch_entry* entry); -int interactive_batch_free(interactive_batch_internal* batch); -int interactive_batch_commit(interactive_batch_internal* batch); -int interactive_batch_add_param(interactive_batch_internal* batch, rapidjson::Pointer& ptr, rapidjson::Value& value); +int interactive_batch_begin(interactive_session session, char *methodName, interactive_batch_type type, interactive_batch_op* batchPtr); +int interactive_batch_add_entry(interactive_batch_op batch, const char * paramsKey, const char* entryId, interactive_batch_entry* entry); +int interactive_batch_free(interactive_batch_op_internal* batch); +int interactive_batch_commit(interactive_batch_op_internal* batch); +int interactive_batch_add_param(interactive_batch_op_internal* batch, rapidjson::Pointer& ptr, rapidjson::Value& value); int interactive_batch_array_push(interactive_batch_array* array, rapidjson::Value& value); int interactive_batch_array_push(interactive_batch_array* array, rapidjson::Pointer& ptr, rapidjson::Value& value); diff --git a/source/internal/interactive_control.cpp b/source/internal/interactive_control.cpp index cb493f6..b0bbc3d 100644 --- a/source/internal/interactive_control.cpp +++ b/source/internal/interactive_control.cpp @@ -543,7 +543,7 @@ int interactive_control_get_meta_property_string(interactive_session session, co return MIXER_OK; } -int interactive_control_batch_begin(interactive_session session, const char* sceneId, interactive_batch* batchPtr) +int interactive_control_batch_begin(interactive_session session, const char* sceneId, interactive_batch_op* batchPtr) { if (nullptr == session || nullptr == batchPtr) { @@ -552,7 +552,7 @@ int interactive_control_batch_begin(interactive_session session, const char* sce RETURN_IF_FAILED(interactive_batch_begin(session, RPC_METHOD_UPDATE_CONTROLS, INTERACTIVE_BATCH_TYPE_CONTROL, batchPtr)); - interactive_batch_internal* batchInternal = reinterpret_cast(*batchPtr); + interactive_batch_op_internal* batchInternal = reinterpret_cast(*batchPtr); std::stringstream ss; ss << "/" << RPC_PARAMS << "/" RPC_SCENE_ID; rapidjson::Pointer ptr(ss.str().c_str()); @@ -564,13 +564,13 @@ int interactive_control_batch_begin(interactive_session session, const char* sce return MIXER_OK; } -int interactive_control_batch_add(interactive_batch batch, const char* controlId, interactive_batch_entry* entry) +int interactive_control_batch_add(interactive_batch_op batch, const char* controlId, interactive_batch_entry* entry) { if (nullptr == batch) { return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batchInternal = reinterpret_cast(batch); + interactive_batch_op_internal* batchInternal = reinterpret_cast(batch); if (batchInternal->type != INTERACTIVE_BATCH_TYPE_CONTROL) { return MIXER_ERROR_INVALID_BATCH_TYPE; @@ -583,14 +583,14 @@ int interactive_control_batch_add(interactive_batch batch, const char* controlId return MIXER_OK; } -int interactive_control_batch_commit(interactive_batch batch) +int interactive_control_batch_commit(interactive_batch_op batch) { if (nullptr == batch) { return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batchInternal = reinterpret_cast(batch); + interactive_batch_op_internal* batchInternal = reinterpret_cast(batch); if (batchInternal->type != INTERACTIVE_BATCH_TYPE_CONTROL) { return MIXER_ERROR_INVALID_BATCH_TYPE; diff --git a/source/internal/interactive_participant.cpp b/source/internal/interactive_participant.cpp index ab409f6..72457a7 100644 --- a/source/internal/interactive_participant.cpp +++ b/source/internal/interactive_participant.cpp @@ -265,7 +265,7 @@ int interactive_participant_get_group(interactive_session session, const char* p return MIXER_OK; } -int interactive_participant_batch_begin(interactive_session session, interactive_batch* batchPtr) +int interactive_participant_batch_begin(interactive_session session, interactive_batch_op* batchPtr) { if (nullptr == session || nullptr == batchPtr) { @@ -277,14 +277,14 @@ int interactive_participant_batch_begin(interactive_session session, interactive return MIXER_OK; } -int interactive_participant_batch_add(interactive_batch batch, const char* sessionId, interactive_batch_entry* entry) +int interactive_participant_batch_add(interactive_batch_op batch, const char* sessionId, interactive_batch_entry* entry) { if (nullptr == batch) { return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batchInternal = reinterpret_cast(batch); + interactive_batch_op_internal* batchInternal = reinterpret_cast(batch); if (batchInternal->type != INTERACTIVE_BATCH_TYPE_PARTICIPANT) { return MIXER_ERROR_INVALID_BATCH_TYPE; @@ -297,14 +297,14 @@ int interactive_participant_batch_add(interactive_batch batch, const char* sessi return MIXER_OK; } -int interactive_participant_batch_commit(interactive_batch batch) +int interactive_participant_batch_commit(interactive_batch_op batch) { if (nullptr == batch) { return MIXER_ERROR_INVALID_POINTER; } - interactive_batch_internal* batchInternal = reinterpret_cast(batch); + interactive_batch_op_internal* batchInternal = reinterpret_cast(batch); if (batchInternal->type != INTERACTIVE_BATCH_TYPE_PARTICIPANT) { return MIXER_ERROR_INVALID_BATCH_TYPE; From 70e437b6163eba2c2038593c97886cce68759c22 Mon Sep 17 00:00:00 2001 From: Mobius5150 Date: Thu, 19 Jul 2018 19:38:01 -0700 Subject: [PATCH 8/8] feat(bash): Refactor macro --- source/internal/interactive_batch.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/source/internal/interactive_batch.cpp b/source/internal/interactive_batch.cpp index e23410c..c16964b 100644 --- a/source/internal/interactive_batch.cpp +++ b/source/internal/interactive_batch.cpp @@ -8,7 +8,7 @@ #include "rapidjson/pointer.h" #define OBJECT_BATCH(o) ((o)->_a) -#define OBJECT_POINTER(o) ((o)->_b) +#define OBJECT_VALUE(o) ((o)->_b) namespace mixer_internal { @@ -25,7 +25,7 @@ inline interactive_batch_op_internal* object_get_batch(interactive_batch_object* inline rapidjson::Value* object_get_value(interactive_batch_object* obj) { - return reinterpret_cast(OBJECT_POINTER(obj)); + return reinterpret_cast(OBJECT_VALUE(obj)); } inline interactive_batch_op_internal* array_get_batch(interactive_batch_array* obj) @@ -35,7 +35,7 @@ inline interactive_batch_op_internal* array_get_batch(interactive_batch_array* o inline rapidjson::Value* array_get_value(interactive_batch_array* obj) { - return reinterpret_cast(OBJECT_POINTER(obj)); + return reinterpret_cast(OBJECT_VALUE(obj)); } int interactive_batch_begin(interactive_session session, char *methodName, interactive_batch_type type, interactive_batch_op* batchPtr) @@ -82,7 +82,7 @@ int interactive_batch_add_entry(interactive_batch_op batch, const char * paramsK ss << "/" << pos; OBJECT_BATCH(&entry->obj) = batchInternal; - OBJECT_POINTER(&entry->obj) = + OBJECT_VALUE(&entry->obj) = &rapidjson::Pointer(ss.str().c_str()) .Set(*batchInternal->document, rapidjson::Value(rapidjson::kObjectType)); @@ -248,7 +248,7 @@ int interactive_batch_add_param_object(interactive_batch_object* obj, const char rapidjson::Value(rapidjson::kObjectType).Move(), object_get_batch(obj)->document->GetAllocator()); OBJECT_BATCH(paramObj) = batch; - OBJECT_POINTER(paramObj) = &jsonObj.FindMember(name)->value; + OBJECT_VALUE(paramObj) = &jsonObj.FindMember(name)->value; return MIXER_OK; } @@ -267,7 +267,7 @@ int interactive_batch_add_param_array(interactive_batch_object* obj, const char* rapidjson::Value(rapidjson::kArrayType).Move(), object_get_batch(obj)->document->GetAllocator()); OBJECT_BATCH(paramArr) = batch; - OBJECT_POINTER(paramArr) = &jsonObj.FindMember(name)->value; + OBJECT_VALUE(paramArr) = &jsonObj.FindMember(name)->value; return MIXER_OK; } @@ -316,7 +316,7 @@ int interactive_batch_array_push_object(interactive_batch_array* array, interact rapidjson::Value(rapidjson::kObjectType).Move(), array_get_batch(array)->document->GetAllocator()); OBJECT_BATCH(pushObj) = batch; - OBJECT_POINTER(pushObj) = &arr[arr.Size() - 1]; + OBJECT_VALUE(pushObj) = &arr[arr.Size() - 1]; return MIXER_OK; } @@ -334,7 +334,7 @@ int interactive_batch_array_push_array(interactive_batch_array* array, interacti rapidjson::Value(rapidjson::kArrayType).Move(), array_get_batch(array)->document->GetAllocator()); OBJECT_BATCH(pushArr) = batch; - OBJECT_POINTER(pushArr) = &arr[arr.Size() - 1]; + OBJECT_VALUE(pushArr) = &arr[arr.Size() - 1]; return MIXER_OK; }