packaging: bumped version, updated changelog.
[profile/ivi/speech-recognition.git] / src / daemon / 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 <errno.h>
31 #include <limits.h>
32 #include <dlfcn.h>
33
34 #include <murphy/common/mm.h>
35
36 #include "srs/daemon/context.h"
37 #include "srs/daemon/plugin.h"
38
39 static srs_plugin_t *find_plugin(srs_context_t *srs, const char *name)
40 {
41     srs_plugin_t    *plugin;
42     mrp_list_hook_t *p, *n;
43
44     mrp_list_foreach(&srs->plugins, p, n) {
45         plugin = mrp_list_entry(p, typeof(*plugin), hook);
46
47         if (!strcmp(plugin->name, name))
48             return plugin;
49     }
50
51     return NULL;
52 }
53
54
55 srs_plugin_t *srs_create_plugin(srs_context_t *srs, const char *name)
56 {
57     srs_plugin_query_t  query;
58     const char         *plugin_name, *description, *authors, *version;
59     int                 srs_version;
60     srs_plugin_api_t   *api;
61     srs_plugin_t       *plugin;
62     char                path[PATH_MAX];
63     void               *h;
64
65     if (find_plugin(srs, name) != NULL) {
66         mrp_log_error("Plugin '%s' already exists.", name);
67         errno = EEXIST;
68         return NULL;
69     }
70
71     if (snprintf(path, sizeof(path), "%s/plugin-%s.so",
72                  srs->plugin_dir, name) >= (int)sizeof(path)) {
73         errno = EOVERFLOW;
74         return NULL;
75     }
76
77     mrp_log_info("Loading plugin '%s' (%s)...", name, path);
78
79     plugin = NULL;
80     h      = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
81
82     if (h == NULL) {
83         const char *error = dlerror();
84
85         if (error != NULL)
86             mrp_log_error("Failed to load plugin '%s' (error: %s).", name,
87                           error);
88         else
89             mrp_log_error("Failed to load plugin '%s'.", name);
90
91         goto fail;
92     }
93
94     plugin = mrp_allocz(sizeof(*plugin));
95
96     if (plugin == NULL)
97         goto fail;
98
99     mrp_list_init(&plugin->hook);
100     plugin->h = h;
101     query     = dlsym(h, SRS_DESCRIBE_PLUGIN_FUNC);
102
103     if (query == NULL) {
104         mrp_log_error("Invalid plugin %s (does not export symbol '%s').",
105                       path, SRS_DESCRIBE_PLUGIN_FUNC);
106         goto fail;
107     }
108
109     api = query(&plugin_name, &description, &authors, &version, &srs_version);
110
111     if (api == NULL) {
112         mrp_log_error("Invalid plugin %s (provided NULL API).", path);
113         goto fail;
114     }
115
116     mrp_log_info("Plugin query gave:");
117     mrp_log_info("    name:        %s", plugin_name);
118     mrp_log_info("    description: %s", description);
119     mrp_log_info("    authors:     %s", authors);
120     mrp_log_info("    version:     %s", version);
121
122     if (srs_version != SRS_PLUGIN_API_VERSION) {
123         mrp_log_error("Plugin %s uses incompatible API version (0x%x != 0x%x).",
124                       name, srs_version, SRS_PLUGIN_API_VERSION);
125         goto fail;
126     }
127
128     plugin->srs         = srs;
129     plugin->name        = mrp_strdup(name);
130     plugin->description = description;
131     plugin->authors     = authors;
132     plugin->api         = api;
133
134     if (!plugin->api->create(plugin)) {
135         mrp_log_error("Failed to create plugin '%s'.", name);
136         goto fail;
137     }
138
139     mrp_list_append(&srs->plugins, &plugin->hook);
140
141     return plugin;
142
143  fail:
144     if (plugin != NULL)
145         srs_destroy_plugin(plugin);
146     else
147         if (h != NULL)
148             dlclose(h);
149
150     return NULL;
151 }
152
153
154 int srs_configure_plugin(srs_plugin_t *plugin, srs_cfg_t *settings)
155 {
156     if (plugin != NULL) {
157         mrp_log_info("Configuring plugin '%s'.", plugin->name);
158         return plugin->api->config(plugin, settings);
159     }
160     else
161         return FALSE;
162 }
163
164
165 int srs_start_plugin(srs_plugin_t *plugin)
166 {
167     if (plugin != NULL) {
168         mrp_log_info("Starting plugin '%s'.", plugin->name);
169         return plugin->api->start(plugin);
170     }
171     else
172         return FALSE;
173 }
174
175
176 void srs_stop_plugin(srs_plugin_t *plugin)
177 {
178     if (plugin != NULL) {
179         mrp_log_info("Stopping plugin '%s'.", plugin->name);
180         plugin->api->stop(plugin);
181     }
182 }
183
184
185 void srs_destroy_plugin(srs_plugin_t *plugin)
186 {
187     if (plugin != NULL) {
188         mrp_log_info("Destroying plugin '%s'.", plugin->name);
189
190         mrp_list_delete(&plugin->hook);
191         plugin->api->destroy(plugin);
192
193         mrp_free(plugin->name);
194         mrp_free(plugin);
195     }
196 }
197
198
199 int srs_configure_plugins(srs_context_t *srs)
200 {
201     srs_plugin_t    *plugin;
202     mrp_list_hook_t *p, *n;
203
204     mrp_list_foreach(&srs->plugins, p, n) {
205         plugin = mrp_list_entry(p, typeof(*plugin), hook);
206
207         if (!srs_configure_plugin(plugin, srs->settings))
208             return FALSE;
209     }
210
211     return TRUE;
212 }
213
214
215 int srs_start_plugins(srs_context_t *srs)
216 {
217     srs_plugin_t    *plugin;
218     mrp_list_hook_t *p, *n;
219
220     mrp_list_foreach(&srs->plugins, p, n) {
221         plugin = mrp_list_entry(p, typeof(*plugin), hook);
222
223         if (!srs_start_plugin(plugin))
224             return FALSE;
225     }
226
227     return TRUE;
228 }
229
230
231 void srs_stop_plugins(srs_context_t *srs)
232 {
233     srs_plugin_t    *plugin;
234     mrp_list_hook_t *p, *n;
235
236     mrp_list_foreach(&srs->plugins, p, n) {
237         plugin = mrp_list_entry(p, typeof(*plugin), hook);
238
239         srs_stop_plugin(plugin);
240     }
241 }
242
243
244 void srs_destroy_plugins(srs_context_t *srs)
245 {
246     srs_plugin_t    *plugin;
247     mrp_list_hook_t *p, *n;
248
249     mrp_list_foreach(&srs->plugins, p, n) {
250         plugin = mrp_list_entry(p, typeof(*plugin), hook);
251
252         srs_destroy_plugin(plugin);
253     }
254 }