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/public-api/dali-core.h>
33 namespace // un-named namespace
35 const unsigned int MAX_SET_PROPERTY_STRING_LENGTH = 256; ///< maximum length of a set property command
37 class JsonPropertyValue
40 JsonPropertyValue(const std::string& str)
42 std::size_t strLength = str.length();
44 mString.reserve(strLength);
45 for(std::size_t i = 0; i < strLength; ++i)
47 const char c = str[i];
48 if((c != '[') && c != ']')
54 std::string GetString() const
58 float GetFloat() const
60 return atof(mString.c_str());
64 return atoi(mString.c_str());
68 return (GetInt() != 0);
71 Dali::Vector2 GetVector2()
75 int count = sscanf(mString.c_str(), "%f,%f", &vec2.x, &vec2.y);
78 DALI_LOG_ERROR("Bad format\n");
83 Dali::Vector3 GetVector3()
87 int count = sscanf(mString.c_str(), "%f,%f,%f", &vec3.x, &vec3.y, &vec3.z);
90 DALI_LOG_ERROR("Bad format\n");
95 Dali::Vector4 GetVector4()
99 int count = sscanf(mString.c_str(), "%f,%f,%f,%f", &vec4.x, &vec4.y, &vec4.z, &vec4.w);
102 DALI_LOG_ERROR("Bad format\n");
111 void SetProperty(Dali::Handle handle, int propertyId, JsonPropertyValue& propertyValue)
113 Dali::Property::Type type = handle.GetPropertyType(propertyId);
116 case Dali::Property::FLOAT:
118 float val = propertyValue.GetFloat();
119 handle.SetProperty(propertyId, Dali::Property::Value(val));
122 case Dali::Property::INTEGER:
124 int val = propertyValue.GetInt();
125 handle.SetProperty(propertyId, Dali::Property::Value(val));
128 case Dali::Property::BOOLEAN:
130 bool val = propertyValue.GetBoolean();
131 handle.SetProperty(propertyId, Dali::Property::Value(val));
134 case Dali::Property::STRING:
136 std::string str = propertyValue.GetString();
137 handle.SetProperty(propertyId, Dali::Property::Value(str));
140 case Dali::Property::VECTOR2:
142 Dali::Vector2 val = propertyValue.GetVector2();
143 handle.SetProperty(propertyId, Dali::Property::Value(val));
146 case Dali::Property::VECTOR3:
148 Dali::Vector3 val = propertyValue.GetVector3();
149 handle.SetProperty(propertyId, Dali::Property::Value(val));
152 case Dali::Property::VECTOR4:
154 Dali::Vector4 val = propertyValue.GetVector4();
155 handle.SetProperty(propertyId, Dali::Property::Value(val));
165 int SetProperties(const std::string& setPropertyMessage)
167 std::istringstream iss(setPropertyMessage);
169 getline(iss, token, '|'); // swallow command name
170 while(getline(iss, token, '|'))
172 std::string actorId, propName, propValue;
173 if(token.compare("---") != 0)
175 std::istringstream propss(token);
176 getline(propss, actorId, ';');
177 getline(propss, propName, ';');
178 getline(propss, propValue);
180 Dali::Actor root = Dali::Stage::GetCurrent().GetRootLayer();
181 int id = atoi(actorId.c_str());
182 Dali::Actor a = root.FindChildById(id);
185 // lookup by name for custom properties
186 int propId = a.GetPropertyIndex(propName);
189 JsonPropertyValue pv(propValue);
190 SetProperty(a, propId, pv);
199 void MatrixToStream(Property::Value value, std::ostream& o)
206 float* matrix = m4.AsFloat();
207 o << "[ [" << matrix[0] << ", " << matrix[1] << ", " << matrix[2] << ", " << matrix[3] << "], "
208 << "[" << matrix[4] << ", " << matrix[5] << ", " << matrix[6] << ", " << matrix[7] << "], "
209 << "[" << matrix[8] << ", " << matrix[9] << ", " << matrix[10] << ", " << matrix[11] << "], "
210 << "[" << matrix[12] << ", " << matrix[13] << ", " << matrix[14] << ", " << matrix[15] << "] ]";
212 else if(value.Get(m3))
214 float* matrix = m3.AsFloat();
215 o << "[ [" << matrix[0] << ", " << matrix[1] << ", " << matrix[2] << "], "
216 << "[" << matrix[3] << ", " << matrix[4] << ", " << matrix[5] << "], "
217 << "[" << matrix[6] << ", " << matrix[7] << ", " << matrix[8] << "] ]";
223 inline std::string Quote(const std::string& in)
225 return (std::string("\"") + in + std::string("\""));
229 std::string ToString(T i)
231 std::stringstream ss;
239 std::string GetPropertyValueString(Dali::Handle handle, int propertyIndex)
241 std::ostringstream valueStream;
242 if(propertyIndex != Dali::Property::INVALID_INDEX)
244 Dali::Property::Value value = handle.GetProperty(propertyIndex);
246 if(value.GetType() == Dali::Property::STRING)
248 // Escape the string (to ensure valid json)
249 // Write out quotes, escapes and control characters using unicode syntax \uXXXX
250 std::ostringstream unescapedValue;
251 unescapedValue << value;
252 std::string valueString = unescapedValue.str();
253 std::ostringstream escapedValue;
254 for(std::string::iterator c = valueString.begin(); c != valueString.end(); ++c)
258 escapedValue << "\\\"";
262 escapedValue << "\\\\";
264 else if('\x00' <= *c && *c <= '\x1f')
266 escapedValue << "\\u" << std::hex << std::setw(4) << std::setfill('0') << int(*c);
273 valueStream << escapedValue.str();
275 else if(value.GetType() == Dali::Property::MATRIX || value.GetType() == Dali::Property::MATRIX3)
277 MatrixToStream(value, valueStream);
281 valueStream << value;
286 valueStream << "INVALID";
289 return valueStream.str();
292 // currently rotations are output in Euler format ( may change)
293 void AppendPropertyNameAndValue(Dali::Handle handle, int propertyIndex, std::ostringstream& outputStream)
295 // get the property name and the value as a string
296 std::string propertyName(handle.GetPropertyName(propertyIndex));
298 // Apply quotes around the property name
299 outputStream << "\"" << propertyName << "\""
302 // Convert value to a string
303 std::string valueString = GetPropertyValueString(handle, propertyIndex);
305 outputStream << "\"" << valueString << "\"";
308 void AppendRendererPropertyNameAndValue(Dali::Renderer renderer, int rendererIndex, const std::string& name, std::ostringstream& outputStream)
310 outputStream << ",[\"renderer[" << rendererIndex << "]." << name << "\""
312 std::string valueString = GetPropertyValueString(renderer, renderer.GetPropertyIndex(name));
313 outputStream << "\"" << valueString << "\"]";
316 bool ExcludeProperty(int propIndex)
318 // all of these are repeat properties of values in vectors....
319 // We don't really need these in the UI
320 return (propIndex == Dali::Actor::Property::NAME ||
321 propIndex == Dali::Actor::Property::ANCHOR_POINT_X ||
322 propIndex == Dali::Actor::Property::ANCHOR_POINT_Y ||
323 propIndex == Dali::Actor::Property::ANCHOR_POINT_Z ||
324 propIndex == Dali::Actor::Property::PARENT_ORIGIN_X ||
325 propIndex == Dali::Actor::Property::PARENT_ORIGIN_Y ||
326 propIndex == Dali::Actor::Property::PARENT_ORIGIN_Z ||
327 propIndex == Dali::Actor::Property::COLOR_RED ||
328 propIndex == Dali::Actor::Property::COLOR_GREEN ||
329 propIndex == Dali::Actor::Property::COLOR_BLUE ||
330 propIndex == Dali::Actor::Property::COLOR_ALPHA ||
331 propIndex == Dali::Actor::Property::POSITION_X ||
332 propIndex == Dali::Actor::Property::POSITION_Y ||
333 propIndex == Dali::Actor::Property::POSITION_Z ||
334 propIndex == Dali::Actor::Property::SIZE_WIDTH ||
335 propIndex == Dali::Actor::Property::SIZE_HEIGHT ||
336 propIndex == Dali::Actor::Property::SCALE_X ||
337 propIndex == Dali::Actor::Property::SCALE_Y ||
338 propIndex == Dali::Actor::Property::SCALE_Z ||
339 propIndex == Dali::Actor::Property::SIZE_DEPTH);
342 std::string DumpJson(Dali::Actor actor, int level)
344 // All the information about this actor
345 std::ostringstream msg;
346 msg << "{ " << Quote("Name") << " : " << Quote(actor.GetProperty<std::string>(Actor::Property::NAME)) << ", " << Quote("level") << " : " << level << ", " << Quote("id") << " : " << actor.GetId() << ", " << Quote("IsVisible")
347 << " : " << actor.GetCurrentProperty<bool>(Actor::Property::VISIBLE) << ", " << Quote("IsSensitive") << " : " << actor.GetProperty<bool>(Actor::Property::SENSITIVE);
349 msg << ", " << Quote("properties") << ": [ ";
351 Dali::Property::IndexContainer indices;
352 actor.GetPropertyIndices(indices);
354 Dali::Property::IndexContainer::Iterator iter = indices.Begin();
356 for(; iter != indices.End(); iter++)
359 if(!ExcludeProperty(i))
367 AppendPropertyNameAndValue(actor, i, msg);
372 if(actor.GetRendererCount() > 0)
374 for(unsigned int i = 0; i < actor.GetRendererCount(); ++i)
376 auto renderer = actor.GetRendererAt(i);
377 AppendRendererPropertyNameAndValue(renderer, i, "offset", msg);
378 AppendRendererPropertyNameAndValue(renderer, i, "size", msg);
379 AppendRendererPropertyNameAndValue(renderer, i, "offsetSizeMode", msg);
380 AppendRendererPropertyNameAndValue(renderer, i, "origin", msg);
381 AppendRendererPropertyNameAndValue(renderer, i, "anchorPoint", msg);
386 msg << ", " << Quote("children") << " : [ ";
388 // Recursively dump all the children as well
389 for(unsigned int i = 0; i < actor.GetChildCount(); ++i)
395 msg << DumpJson(actor.GetChildAt(i), level + 1);
402 std::string GetActorTree()
404 Dali::Actor actor = Dali::Stage::GetCurrent().GetRootLayer();
405 std::string str = DumpJson(actor, 0);
417 void SetProperty(const std::string& message)
419 // check the set property length is within range
420 if(message.length() > MAX_SET_PROPERTY_STRING_LENGTH)
422 DALI_LOG_ERROR("SetProperty message length too long, size = %ul\n", message.length());
426 SetProperties(message);
429 void DumpScene(unsigned int clientId, ClientSendDataInterface* sendData)
432 std::string json = GetActorTree();
433 int length = json.length();
434 snprintf(buf, 32, "%d\n", length);
435 std::string header(buf);
437 sendData->SendData(json.c_str(), json.length(), clientId);
440 } // namespace Automation
442 } // namespace Adaptor
444 } // namespace Internal