2 * Copyright (c) 2012, 2013, 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.
30 #include "srs/daemon/context.h"
31 #include "srs/daemon/resctl.h"
33 #define CONNECT_TIMER (5 * 1000)
36 srs_context_t *srs; /* SRS context */
37 mrp_res_context_t *ctx; /* resource context */
38 mrp_list_hook_t sets; /* resource sets */
39 srs_resctl_event_cb_t cb; /* notification callback */
40 void *user_data; /* opaque notification data */
41 mrp_timer_t *t; /* (re)connect timer */
46 srs_resctx_t *ctx; /* resource context */
47 mrp_res_resource_set_t *set; /* resource set */
48 mrp_list_hook_t hook; /* to list of resource sets */
49 srs_resctl_event_cb_t cb; /* notification callback */
50 void *user_data; /* opaque notification data */
51 char *appclass; /* application class */
52 int shared : 1; /* whether currently shared */
53 mrp_deferred_t *emul; /* deferred cb for emulation */
57 static void context_event(mrp_res_context_t *rctx, mrp_res_error_t err,
59 static void set_event(mrp_res_context_t *rctx,
60 const mrp_res_resource_set_t *rset, void *user_data);
61 static void stop_connect(srs_resctx_t *ctx);
62 static void notify_connect(srs_resctx_t *ctx);
63 static void notify_disconnect(srs_resctx_t *ctx, int requested);
65 static int emul_acquire(srs_resset_t *set, int shared);
66 static int emul_release(srs_resset_t *set);
68 #define CONFIG_SREC "resource.recognition"
69 #define DEFAULT_SREC "speech_recognition"
70 #define CONFIG_SSYN "resource.synthesis"
71 #define DEFAULT_SSYN "speech_synthesis"
73 static const char *name_srec;
74 static const char *name_ssyn;
77 static void get_resource_names(srs_cfg_t *cfg)
79 name_srec = srs_get_string_config(cfg, CONFIG_SREC, DEFAULT_SREC);
80 name_ssyn = srs_get_string_config(cfg, CONFIG_SSYN, DEFAULT_SSYN);
82 mrp_log_info("Using resource '%s' for speech recognition.", name_srec);
83 mrp_log_info("Using resoruce '%s' for speech synthesis.", name_ssyn);
87 static int try_connect(srs_resctx_t *ctx)
89 srs_context_t *srs = ctx->srs;
91 ctx->ctx = mrp_res_create(srs->ml, context_event, ctx);
100 static void connect_timer_cb(mrp_timer_t *t, void *user_data)
102 srs_resctx_t *ctx = (srs_resctx_t *)user_data;
106 if (try_connect(ctx))
111 static int start_connect(srs_resctx_t *ctx)
113 srs_context_t *srs = ctx->srs;
115 ctx->t = mrp_add_timer(srs->ml, CONNECT_TIMER, connect_timer_cb, ctx);
117 return (ctx->t != NULL);
121 static void stop_connect(srs_resctx_t *ctx)
123 mrp_del_timer(ctx->t);
128 int srs_resctl_connect(srs_context_t *srs, srs_resctl_event_cb_t cb,
129 void *user_data, int reconnect)
133 if (srs->rctx != NULL)
136 ctx = mrp_allocz(sizeof(*ctx));
141 mrp_list_init(&ctx->sets);
144 ctx->user_data = user_data;
147 if (try_connect(ctx) || (reconnect && start_connect(ctx)))
157 void srs_resctl_disconnect(srs_context_t *srs)
159 srs_resctx_t *ctx = srs->rctx;
163 mrp_res_destroy(ctx->ctx);
165 notify_disconnect(ctx, TRUE);
173 static void context_event(mrp_res_context_t *rctx, mrp_res_error_t err,
176 srs_resctx_t *ctx = (srs_resctx_t *)user_data;
177 srs_context_t *srs = ctx->srs;
181 switch (rctx->state) {
182 case MRP_RES_CONNECTED:
183 mrp_log_info("Resource context connection is up.");
188 case MRP_RES_DISCONNECTED:
189 mrp_log_info("Resource context connection is down.");
190 notify_disconnect(ctx, FALSE);
196 static void notify_connect(srs_resctx_t *ctx)
198 srs_resctl_event_t e;
200 if (ctx->cb != NULL) {
201 e.connection.type = SRS_RESCTL_EVENT_CONNECTION;
202 e.connection.up = TRUE;
203 ctx->cb(&e, ctx->user_data);
208 static void notify_disconnect(srs_resctx_t *ctx, int requested)
210 mrp_list_hook_t *p, *n;
212 srs_resctl_event_t e;
215 if (ctx->cb != NULL) {
216 e.connection.type = SRS_RESCTL_EVENT_CONNECTION;
217 e.connection.up = FALSE;
218 ctx->cb(&e, ctx->user_data);
222 e.type = SRS_RESCTL_EVENT_DESTROYED;
224 mrp_list_foreach(&ctx->sets, p, n) {
225 set = mrp_list_entry(p, typeof(*set), hook);
228 set->cb(&e, set->user_data);
233 srs_resset_t *srs_resctl_create(srs_context_t *srs, char *appclass,
234 srs_resctl_event_cb_t cb, void *user_data)
236 srs_resctx_t *ctx = srs->rctx;
240 set = mrp_allocz(sizeof(*set));
245 mrp_list_init(&set->hook);
248 set->user_data = user_data;
249 set->shared = shared = TRUE;
250 set->appclass = mrp_strdup(appclass);
252 if (ctx == NULL || ctx->ctx == NULL || srs_resctl_online(srs, set)) {
253 mrp_list_append(&ctx->sets, &set->hook);
259 if (set->set != NULL)
260 mrp_res_delete_resource_set(set->set);
262 mrp_free(set->appclass);
270 void srs_resctl_destroy(srs_resset_t *set)
272 srs_resctx_t *ctx = set ? set->ctx : NULL;
275 if (set->emul != NULL) {
276 mrp_del_deferred(set->emul);
281 mrp_res_delete_resource_set(set->set);
283 mrp_list_delete(&set->hook);
284 mrp_free(set->appclass);
290 int srs_resctl_online(srs_context_t *srs, srs_resset_t *set)
292 srs_resctx_t *ctx = srs->rctx;
293 int shared = set->shared;
298 if (set->emul != NULL) {
299 mrp_del_deferred(set->emul);
304 set->set = mrp_res_create_resource_set(ctx->ctx, set->appclass,
307 if (set->set == NULL)
310 if (name_srec == NULL || name_ssyn == NULL)
311 get_resource_names(srs->settings);
313 if (mrp_res_create_resource(set->set, name_srec, TRUE, shared) &&
314 mrp_res_create_resource(set->set, name_ssyn, TRUE, shared))
317 mrp_res_delete_resource_set(set->set);
324 void srs_resctl_offline(srs_resset_t *set)
331 int srs_resctl_acquire(srs_resset_t *set, int shared)
333 srs_resctx_t *ctx = set ? set->ctx : NULL;
338 if (ctx->ctx == NULL || set->set == NULL)
339 return emul_acquire(set, shared);
341 if (!!shared != !!set->shared) {
342 mrp_res_delete_resource_set(set->set);
343 set->shared = !!shared;
346 set->set = mrp_res_create_resource_set(ctx->ctx, set->appclass,
349 if (set->set == NULL)
352 if (!mrp_res_create_resource(set->set, name_srec,
354 !mrp_res_create_resource(set->set, name_ssyn,
359 if (mrp_res_acquire_resource_set(set->set) == 0)
365 if (set->set != NULL) {
366 mrp_res_delete_resource_set(set->set);
374 int srs_resctl_release(srs_resset_t *set)
376 srs_resctx_t *ctx = set ? set->ctx : NULL;
381 if (ctx->ctx == NULL || set->set == NULL)
382 return emul_release(set);
384 if (mrp_res_release_resource_set(set->set) >= 0)
391 static void set_event(mrp_res_context_t *rctx,
392 const mrp_res_resource_set_t *rset, void *user_data)
394 srs_resset_t *set = (srs_resset_t *)user_data;
395 mrp_res_resource_t *srec, *ssyn;
396 srs_resctl_event_t e;
398 srec = mrp_res_get_resource_by_name(rset, name_srec);
399 ssyn = mrp_res_get_resource_by_name(rset, name_ssyn);
401 if (srec == NULL || ssyn == NULL || srec->state != ssyn->state) {
402 mrp_log_error("Inconsistent resources in set.");
409 e.resource.type = SRS_RESCTL_EVENT_RESOURCE;
410 e.resource.granted = 0;
413 e.resource.granted |= SRS_RESCTL_MASK_SREC;
415 e.resource.granted |= SRS_RESCTL_MASK_SYNT;
417 set->cb(&e, set->user_data);
421 static void emul_acquire_cb(mrp_deferred_t *d, void *user_data)
423 srs_resset_t *set = (srs_resset_t *)user_data;
424 srs_resctl_event_t e;
431 e.resource.type = SRS_RESCTL_EVENT_RESOURCE;
432 e.resource.granted = SRS_RESCTL_MASK_SREC | SRS_RESCTL_MASK_SYNT;
434 set->cb(&e, set->user_data);
438 static int emul_acquire(srs_resset_t *set, int shared)
440 srs_resctx_t *ctx = set ? set->ctx : NULL;
447 if (set->emul != NULL)
450 set->emul = mrp_add_deferred(ctx->srs->ml, emul_acquire_cb, set);
452 if (set->emul != NULL)
459 static void emul_release_cb(mrp_deferred_t *d, void *user_data)
461 srs_resset_t *set = (srs_resset_t *)user_data;
462 srs_resctl_event_t e;
469 e.resource.type = SRS_RESCTL_EVENT_RESOURCE;
470 e.resource.granted = 0;
472 set->cb(&e, set->user_data);
476 static int emul_release(srs_resset_t *set)
478 srs_resctx_t *ctx = set ? set->ctx : NULL;
483 if (set->emul != NULL)
486 set->emul = mrp_add_deferred(set->ctx->srs->ml, emul_release_cb, set);
488 if (set->emul != NULL)