ivi-resource-manager: add appid mapping
[profile/ivi/murphy.git] / src / plugins / ivi-resource-manager / plugin-ivi-resource-manager.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 <stdio.h>
31 #include <string.h>
32 #include <errno.h>
33
34 #include <lualib.h>
35 #include <lauxlib.h>
36
37 #include <murphy/common.h>
38 #include <murphy/common/debug.h>
39 #include <murphy/core/plugin.h>
40 #include <murphy/core/console.h>
41 #include <murphy/core/event.h>
42 #include <murphy/core/context.h>
43 #include <murphy/core/lua-bindings/murphy.h>
44
45 #include <murphy-db/mql.h>
46 #include <murphy-db/mqi.h>
47
48 #include <murphy/resource/config-api.h>
49 #include <murphy/resource/manager-api.h>
50 #include <murphy/resource/client-api.h>
51 #include <murphy/resource/protocol.h>
52
53 #include "screen.h"
54 #include "audio.h"
55 #include "appid.h"
56
57 struct mrp_resmgr_data_s {
58     mrp_plugin_t        *plugin;
59     mrp_event_watch_t   *w;
60     mrp_resmgr_screen_t *screen;
61     mrp_resmgr_audio_t  *audio;
62     mrp_resmgr_appid_t  *appid;
63     mrp_htbl_t          *resources;
64     int                  ndepend;
65     const char         **depends;
66     mrp_zone_mask_t      zones;
67 };
68
69 static void print_resources_cb(mrp_console_t *, void *, int, char **);
70
71 MRP_CONSOLE_GROUP(manager_group, "ivi-resource-manager", NULL, NULL, {
72         MRP_TOKENIZED_CMD("resources", print_resources_cb, FALSE,
73                           "resources", "prints managed resources",
74                           "prints  the resources managed by "
75                           "ivi-resource-manager."),
76 });
77
78 static mrp_resmgr_data_t *resmgr_data;
79
80 void mrp_resmgr_register_dependency(mrp_resmgr_data_t *data,
81                                     const char *db_table_name)
82 {
83     size_t size;
84     const char **depends;
85     char dependency[512];
86     int idx;
87
88     MRP_ASSERT(data && db_table_name, "invalid argument");
89
90     idx = data->ndepend;
91     size = (idx + 1) * sizeof(const char *);
92
93     if (!(depends = mrp_realloc(data->depends, size))) {
94         mrp_log_error("ivi-resource-manager: failed to allocate memory "
95                       "for resource dependencies");
96         data->ndepend = 0;
97         data->depends = NULL;
98         return;
99     }
100
101     snprintf(dependency, sizeof(dependency), "$%s", db_table_name);
102
103     if (!(depends[idx] = mrp_strdup(dependency))) {
104         mrp_log_error("ivi-resource-manager: failed to strdup dependency");
105         data->depends = depends;
106         return;
107     }
108
109     data->ndepend = idx + 1;
110     data->depends = depends;
111 }
112
113 void mrp_resmgr_insert_resource(mrp_resmgr_data_t *data,
114                                 mrp_zone_t *zone,
115                                 mrp_resource_t *key,
116                                 void *resource)
117 {
118     uint32_t zoneid;
119
120     MRP_ASSERT(data && zone && key && resource, "invalid argument");
121     MRP_ASSERT(data->resources, "uninitialised data structure");
122
123     zoneid = mrp_zone_get_id(zone);
124
125     data->zones |= ((mrp_zone_mask_t)1 << zoneid);
126
127     mrp_htbl_insert(data->resources, key, resource);
128 }
129
130 void *mrp_resmgr_remove_resource(mrp_resmgr_data_t *data,
131                                  mrp_zone_t *zone,
132                                  mrp_resource_t *key)
133 {
134     MRP_ASSERT(data && zone && key, "invalid argument");
135     MRP_ASSERT(data->resources, "uninitialised data structure");
136
137     return mrp_htbl_remove(data->resources, key, FALSE);
138 }
139
140 void *mrp_resmgr_lookup_resource(mrp_resmgr_data_t *data, mrp_resource_t *key)
141 {
142     MRP_ASSERT(data && key, "invalid argument");
143     MRP_ASSERT(data->resources, "uninitialised data structure");
144
145     return mrp_htbl_lookup(data->resources, key);
146 }
147
148 mrp_resmgr_screen_t *mrp_resmgr_get_screen(mrp_resmgr_data_t *data)
149 {
150     MRP_ASSERT(data, "invalid argument");
151     MRP_ASSERT(data->screen, "confused with data structures");
152
153     return data->screen;
154 }
155
156 mrp_resmgr_audio_t *mrp_resmgr_get_audio(mrp_resmgr_data_t *data)
157 {
158     MRP_ASSERT(data, "invalid argument");
159     MRP_ASSERT(data->audio, "confused with data structures");
160
161     return data->audio;
162 }
163
164 mrp_resmgr_appid_t *mrp_resmgr_get_appid(mrp_resmgr_data_t *data)
165 {
166     MRP_ASSERT(data, "invalid argument");
167     MRP_ASSERT(data->appid, "confused with data structures");
168
169     return data->appid;
170 }
171
172 static void print_resources_cb(mrp_console_t *c, void *user_data,
173                                int argc, char **argv)
174 {
175     const char *zones[MRP_ZONE_MAX + 1];
176     uint32_t zoneid;
177     char buf[65536];
178
179     MRP_UNUSED(c);
180     MRP_UNUSED(user_data);
181     MRP_UNUSED(argc);
182     MRP_UNUSED(argv);
183
184     mrp_zone_get_all_names(MRP_ZONE_MAX+1, zones);
185
186     printf("Resources managed by ivi-resource-manager:\n");
187
188     for (zoneid = 0;   zones[zoneid];  zoneid++) {
189         printf("   Zone '%s':\n", zones[zoneid]);
190
191         mrp_resmgr_screen_print(resmgr_data->screen, zoneid, buf, sizeof(buf));
192         printf(buf);
193
194         mrp_resmgr_audio_print(resmgr_data->audio, zoneid, buf, sizeof(buf));
195         printf(buf);
196     }
197
198     printf("\n");
199 }
200
201
202 static int resource_update_cb(mrp_scriptlet_t *script, mrp_context_tbl_t *ctbl)
203 {
204     mrp_resmgr_data_t *data = (mrp_resmgr_data_t *)script->data;
205     mrp_zone_mask_t mask;
206     uint32_t zoneid;
207
208     MRP_UNUSED(ctbl);
209
210     for (mask = data->zones, zoneid = 0;   mask;   mask >>= 1, zoneid++) {
211         if ((mask & 1))
212             mrp_resource_owner_recalc(zoneid);
213     }
214
215     return TRUE;
216 }
217
218 static void add_depenedencies_to_resolver(mrp_resmgr_data_t *data)
219 {
220     static const char *target = "_ivi_resources";
221     static mrp_interpreter_t resource_updater = {
222         { NULL, NULL },
223         "resource_updater",
224         NULL,
225         NULL,
226         NULL,
227         resource_update_cb,
228         NULL
229     };
230
231     mrp_plugin_t *plugin;
232     mrp_context_t *ctx;
233     mrp_resolver_t *resolver;
234     char buf[2048];
235     char *p, *e;
236     int i;
237     int success;
238
239     MRP_ASSERT(data, "invalid argument");
240
241     plugin = data->plugin;
242
243     if (!(ctx = plugin->ctx) || !(resolver = ctx->r))
244         return;
245
246     if (!data->ndepend || !data->depends)
247         return;
248
249     for (i = 0, e = (p = buf) + sizeof(buf); i < data->ndepend && p < e; i++)
250         p += snprintf(p, e-p, " %s", data->depends[i]);
251
252     printf("%s:%s\n\tresource_recalc()\n\n", target, buf);
253
254     success = mrp_resolver_add_prepared_target(resolver, target,
255                                                data->depends, data->ndepend,
256                                                &resource_updater, NULL, data);
257     if (!success) {
258         mrp_log_error("ivi-resource-manager: failed to install "
259                       "resolver target '%s'", target);
260     }
261 }
262
263 static void event_cb(mrp_event_watch_t *w, int id, mrp_msg_t *event_data,
264                      void *user_data)
265 {
266     mrp_plugin_t      *plugin   = (mrp_plugin_t *)user_data;
267 #if 0
268     mrp_plugin_arg_t  *args     = plugin->args;
269 #endif
270     mrp_resmgr_data_t *data     = (mrp_resmgr_data_t *)plugin->data;
271     const char        *event    = mrp_get_event_name(id);
272     uint16_t           tag_inst = MRP_PLUGIN_TAG_INSTANCE;
273     uint16_t           tag_name = MRP_PLUGIN_TAG_PLUGIN;
274     const char        *inst;
275     const char        *name;
276     int                success;
277
278     MRP_UNUSED(w);
279
280     mrp_log_info("%s: got event 0x%x (%s):", plugin->instance, id, event);
281
282     if (data && event) {
283         if (!strcmp(event, MRP_PLUGIN_EVENT_STARTED)) {
284             success = mrp_msg_get(event_data,
285                                   MRP_MSG_TAG_STRING(tag_inst, &inst),
286                                   MRP_MSG_TAG_STRING(tag_name, &name),
287                                   MRP_MSG_END);
288             if (success) {
289                 if (!strcmp(inst, plugin->instance)) {
290                     data->screen = mrp_resmgr_screen_create(data);
291                     data->audio  = mrp_resmgr_audio_create(data);
292                     data->appid  = mrp_resmgr_appid_create(data);
293
294                     add_depenedencies_to_resolver(data);
295                 }
296             }
297         } /* if PLUGIN_STARTED */
298     }
299 }
300
301
302 static int subscribe_events(mrp_plugin_t *plugin)
303 {
304     mrp_resmgr_data_t *data = (mrp_resmgr_data_t *)plugin->data;
305     mrp_event_mask_t   events;
306
307     mrp_set_named_events(&events,
308                          MRP_PLUGIN_EVENT_LOADED,
309                          MRP_PLUGIN_EVENT_STARTED,
310                          MRP_PLUGIN_EVENT_FAILED,
311                          MRP_PLUGIN_EVENT_STOPPING,
312                          MRP_PLUGIN_EVENT_STOPPED,
313                          MRP_PLUGIN_EVENT_UNLOADED,
314                          NULL);
315
316     data->w = mrp_add_event_watch(&events, event_cb, plugin);
317
318     return (data->w != NULL);
319 }
320
321
322 static void unsubscribe_events(mrp_plugin_t *plugin)
323 {
324     mrp_resmgr_data_t *data = (mrp_resmgr_data_t *)plugin->data;
325
326     if (data->w) {
327         mrp_del_event_watch(data->w);
328         data->w = NULL;
329     }
330 }
331
332
333 static int hash_compare(const void *key1, const void *key2)
334 {
335     if (key1 < key2)
336         return -1;
337     if (key1 > key2)
338         return 1;
339     return 0;
340 }
341
342 static uint32_t hash_function(const void *key)
343 {
344     return (uint32_t)(((uint64_t)key >> 4) & 0xffffffff);
345 }
346
347
348 static int manager_init(mrp_plugin_t *plugin)
349 {
350 #if 0
351     mrp_plugin_arg_t  *args = plugin->args;
352 #endif
353     mrp_resmgr_data_t *data;
354     mrp_htbl_config_t  cfg;
355
356     mrp_log_info("%s() called for IVI resource manager instance '%s'...",
357                  __FUNCTION__, plugin->instance);
358
359     cfg.nentry = 256;
360     cfg.comp = hash_compare;
361     cfg.hash = hash_function;
362     cfg.free = NULL;
363     cfg.nbucket = cfg.nentry / 4;
364
365     if (!(data = mrp_allocz(sizeof(*data)))) {
366         mrp_log_error("Failed to allocate private data for IVI resource "
367                       "manager plugin instance %s.", plugin->instance);
368         return FALSE;
369     }
370
371     data->plugin = plugin;
372     data->resources = mrp_htbl_create(&cfg);
373
374     plugin->data = data;
375     resmgr_data  = data;
376
377     subscribe_events(plugin);
378
379     return TRUE;
380 }
381
382
383 static void manager_exit(mrp_plugin_t *plugin)
384 {
385     mrp_resmgr_data_t *data;
386
387     mrp_log_info("%s() called for IVI resource manager instance '%s'...",
388                  __FUNCTION__, plugin->instance);
389
390     unsubscribe_events(plugin);
391
392     if ((data = plugin->data) && data == resmgr_data) {
393         mrp_resmgr_screen_destroy(data->screen);
394         mrp_resmgr_audio_destroy(data->audio);
395         mrp_resmgr_appid_destroy(data->appid);
396     }
397 }
398
399
400 #define MANAGER_DESCRIPTION "Plugin to implement IVI resources"
401 #define MANAGER_HELP        "Maybe later ..."
402 #define MANAGER_VERSION      MRP_VERSION_INT(0, 0, 1)
403 #define MANAGER_AUTHORS     "Janos Kovacs <jankovac503@gmail.com>"
404
405 static mrp_plugin_arg_t args[] = {
406 };
407
408
409 MURPHY_REGISTER_PLUGIN("resource-manager",
410                        MANAGER_VERSION,
411                        MANAGER_DESCRIPTION,
412                        MANAGER_AUTHORS,
413                        MANAGER_HELP,
414                        MRP_SINGLETON,
415                        manager_init,
416                        manager_exit,
417                        args, MRP_ARRAY_SIZE(args),
418                        NULL, 0,
419                        NULL, 0,
420                        &manager_group);
421
422 /*
423  * Local Variables:
424  * c-basic-offset: 4
425  * indent-tabs-mode: nil
426  * End:
427  *
428  */