daemon: support running with pa_glib_mainloop/GMainLoop.
authorKrisztian Litkey <kli@iki.fi>
Wed, 21 Aug 2013 17:58:34 +0000 (20:58 +0300)
committerKrisztian Litkey <kli@iki.fi>
Wed, 21 Aug 2013 17:58:34 +0000 (20:58 +0300)
To allow *temporarily* plugins to use gdbus, we need to be able
to run with GMainLoop and consequently to use pa_glib_mainloop.
This is now possible by setting the configuration variable
'gmainloop' to true either in the config file or by passing
the -s gmainloop=true on the command line.

configure.ac
src/Makefile.am
src/daemon/context.h
src/daemon/daemon.c
src/plugins/input-handler/input-plugin.c
src/plugins/sphinx-speech-engine/pulse-interface.c
src/plugins/sphinx-speech-engine/pulse-interface.h

index 0c88793..9a33941 100644 (file)
@@ -107,8 +107,11 @@ AC_SUBST(MURPHY_BREEDLINE_LIBS)
 
 # Check for PulseAudio.
 PKG_CHECK_MODULES(PULSE, libpulse >= 0.9.22)
+PKG_CHECK_MODULES(PULSE_GLIB, libpulse-mainloop-glib >= 0.922)
 AC_SUBST(PULSE_CFLAGS)
 AC_SUBST(PULSE_LIBS)
+AC_SUBST(PULSE_GLIB_CFLAGS)
+AC_SUBST(PULSE_GLIB_LIBS)
 
 # Check if potentially GPL bits are allowed to be enabled.
 AC_ARG_ENABLE(gpl,
@@ -192,6 +195,14 @@ AC_SUBST(SPHINX_LIBS)
 # Check for libudev.
 PKG_CHECK_MODULES(UDEV, libudev)
 
+# Check for glib et al that we need temporarily to allow plugins use gdbus.
+PKG_CHECK_MODULES(GLIB, glib-2.0 gobject-2.0)
+PKG_CHECK_MODULES(MURPHY_GLIB, murphy-glib)
+AC_SUBST(GLIB_CFLAGS)
+AC_SUBST(GLIB_LIBS)
+AC_SUBST(MURPHY_GLIB_CFLAGS)
+AC_SUBST(MURPHY_GLIB_LIBS)
+
 # Shave by default.
 SHAVE_INIT([build-aux], [enable])
 
index a49cdff..5737090 100644 (file)
@@ -5,7 +5,7 @@ plugindir          = $(libdir)/src/plugins
 plugin_LTLIBRARIES =
 
 INCLUDES           = -I$(top_builddir)
-AM_CFLAGS          = $(INCLUDES)
+AM_CFLAGS          = $(INCLUDES) $(GLIB_CFLAGS)
 
 QUIET_GEN          = $(Q:@=@echo '  GEN   '$@;)
 
@@ -31,13 +31,19 @@ srs_daemon_CFLAGS =                                 \
                $(MURPHY_PULSE_CFLAGS)          \
                $(MURPHY_COMMON_CFLAGS)         \
                $(MURPHY_RESOURCE_CFLAGS)       \
-               $(PULSE_CFLAGS)
+               $(PULSE_CFLAGS)                 \
+               $(PULSE_GLIB_CFLAGS)            \
+               $(MURPHY_GLIB_CFLAGS)           \
+               $(GLIB_CFLAGS)
 
 srs_daemon_LDADD =                             \
                $(MURPHY_PULSE_LIBS)            \
                $(MURPHY_RESOURCE_LIBS)         \
                $(MURPHY_COMMON_LIBS)           \
                $(PULSE_LIBS)                   \
+               $(PULSE_GLIB_LIBS)              \
+               $(MURPHY_GLIB_LIBS)             \
+               $(GLIB_LIBS)                    \
                -ldl
 
 srs_daemon_LDFLAGS =                           \
index f1153b7..0c4e9aa 100644 (file)
 #ifndef __SRS_DAEMON_CONTEXT_H__
 #define __SRS_DAEMON_CONTEXT_H__
 
+#include <pulse/mainloop.h>
+#include <pulse/glib-mainloop.h>
+
 #include <murphy/common/list.h>
 #include <murphy/common/pulse-glue.h>
 #include <murphy/common/hashtbl.h>
+#include <murphy/common/glib-glue.h>
 
 #include <murphy/plugins/resource-native/libmurphy-resource/resource-api.h>
 
@@ -46,7 +50,9 @@ typedef struct srs_context_s srs_context_t;
  */
 
 struct srs_context_s {
-    pa_mainloop       *pa;               /* pulseaudio mainloop */
+    GMainLoop         *gl;               /* GMainLoop if enabled and used */
+    void              *pl;               /* PA (native or glib) mainloop */
+    pa_mainloop_api   *pa;               /* PA mainloop API */
     mrp_mainloop_t    *ml;               /* associated murphy mainloop */
     mrp_list_hook_t    clients;          /* connected clients */
     mrp_list_hook_t    plugins;          /* loaded plugins */
index e3f392b..3760dad 100644 (file)
@@ -34,6 +34,8 @@
 #include <murphy/common/log.h>
 #include <murphy/common/utils.h>
 
+#include <glib-object.h>
+
 #include "src/daemon/context.h"
 #include "src/daemon/config.h"
 #include "src/daemon/resourceif.h"
 #include "src/daemon/recognizer.h"
 
 
+static void cleanup_mainloop(srs_context_t *srs);
+
 static void cleanup_context(srs_context_t *srs)
 {
     if (srs != NULL) {
         resource_disconnect(srs);
-
-        if (srs->ml != NULL)
-            mrp_mainloop_destroy(srs->ml);
-
-        if (srs->pa != NULL)
-            pa_mainloop_free(srs->pa);
+        cleanup_mainloop(srs);
 
         mrp_free(srs);
     }
@@ -67,18 +66,9 @@ static srs_context_t *create_context(void)
         mrp_list_init(&srs->plugins);
         mrp_list_init(&srs->recognizers);
         mrp_list_init(&srs->disambiguators);
-
-        srs->pa = pa_mainloop_new();
-        srs->ml = mrp_mainloop_pulse_get(pa_mainloop_get_api(srs->pa));
-
-        if (srs->pa != NULL && srs->ml != NULL)
-            if (resource_connect(srs))
-                return srs;
-
-        cleanup_context(srs);
     }
 
-    return NULL;
+    return srs;
 }
 
 
@@ -108,21 +98,84 @@ static void daemonize(srs_context_t *srs)
 }
 
 
+static void create_mainloop(srs_context_t *srs)
+{
+    if (srs_get_bool_config(srs->settings, "gmainloop", FALSE)) {
+        mrp_log_info("Configured to run with glib mainloop.");
+
+        g_type_init();
+        srs->gl = g_main_loop_new(NULL, FALSE);
+
+        if (srs->gl == NULL) {
+            mrp_log_error("Failed to create GMainLoop.");
+            exit(1);
+        }
+    }
+    else
+        mrp_log_info("Configured to run with native PA mainloop.");
+
+    if (srs->gl == NULL) {
+        srs->pl = pa_mainloop_new();
+        srs->pa = pa_mainloop_get_api(srs->pl);
+        srs->ml = mrp_mainloop_pulse_get(srs->pa);
+    }
+    else {
+        srs->pl = pa_glib_mainloop_new(g_main_loop_get_context(srs->gl));
+        srs->pa = pa_glib_mainloop_get_api(srs->pl);
+        srs->ml = mrp_mainloop_glib_get(srs->gl);
+    }
+
+    if (srs->pa != NULL && srs->ml != NULL)
+        if (resource_connect(srs))
+            return;
+
+    cleanup_context(srs);
+    exit(1);
+}
+
+
 static void run_mainloop(srs_context_t *srs)
 {
-    pa_mainloop_run(srs->pa, &srs->exit_status);
+    if (srs->gl == NULL)
+        pa_mainloop_run((pa_mainloop *)srs->pl, &srs->exit_status);
+    else
+        g_main_loop_run(srs->gl);
 }
 
 
 static void quit_mainloop(srs_context_t *srs, int exit_status)
 {
-    if (srs != NULL)
-        pa_mainloop_quit(srs->pa, exit_status);
+    if (srs != NULL) {
+        if (srs->gl != NULL)
+            g_main_loop_quit(srs->gl);
+        else
+            pa_mainloop_quit((pa_mainloop *)srs->pl, exit_status);
+    }
     else
         exit(exit_status);
 }
 
 
+static void cleanup_mainloop(srs_context_t *srs)
+{
+    mrp_mainloop_destroy(srs->ml);
+    srs->ml = NULL;
+
+    if (srs->gl == NULL) {
+        if (srs->pl != NULL)
+            pa_mainloop_free(srs->pl);
+    }
+    else {
+        pa_glib_mainloop_free(srs->pl);
+        g_main_loop_unref(srs->gl);
+        srs->gl = NULL;
+    }
+
+    srs->pl = NULL;
+    srs->pa = NULL;
+}
+
+
 static void sighandler(mrp_sighandler_t *h, int signum, void *user_data)
 {
     static int rlog = FALSE;
@@ -171,10 +224,12 @@ int main(int argc, char *argv[])
     if (srs != NULL) {
         srs->rlog = mrp_res_set_logger(NULL);
 
-        setup_signals(srs);
         config_parse_cmdline(srs, argc, argv);
         setup_logging(srs);
 
+        create_mainloop(srs);
+        setup_signals(srs);
+
         if (!srs_configure_plugins(srs)) {
             mrp_log_error("Some plugins failed to configure.");
             exit(1);
@@ -196,6 +251,7 @@ int main(int argc, char *argv[])
         srs_stop_plugins(srs);
         srs_destroy_plugins(srs);
 
+        cleanup_mainloop(srs);
         cleanup_context(srs);
 
         exit(0);
index ac37d98..473e864 100644 (file)
@@ -258,7 +258,7 @@ static int add_input(context_t *ctx,
 
     srs_plugin_t *plugin = ctx->plugin;
     srs_context_t *srs = plugin->srs;
-    pa_mainloop_api *mlapi = pa_mainloop_get_api(srs->pa);
+    pa_mainloop_api *mlapi = srs->pa;
     char id[512];
     size_t idx;
     input_t *inp;
@@ -311,7 +311,7 @@ static int remove_input(context_t *ctx,
 {
     srs_plugin_t *plugin = ctx->plugin;
     srs_context_t *srs = plugin->srs;
-    pa_mainloop_api *mlapi = pa_mainloop_get_api(srs->pa);
+    pa_mainloop_api *mlapi = srs->pa;
     input_t *inp, *inputs;
     size_t i, ninput, size;
 
index b72aa3a..fb45da8 100644 (file)
@@ -33,20 +33,17 @@ static void event_callback(pa_context *, pa_subscription_event_type_t,
                            uint32_t, void *);
 
 
-int pulse_interface_create(context_t *ctx, pa_mainloop *mloop)
+int pulse_interface_create(context_t *ctx, pa_mainloop_api *api)
 {
     pulse_interface_t *pulseif;
-    pa_mainloop_api *api = NULL;
 
     if (!(pulseif = mrp_allocz(sizeof(pulse_interface_t))))
         goto failed;
 
-    api = pa_mainloop_get_api(mloop);
-
     if (pa_signal_init(api) < 0)
         goto failed;
 
-    pulseif->mloop = mloop;
+    pulseif->api = api;
 
     ctx->pulseif = pulseif;
 
@@ -104,7 +101,7 @@ void pulse_interface_cork_input_stream(context_t *ctx, bool cork)
 static void connect_to_server(context_t *ctx)
 {
     pulse_interface_t *pulseif = ctx->pulseif;
-    pa_mainloop_api *api = pa_mainloop_get_api(pulseif->mloop);
+    pa_mainloop_api *api = pulseif->api;
     pa_context *pactx;
 
     if (pulseif->pactx) {
index 322a22f..fc468b4 100644 (file)
@@ -7,14 +7,14 @@
 #include "sphinx-plugin.h"
 
 struct pulse_interface_s {
-    pa_mainloop *mloop;
+    pa_mainloop_api *api;
     pa_context *pactx;
     pa_stream *stream;
     bool conup;
     bool corked;
 };
 
-int  pulse_interface_create(context_t *ctx, pa_mainloop *mloop);
+int  pulse_interface_create(context_t *ctx, pa_mainloop_api *api);
 void pulse_interface_destroy(context_t *ctx);
 
 void pulse_interface_cork_input_stream(context_t *ctx, bool cork);