(Network) Add a custom_command option 77/275477/11
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Wed, 25 May 2022 19:43:00 +0000 (20:43 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Thu, 23 Jun 2022 18:00:06 +0000 (19:00 +0100)
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

dali/devel-api/adaptor-framework/application-devel.cpp
dali/devel-api/adaptor-framework/application-devel.h
dali/internal/network/common/automation.cpp
dali/internal/network/common/automation.h
dali/internal/network/common/network-performance-client.cpp
dali/internal/network/common/network-performance-protocol.cpp
dali/internal/network/common/network-performance-protocol.h
dali/internal/network/common/network-service-impl.cpp [new file with mode: 0644]
dali/internal/network/common/network-service-impl.h [new file with mode: 0644]
dali/internal/network/file.list

index 50f5772..533a68c 100644 (file)
@@ -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 <dali/devel-api/adaptor-framework/application-devel.h>
 #include <dali/integration-api/adaptor-framework/scene-holder.h>
+#include <dali/internal/adaptor/common/adaptor-impl.h>
 #include <dali/internal/adaptor/common/application-impl.h>
+#include <dali/internal/network/common/network-service-impl.h>
 
 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<Dali::Internal::Adaptor::Application*>(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
index e82281c..095c252 100644 (file)
@@ -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.
 
 // INTERNAL INCLUDES
 #include <dali/public-api/adaptor-framework/application.h>
+#include <dali/public-api/dali-adaptor-common.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/signals/dali-signal.h>
 
 namespace Dali
 {
 namespace DevelApplication
 {
+
+using CustomCommandReceivedSignalType = Signal<void(const std::string&)>; ///< 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
index 2a5ba8f..ebe4467 100644 (file)
@@ -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.
 
 // EXTERNAL INCLUDES
 #include <dali/integration-api/debug.h>
-#include <dali/internal/adaptor/common/adaptor-impl.h>
 #include <dali/public-api/dali-core.h>
 #include <stdio.h>
 #include <iomanip>
 #include <sstream>
 
+// INTERNAL INCLUDES
+#include <dali/internal/adaptor/common/adaptor-impl.h>
+#include <dali/internal/network/common/network-service-impl.h>
+
 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
index c675001..44e0418 100644 (file)
@@ -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
index 836f2ba..4a02097 100644 (file)
@@ -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 <stdio.h>
+#include <iostream>
 #include <string>
 
 // 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<typename T>
+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;
     }
 
index 5c23e84..d921f58 100644 (file)
@@ -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
index a5123b2..1313e96 100644 (file)
@@ -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 (file)
index 0000000..30dc19e
--- /dev/null
@@ -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 <dali/internal/network/common/network-service-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/common/singleton-service.h>
+
+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<NetworkService*>(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 (file)
index 0000000..3b4b796
--- /dev/null
@@ -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 <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/application-devel.h>
+
+namespace Dali
+{
+namespace Internal::Adaptor
+{
+
+class NetworkService;
+using NetworkServicePtr = IntrusivePtr<NetworkService>;
+
+/**
+ * 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
index 0beeaaf..aaa421c 100644 (file)
@@ -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
 )