Adding support for nightmode theme change 05/8505/4
authorJimmy Huang <jimmy.huang@intel.com>
Wed, 21 Aug 2013 23:35:58 +0000 (16:35 -0700)
committerJimmy Huang <jimmy.huang@intel.com>
Fri, 23 Aug 2013 20:10:49 +0000 (13:10 -0700)
- Added support for AMB for querying NightMode properties
- Dialer will change theme by using theme overlay to darker theme if NightMode is set

Signed-off-by: Jimmy Huang <jimmy.huang@intel.com>
Change-Id: I13f4466d9c538a4fb9d571a2059c5a1b782719c7

Makefile.am
dialer/callscreen.c
dialer/gui.c
dialer/gui.h
dialer/main.c
packaging/lemolo.spec
utils/amb.c [new file with mode: 0644]
utils/amb.h [new file with mode: 0644]
utils/util.c
utils/util.h

index 7665eb2..a627f54 100644 (file)
@@ -26,6 +26,8 @@ EXTRA_DIST =
 noinst_LTLIBRARIES = utils/libofono-efl-utils.la
 
 utils_libofono_efl_utils_la_SOURCES = \
+       utils/amb.c \
+       utils/amb.h \
        utils/contacts-ofono-efl.h \
        utils/log.h \
        utils/ofono.c \
index b447c95..65aa6d2 100644 (file)
@@ -632,6 +632,10 @@ static void _call_auto_place(Callscreen *ctx, OFono_Call *c)
 
        if (!ctx->calls.first) {
                DBG("first call %p", c);
+               _call_clear(ctx, 1);
+               _call_clear(ctx, 2);
+               elm_object_signal_emit(ctx->self, "calls,1", "call");
+
                _call_first_set(ctx, c);
                _call_current_set(ctx, c);
                return;
index e533770..4b03cd9 100644 (file)
@@ -27,14 +27,18 @@ static Evas_Object *contacts = NULL;
 static Evas_Object *history = NULL;
 static Evas_Object *cs = NULL;
 static Evas_Object *flip = NULL;
+static Evas_Object *current_view = NULL;
 
 static OFono_Callback_List_Modem_Node *callback_node_modem_changed = NULL;
 static OFono_Callback_List_USSD_Notify_Node *callback_node_ussd_notify = NULL;
+static AMB_Callback_List_Node *callback_node_night_mode_changed = NULL;
 
 /* XXX elm_flip should just do the right thing, but it does not */
 static Eina_Bool in_call = EINA_FALSE;
 static Eina_Bool in_flip_anim = EINA_FALSE;
 
+static Eina_Bool night_mode = EINA_FALSE;
+
 Contact_Info *gui_contact_search(const char *number, const char **type)
 {
        return contact_search(contacts, number, type);
@@ -71,6 +75,7 @@ static void _gui_show(Evas_Object *o)
        else if (o == history)
                elm_object_signal_emit(main_layout, "show,history", "gui");
        elm_object_focus_set(o, EINA_TRUE);
+       current_view = o;
 }
 
 Evas_Object *gui_simple_popup(const char *title, const char *message)
@@ -231,6 +236,21 @@ static void _ofono_changed(void *data __UNUSED__)
        elm_object_part_text_set(main_layout, "elm.text.voicemail", buf);
 }
 
+static void _night_mode_changed(void *data __UNUSED__)
+{
+       DBG("Night mode changed");
+       Eina_Bool changed = amb_night_mode_get();
+       if (night_mode != changed)
+       {
+               DBG("Nightmode changed to %d", changed);
+               night_mode = changed;
+               util_set_night_mode(night_mode);
+
+               if (current_view)
+                       _gui_show(current_view);
+       }
+}
+
 static void _ofono_ussd_notify(void *data __UNUSED__, Eina_Bool needs_reply,
                                const char *message)
 {
@@ -314,6 +334,8 @@ Eina_Bool gui_init(void)
                ofono_modem_changed_cb_add(_ofono_changed, NULL);
        callback_node_ussd_notify =
                ofono_ussd_notify_cb_add(_ofono_ussd_notify, NULL);
+       callback_node_night_mode_changed =
+               amb_properties_changed_cb_add(_night_mode_changed, NULL);
 
        /* TODO: make it match better with Tizen: icon and other properties */
        obj = elm_layout_edje_get(lay);
index 22f5afe..9a6396a 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "contacts-ofono-efl.h"
 #include "ofono.h"
+#include "amb.h"
 
 Evas_Object *gui_simple_popup(const char *title, const char *message);
 
index b0b4948..3d4a55f 100644 (file)
@@ -11,6 +11,7 @@
 
 #ifndef ELM_LIB_QUICKLAUNCH
 
+#include "amb.h"
 #include "gui.h"
 #include "log.h"
 #include "ofono.h"
@@ -207,6 +208,14 @@ EAPI int elm_main(int argc, char **argv)
                goto end_ofono;
        }
 
+#ifdef HAVE_TIZEN
+       if (!amb_init()) {
+               CRITICAL("Could not setup automotive-message-broker");
+               _app_exit_code = EXIT_FAILURE;
+               goto end_amb;
+       }
+#endif
+
        if (!gui_init()) {
                CRITICAL("Could not setup graphical user interface");
                _app_exit_code = EXIT_FAILURE;
@@ -235,6 +244,10 @@ EAPI int elm_main(int argc, char **argv)
 
 end_util:
        util_shutdown();
+#ifdef HAVE_TIZEN
+end_amb:
+       amb_shutdown();
+#endif
 end_ofono:
        ofono_shutdown();
 end_rc:
index 4f9b3d1..a55dafe 100644 (file)
@@ -20,6 +20,7 @@ BuildRequires:  pkgconfig(appsvc)
 BuildRequires:  pkgconfig(notification)
 BuildRequires:  edje-tools
 Requires: ofono
+Requires: automotive-message-broker
 
 %description
 Provides a dialer application for an In-Vehicle Infotainment (IVI) system, where
diff --git a/utils/amb.c b/utils/amb.c
new file mode 100644 (file)
index 0000000..6e15048
--- /dev/null
@@ -0,0 +1,420 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <Elementary.h>
+#include <E_DBus.h>
+
+#include "amb.h"
+#include "log.h"
+
+typedef struct _AMB_Manager AMB_Manager;
+typedef struct _AMB_Bus_Object AMB_Bus_Object;
+
+static const char bus_name[] = "org.automotive.message.broker";
+
+static E_DBus_Connection *bus_conn = NULL;
+static char *bus_id = NULL;
+static AMB_Manager *amb_manager = NULL;
+static E_DBus_Signal_Handler *sig_amb_properties_changed = NULL;
+static DBusPendingCall *amb_get_night_mode_path = NULL;
+
+struct _AMB_Callback_List_Node
+{
+       EINA_INLIST;
+       void (*cb)(void *data);
+       const void *cb_data;
+};
+
+static Eina_Inlist *cbs_amb_connected = NULL;
+static Eina_Inlist *cbs_amb_disconnected = NULL;
+static Eina_Inlist *cbs_amb_properties_changed = NULL;
+
+#define AMB_MANAGER_IFACE                      "org.automotive.Manager"
+#define AMB_PROPERTIES_IFACE                   "org.freedesktop.DBus.Properties"
+#define AMB_NIGHT_MODE_IFACE                   "org.automotive.NightMode"
+#define PROP_NIGHT_MODE_STRING                 "NightMode"
+
+static Eina_Bool _dbus_bool_get(DBusMessageIter *itr)
+{
+       dbus_bool_t val;
+       dbus_message_iter_get_basic(itr, &val);
+       return val;
+}
+
+struct _AMB_Bus_Object
+{
+       const char *path;
+       Eina_List *dbus_signals; /* of E_DBus_Signal_Handler */
+};
+
+static void _bus_object_free(AMB_Bus_Object *o)
+{
+       E_DBus_Signal_Handler *sh;
+
+       eina_stringshare_del(o->path);
+
+       EINA_LIST_FREE(o->dbus_signals, sh)
+               e_dbus_signal_handler_del(bus_conn, sh);
+}
+
+struct _AMB_Manager
+{
+       AMB_Bus_Object base;
+       const char *name;
+       unsigned int interfaces;
+       unsigned char vehiclespeed;
+       Eina_Bool nightmode : 1;
+};
+
+static void _amb_property_update(AMB_Manager *m, const char *interface,
+                                       DBusMessageIter *property)
+{
+       if (strcmp(interface, AMB_NIGHT_MODE_IFACE) == 0) {
+               /* TODO: change later to use night mode */
+               DBusMessageIter entry, variant;
+               const char *key;
+
+               dbus_message_iter_recurse(property, &entry);
+               dbus_message_iter_get_basic(&entry, &key);
+
+               if (strcmp(key, PROP_NIGHT_MODE_STRING) == 0) {
+
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &variant);
+                       m->nightmode = _dbus_bool_get(&variant);
+                       DBG("NightMode updated: %d", m->nightmode);
+               } else {
+                       DBG("invalid key: %s", key);
+               }
+       } else {
+               DBG("%s (unused property)", interface);
+       }
+}
+
+static AMB_Manager *_amb_get(void)
+{
+       return amb_manager;
+}
+
+static void _notify_amb_callbacks_list(Eina_Inlist *list)
+{
+       AMB_Callback_List_Node *node;
+
+       EINA_INLIST_FOREACH(list, node)
+               node->cb((void *) node->cb_data);
+}
+
+static void _amb_get_night_mode_reply(void *data __UNUSED__, DBusMessage *msg,
+                                       DBusError *err)
+{
+       if (!msg) {
+               if (err)
+                       ERR("%s: %s", err->name, err->message);
+               else
+                       ERR("No message");
+               return;
+       }
+
+       DBusError e;
+       dbus_error_init(&e);
+       dbus_bool_t value;
+
+       AMB_Manager *m = _amb_get();
+
+       dbus_message_get_args(msg, &e, DBUS_TYPE_BOOLEAN, &value, DBUS_TYPE_INVALID);
+
+       m->nightmode = value;
+       DBG("NightMode is set to: %d", m->nightmode);
+       _notify_amb_callbacks_list(cbs_amb_properties_changed);
+}
+
+static void _amb_manager_property_get(char *property, char *path, E_DBus_Method_Return_Cb cb, void *data)
+{
+       DBusMessage *msg;
+
+       EINA_SAFETY_ON_NULL_RETURN(property);
+       EINA_SAFETY_ON_NULL_RETURN(path);
+
+       if (strcmp(property, PROP_NIGHT_MODE_STRING) == 0) {
+               char* interface_name = AMB_NIGHT_MODE_IFACE;
+
+               msg = dbus_message_new_method_call(
+                       bus_id, path, AMB_PROPERTIES_IFACE, "Get");
+
+               dbus_message_append_args(msg,
+                       DBUS_TYPE_STRING, &interface_name,
+                       DBUS_TYPE_STRING, &property,
+                       DBUS_TYPE_INVALID);
+
+               e_dbus_message_send(bus_conn, msg, cb, -1, data);
+       }
+
+       dbus_message_unref(msg);
+}
+
+static void _amb_get_night_mode_path_reply(void *data __UNUSED__, DBusMessage *msg,
+                                       DBusError *err)
+{
+       amb_get_night_mode_path = NULL;
+
+       if (!msg) {
+               if (err)
+                       ERR("%s: %s", err->name, err->message);
+               else
+                       ERR("No message");
+               return;
+       }
+
+       DBusError e;
+       char *path;
+       dbus_error_init(&e);
+       dbus_message_get_args(msg, &e, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
+
+       if(!path) { 
+               ERR("Could not get NightMode object path");
+               return;
+       }
+
+       _amb_manager_property_get(PROP_NIGHT_MODE_STRING, path, _amb_get_night_mode_reply, NULL);
+}
+
+static AMB_Manager *_amb_new(const char *path)
+{
+       AMB_Manager *m = calloc(1, sizeof(AMB_Manager));
+       EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
+
+       m->base.path = eina_stringshare_add(path);
+       EINA_SAFETY_ON_NULL_GOTO(m->base.path, error_path);
+
+       return m;
+
+error_path:
+       free(m);
+       return NULL;
+}
+
+static void _amb_free(AMB_Manager *m)
+{
+       eina_stringshare_del(m->name);
+
+       _bus_object_free(&m->base);
+       free(m);
+}
+
+static void _amb_properties_changed(void *data __UNUSED__, DBusMessage *msg)
+{
+       const char *path;
+       AMB_Manager *m = _amb_get();
+       DBusMessageIter iter, value;
+       const char *interface;
+
+       if (!msg || !dbus_message_iter_init(msg, &iter)) {
+               ERR("Could not handle message %p", msg);
+               return;
+       }
+
+       path = dbus_message_get_path(msg);
+
+       dbus_message_iter_get_basic(&iter, &interface);
+       dbus_message_iter_next(&iter);
+       dbus_message_iter_recurse(&iter, &value);
+
+       if (strcmp(interface, AMB_NIGHT_MODE_IFACE) == 0) {
+               _amb_property_update(m, interface, &value);
+               _notify_amb_callbacks_list(cbs_amb_properties_changed);
+       }
+}
+
+static void _amb_load(void)
+{
+       amb_manager = _amb_new("/");
+       EINA_SAFETY_ON_NULL_RETURN(amb_manager);
+
+       char *property_name = PROP_NIGHT_MODE_STRING; 
+
+       DBusMessage *msg = dbus_message_new_method_call(
+               bus_id, "/", AMB_MANAGER_IFACE, "findProperty");
+
+       dbus_message_append_args(msg,
+               DBUS_TYPE_STRING, &property_name,
+               DBUS_TYPE_INVALID);
+
+       amb_get_night_mode_path = e_dbus_message_send(
+               bus_conn, msg, _amb_get_night_mode_path_reply, -1, NULL);
+
+       dbus_message_unref(msg);
+}
+
+static void _amb_connected(const char *id)
+{
+       free(bus_id);
+       bus_id = strdup(id);
+
+       sig_amb_properties_changed = e_dbus_signal_handler_add(
+               bus_conn, bus_id, NULL,
+               AMB_PROPERTIES_IFACE,
+               "PropertiesChanged",
+               _amb_properties_changed, NULL);
+
+       _amb_load();
+
+       _notify_amb_callbacks_list(cbs_amb_connected);
+}
+
+static void _amb_disconnected(void)
+{
+       if (sig_amb_properties_changed) {
+               e_dbus_signal_handler_del(bus_conn, sig_amb_properties_changed);
+               sig_amb_properties_changed = NULL;
+       }
+
+       if (bus_id) {
+               _notify_amb_callbacks_list(cbs_amb_disconnected);
+               free(bus_id);
+               bus_id = NULL;
+       }
+}
+
+static void _name_owner_changed(void *data __UNUSED__, DBusMessage *msg)
+{
+       DBusError err;
+       const char *name, *from, *to;
+
+       dbus_error_init(&err);
+       if (!dbus_message_get_args(msg, &err,
+                                       DBUS_TYPE_STRING, &name,
+                                       DBUS_TYPE_STRING, &from,
+                                       DBUS_TYPE_STRING, &to,
+                                       DBUS_TYPE_INVALID)) {
+               ERR("Could not get NameOwnerChanged arguments: %s: %s",
+                       err.name, err.message);
+               dbus_error_free(&err);
+               return;
+       }
+
+       if (strcmp(name, bus_name) != 0)
+               return;
+
+       DBG("NameOwnerChanged %s from=%s to=%s", name, from, to);
+
+       if (from[0] == '\0' && to[0] != '\0') {
+               INF("amb appeared as %s", to);
+               _amb_connected(to);
+       } else if (from[0] != '\0' && to[0] == '\0') {
+               INF("amb disappeared from %s", from);
+               _amb_disconnected();
+       }
+}
+
+static void _amb_get_name_owner(void *data __UNUSED__, DBusMessage *msg, DBusError *err)
+{
+       DBusMessageIter itr;
+       const char *id;
+
+       if (!msg) {
+               if (err)
+                       ERR("%s: %s", err->name, err->message);
+               else
+                       ERR("No message");
+               return;
+       }
+
+       dbus_message_iter_init(msg, &itr);
+       dbus_message_iter_get_basic(&itr, &id);
+       if (!id || id[0] == '\0') {
+               ERR("No name owner fo %s!", bus_name);
+               return;
+       }
+
+       INF("amb bus id: %s", id);
+       _amb_connected(id);
+}
+
+Eina_Bool amb_nightmode_get(void)
+{
+       AMB_Manager *m = _amb_get();
+       EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
+       return m->nightmode;
+}
+
+Eina_Bool amb_init(void)
+{
+       if (!elm_need_e_dbus()) {
+               CRITICAL("Elementary does not support DBus.");
+               return EINA_FALSE;
+       }
+
+       bus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
+       if (!bus_conn) {
+               CRITICAL("Could not get DBus System Bus");
+               return EINA_FALSE;
+       }
+
+       e_dbus_signal_handler_add(bus_conn, E_DBUS_FDO_BUS, E_DBUS_FDO_PATH,
+                                       E_DBUS_FDO_INTERFACE,
+                                       "NameOwnerChanged",
+                                       _name_owner_changed, NULL);
+
+       e_dbus_get_name_owner(bus_conn, bus_name, _amb_get_name_owner, NULL);
+
+       return EINA_TRUE;
+}
+
+void amb_shutdown(void)
+{
+       if (amb_manager) {
+               _amb_free(amb_manager);
+               amb_manager = NULL;
+       }       
+       _amb_disconnected();
+}
+
+Eina_Bool amb_night_mode_get(void)
+{
+       AMB_Manager *m = _amb_get();
+       EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
+       return m->nightmode;
+}
+
+static AMB_Callback_List_Node * _amb_callback_list_node_create(
+       void (*cb)(void *data),const void *data)
+{
+       AMB_Callback_List_Node  *node_new;
+
+       node_new = calloc(1, sizeof(AMB_Callback_List_Node));
+       EINA_SAFETY_ON_NULL_RETURN_VAL(node_new, NULL);
+
+       node_new->cb_data = data;
+       node_new->cb = cb;
+
+       return node_new;
+}
+
+static void _amb_callback_list_delete(Eina_Inlist **list,
+                                       AMB_Callback_List_Node *node)
+{
+       EINA_SAFETY_ON_NULL_RETURN(*list);
+       *list = eina_inlist_remove(*list, EINA_INLIST_GET(node));
+       free(node);
+}
+
+AMB_Callback_List_Node *
+amb_properties_changed_cb_add(void (*cb)(void *data), const void *data)
+{
+       AMB_Callback_List_Node *node;
+
+       EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
+       node = _amb_callback_list_node_create(cb, data);
+       EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
+
+       cbs_amb_properties_changed = eina_inlist_append(cbs_amb_properties_changed,
+                                               EINA_INLIST_GET(node));
+
+       return node;
+}
+
+void amb_properties_changed_cb_del(AMB_Callback_List_Node *node)
+{
+       EINA_SAFETY_ON_NULL_RETURN(node);
+       _amb_callback_list_delete(&cbs_amb_properties_changed, node);
+}
diff --git a/utils/amb.h b/utils/amb.h
new file mode 100644 (file)
index 0000000..86f95f3
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _AMB_H__
+#define _AMB_H__
+
+typedef enum
+{
+       AMB_ERROR_NONE = 0,
+       AMB_ERROR_FAILED
+} AMB_Error;
+
+typedef struct _AMB_Callback_List_Node AMB_Callback_List_Node;
+
+AMB_Callback_List_Node *amb_properties_changed_cb_add(void (*cb)(void *data), const void *data);
+
+void amb_properties_changed_cb_del(AMB_Callback_List_Node *callback_node);
+
+Eina_Bool amb_night_mode_get(void);
+
+Eina_Bool amb_init(void);
+
+void amb_shutdown(void);
+
+#endif
index 0949b33..81bb9b2 100644 (file)
@@ -159,6 +159,29 @@ Evas_Object *layout_add(Evas_Object *parent, const char *style)
        return layout;
 }
 
+Eina_Bool util_set_night_mode(Eina_Bool night_mode)
+{
+        snprintf(def_theme, sizeof(def_theme), "%s/themes/night.edj",
+                        elm_app_data_dir_get());
+
+        elm_theme_extension_add(NULL, def_theme);
+
+        if (night_mode)
+        {
+                night_mode = EINA_TRUE;
+                elm_theme_overlay_add(NULL, def_theme);
+                DBG("Load theme at %s", def_theme);
+        }
+        else
+        {
+                night_mode = EINA_FALSE;
+                elm_theme_overlay_del(NULL, def_theme);
+                DBG("Unload theme at %s", def_theme);
+        }
+
+       return EINA_TRUE;
+}
+
 Eina_Bool util_init(const char *theme)
 {
        elm_app_compile_bin_dir_set(PACKAGE_BIN_DIR);
index 246dbe6..cb0a279 100644 (file)
@@ -17,6 +17,8 @@ Evas_Object *picture_icon_get(Evas_Object *parent, const char *picture);
 
 Evas_Object *layout_add(Evas_Object *parent, const char *style);
 
+Eina_Bool util_set_night_mode(Eina_Bool night_mode);
+
 Eina_Bool util_init(const char *theme);
 void util_shutdown(void);