From 6d390e9abf13b70e7134bc4c030f80657673f32f Mon Sep 17 00:00:00 2001 From: Adeel Kazmi Date: Wed, 25 May 2022 20:43:00 +0100 Subject: [PATCH] (Network) Add a custom_command option Add -DENABLE_NETWORK_LOGGING=ON to cmake build to enable this and when running, DALI_NETWORK_CONTROL=1 must also be set. The default port is 3031, every new DALi app uses the next available port after this. Change-Id: Ia20a25f5ca3faa0d17f3fee0b3bb9e64d09af31c --- .../adaptor-framework/application-devel.cpp | 18 ++++- .../adaptor-framework/application-devel.h | 25 ++++++- dali/internal/network/common/automation.cpp | 19 ++++- dali/internal/network/common/automation.h | 11 ++- .../network/common/network-performance-client.cpp | 67 ++++++++++++------ .../common/network-performance-protocol.cpp | 6 +- .../network/common/network-performance-protocol.h | 3 +- .../network/common/network-service-impl.cpp | 59 ++++++++++++++++ .../internal/network/common/network-service-impl.h | 81 ++++++++++++++++++++++ dali/internal/network/file.list | 3 +- 10 files changed, 260 insertions(+), 32 deletions(-) create mode 100644 dali/internal/network/common/network-service-impl.cpp create mode 100644 dali/internal/network/common/network-service-impl.h diff --git a/dali/devel-api/adaptor-framework/application-devel.cpp b/dali/devel-api/adaptor-framework/application-devel.cpp index 50f5772..533a68c 100644 --- a/dali/devel-api/adaptor-framework/application-devel.cpp +++ b/dali/devel-api/adaptor-framework/application-devel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,9 @@ // INTERNAL INCLUDES #include #include +#include #include +#include namespace Dali { @@ -44,8 +46,7 @@ Application New(int* argc, char** argv[], const std::string& stylesheet, Applica //Store only the value before adaptor is created internal->StoreWindowPositionSize(positionSize); - } - else + } else { internal = Internal::Adaptor::Application::New(argc, argv, stylesheet, windowMode, positionSize, Internal::Adaptor::Framework::NORMAL, type); } @@ -67,6 +68,17 @@ Application DownCast(Dali::RefObject* refObject) return Application(dynamic_cast(refObject)); } +CustomCommandReceivedSignalType& CustomCommandReceivedSignal(Application application) +{ + DALI_ASSERT_ALWAYS(Adaptor::IsAvailable() && "Adaptor is not available") + + Internal::Adaptor::NetworkServicePtr networkService = Internal::Adaptor::NetworkService::Get(); + + DALI_ASSERT_ALWAYS(networkService && "Network Service Unavailable"); + + return networkService->CustomCommandReceivedSignal(); +} + } // namespace DevelApplication } // namespace Dali diff --git a/dali/devel-api/adaptor-framework/application-devel.h b/dali/devel-api/adaptor-framework/application-devel.h index e82281c..095c252 100644 --- a/dali/devel-api/adaptor-framework/application-devel.h +++ b/dali/devel-api/adaptor-framework/application-devel.h @@ -2,7 +2,7 @@ #define DALI_APPLICATION_DEVEL_H /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,11 +20,18 @@ // INTERNAL INCLUDES #include +#include + +// EXTERNAL INCLUDES +#include namespace Dali { namespace DevelApplication { + +using CustomCommandReceivedSignalType = Signal; ///< Signal signature for CustomCommandReceivedSignal + /** * @brief This is the constructor for applications. * Especially, it is for keyboard application. @@ -76,6 +83,22 @@ DALI_ADAPTOR_API std::string GetDataPath(); */ DALI_ADAPTOR_API Application DownCast(Dali::RefObject* refObject); +/** + * @brief This signal will be triggered when a custom command is received. + * + * For this signal to be triggered, the adaptor must be built with -DENABLE_NETWORK_LOGGING=ON + * and when running, DALI_NETWORK_CONTROL=1 must also be set. + * + * A callback of the following type may be connected: + * @code + * void YourCallbackName(const std::string&); + * @endcode + * + * @param[in] application A handle to the Application + * @return The signal when a custom command is received + */ +DALI_ADAPTOR_API CustomCommandReceivedSignalType& CustomCommandReceivedSignal(Application application); + } // namespace DevelApplication } // namespace Dali diff --git a/dali/internal/network/common/automation.cpp b/dali/internal/network/common/automation.cpp index 2a5ba8f..ebe4467 100644 --- a/dali/internal/network/common/automation.cpp +++ b/dali/internal/network/common/automation.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,12 +21,15 @@ // EXTERNAL INCLUDES #include -#include #include #include #include #include +// INTERNAL INCLUDES +#include +#include + using Dali::Matrix; using Dali::Matrix3; using Dali::Property; @@ -453,6 +456,18 @@ void DumpScene(unsigned int clientId, ClientSendDataInterface* sendData) sendData->SendData(json.c_str(), json.length(), clientId); } +void SetCustomCommand(const std::string& message) +{ + if(Adaptor::IsAvailable()) + { + Internal::Adaptor::NetworkServicePtr networkService = Internal::Adaptor::NetworkService::Get(); + if(networkService) + { + networkService->EmitCustomCommandReceivedSignal(message); + } + } +} + } // namespace Automation } // namespace Adaptor diff --git a/dali/internal/network/common/automation.h b/dali/internal/network/common/automation.h index c675001..44e0418 100644 --- a/dali/internal/network/common/automation.h +++ b/dali/internal/network/common/automation.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_ADAPTOR_AUTOMATION_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -59,6 +59,15 @@ void SetProperty(const std::string& message); */ void DumpScene(unsigned int clientId, ClientSendDataInterface* sendData); + +/** + * @brief Sets a custom command. + * No ClientSendDataInterface required, as no response is sent back + * @param[in] message custom message + */ +void SetCustomCommand(const std::string& message); + + } // namespace Automation } // namespace Adaptor diff --git a/dali/internal/network/common/network-performance-client.cpp b/dali/internal/network/common/network-performance-client.cpp index 836f2ba..4a02097 100644 --- a/dali/internal/network/common/network-performance-client.cpp +++ b/dali/internal/network/common/network-performance-client.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ // EXTERNAL INCLUDES #include +#include #include // INTERNAL INCLUDES @@ -52,6 +53,7 @@ public: { UNKNOWN_COMMAND, SET_PROPERTY, + CUSTOM_COMMAND, DUMP_SCENE }; @@ -67,21 +69,28 @@ public: void AssignSetPropertyCommand(std::string setPropertyCommand) { - mCommandId = SET_PROPERTY; - mPropertyCommand = setPropertyCommand; + mCommandId = SET_PROPERTY; + mCommandString = setPropertyCommand; } + void AssignDumpSceneCommand() { mCommandId = DUMP_SCENE; } + void AssignCustomCommand(std::string&& customCommand) + { + mCommandId = CUSTOM_COMMAND; + mCommandString = std::move(customCommand); + } + void RunCallback() { switch(mCommandId) { case SET_PROPERTY: { - Automation::SetProperty(mPropertyCommand); + Automation::SetProperty(mCommandString); break; } case DUMP_SCENE: @@ -89,6 +98,11 @@ public: Automation::DumpScene(mClientId, &mSendDataInterface); break; } + case CUSTOM_COMMAND: + { + Automation::SetCustomCommand(mCommandString); + break; + } default: { DALI_ASSERT_DEBUG(0 && "Unknown command"); @@ -103,12 +117,29 @@ public: } private: - std::string mPropertyCommand; ///< property command + std::string mCommandString; ///< command string for property or custom command ClientSendDataInterface& mSendDataInterface; ///< Abstract client send data interface CommandId mCommandId; ///< command id const unsigned int mClientId; ///< client id }; +/** + * @brief Helper to ensure the AutomationCallback method we want is called in the main thread + */ +template +void TriggerOnMainThread(unsigned int clientId, ClientSendDataInterface& sendDataInterface, T&& lambda) +{ + // this needs to be run on the main thread, use the trigger event.... + AutomationCallback* callback = new AutomationCallback(clientId, sendDataInterface); + lambda(callback); + + // create a trigger event that automatically deletes itself after the callback has run in the main thread + TriggerEventInterface* interface = TriggerEventFactory::CreateTriggerEvent(callback, TriggerEventInterface::DELETE_AFTER_TRIGGER); + + // asynchronous call, the call back will be run sometime later on the main thread + interface->Trigger(); +} + } // unnamed namespace NetworkPerformanceClient::NetworkPerformanceClient(pthread_t* thread, @@ -217,29 +248,21 @@ void NetworkPerformanceClient::ProcessCommand(char* buffer, unsigned int bufferS case PerformanceProtocol::DUMP_SCENE_GRAPH: { - // this needs to be run on the main thread, use the trigger event.... - AutomationCallback* callback = new AutomationCallback(mClientId, mSendDataInterface); - callback->AssignDumpSceneCommand(); - - // create a trigger event that automatically deletes itself after the callback has run in the main thread - TriggerEventInterface* interface = TriggerEventFactory::CreateTriggerEvent(callback, TriggerEventInterface::DELETE_AFTER_TRIGGER); - - // asynchronous call, the call back will be run sometime later on the main thread - interface->Trigger(); + TriggerOnMainThread(mClientId, mSendDataInterface, [&](AutomationCallback* callback){callback->AssignDumpSceneCommand();}); break; } case PerformanceProtocol::SET_PROPERTIES: { - // this needs to be run on the main thread, use the trigger event.... - AutomationCallback* callback = new AutomationCallback(mClientId, mSendDataInterface); - callback->AssignSetPropertyCommand(stringParam); - - // create a trigger event that automatically deletes itself after the callback has run in the main thread - TriggerEventInterface* interface = TriggerEventFactory::CreateTriggerEvent(callback, TriggerEventInterface::DELETE_AFTER_TRIGGER); + TriggerOnMainThread(mClientId, mSendDataInterface, [&](AutomationCallback* callback){callback->AssignSetPropertyCommand(stringParam);}); + response = "Completed"; + break; + } - // asynchronous call, the call back will be run sometime later on the main thread - interface->Trigger(); + case PerformanceProtocol::CUSTOM_COMMAND: + { + TriggerOnMainThread(mClientId, mSendDataInterface, [&](AutomationCallback* callback){callback->AssignCustomCommand(std::move(stringParam));}); + response = "Completed"; break; } diff --git a/dali/internal/network/common/network-performance-protocol.cpp b/dali/internal/network/common/network-performance-protocol.cpp index 5c23e84..d921f58 100644 --- a/dali/internal/network/common/network-performance-protocol.cpp +++ b/dali/internal/network/common/network-performance-protocol.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -64,6 +64,7 @@ CommandInfo CommandLookup[]= {ENABLE_TIME_MARKER_BIT_MASK, "set_marker", UNSIGNED_INT}, {DUMP_SCENE_GRAPH, "dump_scene", NO_PARAMS }, {SET_PROPERTIES, "set_properties", STRING }, + {CUSTOM_COMMAND, "custom_command", STRING }, {UNKNOWN_COMMAND, "unknown", NO_PARAMS } }; // clang-format on @@ -96,6 +97,9 @@ const char* const helpMsg = GREEN " set_properties " PARAM "|ActorIndex;Property;Value|" NORMAL ", e.g: \n" GREEN " set_properties " PARAM "|178;Size;[ 144.0, 144.0, 144.0 ]|178;Color;[ 1.0, 1,0, 1.0 ]|\n" "\n" + GREEN " custom_command " NORMAL " - A custom command for an application. Format:\n\n" + GREEN " custom_command " PARAM "ANY_STRING" NORMAL "\n" + "\n" GREEN " dump_scene" NORMAL " - dump the current scene in json format\n"; // clang-format off } // un-named namespace diff --git a/dali/internal/network/common/network-performance-protocol.h b/dali/internal/network/common/network-performance-protocol.h index a5123b2..1313e96 100644 --- a/dali/internal/network/common/network-performance-protocol.h +++ b/dali/internal/network/common/network-performance-protocol.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_ADAPTOR_NETWORK_PERFORMANCE_PROTOCOL_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,6 +39,7 @@ enum CommandId ENABLE_TIME_MARKER_BIT_MASK = 4, ///< bit mask of time markers to enable SET_PROPERTIES = 5, ///< set property DUMP_SCENE_GRAPH = 6, ///< dump the scene graph + CUSTOM_COMMAND = 7, ///< custom command for the application UNKNOWN_COMMAND = 4096 }; diff --git a/dali/internal/network/common/network-service-impl.cpp b/dali/internal/network/common/network-service-impl.cpp new file mode 100644 index 0000000..30dc19e --- /dev/null +++ b/dali/internal/network/common/network-service-impl.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali::Internal::Adaptor +{ +NetworkServicePtr NetworkService::Get() +{ + NetworkServicePtr networkService; + + Dali::SingletonService service(SingletonService::Get()); + if(service) + { + // Check whether the singleton is already created + Dali::BaseHandle handle = service.GetSingleton(typeid(NetworkService)); + if(handle) + { + // If so, downcast the handle + networkService = NetworkServicePtr(dynamic_cast(handle.GetObjectPtr())); + } + else + { + // Create a singleon instance + networkService = NetworkServicePtr(new NetworkService()); + service.Register(typeid(NetworkService), BaseHandle(networkService.Get())); + } + } + + return networkService; +} + +void NetworkService::EmitCustomCommandReceivedSignal(const std::string& message) +{ + if(!mCustomCommandReceivedSignal.Empty()) + { + mCustomCommandReceivedSignal.Emit(message); + } +} + +} // namespace Dali::Internal::Adaptor diff --git a/dali/internal/network/common/network-service-impl.h b/dali/internal/network/common/network-service-impl.h new file mode 100644 index 0000000..3b4b796 --- /dev/null +++ b/dali/internal/network/common/network-service-impl.h @@ -0,0 +1,81 @@ +#ifndef DALI_INTERNAL_NETWORK_SERVICE_H +#define DALI_INTERNAL_NETWORK_SERVICE_H + +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Internal::Adaptor +{ + +class NetworkService; +using NetworkServicePtr = IntrusivePtr; + +/** + * Provides methods to interface with the network services offered by DALi. + * + * This is only available when the adaptor is built with with -DENABLE_NETWORK_LOGGING=ON + * and when running, DALI_NETWORK_CONTROL=1 must also be set. + */ +class NetworkService : public Dali::BaseObject +{ +public: + NetworkService() = default; ///< Constructor + ~NetworkService() override = default; ///< Default Destructor + NetworkService(const NetworkService&) = delete; ///< Deleted copy constructor + NetworkService(NetworkService&&) = delete; ///< Deleted move constructor + NetworkService& operator=(NetworkService&) = delete; ///< Deleted copy assignment operator + NetworkService& operator=(NetworkService&&) = delete; ///< Deleted move assignment operator + + /** + * @brief Retrieve the NetworkService Singleton. + * @return An intrusive pointer to the NetworkService + */ + static NetworkServicePtr Get(); + + /** + * @brief This signal will be triggered when a custom command is received. + * @return The signal when a custom command is received + */ + DevelApplication::CustomCommandReceivedSignalType& CustomCommandReceivedSignal() + { + return mCustomCommandReceivedSignal; + } + + /** + * @brief Emit the Custom Command Received Signal + */ + void EmitCustomCommandReceivedSignal(const std::string& message); + +private: + DevelApplication::CustomCommandReceivedSignalType mCustomCommandReceivedSignal; + +}; // class NetworkService + +} // namespace Internal::Adaptor + +} // namespace Dali + +#endif // DALI_INTERNAL_NETWORK_SERVICE_H diff --git a/dali/internal/network/file.list b/dali/internal/network/file.list index 0beeaaf..aaa421c 100644 --- a/dali/internal/network/file.list +++ b/dali/internal/network/file.list @@ -1,7 +1,8 @@ # module: network, backend: common SET( adaptor_network_common_src_files - ${adaptor_network_dir}/common/socket-factory.cpp + ${adaptor_network_dir}/common/network-service-impl.cpp + ${adaptor_network_dir}/common/socket-factory.cpp ${adaptor_network_dir}/common/socket-impl.cpp ) -- 2.7.4