2 * Copyright (c) 2011-2020 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 #include "sst_vconf.h"
25 #include "sst_interface.h"
27 static GHashTable *sst_vconf_map_org = NULL;
28 static GHashTable *sst_vconf_map = NULL;
30 struct sst_vconf_info_s {
31 system_settings_key_e key;
32 system_settings_changed_cb cb;
36 int sst_vconf_set(sst_interface *iface, void *value)
42 switch (iface->data_type) {
43 case SYSTEM_SETTING_DATA_TYPE_STRING:
44 vconf_char = (char*)value;
45 if (vconf_set_str(iface->vconf_key, vconf_char))
46 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
48 case SYSTEM_SETTING_DATA_TYPE_INT:
49 //todo: change double pointer to valide data type
50 vconf_int = **(int**)value;
51 if (vconf_set_int(iface->vconf_key, vconf_int))
52 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
54 case SYSTEM_SETTING_DATA_TYPE_BOOL:
55 vconf_bool = *(bool*)value;
56 if (vconf_set_bool(iface->vconf_key, vconf_bool))
57 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
60 ERR("Unknown type(%d)", iface->data_type);
61 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
64 return SYSTEM_SETTINGS_ERROR_NONE;
67 int sst_vconf_get(sst_interface *iface, void **value)
71 int **val = (int**)value;
74 switch (iface->data_type) {
75 case SYSTEM_SETTING_DATA_TYPE_STRING:
76 if (sst_vconf_get_string(iface->vconf_key, &vconf_char))
77 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
80 case SYSTEM_SETTING_DATA_TYPE_INT:
81 if (vconf_get_int(iface->vconf_key, &vconf_int))
82 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
85 case SYSTEM_SETTING_DATA_TYPE_BOOL:
86 if (sst_vconf_get_real_bool(iface->vconf_key, &vconf_bool))
87 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
88 *value = (void*)vconf_bool;
91 ERR("Unknown type(%d)", iface->data_type);
92 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
95 return SYSTEM_SETTINGS_ERROR_NONE;
98 int sst_vconf_get_real_bool(const char *vconf_key, bool *value)
101 int ret = vconf_get_bool(vconf_key, &temp);
102 if (VCONF_OK != ret) {
103 ERR("vconf_get_bool(%s) Fail(%d)", vconf_key, ret);
104 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
107 *value = temp ? true : false;
109 return SYSTEM_SETTINGS_ERROR_NONE;
112 int sst_vconf_get_string(const char *vconf_key, char **value)
114 char *str_value = vconf_get_str(vconf_key);
115 if (NULL == str_value) {
116 ERR("vconf_get_str(%s) Fail(NULL)", vconf_key);
117 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
121 return SYSTEM_SETTINGS_ERROR_NONE;
124 static inline GHashTable* _map_erase(GHashTable *hash_table, const char *key)
126 g_hash_table_remove(hash_table, key);
127 if (0 == g_hash_table_size(hash_table)) {
128 g_hash_table_unref(hash_table);
134 static void _callback_fn_org(keynode_t *node, void *user_data)
136 RET_IF(NULL == sst_vconf_map_org);
138 GList *list = g_hash_table_lookup(sst_vconf_map_org, node->keyname);
140 for (it = list; it; it = it->next) {
141 struct sst_vconf_info_s *info = it->data;
142 if (info && info->cb)
143 info->cb(info->key, info->cb_data);
147 static gint _compare_key(gconstpointer a, gconstpointer b)
149 const struct sst_vconf_info_s *info = a;
151 RETV_IF(NULL == a, 1);
153 if (info->key == GPOINTER_TO_INT(b))
159 int sst_vconf_set_cb(sst_interface *iface, system_settings_changed_cb cb, void *user_data)
163 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
164 RETV_IF(NULL == cb, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
166 if (sst_vconf_map_org) {
167 list = g_hash_table_lookup(sst_vconf_map_org, iface->vconf_key);
168 GList *found = g_list_find_custom(list, GINT_TO_POINTER(iface->key), _compare_key);
170 ERR("callback Already Exist");
171 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
174 sst_vconf_map_org = g_hash_table_new(g_str_hash, g_str_equal);
177 struct sst_vconf_info_s *info = malloc(sizeof(struct sst_vconf_info_s));
179 ERR("malloc() Fail(%d)", errno);
180 return SYSTEM_SETTINGS_ERROR_OUT_OF_MEMORY;
182 info->key = iface->key;
184 info->cb_data = user_data;
186 GList *new_list = g_list_append(list, info);
187 g_hash_table_replace(sst_vconf_map_org, (char*)iface->vconf_key, new_list);
190 int ret = vconf_notify_key_changed(iface->vconf_key, _callback_fn_org, NULL);
191 if (VCONF_OK != ret) {
192 ERR("vconf_notify_key_changed(%s) Fail", iface->vconf_key);
193 new_list = g_list_remove(new_list, info);
194 if (NULL == new_list)
195 sst_vconf_map_org = _map_erase(sst_vconf_map_org, iface->vconf_key);
197 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
201 return SYSTEM_SETTINGS_ERROR_NONE;
204 int sst_vconf_unset_cb(sst_interface *iface)
206 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
207 RETV_IF(NULL == sst_vconf_map_org, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
209 GList *list = g_hash_table_lookup(sst_vconf_map_org, iface->vconf_key);
210 GList *found = g_list_find_custom(list, GINT_TO_POINTER(iface->key), _compare_key);
213 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
216 if (1 == g_list_length(list)) {
217 int ret = vconf_ignore_key_changed(iface->vconf_key, _callback_fn_org);
218 if (VCONF_OK != ret) {
219 ERR("vconf_ignore_key_changed(%s) Fail", iface->vconf_key);
220 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
224 list = g_list_remove_link(list, found);
226 g_hash_table_replace(sst_vconf_map_org, (char*)iface->vconf_key, list);
228 sst_vconf_map_org = _map_erase(sst_vconf_map_org, iface->vconf_key);
233 return SYSTEM_SETTINGS_ERROR_NONE;
236 static void _callback_fn(keynode_t *node, void *user_data)
238 RET_IF(NULL == sst_vconf_map);
240 GList *list = g_hash_table_lookup(sst_vconf_map, node->keyname);
242 for (it = list; it; it = it->next) {
243 struct sst_vconf_info_s *info = it->data;
244 if (info && info->cb)
245 info->cb(info->key, info->cb_data);
249 static gint _compare_cb(gconstpointer a, gconstpointer b)
251 const struct sst_vconf_info_s *info = a;
253 RETV_IF(NULL == a, 1);
254 RETV_IF(NULL == b, 1);
262 int sst_vconf_add_multi_cb(sst_interface *iface, system_settings_changed_cb cb, void *user_data)
266 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
267 RETV_IF(NULL == cb, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
270 list = g_hash_table_lookup(sst_vconf_map, iface->vconf_key);
271 GList *found = g_list_find_custom(list, cb, _compare_cb);
273 ERR("callback Already Exist");
274 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
277 sst_vconf_map = g_hash_table_new(g_str_hash, g_str_equal);
280 struct sst_vconf_info_s *info = malloc(sizeof(struct sst_vconf_info_s));
282 ERR("malloc() Fail(%d)", errno);
283 return SYSTEM_SETTINGS_ERROR_OUT_OF_MEMORY;
285 info->key = iface->key;
287 info->cb_data = user_data;
289 GList *new_list = g_list_append(list, info);
290 g_hash_table_replace(sst_vconf_map, (char*)iface->vconf_key, new_list);
293 int ret = vconf_notify_key_changed(iface->vconf_key, _callback_fn, NULL);
294 if (VCONF_OK != ret) {
295 ERR("vconf_notify_key_changed(%s) Fail", iface->vconf_key);
296 new_list = g_list_remove(new_list, info);
297 if (NULL == new_list)
298 sst_vconf_map = _map_erase(sst_vconf_map, iface->vconf_key);
300 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
304 return SYSTEM_SETTINGS_ERROR_NONE;
307 int sst_vconf_del_multi_cb(sst_interface *iface, system_settings_changed_cb cb)
309 RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
310 RETV_IF(NULL == cb, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
311 RETV_IF(NULL == sst_vconf_map, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
313 GList *list = g_hash_table_lookup(sst_vconf_map, iface->vconf_key);
314 GList *found = g_list_find_custom(list, cb, _compare_cb);
317 return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
320 if (1 == g_list_length(list)) {
321 int ret = vconf_ignore_key_changed(iface->vconf_key, _callback_fn);
322 if (VCONF_OK != ret) {
323 ERR("vconf_ignore_key_changed(%s) Fail", iface->vconf_key);
324 return SYSTEM_SETTINGS_ERROR_IO_ERROR;
328 list = g_list_remove_link(list, found);
330 g_hash_table_replace(sst_vconf_map, (char*)iface->vconf_key, list);
332 sst_vconf_map = _map_erase(sst_vconf_map, iface->vconf_key);
337 return SYSTEM_SETTINGS_ERROR_NONE;