--- /dev/null
+/*
+* Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* 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.
+*/
+
+#ifndef __TIZEN_MEDIA_ROSE_CTLINFO_H__
+#define __TIZEN_MEDIA_ROSE_CTLINFO_H__
+
+#include <glib.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _rose_control_info rose_control_info;
+typedef struct _rose_sdc_element rose_sdc_element;
+
+typedef struct _rose_sdc_namespace rose_sdc_namespace;
+typedef struct _rose_sdc_light rose_sdc_light;
+typedef struct _rose_sdc_flash rose_sdc_flash;
+typedef struct _rose_sdc_wind rose_sdc_wind;
+typedef struct _rose_sdc_vibration rose_sdc_vibration;
+
+
+/* Sensory Device Capabilitye type */
+typedef enum {
+ SDC_TYPE_NONE,
+ SDC_TYPE_LIGHT,
+ SDC_TYPE_FLASH,
+ SDC_TYPE_WIND,
+ SDC_TYPE_VIBRATION,
+ SDC_TYPE_MAX,
+} rose_sdc_type_e;
+
+struct _rose_sdc_light {
+ gboolean color_flag;
+ gboolean unit_flag;
+ gboolean max_intensity_flag;
+ gboolean num_of_light_levels_flag;
+
+ GList *color;
+ gchar *unit;
+ guint max_intensity;
+ guint num_of_light_levels;
+};
+
+struct _rose_sdc_flash {
+ gboolean max_freq_flag;
+ gboolean num_of_freq_levels_flag;
+ rose_sdc_light *light;
+ gint max_freq;
+ guint num_of_freq_levels;
+};
+
+struct _rose_sdc_wind {
+ gboolean unit_flag;
+ gboolean max_wind_speed_flag;
+ gboolean num_of_levels_flag;
+
+ gchar *unit;
+ guint max_wind_speed;
+ guint num_of_levels;
+};
+
+struct _rose_sdc_vibration {
+ gboolean unit_flag;
+ gboolean max_intensity_flag;
+ gboolean num_of_levels_flag;
+
+ gchar *unit;
+ guint max_intensity;
+ guint num_of_levels;
+};
+
+struct _rose_sdc_namespace {
+ gchar *prefix;
+ gchar *href;
+};
+
+struct _rose_sdc_element {
+ gboolean zerothorderdelaytime_flag;
+ gboolean firstorderdelaytime_flag;
+ gchar *id;
+
+ rose_sdc_type_e sdc_type;
+
+ /* zerothOrderDealyTime (ms) */
+ guint zerothorderdelaytime;
+ /* firstOrderDealyTime (ms) */
+ guint firstorderdelaytime;
+
+ rose_sdc_light *light;
+ rose_sdc_flash *flash;
+ rose_sdc_wind *wind;
+ rose_sdc_vibration *vibration;
+};
+
+struct _rose_control_info {
+ GList *namespace;
+ /* rose_sdc_element */
+ GList *sdc_elements;
+};
+
+int rose_ctl_info_parse(xmlNode * a_node, rose_control_info ** ctl_info);
+void rose_ctl_info_free(rose_control_info * ctl_info);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TIZEN_MEDIA_ROSE_CTLINFO_H__ */
--- /dev/null
+/*
+* Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* 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.
+*/
+
+#include <string.h>
+#include "rose_tizen_priv.h"
+#include "rose_tizen_parse_xml.h"
+
+static gboolean _parse_namespace(xmlNode * node, rose_control_info *ctl_info);
+static void _free_namespace(rose_sdc_namespace * namespace);
+static gboolean _get_xml_prop_sdc_type(xmlNode * node,
+ const gchar * property_name, rose_sdc_type_e * property_value);
+
+static gboolean _parse_sdc_element(xmlNode * node, rose_control_info *ctl_info);
+static gboolean _parse_sdc_list(xmlNode * node, rose_control_info *ctl_info);
+static gboolean _parse_sdc_light_type(xmlNode * node, rose_sdc_light **light);
+static gboolean _parse_sdc_flash_type(xmlNode * node, rose_sdc_flash **flash);
+static gboolean _parse_sdc_wind_type(xmlNode * node, rose_sdc_wind **wind);
+static gboolean _parse_sdc_vibration_type(xmlNode * node, rose_sdc_vibration **vibration);
+
+static void _free_sdc_element(rose_sdc_element * sdc_element);
+static void _free_sdc_light_type(rose_sdc_light *light);
+static void _free_sdc_flash_type(rose_sdc_flash *flash);
+static void _free_sdc_wind_type(rose_sdc_wind *wind);
+static void _free_sdc_vibration_type(rose_sdc_vibration *vibration);
+
+static gboolean _parse_namespace(xmlNode * node, rose_control_info *ctl_info)
+{
+ xmlNs *curr_ns;
+ gboolean exist = FALSE;
+
+ if (!ctl_info || !node)
+ return FALSE;
+
+ g_list_free_full(ctl_info->namespace, (GDestroyNotify) _free_namespace);
+
+ for (curr_ns = node->ns; curr_ns; curr_ns = curr_ns->next) {
+ if (curr_ns->prefix && curr_ns->href) {
+ rose_sdc_namespace *namespace = g_slice_new0(rose_sdc_namespace);
+ namespace->prefix = xmlMemStrdup((const gchar *)curr_ns->prefix);
+ namespace->href = xmlMemStrdup((const gchar *)curr_ns->href);
+ LOGD(" - %s namespace: %s", curr_ns->prefix, curr_ns->href);
+ ctl_info->namespace = g_list_append(ctl_info->namespace, namespace);
+ exist = TRUE;
+ }
+ }
+
+ return exist;
+}
+
+static void _free_namespace(rose_sdc_namespace * namespace)
+{
+ if (!namespace)
+ return;
+
+ if (namespace->prefix)
+ xmlFree(namespace->prefix);
+ if (namespace->href)
+ xmlFree(namespace->href);
+
+ g_slice_free(rose_sdc_namespace, namespace);
+}
+
+int rose_ctl_info_parse(xmlNode * node, rose_control_info ** ctl_info)
+{
+ xmlNode *cur_node;
+ rose_control_info * new_ctl_info;
+ int ret = ROSE_ERROR_NONE;
+ gboolean exist = FALSE;
+
+ rose_ctl_info_free(*ctl_info);
+ *ctl_info = NULL;
+
+ new_ctl_info = g_slice_new0(rose_control_info);
+
+ LOGD("namespaces of root ControlInfo node:");
+ exist |= _parse_namespace(node, new_ctl_info);
+
+ for (cur_node = node->children; cur_node; cur_node = cur_node->next) {
+ if (cur_node->type != XML_ELEMENT_NODE)
+ continue;
+
+ if (xmlStrstr(cur_node->name, (xmlChar *) "SensoryDeviceCapabilityList")) {
+ LOGD("Parsing SensoryDeviceCapabilityList");
+ _parse_sdc_list(cur_node, new_ctl_info);
+ } else {
+ /* now ctlinfo parse sdc list */
+ LOGW("there is no node in ControlInfo");
+ }
+ }
+
+ if (!exist) {
+ LOGW("There is no Element");
+ g_slice_free(rose_control_info, new_ctl_info);
+ new_ctl_info = NULL;
+ ret = ROSE_ERROR_INVALID_OPERATION;
+ }
+
+ return ret;
+}
+
+static gboolean _parse_sdc_list(xmlNode * node, rose_control_info *ctl_info)
+{
+ gboolean exist = FALSE;
+ xmlNode *cur_node;
+
+ for (cur_node = node->children; cur_node; cur_node = cur_node->next) {
+ if (cur_node->type != XML_ELEMENT_NODE)
+ continue;
+
+ if (xmlStrstr(cur_node->name, (xmlChar *) "SensoryDeviceCapability")) {
+ LOGD("Parsing ReferenceEffect");
+ exist |= _parse_sdc_element(cur_node, ctl_info);
+ } else {
+ LOGI("%s is not support now", cur_node->name);
+ }
+ }
+
+ return exist;
+}
+
+static gboolean _parse_sdc_element(xmlNode * node, rose_control_info *ctl_info)
+{
+ rose_sdc_element *new_sdc_element = NULL;
+ gboolean exist = FALSE;
+
+ new_sdc_element = g_slice_new0(rose_sdc_element);
+
+ exist |= _get_xml_prop_string(node, "id", &new_sdc_element->id);
+
+ exist |= new_sdc_element->zerothorderdelaytime_flag
+ = _get_xml_prop_unsigned_integer(node, "zerothOrderDelayTime",
+ &new_sdc_element->zerothorderdelaytime);
+
+ exist |= new_sdc_element->firstorderdelaytime_flag
+ = _get_xml_prop_unsigned_integer(node, "firstOrderDelayTime",
+ &new_sdc_element->firstorderdelaytime);
+
+ exist |= _get_xml_prop_sdc_type(node, "type", &new_sdc_element->sdc_type);
+
+ if (new_sdc_element->sdc_type > SDC_TYPE_NONE) {
+ switch (new_sdc_element->sdc_type) {
+ case SDC_TYPE_LIGHT:
+ exist |= _parse_sdc_light_type(node, &new_sdc_element->light);
+ case SDC_TYPE_FLASH:
+ exist |= _parse_sdc_flash_type(node, &new_sdc_element->flash);
+ break;
+ case SDC_TYPE_WIND:
+ exist |= _parse_sdc_wind_type(node, &new_sdc_element->wind);
+ break;
+ case SDC_TYPE_VIBRATION:
+ exist |= _parse_sdc_vibration_type(node, &new_sdc_element->vibration);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!exist) {
+ g_slice_free(rose_sdc_element, new_sdc_element);
+ new_sdc_element = NULL;
+ return FALSE;
+ }
+
+ ctl_info->sdc_elements = g_list_append(ctl_info->sdc_elements, new_sdc_element);
+
+ return exist;
+}
+
+static gboolean _get_xml_prop_sdc_type(xmlNode * node, const gchar * property_name, rose_sdc_type_e * property_value)
+{
+ xmlChar *prop_string;
+ gboolean exists = TRUE;
+
+ ROSE_CHECK_NULL_FALSE(property_value);
+
+ *property_value = SDC_TYPE_NONE;
+ prop_string = xmlGetProp(node, (const xmlChar *)property_name);
+ if (!prop_string)
+ return FALSE;
+
+ if (xmlStrstr(prop_string, (xmlChar *) "LightCapabilityType")) {
+ *property_value = SDC_TYPE_LIGHT;
+ LOGD(" - %s: LightCapabilityType", property_name);
+ } else if (xmlStrstr(prop_string, (xmlChar *) "FlashCapabilityType")) {
+ *property_value = SDC_TYPE_FLASH;
+ LOGD(" - %s: FlashCapabilityType", property_name);
+ } else if (xmlStrstr(prop_string, (xmlChar *) "WindCapabilityType")) {
+ *property_value = SDC_TYPE_WIND;
+ LOGD(" - %s: WindCapabilityType", property_name);
+ } else if (xmlStrstr(prop_string, (xmlChar *) "VibrationCapabilityType")) {
+ *property_value = SDC_TYPE_VIBRATION;
+ LOGD(" - %s: VibrationCapabilityType", property_name);
+ } else {
+ exists = FALSE;
+ LOGW("failed to parse sdc type property %s from xml string %s", property_name, prop_string);
+ }
+
+ xmlFree(prop_string);
+
+ return exists;
+}
+
+static gboolean _parse_sdc_light_type(xmlNode * node, rose_sdc_light **light)
+{
+ rose_sdc_light *new_light = NULL;
+ gboolean exist = FALSE;
+ // xmlNode *cur_node;
+
+ new_light = g_slice_new0(rose_sdc_light);
+
+ exist |= new_light->unit_flag =
+ _get_xml_prop_string(node, "unit", &new_light->unit);
+
+ exist |= new_light->max_intensity_flag
+ = _get_xml_prop_unsigned_integer(node, "maxIntensity",
+ &new_light->max_intensity);
+
+ exist |= new_light->num_of_light_levels_flag
+ = _get_xml_prop_unsigned_integer(node, "numOfLightLevels",
+ &new_light->num_of_light_levels);
+#if 0
+/* need to check color element */
+ for (cur_node = node->children; cur_node; cur_node = cur_node->next) {
+ if (cur_node->type != XML_ELEMENT_NODE)
+ continue;
+ if (xmlStrstr(cur_node->name, (xmlChar *) "Color")) {
+ gchar *color = NULL;
+ }
+ }
+#endif
+ if (!exist) {
+ g_slice_free(rose_sdc_light, new_light);
+ new_light = NULL;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean _parse_sdc_flash_type(xmlNode * node, rose_sdc_flash **flash)
+{
+ rose_sdc_flash *new_flash = NULL;
+ gboolean exist = FALSE;
+
+ new_flash = g_slice_new0(rose_sdc_flash);
+
+ exist |= new_flash->max_freq_flag
+ = _get_xml_prop_signed_integer(node, "maxFrequency",
+ &new_flash->max_freq);
+
+ exist |= new_flash->num_of_freq_levels_flag
+ = _get_xml_prop_unsigned_integer(node, "numOfFreqLevels",
+ &new_flash->num_of_freq_levels);
+ exist |= _parse_sdc_light_type (node, &new_flash->light);
+
+ if (!exist) {
+ g_slice_free(rose_sdc_flash, new_flash);
+ new_flash = NULL;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean _parse_sdc_wind_type(xmlNode * node, rose_sdc_wind **wind)
+{
+ rose_sdc_wind *new_wind = NULL;
+ gboolean exist = FALSE;
+
+ new_wind = g_slice_new0(rose_sdc_wind);
+
+ exist |= new_wind->unit_flag =
+ _get_xml_prop_string(node, "unit", &new_wind->unit);
+
+ exist |= new_wind->max_wind_speed_flag
+ = _get_xml_prop_unsigned_integer(node, "maxWindSpeed",
+ &new_wind->max_wind_speed);
+
+ exist |= new_wind->num_of_levels_flag
+ = _get_xml_prop_unsigned_integer(node, "numOfLevels",
+ &new_wind->num_of_levels);
+
+ if (!exist) {
+ g_slice_free(rose_sdc_wind, new_wind);
+ new_wind = NULL;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean _parse_sdc_vibration_type(xmlNode * node, rose_sdc_vibration **vibration)
+{
+ rose_sdc_vibration *new_vibration = NULL;
+ gboolean exist = FALSE;
+
+ new_vibration = g_slice_new0(rose_sdc_vibration);
+
+ exist |= new_vibration->unit_flag =
+ _get_xml_prop_string(node, "unit", &new_vibration->unit);
+
+ exist |= new_vibration->max_intensity_flag
+ = _get_xml_prop_unsigned_integer(node, "maxIntensity",
+ &new_vibration->max_intensity);
+
+ exist |= new_vibration->num_of_levels_flag
+ = _get_xml_prop_unsigned_integer(node, "numOfLevels",
+ &new_vibration->num_of_levels);
+
+ if (!exist) {
+ g_slice_free(rose_sdc_vibration, new_vibration);
+ new_vibration = NULL;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void _free_sdc_light_type(rose_sdc_light *light)
+{
+ if (!light)
+ return;
+ g_list_free_full(light->color, g_free);
+ g_free(light->unit);
+ g_slice_free(rose_sdc_light, light);
+}
+
+static void _free_sdc_flash_type(rose_sdc_flash *flash)
+{
+ if (!flash)
+ return;
+ _free_sdc_light_type(flash->light);
+ g_slice_free(rose_sdc_flash, flash);
+}
+
+static void _free_sdc_wind_type(rose_sdc_wind *wind)
+{
+ if (!wind)
+ return;
+ g_free(wind->unit);
+ g_slice_free(rose_sdc_wind, wind);
+}
+
+static void _free_sdc_vibration_type(rose_sdc_vibration *vibration)
+{
+ if (!vibration)
+ return;
+ g_free(vibration->unit);
+ g_slice_free(rose_sdc_vibration, vibration);
+}
+
+static void _free_sdc_element(rose_sdc_element * sdc_element)
+{
+ if (!sdc_element)
+ return;
+ g_free (sdc_element->id);
+ _free_sdc_light_type(sdc_element->light);
+ _free_sdc_flash_type(sdc_element->flash);
+ _free_sdc_wind_type(sdc_element->wind);
+ _free_sdc_vibration_type(sdc_element->vibration);
+
+ g_slice_free(rose_sdc_element, sdc_element);
+}
+
+void rose_ctl_info_free(rose_control_info * ctl_info)
+{
+ if (!ctl_info)
+ return;
+
+ g_list_free_full(ctl_info->namespace, (GDestroyNotify) _free_namespace);
+ g_list_free_full(ctl_info->sdc_elements, (GDestroyNotify) _free_sdc_element);
+
+ g_slice_free(rose_control_info, ctl_info);
+}
+