3 * Copyright (c) 2021 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/internal/adaptor/common/adaptor-impl.h>
25 #include <dali/public-api/dali-core.h>
34 namespace // un-named namespace
36 const unsigned int MAX_SET_PROPERTY_STRING_LENGTH = 256; ///< maximum length of a set property command
38 class JsonPropertyValue
41 JsonPropertyValue(const std::string& str)
43 std::size_t strLength = str.length();
45 mString.reserve(strLength);
46 for(std::size_t i = 0; i < strLength; ++i)
48 const char c = str[i];
49 if((c != '[') && c != ']')
55 std::string GetString() const
59 float GetFloat() const
61 return atof(mString.c_str());
65 return atoi(mString.c_str());
69 return (GetInt() != 0);
72 Dali::Vector2 GetVector2()
76 int count = sscanf(mString.c_str(), "%f,%f", &vec2.x, &vec2.y);
79 DALI_LOG_ERROR("Bad format\n");
84 Dali::Vector3 GetVector3()
88 int count = sscanf(mString.c_str(), "%f,%f,%f", &vec3.x, &vec3.y, &vec3.z);
91 DALI_LOG_ERROR("Bad format\n");
96 Dali::Vector4 GetVector4()
100 int count = sscanf(mString.c_str(), "%f,%f,%f,%f", &vec4.x, &vec4.y, &vec4.z, &vec4.w);
103 DALI_LOG_ERROR("Bad format\n");
112 void SetProperty(Dali::Handle handle, int propertyId, JsonPropertyValue& propertyValue)
114 Dali::Property::Type type = handle.GetPropertyType(propertyId);
117 case Dali::Property::FLOAT:
119 float val = propertyValue.GetFloat();
120 handle.SetProperty(propertyId, Dali::Property::Value(val));
123 case Dali::Property::INTEGER:
125 int val = propertyValue.GetInt();
126 handle.SetProperty(propertyId, Dali::Property::Value(val));
129 case Dali::Property::BOOLEAN:
131 bool val = propertyValue.GetBoolean();
132 handle.SetProperty(propertyId, Dali::Property::Value(val));
135 case Dali::Property::STRING:
137 std::string str = propertyValue.GetString();
138 handle.SetProperty(propertyId, Dali::Property::Value(str));
141 case Dali::Property::VECTOR2:
143 Dali::Vector2 val = propertyValue.GetVector2();
144 handle.SetProperty(propertyId, Dali::Property::Value(val));
147 case Dali::Property::VECTOR3:
149 Dali::Vector3 val = propertyValue.GetVector3();
150 handle.SetProperty(propertyId, Dali::Property::Value(val));
153 case Dali::Property::VECTOR4:
155 Dali::Vector4 val = propertyValue.GetVector4();
156 handle.SetProperty(propertyId, Dali::Property::Value(val));
166 int SetProperties(const std::string& setPropertyMessage)
168 Dali::Actor root = Dali::Internal::Adaptor::Adaptor::Get().GetWindows()[0].GetRootLayer();
170 std::istringstream iss(setPropertyMessage);
172 getline(iss, token, '|'); // swallow command name
173 while(getline(iss, token, '|'))
175 std::string actorId, propName, propValue;
176 if(token.compare("---") != 0)
178 std::istringstream propss(token);
179 getline(propss, actorId, ';');
180 getline(propss, propName, ';');
181 getline(propss, propValue);
183 int id = atoi(actorId.c_str());
184 Dali::Actor a = root.FindChildById(id);
187 // lookup by name for custom properties
188 int propId = a.GetPropertyIndex(propName);
191 JsonPropertyValue pv(propValue);
192 SetProperty(a, propId, pv);
201 void MatrixToStream(Property::Value value, std::ostream& o)
208 float* matrix = m4.AsFloat();
209 o << "[ [" << matrix[0] << ", " << matrix[1] << ", " << matrix[2] << ", " << matrix[3] << "], "
210 << "[" << matrix[4] << ", " << matrix[5] << ", " << matrix[6] << ", " << matrix[7] << "], "
211 << "[" << matrix[8] << ", " << matrix[9] << ", " << matrix[10] << ", " << matrix[11] << "], "
212 << "[" << matrix[12] << ", " << matrix[13] << ", " << matrix[14] << ", " << matrix[15] << "] ]";
214 else if(value.Get(m3))
216 float* matrix = m3.AsFloat();
217 o << "[ [" << matrix[0] << ", " << matrix[1] << ", " << matrix[2] << "], "
218 << "[" << matrix[3] << ", " << matrix[4] << ", " << matrix[5] << "], "
219 << "[" << matrix[6] << ", " << matrix[7] << ", " << matrix[8] << "] ]";
225 inline std::string Quote(const std::string& in)
227 return (std::string("\"") + in + std::string("\""));
231 std::string ToString(T i)
233 std::stringstream ss;
241 std::string GetPropertyValueString(Dali::Handle handle, int propertyIndex)
243 std::ostringstream valueStream;
244 if(propertyIndex != Dali::Property::INVALID_INDEX)
246 Dali::Property::Value value = handle.GetProperty(propertyIndex);
248 switch(value.GetType())
250 case Dali::Property::STRING:
251 case Dali::Property::MAP:
252 case Dali::Property::ARRAY:
254 // Escape the string (to ensure valid json)
255 // Write out quotes, escapes and control characters using unicode syntax \uXXXX
256 std::ostringstream unescapedValue;
257 unescapedValue << value;
258 std::string valueString = unescapedValue.str();
259 std::ostringstream escapedValue;
260 for(std::string::iterator c = valueString.begin(); c != valueString.end(); ++c)
264 escapedValue << "\\\"";
268 escapedValue << "\\\\";
272 escapedValue << "\\\n";
274 else if('\x00' <= *c && *c <= '\x1f')
276 escapedValue << "\\u" << std::hex << std::setw(4) << std::setfill('0') << int(*c);
283 valueStream << escapedValue.str();
286 case Dali::Property::MATRIX:
287 case Dali::Property::MATRIX3:
289 MatrixToStream(value, valueStream);
294 valueStream << value;
301 valueStream << "INVALID";
304 return valueStream.str();
307 // currently rotations are output in Euler format ( may change)
308 void AppendPropertyNameAndValue(Dali::Handle handle, int propertyIndex, std::ostringstream& outputStream)
310 // get the property name and the value as a string
311 std::string propertyName(handle.GetPropertyName(propertyIndex));
313 // Apply quotes around the property name
314 outputStream << "\"" << propertyName << "\""
317 // Convert value to a string
318 std::string valueString = GetPropertyValueString(handle, propertyIndex);
320 outputStream << "\"" << valueString << "\"";
323 void AppendRendererPropertyNameAndValue(Dali::Renderer renderer, int rendererIndex, const std::string& name, std::ostringstream& outputStream)
325 outputStream << ",[\"renderer[" << rendererIndex << "]." << name << "\""
327 std::string valueString = GetPropertyValueString(renderer, renderer.GetPropertyIndex(name));
328 outputStream << "\"" << valueString << "\"]";
331 bool ExcludeProperty(int propIndex)
333 // all of these are repeat properties of values in vectors....
334 // We don't really need these in the UI
335 return (propIndex == Dali::Actor::Property::NAME ||
336 propIndex == Dali::Actor::Property::ANCHOR_POINT_X ||
337 propIndex == Dali::Actor::Property::ANCHOR_POINT_Y ||
338 propIndex == Dali::Actor::Property::ANCHOR_POINT_Z ||
339 propIndex == Dali::Actor::Property::PARENT_ORIGIN_X ||
340 propIndex == Dali::Actor::Property::PARENT_ORIGIN_Y ||
341 propIndex == Dali::Actor::Property::PARENT_ORIGIN_Z ||
342 propIndex == Dali::Actor::Property::COLOR_RED ||
343 propIndex == Dali::Actor::Property::COLOR_GREEN ||
344 propIndex == Dali::Actor::Property::COLOR_BLUE ||
345 propIndex == Dali::Actor::Property::COLOR_ALPHA ||
346 propIndex == Dali::Actor::Property::POSITION_X ||
347 propIndex == Dali::Actor::Property::POSITION_Y ||
348 propIndex == Dali::Actor::Property::POSITION_Z ||
349 propIndex == Dali::Actor::Property::SIZE_WIDTH ||
350 propIndex == Dali::Actor::Property::SIZE_HEIGHT ||
351 propIndex == Dali::Actor::Property::SCALE_X ||
352 propIndex == Dali::Actor::Property::SCALE_Y ||
353 propIndex == Dali::Actor::Property::SCALE_Z ||
354 propIndex == Dali::Actor::Property::SIZE_DEPTH);
357 std::string DumpJson(Dali::Actor actor, int level)
359 // All the information about this actor
360 std::ostringstream msg;
361 int id = actor["id"];
362 msg << "{ " << Quote("Name") << " : " << Quote(actor.GetProperty<std::string>(Dali::Actor::Property::NAME)) << ", " << Quote("level") << " : " << level << ", " << Quote("id") << " : " << id << ", " << Quote("IsVisible")
363 << " : " << actor.GetCurrentProperty<bool>(Dali::Actor::Property::VISIBLE) << ", " << Quote("IsSensitive") << " : " << actor.GetProperty<bool>(Dali::Actor::Property::SENSITIVE);
365 msg << ", " << Quote("properties") << ": [ ";
367 Dali::Property::IndexContainer indices;
368 actor.GetPropertyIndices(indices);
370 Dali::Property::IndexContainer::Iterator iter = indices.Begin();
372 for(; iter != indices.End(); iter++)
375 if(!ExcludeProperty(i))
383 AppendPropertyNameAndValue(actor, i, msg);
388 if(actor.GetRendererCount() > 0)
390 for(unsigned int i = 0; i < actor.GetRendererCount(); ++i)
392 auto renderer = actor.GetRendererAt(i);
393 AppendRendererPropertyNameAndValue(renderer, i, "offset", msg);
394 AppendRendererPropertyNameAndValue(renderer, i, "size", msg);
395 AppendRendererPropertyNameAndValue(renderer, i, "offsetSizeMode", msg);
396 AppendRendererPropertyNameAndValue(renderer, i, "origin", msg);
397 AppendRendererPropertyNameAndValue(renderer, i, "anchorPoint", msg);
402 msg << ", " << Quote("children") << " : [ ";
404 // Recursively dump all the children as well
405 for(unsigned int i = 0; i < actor.GetChildCount(); ++i)
411 msg << DumpJson(actor.GetChildAt(i), level + 1);
418 std::string GetActorTree()
420 Dali::Actor actor = Dali::Internal::Adaptor::Adaptor::Get().GetWindows()[0].GetRootLayer();
421 std::string str = DumpJson(actor, 0);
433 void SetProperty(const std::string& message)
435 // check the set property length is within range
436 if(message.length() > MAX_SET_PROPERTY_STRING_LENGTH)
438 DALI_LOG_ERROR("SetProperty message length too long, size = %ul\n", message.length());
442 SetProperties(message);
445 void DumpScene(unsigned int clientId, ClientSendDataInterface* sendData)
448 std::string json = GetActorTree();
449 int length = json.length();
450 snprintf(buf, 32, "%d\n", length);
451 std::string header(buf);
453 sendData->SendData(json.c_str(), json.length(), clientId);
456 } // namespace Automation
458 } // namespace Adaptor
460 } // namespace Internal