Introduce the display plugin system 09/27309/2
authorManuel Bachmann <manuel.bachmann@open.eurogiciel.org>
Wed, 10 Sep 2014 14:48:55 +0000 (16:48 +0200)
committerManuel Bachmann <manuel.bachmann@open.eurogiciel.org>
Thu, 11 Sep 2014 09:46:37 +0000 (11:46 +0200)
At startup, "notification-display-service" will now search
for plugins in the "/usr/lib$ARCH/notification-service
/plugins" directory. If one is found, it will use it to
display notifications on screens. Otherwise, it will fall
back to pure text with dlog.

There is currently one plugin : wlmessage.so.

Change-Id: I663fc24ec2c9fd8c1f0a2f07be08f479f2a4569d
Signed-off-by: Manuel Bachmann <manuel.bachmann@open.eurogiciel.org>
Makefile.am
configure.ac
notification_display_service.c
packaging/notification-service.spec
plugins/Makefile.am [new file with mode: 0644]
plugins/wlmessage.c [new file with mode: 0644]

index 3ff5d19..532cab3 100644 (file)
@@ -1,7 +1,10 @@
+SUBDIRS = plugins
+moduledir = $(libdir)/notification-service/plugins
+
 bin_PROGRAMS = notification-service notification-display-service sample-display-client send-notification bluetooth_notification_client
 
 AM_CFLAGS = $(GCC_CFLAGS)
-AM_CPPFLAGS = $(GCC_CFLAGS)
+AM_CPPFLAGS = $(GCC_CFLAGS) -DPLUGINSDIR='"$(moduledir)"'
 
 notification_service_SOURCES = \
     main.c \
@@ -12,7 +15,7 @@ notification_service_LDADD = $(TIZEN_LIBS)
 
 notification_display_service_SOURCES = notification_display_service.c
 notification_display_service_CFLAGS = -I. $(TIZEN_CFLAGS)
-notification_display_service_LDADD = $(TIZEN_LIBS)
+notification_display_service_LDADD = $(TIZEN_LIBS) $(DLOPEN_LIBS)
 
 send_notification_SOURCES = send_notification.c
 send_notification_CFLAGS = -I. $(TIZEN_CFLAGS)
index edb8edb..2987c6b 100644 (file)
@@ -10,10 +10,15 @@ LT_PREREQ([2.2])
 LT_INIT([disable-static])
 
 PKG_PROG_PKG_CONFIG()
+
+AC_CHECK_FUNC([dlopen], [],
+              AC_CHECK_LIB([dl], [dlopen], DLOPEN_LIBS="-ldl"))
+AC_SUBST(DLOPEN_LIBS)
+
 PKG_CHECK_MODULES([TIZEN], [eina ecore com-core notification dbus-1 bluetooth-api dlog libwlmessage])
 AC_SUBST(TIZEN_CFLAGS)
 AC_SUBST(TIZEN_LIBS)
 
-AC_CONFIG_FILES([Makefile notifications.service notifications-display.service])
+AC_CONFIG_FILES([Makefile plugins/Makefile notifications.service notifications-display.service])
 AC_PROG_RANLIB([ranlib])
 AC_OUTPUT
index df35e42..30211ac 100644 (file)
 #include <stdio.h>
-#include <sys/stat.h>
+#include <unistd.h>
 #include <glib.h>
+#include <dirent.h>
 #include <notification.h>
+#include <dlfcn.h>
 #include <dlog.h>
-#include <libwlmessage.h>
 
 
-void display_notifications_cb (void *data, notification_type_e notif_type)
+void load_plugins (char *path, int (**fct)(notification_h))
 {
-       notification_h noti = NULL;
-       notification_list_h notification_list = NULL;
-       notification_list_h get_list = NULL;
+       DIR *dir;
+       struct dirent *plugins_dir;
+       char *plugin_path;
+       void *plugin;
+       int (*plugin_fct)(notification_h);
+
+       dir = opendir (path);
+       if (!dir)
+               return;
+
+       while ((plugins_dir = readdir(dir)) != NULL) {
+               if (g_str_has_suffix (plugins_dir->d_name, ".so")) {
+                       plugin_path = g_strconcat (path, G_DIR_SEPARATOR_S, plugins_dir->d_name, NULL);
+                       plugin = dlopen (plugin_path, RTLD_NOW | RTLD_LOCAL);
+                       plugin_fct = dlsym (plugin, "display_notification");
+                       g_free (plugin_path);
+                       if (!plugin) {
+                               LOGD("\"%s\" is not a plugin, continuing", plugins_dir->d_name);
+                               continue;
+                       } else if (!plugin_fct) {
+                               LOGD("Plugin \"%s\" incompatible, continuing", plugins_dir->d_name);
+                               dlclose (plugins_dir->d_name);
+                               continue;
+                       } else {
+                                /* use the first working plugin, if not configured otherwise */
+                               LOGD("Plugin \"%s\" compatible, loading...", plugins_dir->d_name);
+                               *fct = plugin_fct;
+                               break;
+                       }
+               }
+       }
+
+       closedir (dir);
+}
 
+int display_notification_text (notification_h noti)
+{
        char *pkgname = NULL;
        char *title = NULL;
        char *content = NULL;
        char *image_path = NULL;
 
+       notification_get_pkgname (noti, &pkgname);
+       if (pkgname == NULL)
+               notification_get_application (noti, &pkgname);
+       notification_get_title (noti, &title, NULL);
+       notification_get_text (noti, NOTIFICATION_TEXT_TYPE_CONTENT, &content);
+       notification_get_image (noti, NOTIFICATION_IMAGE_TYPE_ICON, &image_path);
+
+       LOGD("\nNew Notification : %s", title);
+       LOGD("Icon : %s", image_path);
+       LOGD("Message : %s", content);
+
+       return 1;
+}
+
+void display_notifications_cb (void *data, notification_type_e notif_type)
+{
+       int (*fct)(notification_h) = data;
+       notification_h noti = NULL;
+       notification_list_h notification_list = NULL;
+       notification_list_h get_list = NULL;
+
        notification_get_list (NOTIFICATION_TYPE_NOTI, -1, &notification_list);
        if (notification_list) {
                get_list = notification_list_get_head (notification_list);
                while (get_list) {
                        noti = notification_list_get_data (get_list);
-                       notification_get_pkgname (noti, &pkgname);
-                       if (pkgname == NULL)
-                               notification_get_application (noti, &pkgname);
-                       notification_get_title (noti, &title, NULL);
-                       notification_get_text (noti, NOTIFICATION_TEXT_TYPE_CONTENT, &content);
-                       notification_get_image (noti, NOTIFICATION_IMAGE_TYPE_ICON, &image_path);
-
-                       struct wlmessage *wlmessage = wlmessage_create ();
-                       wlmessage_set_title (wlmessage, title);
-                       wlmessage_set_icon (wlmessage, image_path);
-                       wlmessage_set_message (wlmessage, content);
-                       wlmessage_add_button (wlmessage, 0, "Ok");
-                       if (wlmessage_show (wlmessage, NULL) < 0) {
-                               wlmessage_destroy (wlmessage);
-                               return;
-                       }
-                       wlmessage_destroy (wlmessage);
-
-                       LOGD("\nNew Notification : %s\n", title);
-                       LOGD("Icon : %s\n", image_path);
-                       LOGD("Message : %s\n", content);
 
-                       get_list = notification_list_remove(get_list, noti);
-                       notification_delete(noti);
+                        /* if the display function was successful, delete the notification */
+                       if  ( (*fct)(noti) ) {
+                               get_list = notification_list_remove(get_list, noti);
+                               notification_delete(noti);
+                       }
                }
        }
 }
 
+
 int main (int argc, char **argv)
 {
        GMainLoop *mainloop = NULL;
+       gboolean error_s;
        notification_error_e error_n;
-       int error_s;
-       struct stat buf;
+       int (*disp_fct)(notification_h);
+
+        /* fall back to pure text notification if no plugin works */
+       disp_fct = &display_notification_text;
+       LOGD("Checking for display plugins...");
+       if (g_file_test (PLUGINSDIR, G_FILE_TEST_IS_DIR))
+               load_plugins (PLUGINSDIR, &disp_fct);
 
 retry_socket:
        LOGD("Checking if the notifications server socket exists...");
-       error_s = stat ("/tmp/.notification.service", &buf);
-       if (error_s == -1) {
+       error_s = g_file_test ("/tmp/.notification.service", G_FILE_TEST_EXISTS);
+       if (!error_s) {
                LOGD("Could not find the notifications server socket");
                sleep (5);
                goto retry_socket;
@@ -68,7 +112,7 @@ retry_socket:
 
 retry_service:
        LOGD("Checking if the notifications server is available...");
-       error_n = notification_resister_changed_cb (display_notifications_cb, NULL);
+       error_n = notification_resister_changed_cb (display_notifications_cb, (*disp_fct));
        if (error_n != NOTIFICATION_ERROR_NONE) {
                LOGD("Could not register with notifications server");
                sleep (5);
index cc557c6..68dd000 100644 (file)
@@ -56,6 +56,7 @@ make %{?_smp_mflags}
 %defattr(-,root,root,-)
 %{_bindir}/notification-service
 %{_bindir}/notification-display-service
+%{_libdir}/notification-service/plugins/wlmessage.so
 %{_unitdir}/notifications.service
 %{_unitdir}/notifications-display.service
 %{_unitdir}/graphical.target.wants/notifications.service
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
new file mode 100644 (file)
index 0000000..0d2c4b7
--- /dev/null
@@ -0,0 +1,14 @@
+bin_PROGRAMS =
+moduledir = $(libdir)/notification-service/plugins
+
+AM_CFLAGS = $(GCC_CFLAGS)
+AM_CPPFLAGS = $(GCC_CFLAGS)
+
+module_LTLIBRARIES = wlmessage.la
+
+wlmessage_la_SOURCES = wlmessage.c
+
+wlmessage_la_LDFLAGS = -module -avoid-version
+wlmessage_la_CPPFLAGS = $(AM_CPPFLAGS)
+wlmessage_la_CFLAGS = $(TIZEN_CFLAGS)
+wlmessage_la_LIBADD = $(TIZEN_LIBS)
diff --git a/plugins/wlmessage.c b/plugins/wlmessage.c
new file mode 100644 (file)
index 0000000..6f691af
--- /dev/null
@@ -0,0 +1,30 @@
+#include <notification.h>
+#include <libwlmessage.h>
+
+
+int display_notification (notification_h noti)
+{
+       char *pkgname = NULL;
+       char *title = NULL;
+       char *content = NULL;
+       char *image_path = NULL;
+
+       notification_get_pkgname (noti, &pkgname);
+       if (pkgname == NULL)
+               notification_get_application (noti, &pkgname);
+       notification_get_title (noti, &title, NULL);
+       notification_get_text (noti, NOTIFICATION_TEXT_TYPE_CONTENT, &content);
+       notification_get_image (noti, NOTIFICATION_IMAGE_TYPE_ICON, &image_path);
+
+       struct wlmessage *wlmessage = wlmessage_create ();
+       wlmessage_set_title (wlmessage, title);
+       wlmessage_set_icon (wlmessage, image_path);
+       wlmessage_set_message (wlmessage, content);
+       wlmessage_add_button (wlmessage, 0, "Ok");
+       if (wlmessage_show (wlmessage, NULL) < 0) {
+               wlmessage_destroy (wlmessage);
+               return 0;
+       }
+
+       return 1;
+}