#include "sst_misc.h"
#include "sst_interface.h"
-static GHashTable *sst_vconf_map_org = NULL;
+static GHashTable *sst_vconf_map_old = NULL;
static GHashTable *sst_vconf_map = NULL;
+static GHashTable *sst_vconf_map_new = NULL;
struct sst_vconf_info_s {
system_settings_key_e key;
return SYSTEM_SETTINGS_ERROR_NONE;
}
-static inline GHashTable* _map_erase(GHashTable *hash_table, const char *key)
+//Because of a lot of parameters, it is an inline function
+static inline int _subscribe(sst_interface *iface, system_settings_changed_cb cb, void *user_data, GHashTable **vconf_map, GList *list, vconf_callback_fn vconf_cb, system_settings_cb_id *id)
{
- g_hash_table_remove(hash_table, key);
- if (0 == g_hash_table_size(hash_table)) {
- g_hash_table_unref(hash_table);
- return NULL;
+ GHashTable *map = *vconf_map;
+ struct sst_vconf_info_s *info = malloc(sizeof(struct sst_vconf_info_s));
+ if (NULL == info) {
+ ERR("malloc() Fail(%d)", errno);
+ return SYSTEM_SETTINGS_ERROR_OUT_OF_MEMORY;
}
- return hash_table;
+ info->key = iface->key;
+ info->cb = cb;
+ info->cb_data = user_data;
+
+ GList *new_list = g_list_append(list, info);
+ g_hash_table_replace(map, (char*)iface->vconf_key, new_list);
+
+ if (NULL == list) {
+ int ret = vconf_notify_key_changed(iface->vconf_key, vconf_cb, NULL);
+ if (VCONF_OK != ret) {
+ ERR("vconf_notify_key_changed(%s) Fail", iface->vconf_key);
+ new_list = g_list_remove(new_list, info);
+ if (NULL == new_list) {
+ g_hash_table_remove(map, iface->vconf_key);
+ if (0 == g_hash_table_size(map)) {
+ g_hash_table_unref(map);
+ *vconf_map = NULL;
+ }
+ }
+ free(info);
+ return SYSTEM_SETTINGS_ERROR_IO_ERROR;
+ }
+ }
+
+ if (id)
+ *id = info;
+
+ return SYSTEM_SETTINGS_ERROR_NONE;
}
-static void _callback_fn_org(keynode_t *node, void *user_data)
+static int _unsubscribe(const char *vconf_key, GList *found, GHashTable **vconf_map, vconf_callback_fn cb)
{
- RET_IF(NULL == sst_vconf_map_org);
+ GHashTable *map = *vconf_map;
+ GList *list = g_list_first(found);
+
+ if (1 == g_list_length(list)) {
+ int ret = vconf_ignore_key_changed(vconf_key, cb);
+ if (VCONF_OK != ret) {
+ ERR("vconf_ignore_key_changed(%s) Fail", vconf_key);
+ return SYSTEM_SETTINGS_ERROR_IO_ERROR;
+ }
+ }
+
+ list = g_list_remove_link(list, found);
+ if (list) {
+ g_hash_table_replace(map, (char*)vconf_key, list);
+ } else {
+ g_hash_table_remove(map, vconf_key);
+ if (0 == g_hash_table_size(map)) {
+ g_hash_table_unref(map);
+ *vconf_map = NULL;
+ }
+ }
- GList *list = g_hash_table_lookup(sst_vconf_map_org, node->keyname);
+ free(found->data);
+ g_list_free(found);
+
+ return SYSTEM_SETTINGS_ERROR_NONE;
+}
+
+static void _callback_fn_old(keynode_t *node, void *user_data)
+{
+ RET_IF(NULL == sst_vconf_map_old);
+
+ GList *list = g_hash_table_lookup(sst_vconf_map_old, node->keyname);
GList *it;
for (it = list; it; it = it->next) {
struct sst_vconf_info_s *info = it->data;
RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
RETV_IF(NULL == cb, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
- if (sst_vconf_map_org) {
- list = g_hash_table_lookup(sst_vconf_map_org, iface->vconf_key);
+ if (sst_vconf_map_old) {
+ list = g_hash_table_lookup(sst_vconf_map_old, iface->vconf_key);
GList *found = g_list_find_custom(list, GINT_TO_POINTER(iface->key), _compare_key);
if (found) {
ERR("callback Already Exist");
return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
}
} else {
- sst_vconf_map_org = g_hash_table_new(g_str_hash, g_str_equal);
- }
-
- struct sst_vconf_info_s *info = malloc(sizeof(struct sst_vconf_info_s));
- if (NULL == info) {
- ERR("malloc() Fail(%d)", errno);
- return SYSTEM_SETTINGS_ERROR_OUT_OF_MEMORY;
- }
- info->key = iface->key;
- info->cb = cb;
- info->cb_data = user_data;
-
- GList *new_list = g_list_append(list, info);
- g_hash_table_replace(sst_vconf_map_org, (char*)iface->vconf_key, new_list);
-
- if (NULL == list) {
- int ret = vconf_notify_key_changed(iface->vconf_key, _callback_fn_org, NULL);
- if (VCONF_OK != ret) {
- ERR("vconf_notify_key_changed(%s) Fail", iface->vconf_key);
- new_list = g_list_remove(new_list, info);
- if (NULL == new_list)
- sst_vconf_map_org = _map_erase(sst_vconf_map_org, iface->vconf_key);
- free(info);
- return SYSTEM_SETTINGS_ERROR_IO_ERROR;
- }
+ sst_vconf_map_old = g_hash_table_new(g_str_hash, g_str_equal);
}
- return SYSTEM_SETTINGS_ERROR_NONE;
+ return _subscribe(iface, cb, user_data, &sst_vconf_map_old, list, _callback_fn_old, NULL);
}
int sst_vconf_unset_cb(sst_interface *iface)
{
RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
- RETV_IF(NULL == sst_vconf_map_org, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
+ RETV_IF(NULL == sst_vconf_map_old, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
- GList *list = g_hash_table_lookup(sst_vconf_map_org, iface->vconf_key);
+ GList *list = g_hash_table_lookup(sst_vconf_map_old, iface->vconf_key);
GList *found = g_list_find_custom(list, GINT_TO_POINTER(iface->key), _compare_key);
if (NULL == found) {
ERR("No callback");
return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
}
- if (1 == g_list_length(list)) {
- int ret = vconf_ignore_key_changed(iface->vconf_key, _callback_fn_org);
- if (VCONF_OK != ret) {
- ERR("vconf_ignore_key_changed(%s) Fail", iface->vconf_key);
- return SYSTEM_SETTINGS_ERROR_IO_ERROR;
- }
- }
-
- list = g_list_remove_link(list, found);
- if (list)
- g_hash_table_replace(sst_vconf_map_org, (char*)iface->vconf_key, list);
- else
- sst_vconf_map_org = _map_erase(sst_vconf_map_org, iface->vconf_key);
-
- free(found->data);
- g_list_free(found);
-
- return SYSTEM_SETTINGS_ERROR_NONE;
+ return _unsubscribe(iface->vconf_key, found, &sst_vconf_map_old, _callback_fn_old);
}
static void _callback_fn(keynode_t *node, void *user_data)
sst_vconf_map = g_hash_table_new(g_str_hash, g_str_equal);
}
- struct sst_vconf_info_s *info = malloc(sizeof(struct sst_vconf_info_s));
- if (NULL == info) {
- ERR("malloc() Fail(%d)", errno);
- return SYSTEM_SETTINGS_ERROR_OUT_OF_MEMORY;
- }
- info->key = iface->key;
- info->cb = cb;
- info->cb_data = user_data;
-
- GList *new_list = g_list_append(list, info);
- g_hash_table_replace(sst_vconf_map, (char*)iface->vconf_key, new_list);
-
- if (NULL == list) {
- int ret = vconf_notify_key_changed(iface->vconf_key, _callback_fn, NULL);
- if (VCONF_OK != ret) {
- ERR("vconf_notify_key_changed(%s) Fail", iface->vconf_key);
- new_list = g_list_remove(new_list, info);
- if (NULL == new_list)
- sst_vconf_map = _map_erase(sst_vconf_map, iface->vconf_key);
- free(info);
- return SYSTEM_SETTINGS_ERROR_IO_ERROR;
- }
- }
-
- return SYSTEM_SETTINGS_ERROR_NONE;
+ return _subscribe(iface, cb, user_data, &sst_vconf_map, list, _callback_fn, NULL);
}
int sst_vconf_del_multi_cb(sst_interface *iface, system_settings_changed_cb cb)
return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
}
- if (1 == g_list_length(list)) {
- int ret = vconf_ignore_key_changed(iface->vconf_key, _callback_fn);
- if (VCONF_OK != ret) {
- ERR("vconf_ignore_key_changed(%s) Fail", iface->vconf_key);
- return SYSTEM_SETTINGS_ERROR_IO_ERROR;
- }
+ return _unsubscribe(iface->vconf_key, found, &sst_vconf_map, _callback_fn);
+}
+
+static void _callback_fn_new(keynode_t *node, void *user_data)
+{
+ RET_IF(NULL == sst_vconf_map_new);
+
+ GList *list = g_hash_table_lookup(sst_vconf_map_new, node->keyname);
+ GList *it;
+ for (it = list; it; it = it->next) {
+ struct sst_vconf_info_s *info = it->data;
+ if (info && info->cb)
+ info->cb(info->key, info->cb_data);
}
+}
- list = g_list_remove_link(list, found);
- if (list)
- g_hash_table_replace(sst_vconf_map, (char*)iface->vconf_key, list);
- else
- sst_vconf_map = _map_erase(sst_vconf_map, iface->vconf_key);
+int sst_vconf_subscribe(sst_interface *iface, system_settings_changed_cb cb, void *user_data, system_settings_cb_id *id)
+{
+ GList *list = NULL;
- free(found->data);
- g_list_free(found);
+ RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
+ RETV_IF(NULL == cb, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
- return SYSTEM_SETTINGS_ERROR_NONE;
+ if (sst_vconf_map_new) {
+ list = g_hash_table_lookup(sst_vconf_map_new, iface->vconf_key);
+ } else {
+ sst_vconf_map_new = g_hash_table_new(g_str_hash, g_str_equal);
+ }
+
+ return _subscribe(iface, cb, user_data, &sst_vconf_map_new, list, _callback_fn_new, id);
}
+
+int sst_vconf_unsubscribe(sst_interface *iface, system_settings_cb_id id)
+{
+ RETV_IF(NULL == iface, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
+ RETV_IF(NULL == id, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
+ RETV_IF(NULL == sst_vconf_map_new, SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER);
+
+ GList *list = g_hash_table_lookup(sst_vconf_map_new, iface->vconf_key);
+ GList *found = g_list_find(list, id);
+ if (NULL == found) {
+ ERR("No callback");
+ return SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
+ }
+
+ return _unsubscribe(iface->vconf_key, found, &sst_vconf_map_new, _callback_fn_new);
+}
\ No newline at end of file