sphinx-speech-engine: deliver recognition notifications.
[profile/ivi/speech-recognition.git] / src / plugins / sphinx-speech-engine / sphinx-plugin.c
1 /*
2  * Copyright (c) 2012, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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.
16  *
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.
28  */
29
30 #include <murphy/common/debug.h>
31 #include <murphy/common/mainloop.h>
32
33 #include <pulse/pulseaudio.h>
34 #include <pulse/mainloop.h>
35
36 #include "options.h"
37 #include "decoder-set.h"
38 #include "utterance.h"
39 #include "filter-buffer.h"
40 #include "input-buffer.h"
41 #include "pulse-interface.h"
42
43
44 #define SPHINX_NAME        "sphinx-speech"
45 #define SPHINX_DESCRIPTION "A CMU Sphinx-based speech engine backend plugin."
46 #define SPHINX_AUTHORS     "Janos Kovacs <janos.kovacs@intel.com>"
47 #define SPHINX_VERSION     "0.0.1"
48
49 struct plugin_s {
50     srs_plugin_t *self;               /* us, the backend plugin */
51     struct {
52         srs_srec_notify_t callback;   /* recognition notification callback */
53         void *data;                   /* notifiation callback data */
54     } notify;
55 };
56
57
58 int32_t plugin_utterance_handler(context_t *ctx, srs_srec_utterance_t *utt)
59 {
60     plugin_t *pl;
61     srs_srec_notify_t notify;
62     int32_t length;
63
64     if (!(pl = ctx->plugin) || !(notify = pl->notify.callback))
65         length = -1;
66     else {
67         length = notify(utt, pl->notify.data);
68
69         if (length < 0 && utt->length)
70             length = utt->length;
71     }
72
73     return length;
74 }
75
76 static int activate(void *user_data)
77 {
78     context_t *ctx = (context_t *)user_data;
79
80     MRP_UNUSED(ctx);
81
82     mrp_log_info("Activating CMU Sphinx backend.");
83
84     return TRUE;
85 }
86
87
88 static void deactivate(void *user_data)
89 {
90     context_t *ctx = (context_t *)user_data;
91
92     MRP_UNUSED(ctx);
93
94     mrp_log_info("Deactivating CMU Sphinx backend.");
95 }
96
97
98 static int flush(uint32_t start, uint32_t end, void *user_data)
99 {
100     context_t *ctx = (context_t *)user_data;
101
102     MRP_UNUSED(ctx);
103
104     mrp_debug("flushing CMU Sphinx backend buffer (%u - %u)", start, end);
105
106     return TRUE;
107 }
108
109
110 static int rescan(uint32_t start, uint32_t end, void *user_data)
111 {
112     context_t *ctx = (context_t *)user_data;
113
114     MRP_UNUSED(ctx);
115
116     mrp_debug("scheduling CMU Sphinx backend buffer rescan (%u - %u)",
117               start, end);
118
119     return TRUE;
120 }
121
122
123 static void *sampledup(uint32_t start, uint32_t end, void *user_data)
124 {
125     context_t *ctx = (context_t *)user_data;
126
127     MRP_UNUSED(ctx);
128
129     mrp_debug("duplicating CMU Sphinx backend samples (%u - %u)", start, end);
130
131
132     return (void *)4;
133 }
134
135
136 static int check_decoder(const char *decoder, void *user_data)
137 {
138     context_t *ctx = (context_t *)user_data;
139
140     MRP_UNUSED(ctx);
141
142     mrp_debug("checking availability of decoder '%s' for CMU Sphinx backend",
143               decoder);
144
145     return TRUE;
146 }
147
148
149 static int select_decoder(const char *decoder, void *user_data)
150 {
151     context_t *ctx = (context_t *)user_data;
152
153     MRP_UNUSED(ctx);
154
155     mrp_debug("selecting decoder '%s' for CMU Sphinx backend", decoder);
156
157     return TRUE;
158 }
159
160 static int create_sphinx(srs_plugin_t *plugin)
161 {
162     srs_srec_api_t api = {
163     activate:         activate,
164     deactivate:       deactivate,
165     flush:            flush,
166     rescan:           rescan,
167     sampledup:        sampledup,
168     check_decoder:    check_decoder,
169     select_decoder:   select_decoder,
170     };
171
172     srs_context_t *srs = plugin->srs;
173     context_t     *ctx = NULL;
174     plugin_t      *pl = NULL;
175     int            sts;
176
177     mrp_debug("creating CMU Sphinx speech recognition backend plugin");
178
179     if ((ctx = mrp_allocz(sizeof(context_t))) &&
180         (pl  = mrp_allocz(sizeof(plugin_t)))   )
181     {
182         ctx->plugin = pl;
183
184         pl->self = plugin;
185
186         sts = srs_register_srec(srs, SPHINX_NAME, &api, ctx,
187                                 &pl->notify.callback,
188                                 &pl->notify.data);
189         if (sts == 0) {
190             plugin->plugin_data = ctx;
191             return TRUE;
192         }
193     }
194
195     mrp_free(pl);
196     mrp_free(ctx);
197
198     mrp_log_error("Failed to create CMU Sphinx plugin.");
199
200     return FALSE;
201 }
202
203
204 static int config_sphinx(srs_plugin_t *plugin, srs_cfg_t *settings)
205 {
206     context_t *ctx = (context_t *)plugin->plugin_data;
207     srs_cfg_t *cfg;
208     int        n, i;
209
210     mrp_debug("configuring CMU Sphinx speech recognition backend plugin");
211
212     n = srs_collect_config(settings, SPHINX_PREFIX, &cfg);
213
214     mrp_log_info("Found %d CMU Sphinx plugin configuration keys.", n);
215
216     if (options_create(ctx, n, cfg) < 0 ||
217         decoder_set_create(ctx)     < 0 ||
218         filter_buffer_create(ctx)   < 0 ||
219         input_buffer_create(ctx)    < 0  )
220     {
221         mrp_log_error("Failed to configure CMU Sphinx plugin.");
222         return FALSE;
223     }
224
225     srs_free_config(cfg);
226
227     return TRUE;
228 }
229
230
231 static int start_sphinx(srs_plugin_t *plugin)
232 {
233     srs_context_t *srs = plugin->srs;
234     context_t *ctx = (context_t *)plugin->plugin_data;
235
236     mrp_debug("start CMU Sphinx speech recognition backend plugin");
237
238     if (pulse_interface_create(ctx, srs->pa) < 0) {
239         mrp_log_error("Failed to start CMU Sphinx plugin: can't create "
240                       "pulseaudio interface");
241     }
242
243     return TRUE;
244 }
245
246
247 static void stop_sphinx(srs_plugin_t *plugin)
248 {
249     context_t *ctx = (context_t *)plugin->plugin_data;
250
251     mrp_debug("stop CMU Sphinx speech recognition backend plugin");
252
253     pulse_interface_destroy(ctx);
254 }
255
256
257 static void destroy_sphinx(srs_plugin_t *plugin)
258 {
259     srs_context_t *srs = plugin->srs;
260     context_t     *ctx = (context_t *)plugin->plugin_data;
261
262     mrp_debug("destroy CMU Sphinx speech recognition backend plugin");
263
264     if (ctx != NULL) {
265         srs_unregister_srec(srs, SPHINX_NAME);
266         mrp_free(ctx->plugin);
267
268         input_buffer_destroy(ctx);
269         filter_buffer_destroy(ctx);
270         decoder_set_destroy(ctx);
271         options_destroy(ctx);
272
273         mrp_free(ctx);
274     }
275 }
276
277
278 SRS_DECLARE_PLUGIN(SPHINX_NAME, SPHINX_DESCRIPTION, SPHINX_AUTHORS,
279                    SPHINX_VERSION, create_sphinx, config_sphinx,
280                    start_sphinx, stop_sphinx, destroy_sphinx)
281
282
283 /*
284  * Local Variables:
285  * c-basic-offset: 4
286  * indent-tabs-mode: nil
287  * End:
288  *
289  */