2 * Copyright (c) 2012, Intel Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Intel Corporation nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <murphy/common/macros.h>
33 #include <murphy/common/mm.h>
34 #include <murphy/common/log.h>
35 #include <murphy/common/utils.h>
37 #include <glib-object.h>
39 #include "srs/daemon/context.h"
40 #include "srs/daemon/config.h"
41 #include "srs/daemon/resctl.h"
42 #include "srs/daemon/plugin.h"
43 #include "srs/daemon/client.h"
44 #include "srs/daemon/recognizer.h"
45 #include "srs/daemon/pulse.h"
47 static void cleanup_mainloop(srs_context_t *srs);
48 static void resctl_state_change(srs_resctl_event_t *e, void *user_data);
50 static void cleanup_context(srs_context_t *srs)
53 srs_resctl_disconnect(srs);
54 srs_pulse_cleanup(srs->pulse);
55 cleanup_mainloop(srs);
58 * XXX TODO: should purge recognizers, disambiguators, synthesizers...
66 static srs_context_t *create_context(void)
68 srs_context_t *srs = mrp_allocz(sizeof(*srs));
71 mrp_list_init(&srs->clients);
72 mrp_list_init(&srs->plugins);
73 mrp_list_init(&srs->recognizers);
74 mrp_list_init(&srs->disambiguators);
81 static void setup_logging(srs_context_t *srs)
85 target = mrp_log_parse_target(srs->log_target);
88 mrp_log_set_target(target);
90 mrp_log_error("invalid log target '%s'", srs->log_target);
94 static void daemonize(srs_context_t *srs)
96 if (!srs->foreground) {
97 mrp_log_info("Switching to daemon mode.");
99 if (!mrp_daemonize("/", "/dev/null", "/dev/null")) {
100 mrp_log_error("Failed to daemonize.");
107 static void create_mainloop(srs_context_t *srs)
109 if (srs_config_get_bool(srs->settings, "gmainloop", FALSE)) {
110 mrp_log_info("Configured to run with glib mainloop.");
112 #ifndef GLIB_VERSION_2_36
115 srs->gl = g_main_loop_new(NULL, FALSE);
117 if (srs->gl == NULL) {
118 mrp_log_error("Failed to create GMainLoop.");
123 mrp_log_info("Configured to run with native PA mainloop.");
125 if (srs->gl == NULL) {
126 srs->pl = pa_mainloop_new();
127 srs->pa = pa_mainloop_get_api(srs->pl);
128 srs->ml = mrp_mainloop_pulse_get(srs->pa);
131 srs->pl = pa_glib_mainloop_new(g_main_loop_get_context(srs->gl));
132 srs->pa = pa_glib_mainloop_get_api(srs->pl);
133 srs->ml = mrp_mainloop_glib_get(srs->gl);
136 srs->pulse = srs_pulse_setup(srs->pa, "SRS daemon");
138 if (srs->pa != NULL && srs->pulse != NULL && srs->ml != NULL) {
139 if (srs_resctl_connect(srs, resctl_state_change, srs, TRUE))
143 cleanup_context(srs);
148 static void run_mainloop(srs_context_t *srs)
151 pa_mainloop_run((pa_mainloop *)srs->pl, &srs->exit_status);
153 g_main_loop_run(srs->gl);
157 static void quit_mainloop(srs_context_t *srs, int exit_status)
161 g_main_loop_quit(srs->gl);
163 pa_mainloop_quit((pa_mainloop *)srs->pl, exit_status);
170 static void cleanup_mainloop(srs_context_t *srs)
172 mrp_mainloop_destroy(srs->ml);
175 if (srs->gl == NULL) {
177 pa_mainloop_free(srs->pl);
180 pa_glib_mainloop_free(srs->pl);
181 g_main_loop_unref(srs->gl);
190 static void resctl_state_change(srs_resctl_event_t *e, void *user_data)
192 srs_context_t *srs = (srs_context_t *)user_data;
194 if (e->type != SRS_RESCTL_EVENT_CONNECTION)
197 if (e->connection.up) {
198 mrp_log_info("Resource control connection is up.");
199 client_create_resources(srs);
202 mrp_log_info("Resource control connection is down.");
203 client_reset_resources(srs);
208 static void sighandler(mrp_sighandler_t *h, int signum, void *user_data)
210 static int rlog = FALSE;
212 srs_context_t *srs = (srs_context_t *)user_data;
218 mrp_log_info("Received SIGINT, exiting...");
219 quit_mainloop(srs, 0);
223 mrp_log_info("Received SIGTERM, exiting...");
224 quit_mainloop(srs, 0);
228 mrp_log_info("%s resource library logging...",
229 rlog ? "Disabling" : "Enabling");
230 mrp_res_set_logger(rlog ? NULL : srs->rlog);
237 static void setup_signals(srs_context_t *srs)
239 mrp_add_sighandler(srs->ml, SIGINT , sighandler, srs);
240 mrp_add_sighandler(srs->ml, SIGTERM, sighandler, srs);
241 mrp_add_sighandler(srs->ml, SIGUSR2, sighandler, srs);
245 int main(int argc, char *argv[], char *env[])
251 srs = create_context();
254 srs->rlog = mrp_res_set_logger(NULL);
256 config_parse_cmdline(srs, argc, argv, env);
259 create_mainloop(srs);
262 if (!srs_configure_plugins(srs)) {
263 mrp_log_error("Some plugins failed to configure.");
267 if (!srs_start_plugins(srs)) {
268 mrp_log_error("Some plugins failed to start.");
273 srec = srs_config_get_string(cfg, "daemon.speech-backend", NULL);
274 srs_activate_srec(srs, srec);
280 srs_stop_plugins(srs);
281 srs_destroy_plugins(srs);
283 cleanup_context(srs);