3 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 #include <dali/internal/network/common/automation.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/public-api/dali-core.h>
30 #include <dali/internal/adaptor/common/adaptor-impl.h>
31 #include <dali/internal/network/common/network-service-impl.h>
37 namespace // un-named namespace
39 const unsigned int MAX_SET_PROPERTY_STRING_LENGTH = 256; ///< maximum length of a set property command
41 class JsonPropertyValue
44 JsonPropertyValue(const std::string& str)
46 std::size_t strLength = str.length();
48 mString.reserve(strLength);
49 for(std::size_t i = 0; i < strLength; ++i)
51 const char c = str[i];
52 if((c != '[') && c != ']')
58 std::string GetString() const
62 float GetFloat() const
64 return atof(mString.c_str());
68 return atoi(mString.c_str());
72 return (GetInt() != 0);
75 Dali::Vector2 GetVector2()
79 int count = sscanf(mString.c_str(), "%f,%f", &vec2.x, &vec2.y);
82 DALI_LOG_ERROR("Bad format\n");
87 Dali::Vector3 GetVector3()
91 int count = sscanf(mString.c_str(), "%f,%f,%f", &vec3.x, &vec3.y, &vec3.z);
94 DALI_LOG_ERROR("Bad format\n");
99 Dali::Vector4 GetVector4()
103 int count = sscanf(mString.c_str(), "%f,%f,%f,%f", &vec4.x, &vec4.y, &vec4.z, &vec4.w);
106 DALI_LOG_ERROR("Bad format\n");
115 void SetProperty(Dali::Handle handle, int propertyId, JsonPropertyValue& propertyValue)
117 Dali::Property::Type type = handle.GetPropertyType(propertyId);
120 case Dali::Property::FLOAT:
122 float val = propertyValue.GetFloat();
123 handle.SetProperty(propertyId, Dali::Property::Value(val));
126 case Dali::Property::INTEGER:
128 int val = propertyValue.GetInt();
129 handle.SetProperty(propertyId, Dali::Property::Value(val));
132 case Dali::Property::BOOLEAN:
134 bool val = propertyValue.GetBoolean();
135 handle.SetProperty(propertyId, Dali::Property::Value(val));
138 case Dali::Property::STRING:
140 std::string str = propertyValue.GetString();
141 handle.SetProperty(propertyId, Dali::Property::Value(str));
144 case Dali::Property::VECTOR2:
146 Dali::Vector2 val = propertyValue.GetVector2();
147 handle.SetProperty(propertyId, Dali::Property::Value(val));
150 case Dali::Property::VECTOR3:
152 Dali::Vector3 val = propertyValue.GetVector3();
153 handle.SetProperty(propertyId, Dali::Property::Value(val));
156 case Dali::Property::VECTOR4:
158 Dali::Vector4 val = propertyValue.GetVector4();
159 handle.SetProperty(propertyId, Dali::Property::Value(val));
169 int SetProperties(const std::string& setPropertyMessage)
171 Dali::Actor root = Dali::Internal::Adaptor::Adaptor::Get().GetWindows()[0].GetRootLayer();
173 std::istringstream iss(setPropertyMessage);
175 getline(iss, token, '|'); // swallow command name
176 while(getline(iss, token, '|'))
178 std::string actorId, propName, propValue;
179 if(token.compare("---") != 0)
181 std::istringstream propss(token);
182 getline(propss, actorId, ';');
183 getline(propss, propName, ';');
184 getline(propss, propValue);
186 int id = atoi(actorId.c_str());
187 Dali::Actor a = root.FindChildById(id);
190 // lookup by name for custom properties
191 int propId = a.GetPropertyIndex(propName);
194 JsonPropertyValue pv(propValue);
195 SetProperty(a, propId, pv);
204 void MatrixToStream(Property::Value value, std::ostream& o)
211 float* matrix = m4.AsFloat();
212 o << "[ [" << matrix[0] << ", " << matrix[1] << ", " << matrix[2] << ", " << matrix[3] << "], "
213 << "[" << matrix[4] << ", " << matrix[5] << ", " << matrix[6] << ", " << matrix[7] << "], "
214 << "[" << matrix[8] << ", " << matrix[9] << ", " << matrix[10] << ", " << matrix[11] << "], "
215 << "[" << matrix[12] << ", " << matrix[13] << ", " << matrix[14] << ", " << matrix[15] << "] ]";
217 else if(value.Get(m3))
219 float* matrix = m3.AsFloat();
220 o << "[ [" << matrix[0] << ", " << matrix[1] << ", " << matrix[2] << "], "
221 << "[" << matrix[3] << ", " << matrix[4] << ", " << matrix[5] << "], "
222 << "[" << matrix[6] << ", " << matrix[7] << ", " << matrix[8] << "] ]";
228 inline std::string Quote(const std::string& in)
230 return (std::string("\"") + in + std::string("\""));
234 std::string ToString(T i)
236 std::stringstream ss;
244 std::string GetPropertyValueString(Dali::Handle handle, int propertyIndex)
246 std::ostringstream valueStream;
247 if(propertyIndex != Dali::Property::INVALID_INDEX)
249 Dali::Property::Value value = handle.GetProperty(propertyIndex);
251 switch(value.GetType())
253 case Dali::Property::STRING:
254 case Dali::Property::MAP:
255 case Dali::Property::ARRAY:
257 // Escape the string (to ensure valid json)
258 // Write out quotes, escapes and control characters using unicode syntax \uXXXX
259 std::ostringstream unescapedValue;
260 unescapedValue << value;
261 std::string valueString = unescapedValue.str();
262 std::ostringstream escapedValue;
263 for(std::string::iterator c = valueString.begin(); c != valueString.end(); ++c)
267 escapedValue << "\\\"";
271 escapedValue << "\\\\";
275 escapedValue << "\\\n";
277 else if('\x00' <= *c && *c <= '\x1f')
279 escapedValue << "\\u" << std::hex << std::setw(4) << std::setfill('0') << int(*c);
286 valueStream << escapedValue.str();
289 case Dali::Property::MATRIX:
290 case Dali::Property::MATRIX3:
292 MatrixToStream(value, valueStream);
297 valueStream << value;
304 valueStream << "INVALID";
307 return valueStream.str();
310 // currently rotations are output in Euler format ( may change)
311 void AppendPropertyNameAndValue(Dali::Handle handle, int propertyIndex, std::ostringstream& outputStream)
313 // get the property name and the value as a string
314 std::string propertyName(handle.GetPropertyName(propertyIndex));
316 // Apply quotes around the property name
317 outputStream << "\"" << propertyName << "\""
320 // Convert value to a string
321 std::string valueString = GetPropertyValueString(handle, propertyIndex);
323 outputStream << "\"" << valueString << "\"";
326 void AppendRendererPropertyNameAndValue(Dali::Renderer renderer, int rendererIndex, const std::string& name, std::ostringstream& outputStream)
328 outputStream << ",[\"renderer[" << rendererIndex << "]." << name << "\""
330 std::string valueString = GetPropertyValueString(renderer, renderer.GetPropertyIndex(name));
331 outputStream << "\"" << valueString << "\"]";
334 bool ExcludeProperty(int propIndex)
336 // all of these are repeat properties of values in vectors....
337 // We don't really need these in the UI
338 return (propIndex == Dali::Actor::Property::NAME ||
339 propIndex == Dali::Actor::Property::ANCHOR_POINT_X ||
340 propIndex == Dali::Actor::Property::ANCHOR_POINT_Y ||
341 propIndex == Dali::Actor::Property::ANCHOR_POINT_Z ||
342 propIndex == Dali::Actor::Property::PARENT_ORIGIN_X ||
343 propIndex == Dali::Actor::Property::PARENT_ORIGIN_Y ||
344 propIndex == Dali::Actor::Property::PARENT_ORIGIN_Z ||
345 propIndex == Dali::Actor::Property::COLOR_RED ||
346 propIndex == Dali::Actor::Property::COLOR_GREEN ||
347 propIndex == Dali::Actor::Property::COLOR_BLUE ||
348 propIndex == Dali::Actor::Property::COLOR_ALPHA ||
349 propIndex == Dali::Actor::Property::POSITION_X ||
350 propIndex == Dali::Actor::Property::POSITION_Y ||
351 propIndex == Dali::Actor::Property::POSITION_Z ||
352 propIndex == Dali::Actor::Property::SIZE_WIDTH ||
353 propIndex == Dali::Actor::Property::SIZE_HEIGHT ||
354 propIndex == Dali::Actor::Property::SCALE_X ||
355 propIndex == Dali::Actor::Property::SCALE_Y ||
356 propIndex == Dali::Actor::Property::SCALE_Z ||
357 propIndex == Dali::Actor::Property::SIZE_DEPTH);
360 std::string DumpJson(Dali::Actor actor, int level)
362 // All the information about this actor
363 std::ostringstream msg;
364 int id = actor["id"];
365 msg << "{ " << Quote("Name") << " : " << Quote(actor.GetProperty<std::string>(Dali::Actor::Property::NAME)) << ", " << Quote("level") << " : " << level << ", " << Quote("id") << " : " << id << ", " << Quote("IsVisible")
366 << " : " << actor.GetCurrentProperty<bool>(Dali::Actor::Property::VISIBLE) << ", " << Quote("IsSensitive") << " : " << actor.GetProperty<bool>(Dali::Actor::Property::SENSITIVE);
368 msg << ", " << Quote("properties") << ": [ ";
370 Dali::Property::IndexContainer indices;
371 actor.GetPropertyIndices(indices);
373 Dali::Property::IndexContainer::Iterator iter = indices.Begin();
375 for(; iter != indices.End(); iter++)
378 if(!ExcludeProperty(i))
386 AppendPropertyNameAndValue(actor, i, msg);
391 if(actor.GetRendererCount() > 0)
393 for(unsigned int i = 0; i < actor.GetRendererCount(); ++i)
395 auto renderer = actor.GetRendererAt(i);
396 AppendRendererPropertyNameAndValue(renderer, i, "offset", msg);
397 AppendRendererPropertyNameAndValue(renderer, i, "size", msg);
398 AppendRendererPropertyNameAndValue(renderer, i, "offsetSizeMode", msg);
399 AppendRendererPropertyNameAndValue(renderer, i, "origin", msg);
400 AppendRendererPropertyNameAndValue(renderer, i, "anchorPoint", msg);
405 msg << ", " << Quote("children") << " : [ ";
407 // Recursively dump all the children as well
408 for(unsigned int i = 0; i < actor.GetChildCount(); ++i)
414 msg << DumpJson(actor.GetChildAt(i), level + 1);
421 std::string GetActorTree()
423 Dali::Actor actor = Dali::Internal::Adaptor::Adaptor::Get().GetWindows()[0].GetRootLayer();
424 std::string str = DumpJson(actor, 0);
436 void SetProperty(const std::string& message)
438 // check the set property length is within range
439 if(message.length() > MAX_SET_PROPERTY_STRING_LENGTH)
441 DALI_LOG_ERROR("SetProperty message length too long, size = %ul\n", message.length());
445 SetProperties(message);
448 void DumpScene(unsigned int clientId, ClientSendDataInterface* sendData)
451 std::string json = GetActorTree();
452 int length = json.length();
453 snprintf(buf, 32, "%d\n", length);
454 std::string header(buf);
456 sendData->SendData(json.c_str(), json.length(), clientId);
459 void SetCustomCommand(const std::string& message)
461 if(Adaptor::IsAvailable())
463 Internal::Adaptor::NetworkServicePtr networkService = Internal::Adaptor::NetworkService::Get();
466 networkService->EmitCustomCommandReceivedSignal(message);
471 } // namespace Automation
473 } // namespace Adaptor
475 } // namespace Internal