4 #include <Elementary.h>
10 typedef struct _Locale_Manager Locale_Manager;
11 typedef struct _Locale_Bus_Object Locale_Bus_Object;
13 static const char bus_name[] = "org.freedesktop.locale1";
15 static Eldbus_Connection *bus_conn = NULL;
16 static char *bus_id = NULL;
17 static Locale_Manager *locale_manager = NULL;
18 static Eldbus_Signal_Handler *sig_locale_properties_changed = NULL;
20 struct _Locale_Callback_List_Node
23 void (*cb)(void *data);
27 static Eina_Inlist *cbs_locale_connected = NULL;
28 static Eina_Inlist *cbs_locale_disconnected = NULL;
29 static Eina_Inlist *cbs_locale_properties_changed = NULL;
31 #define LOCALE_IFACE "org.freedesktop.locale1"
32 #define LOCALE_BUS_PATH "/org/freedesktop/locale1"
33 #define LOCALE_PROPERTIES_IFACE "org.freedesktop.DBus.Properties"
34 #define PROP_LOCALE_STRING "Locale"
36 struct _Locale_Bus_Object
39 Eina_List *dbus_signals; /* of Eldbus_Signal_Handler */
42 static void _bus_object_free(Locale_Bus_Object *o)
44 Eldbus_Signal_Handler *sh;
46 eina_stringshare_del(o->path);
48 EINA_LIST_FREE(o->dbus_signals, sh)
49 eldbus_signal_handler_del(sh);
52 struct _Locale_Manager
54 Locale_Bus_Object base;
56 unsigned int interfaces;
60 static Locale_Manager *_locale_get(void)
62 return locale_manager;
65 static void _notify_locale_callbacks_list(Eina_Inlist *list)
67 Locale_Callback_List_Node *node;
69 EINA_INLIST_FOREACH(list, node)
70 node->cb((void *) node->cb_data);
73 static void _locale_get_property_reply(void *data, Eldbus_Message *msg,
74 Eldbus_Pending *pending __UNUSED__)
76 Eldbus_Message_Iter *variant, *array;
77 const char *type, *locale, *err_name, *err_message;
79 EINA_SAFETY_ON_NULL_RETURN(data);
86 if (eldbus_message_error_get(msg, &err_name, &err_message)) {
87 ERR("Failed to get property: %s: %s", err_name, err_message);
91 if (!eldbus_message_arguments_get(msg, "v", &variant)) {
92 ERR("Could not get arguments");
96 if (!eldbus_message_iter_arguments_get(variant, "as", &array)) {
97 ERR("Could not get arguments");
101 if (!eldbus_message_iter_get_and_next(array, 's', &locale)) {
102 ERR("Could not get locale");
106 char *property_name = (char*) data;
107 Locale_Manager *m = _locale_get();
109 if (strcmp(property_name, PROP_LOCALE_STRING) == 0) {
111 eina_stringshare_replace(&m->lang, locale);
113 m->lang = eina_stringshare_add(locale);
115 DBG("Locale is set to: %s", m->lang);
120 _notify_locale_callbacks_list(cbs_locale_properties_changed);
123 static void _locale_property_get(char *property, char *path, Eldbus_Message_Cb cb, void *data)
126 char *interface_name;
128 EINA_SAFETY_ON_NULL_RETURN(property);
129 EINA_SAFETY_ON_NULL_RETURN(path);
131 if (strcmp(property, PROP_LOCALE_STRING) == 0) {
132 interface_name = LOCALE_IFACE;
137 msg = eldbus_message_method_call_new(
138 bus_id, LOCALE_BUS_PATH, LOCALE_PROPERTIES_IFACE, "Get");
140 eldbus_message_arguments_append(msg, "ss", interface_name, property);
141 eldbus_connection_send(bus_conn, msg, cb, data, -1);
144 static Locale_Manager *_locale_new(const char *path)
146 Locale_Manager *m = calloc(1, sizeof(Locale_Manager));
147 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
149 m->base.path = eina_stringshare_add(path);
150 EINA_SAFETY_ON_NULL_GOTO(m->base.path, error_path);
159 static void _locale_free(Locale_Manager *m)
162 eina_stringshare_del(m->lang);
164 eina_stringshare_del(m->base.path);
166 _bus_object_free(&m->base);
170 static void _locale_properties_changed(void *data __UNUSED__, Eldbus_Message *msg)
172 Eldbus_Message_Iter *array1, *array2;
173 const char *interface, *err_name, *err_message;
175 if (eldbus_message_error_get(msg, &err_name, &err_message)) {
176 ERR("Failed to get signal: %s: %s", err_name, err_message);
180 if (!eldbus_message_arguments_get(msg, "sa{sv}as", &interface, &array1, &array2)) {
181 ERR("Could not get PropertiesChanged arguments");
185 DBG("Locale property changed at %s", interface);
186 if (strcmp(interface, LOCALE_IFACE) == 0) {
187 _locale_property_get(PROP_LOCALE_STRING, LOCALE_BUS_PATH, _locale_get_property_reply, PROP_LOCALE_STRING);
191 static void _locale_load(void)
193 locale_manager = _locale_new("/");
194 EINA_SAFETY_ON_NULL_RETURN(locale_manager);
197 static void _locale_connected(const char *id)
202 sig_locale_properties_changed = eldbus_signal_handler_add(
203 bus_conn, bus_id, NULL,
204 LOCALE_PROPERTIES_IFACE,
206 _locale_properties_changed, NULL);
210 _notify_locale_callbacks_list(cbs_locale_connected);
213 static void _locale_disconnected(void)
215 if (sig_locale_properties_changed) {
216 eldbus_signal_handler_del(sig_locale_properties_changed);
217 sig_locale_properties_changed = NULL;
221 _notify_locale_callbacks_list(cbs_locale_disconnected);
227 static void _name_owner_changed(void *data __UNUSED__, Eldbus_Message *msg)
229 const char *name, *from, *to;
231 if (!eldbus_message_arguments_get(msg, "sss", &name, &from, &to)) {
232 ERR("Could not get NameOwnerChanged arguments");
236 if (strcmp(name, bus_name) != 0)
239 DBG("NameOwnerChanged %s from=%s to=%s", name, from, to);
241 if (from[0] == '\0' && to[0] != '\0') {
242 INF("localed appeared as %s", to);
243 _locale_connected(to);
244 } else if (from[0] != '\0' && to[0] == '\0') {
245 INF("localed disappeared from %s", from);
246 _locale_disconnected();
250 static void _locale_get_name_owner(void *data __UNUSED__, Eldbus_Message *msg,
251 Eldbus_Pending *pending __UNUSED__)
254 const char *err_name, *err_message;
261 if (eldbus_message_error_get(msg, &err_name, &err_message)) {
262 ERR("Failed to get name owner: %s: %s", err_name, err_message);
266 if (!eldbus_message_arguments_get(msg, "s", &id)) {
267 ERR("Could not get arguments");
271 if (!id || id[0] == '\0') {
272 ERR("No name owner fo %s!", bus_name);
276 INF("localed bus id: %s", id);
277 _locale_connected(id);
280 const char* locale_lang_get(void)
282 Locale_Manager *m = _locale_get();
283 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
288 Eina_Bool locale_init(void)
290 if (!elm_need_eldbus()) {
291 CRITICAL("Elementary does not support DBus.");
295 bus_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
297 CRITICAL("Could not get DBus System Bus");
301 eldbus_signal_handler_add(bus_conn, ELDBUS_FDO_BUS, ELDBUS_FDO_PATH,
302 ELDBUS_FDO_INTERFACE,
304 _name_owner_changed, NULL);
306 eldbus_name_owner_get(bus_conn, bus_name, _locale_get_name_owner, NULL);
311 void locale_shutdown(void)
313 if (locale_manager) {
314 _locale_free(locale_manager);
315 locale_manager = NULL;
317 _locale_disconnected();
320 static Locale_Callback_List_Node * _locale_callback_list_node_create(
321 void (*cb)(void *data),const void *data)
323 Locale_Callback_List_Node *node_new;
325 node_new = calloc(1, sizeof(Locale_Callback_List_Node));
326 EINA_SAFETY_ON_NULL_RETURN_VAL(node_new, NULL);
328 node_new->cb_data = data;
334 static void _locale_callback_list_delete(Eina_Inlist **list,
335 Locale_Callback_List_Node *node)
337 EINA_SAFETY_ON_NULL_RETURN(*list);
338 *list = eina_inlist_remove(*list, EINA_INLIST_GET(node));
342 Locale_Callback_List_Node *
343 locale_properties_changed_cb_add(void (*cb)(void *data), const void *data)
345 Locale_Callback_List_Node *node;
347 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
348 node = _locale_callback_list_node_create(cb, data);
349 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
351 cbs_locale_properties_changed = eina_inlist_append(cbs_locale_properties_changed,
352 EINA_INLIST_GET(node));
357 void locale_properties_changed_cb_del(Locale_Callback_List_Node *node)
359 EINA_SAFETY_ON_NULL_RETURN(node);
360 _locale_callback_list_delete(&cbs_locale_properties_changed, node);