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