Fix compilation with new Murphy resource set interface.
[profile/ivi/ico-uxf-homescreen.git] / lib / system-controller / ico_syc_mrp_resource.c
1 /*
2  * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
3  *
4  * This program is licensed under the terms and conditions of the
5  * Apache License, version 2.0.  The full text of the Apache License is at
6  * http://www.apache.org/licenses/LICENSE-2.0
7  *
8  */
9
10 //==========================================================================
11 /**
12  *  @file   ico_syc_mrp_resource.c
13  *
14  *  @brief 
15  */
16 //==========================================================================
17
18 #include <murphy/common.h>
19 #include <murphy/common/ecore-glue.h>
20 #include <murphy/domain-control/client.h>
21
22 #include <ico_log.h>
23 #include "ico_syc_error.h"
24 #include "ico_syc_mrp_resource_private.h"
25
26
27 static void ico_syc_mrp_resource_cb(mrp_res_context_t *ctx,
28                                     const mrp_res_resource_set_t *rs,
29                                     void *userdata);
30
31 static void ico_syc_mrp_state_cb(mrp_res_context_t *ctx,
32                                  mrp_res_error_t err,
33                                  void *userdata);
34
35 static void ico_syc_mrp_connect_notify(mrp_domctl_t *dc,int connected,
36                                        int errcode, const char *errmsg,
37                                        void *user_data);
38
39 static void ico_syc_mrp_data_notify(mrp_domctl_t *dc,
40                                     mrp_domctl_data_t *tables,
41                                     int ntable, void *user_data);
42
43 static mrp_res_queue_item_t *
44 ico_syc_mrp_create_queue_item(resource_request_t *req);
45 static resource_request_t *
46 ico_syc_mrp_find_request(int req_id, char *appid);
47 #if 0
48 static void ico_syc_mrp_process_input_queue(void);
49 static void ico_syc_mrp_process_display_queue(void);
50 #endif
51 static void ico_syc_mrp_process_sound_queue(void);
52             
53 /* Murphy resource library */ 
54 static bool                     mrp_res_connected = FALSE; 
55 static mrp_res_context_t        *mrp_ctx = NULL; 
56 static mrp_mainloop_t           *mrp_ml = NULL; 
57 static mrp_domctl_t             *mrp_dc = NULL; 
58  
59 static mrp_list_hook_t          mrp_sound_wait_queue; 
60  
61 static mrp_list_hook_t          mrp_reqs; 
62
63
64 /*
65  * tables for inserting and reading data from Murphy
66  */
67
68 #define ACTIVE_APP_COLUMNS      \
69     "zone       varchar(128),"  \
70     "appid      varchar(128)"
71
72 #define ACTIVE_APP_INDEX "zone, appid"
73
74 #define DISPLAY_OWNER_SELECT "*"
75 #define DISPLAY_OWNER_WHERE  NULL
76
77 mrp_domctl_table_t ico_tables[] = {
78     MRP_DOMCTL_TABLE("active_screen",
79                      ACTIVE_APP_COLUMNS,
80                      ACTIVE_APP_INDEX),
81 };
82
83 mrp_domctl_watch_t ico_watches[] = {
84     MRP_DOMCTL_WATCH("display-owner",
85                      DISPLAY_OWNER_SELECT,
86                      DISPLAY_OWNER_WHERE, 0),
87 };
88
89 static ico_syc_mrp_enforce_sound_t ico_syc_mrp_enforce_soundCB = NULL;
90 static void *cb_user_data = NULL;
91
92
93 /*-------------------------------------------------------------------------*/
94 /*
95  *  public functions
96  */
97 /*-------------------------------------------------------------------------*/
98 int ico_syc_mrp_init(ico_syc_mrp_enforce_sound_t soundcb, void *user_data)
99
100 {
101
102     ICO_DBG("ico_syc_mrp_init: Enter");
103
104     ico_syc_mrp_enforce_soundCB = soundcb;
105     cb_user_data = user_data;
106
107     mrp_list_init(&mrp_sound_wait_queue);
108
109     mrp_list_init(&mrp_reqs);
110
111     ICO_DBG("called: mrp_mainloop_ecore_get()");
112     mrp_ml = mrp_mainloop_ecore_get();
113
114     ICO_DBG("called: mrp_res_connecte()");
115     mrp_ctx = mrp_res_create(mrp_ml, ico_syc_mrp_state_cb, NULL);
116
117     if (!mrp_ctx) {
118         ICO_ERR("ico_syc_mrp_init: Leave(mrp_res_create Error)");
119         return ICO_SYC_EIO;
120     }
121
122     ICO_DBG("called: mrp_domctl_create()");
123     mrp_dc = mrp_domctl_create("ico-homescreen", mrp_ml,
124                                ico_tables, MRP_ARRAY_SIZE(ico_tables),
125                                ico_watches, MRP_ARRAY_SIZE(ico_watches),
126                                ico_syc_mrp_connect_notify,
127                                ico_syc_mrp_data_notify, NULL);
128
129     if (mrp_dc == NULL) {
130         ICO_ERR("ico_syc_mrp_init: Leave(mrp_domctl_create Error)");
131         return ICO_SYC_EIO;
132     } 
133
134     ICO_DBG("called: mrp_domctl_connect()");
135     if (!mrp_domctl_connect(mrp_dc, MRP_DEFAULT_DOMCTL_ADDRESS, 0)) {
136         ICO_ERR("ico_syc_mrp_init: Leave(mrp_domctl_connect Error)");
137         return ICO_SYC_EIO;
138     } 
139
140     return ICO_SYC_EOK;
141 }
142
143 void ico_syc_mrp_term(void)
144 {
145     if (NULL != mrp_ctx) {
146         mrp_res_destroy(mrp_ctx);
147     }
148
149     if (NULL != mrp_dc) {
150         mrp_domctl_destroy(mrp_dc);
151     }
152
153     if (NULL != mrp_ml) {
154         mrp_mainloop_destroy(mrp_ml);
155     }
156 }
157
158 void
159 ico_syc_mrp_add_request(resource_request_t *req)
160 {
161     /* store the request for Murphy */
162     ICO_DBG("ico_syc_mrp_add_request: "
163             "add request %p to mrp_reqs list", req);
164     mrp_list_init(&req->hook);
165     mrp_list_append(&mrp_reqs, &req->hook);
166
167 }
168
169 void
170 ico_syc_mrp_del_request(resource_request_t *req)
171 {
172     if (NULL == req) {
173         return;
174     }
175
176     resource_request_t *findreq = ico_syc_mrp_find_request(req->id,
177                                                            req->appid);
178     if (NULL != findreq) {
179         if (req->pid != findreq->pid) {
180             ICO_DBG("ico_syc_mrp_del_request: pid not match");
181             return;
182         }
183     }
184     else {
185         ICO_DBG("ico_syc_mrp_del_request: not found in req list");
186         return;
187     }
188
189     ICO_DBG("ico_syc_mrp_del_request: "
190             "del request %p to mrp_reqs list", req);
191     mrp_list_delete(&req->hook);
192
193     if (mrp_ctx && req->rset) {
194         mrp_res_release_resource_set(req->rset);
195         mrp_res_delete_resource_set(req->rset);
196         req->rset = NULL;
197     }
198 }
199
200 bool
201 ico_syc_mrp_acquire_sound_resource(resource_request_t *newreq)
202 {
203     mrp_res_resource_set_t      *rs;
204
205     ICO_DBG("ico_syc_mrp_acquire_sound_resource: Enter");
206
207     resource_request_t *req = ico_syc_mrp_find_request(newreq->id,
208                                                        newreq->appid);
209     if (NULL == req) {
210         ico_syc_mrp_add_request(newreq);
211         req = newreq;
212     }
213
214     if (mrp_ctx) {
215         if (!mrp_res_connected) {
216             mrp_res_queue_item_t *item;
217
218             ICO_DBG("ico_syc_mrp_acquire_sound_resource: "
219                     "resource context is not connected yet, queueing");
220
221             item = ico_syc_mrp_create_queue_item(req);
222             mrp_list_append(&mrp_sound_wait_queue, &item->hook);
223
224             ICO_DBG("ico_syc_mrp_acquire_sound_resource: Leave(true)");
225             return true;
226         }
227
228         if (!req->rset) {
229             int addprio = req->resid & RESID_TYPE_MASK;
230             const char *resource_class =
231                 (addprio == RESID_TYPE_BASIC) ? "basic" : "emergency";
232             mrp_res_resource_t *res;
233             mrp_res_attribute_t *attr;
234
235             ICO_DBG("ico_syc_mrp_acquire_sound_resource: "
236                     "could not create resource for sound");
237
238             ICO_DBG("called: mrp_res_create_resource_set()");
239             rs = mrp_res_create_resource_set(mrp_ctx,
240                                              resource_class,
241                                              ico_syc_mrp_resource_cb,
242                                              req);
243
244             if (!rs) {
245                 ICO_ERR("ico_syc_mrp_acquire_sound_resource: "
246                         "could not create resource set for audio");
247                 return false;
248             }
249
250             ICO_DBG("called: mrp_res_set_autorelease()");
251             if (!mrp_res_set_autorelease(FALSE, rs)) {
252                 ICO_ERR("ico_syc_mrp_acquire_sound_resource: "
253                         "failed to set auto release mode");
254                 ICO_DBG("ico_syc_mrp_acquire_sound_resource: Leave(false)");
255                 return false;
256             }
257
258             ICO_DBG("called: mrp_res_create_resource");
259             res = mrp_res_create_resource(rs, "audio_playback", TRUE, FALSE);
260
261             if (!res) {
262                 ICO_ERR("ico_syc_mrp_acquire_sound_resource: "
263                         "could not create resource for audio");
264                 ICO_DBG("ico_syc_mrp_acquire_sound_resource: Leave(false)");
265                 return false;
266             }
267
268             ICO_DBG("pid=%d category=%d appid=%s priority=%d",
269                     req->pid, req->category, req->appid, req->prio);
270             attr = mrp_res_get_attribute_by_name(res, "pid");
271             if (attr && attr->type == mrp_string) {
272                 char numbuf[16];
273                 int ret;
274
275                 ret = snprintf(numbuf, sizeof(numbuf), "%d", req->pid);
276
277                 if (ret > 0 && (size_t)ret < sizeof(numbuf)) {
278                     mrp_res_set_attribute_string(attr, numbuf);
279                 }
280             }
281             attr = mrp_res_get_attribute_by_name(res, "category");
282             if (attr && attr->type == mrp_int32) {
283                 mrp_res_set_attribute_int(attr, req->category);
284             }
285
286             attr = mrp_res_get_attribute_by_name(res, "appid");
287             if (attr && attr->type == mrp_string) {
288                 mrp_res_set_attribute_string(attr, req->appid);
289             }
290
291             attr = mrp_res_get_attribute_by_name(res, "priority");
292             if (attr && attr->type == mrp_int32) {
293                mrp_res_set_attribute_int(attr, 0/*req->prio*/);
294             }
295
296             req->rset = rs;
297             req->released = 0;
298         }
299
300         ICO_DBG("called: mrp_res_acquire_resource_set()");
301         mrp_res_acquire_resource_set(req->rset);
302     }
303
304     ICO_DBG("ico_syc_mrp_acquire_sound_resource: Leave(true)");
305     return true;
306 }
307
308 bool
309 ico_syc_mrp_release_sound_resource(resource_request_t *req)
310 {
311     ICO_DBG("ico_syc_mrp_release_sound_resource: Enter");
312
313     ico_syc_mrp_del_request(req);
314 #if 0
315     if (mrp_ctx && req->rset) {
316         if (REQTYPE_APP == req->reqtype) {
317             mrp_res_release_resource_set(mrp_ctx, req->rset);
318             req->released = 1;
319         }
320         else {
321             mrp_res_release_resource_set(mrp_ctx, req->rset);
322             mrp_res_delete_resource_set(mrp_ctx, req->rset);
323             req->rset = NULL;
324         }
325     }
326 #endif
327     ICO_DBG("ico_syc_mrp_release_sound_resource: Leave(true)");
328     return true;
329 }
330
331 /*-------------------------------------------------------------------------*/
332 /*
333  *  private functions
334  */
335 /*-------------------------------------------------------------------------*/
336 static mrp_res_queue_item_t *
337 ico_syc_mrp_create_queue_item(resource_request_t *req)
338 {
339     mrp_res_queue_item_t *item = mrp_allocz(sizeof(mrp_res_queue_item_t));
340     int ret = 0;
341
342     ICO_DBG("ico_syc_mrp_create_queue_item: Enter");
343
344     if (NULL == item) {
345         ICO_ERR("mrp_allocz failed.");
346         return NULL;
347     }
348
349     mrp_list_init(&item->hook);
350
351     if (req->resid | RESID_KIND_SOUND) {
352         item->req_id   = req->soundid;
353         item->zone_idx = req->soundzoneid;
354     }
355
356     item->prio     = req->prio;
357     item->res_type = req->resid;
358
359     ret = snprintf(item->appid, MURPHY_APPID_MAXIMUM_LENGTH, "%s", req->appid);
360
361     if (ret < 0 || ret >= MURPHY_APPID_MAXIMUM_LENGTH) {
362         mrp_free(item);
363         ICO_DBG("ico_syc_mrp_create_queue_item: Leave(NULL)");
364         return NULL;
365     }
366
367     ICO_DBG("murphy: created queue item (id: %d, zone: %d, prio: %d, type: %d)",
368             item->req_id, item->zone_idx, item->prio, item->res_type);
369
370     ICO_DBG("ico_syc_mrp_create_queue_item: Leave(0x%08x)", item);
371     return item;
372 }
373
374 static resource_request_t *
375 ico_syc_mrp_find_request(int req_id, char *appid)
376 {
377     mrp_list_hook_t *p, *n;
378     resource_request_t *req;
379
380     ICO_DBG("ico_syc_mrp_find_request: Enter");
381
382     /* go through all mrp_res_queue_item_t structs in the list */
383
384     mrp_list_foreach(&mrp_reqs, p, n) {
385         req = mrp_list_entry(p, typeof(*req), hook);
386
387         ICO_DBG("ico_syc_mrp_find_request: req(id=%d appid=%s)",
388                 req->id, req->appid);
389         if (req->id == req_id && strcmp(req->appid, appid) == 0) {
390             ICO_DBG("ico_syc_mrp_find_request: Leave(0x%08x)", req);
391             return req;
392         }
393     }
394
395     ICO_DBG("ico_syc_mrp_find_request: Leave(NULL)");
396     return NULL;
397 }
398
399 static void
400 ico_syc_mrp_process_sound_queue(void)
401 {
402     mrp_list_hook_t *p, *n;
403     mrp_res_queue_item_t *item;
404
405     ICO_DBG("ico_syc_mrp_process_sound_queue: Enter");
406
407     /* go through all mrp_res_queue_item_t structs in the list */
408
409     mrp_list_foreach(&mrp_sound_wait_queue, p, n) {
410         resource_request_t *req;
411         item = mrp_list_entry(p, typeof(*item), hook);
412
413         req = ico_syc_mrp_find_request(item->req_id, item->appid);
414
415         if (req) {
416             ico_syc_mrp_acquire_sound_resource(req);
417         }
418         else  {
419             ICO_WRN("murphy: application (appid: %s, id: %d, zone: %d)"
420                     " went away before resource handling",
421                     item->appid, item->req_id, item->zone_idx);
422         }
423
424         mrp_list_delete(&item->hook);
425         mrp_free(item);
426     }
427
428     ICO_DBG("ico_syc_mrp_process_sound_queue: Leave");
429 }
430                        
431 static void
432 ico_syc_mrp_resource_cb(mrp_res_context_t *ctx,
433                         const mrp_res_resource_set_t *rs,
434                         void *userdata)
435 {
436     resource_request_t *req = NULL;
437
438     //mrp_res_queue_item_t *item = userdata;
439     resource_request_t *item = userdata;
440
441     unsigned short state = RES_STATE_ACQUIRED;
442
443     ICO_DBG("ico_syc_mrp_resource_cb: Enter"
444             "(req_id=%d appid=%s)", item->id, item->appid);
445             //"(req_id=%d appid=%s)", item->req_id, item->appid);
446
447     if (NULL == item) {
448         return;
449     }
450
451     //if (item->res_type | RESID_KIND_SOUND) {
452     if (item->resid & RESID_KIND_SOUND) {
453         //req = ico_syc_mrp_find_request(item->req_id, item->appid);
454         req = ico_syc_mrp_find_request(item->id, item->appid);
455         ICO_DBG("RESID_KIND_SOUND req=0x%08x", req);
456     }
457
458     if (NULL == req) {
459         ICO_ERR("murphy: the request wasn't found!");
460         ICO_DBG("ico_syc_mrp_resource_cb: Leave");
461         return;
462     }
463
464     if (!mrp_res_equal_resource_set(rs, req->rset)) {
465         ICO_DBG("mrp_res_equal_resource_set : not match");
466         ICO_DBG("ico_syc_mrp_resource_cb: Leave");
467         return;
468     }
469
470     /* delete the previous set */
471     ICO_DBG("called: mrp_res_delete_resource");
472     mrp_res_delete_resource_set(req->rset);
473
474     /* copy the new set into place */
475     ICO_DBG("called: mrp_res_copy_resource_set");
476     req->rset = mrp_res_copy_resource_set(rs);
477
478     switch(req->rset->state) {
479     case MRP_RES_RESOURCE_ACQUIRED:
480         ICO_DBG("ico_syc_mrp_resource_cb: state=MRP_RES_RESOURCE_ACQUIRED");
481         state = RES_STATE_ACQUIRED;
482         break;
483     case MRP_RES_RESOURCE_LOST:
484         ICO_DBG("ico_syc_mrp_resource_cb: state=MRP_RES_RESOURCE_LOST");
485     case MRP_RES_RESOURCE_AVAILABLE:
486         ICO_DBG("ico_syc_mrp_resource_cb: state=MRP_RES_RESOURCE_AVAILABLE");
487         if (req->released) {
488             state = RES_STATE_RELEASED;
489         }
490         else {
491             state = RES_STATE_WAITING;
492         }
493         break;
494     default:
495         ICO_WRN("ico_syc_mrp_resource_cb: state=UNKNOWN");
496         state = RES_STATE_RELEASED;
497         break;
498     }
499
500     /* send decision to client, if needed */
501     if (req->reqtype == REQTYPE_APP) {
502         if (req->state != state) {
503 // TODO CicoSCServer::sendMessage();
504 //            if (ico_apf_resource_send_to_client(
505 //                req->appid, state, req->resid, req->device, req->id)
506 //                        != ICO_APF_RESOURCE_E_NONE) {
507 //                ICO_WRN("murphy: failed to send decision to client (%s)",
508 //                        req->appid);
509 //            }
510             req->state = state;
511         }
512     }
513
514     /* do the enforcing */
515     if (req->resid & RESID_KIND_SOUND) {
516         if (NULL != ico_syc_mrp_enforce_soundCB) {
517             ico_syc_mrp_enforce_soundCB(state, req, cb_user_data);
518         }
519     }
520     else {
521         ICO_WRN("unknown resource id");
522     }
523
524     ICO_DBG("ico_syc_mrp_resource_cb: Leave");
525 }
526                        
527 static void
528 ico_syc_mrp_state_cb(mrp_res_context_t *ctx,
529                      mrp_res_error_t err,
530                      void *userdata)
531 {
532     ICO_DBG("ico_syc_mrp_state_cb: Enter");
533     if (err != MRP_RES_ERROR_NONE) {
534         ICO_DBG("ico_syc_mrp_state_cb: state callback error(%d)", err);
535         return;
536     }
537
538     switch (ctx->state)
539     {
540         case MRP_RES_CONNECTED:
541             ICO_DBG("ico_syc_mrp_state_cb: connected to murphyd");
542             mrp_res_connected = TRUE;
543
544             /* process the queued resources */
545             ico_syc_mrp_process_sound_queue();
546             break;
547         case MRP_RES_DISCONNECTED:
548             ICO_DBG("ico_syc_mrp_state_cb: disconnected from murphyd");
549             if (ctx) {
550                 mrp_res_destroy(ctx);
551                 mrp_ctx = NULL;
552             }
553             mrp_res_connected = FALSE;
554             break;
555         default:
556             ICO_ERR("ico_syc_mrp_state_cb: state error");
557             break;
558     }
559
560     ICO_DBG("ico_syc_mrp_state_cb: Leave");
561 }
562
563 static void
564 ico_syc_mrp_connect_notify(mrp_domctl_t *dc,int connected,
565                            int errcode, const char *errmsg,
566                            void *user_data)
567 {
568     ICO_DBG("ico_syc_mrp_connect_notify: Enter");
569     ICO_DBG("ico_syc_mrp_connect_notify: Leave");
570 }
571
572 static void
573 ico_syc_mrp_data_notify(mrp_domctl_t *dc,
574                         mrp_domctl_data_t *tables,
575                         int ntable, void *user_data)
576 {
577     ICO_DBG("ico_syc_mrp_data_notify: Enter");
578     ICO_DBG("ico_syc_mrp_data_notify: Leave");
579 }
580
581 static void
582 ico_sys_mrp_export_notify(mrp_domctl_t *dc, int errcode,
583                           const char *errmsg, void *user_data)
584 {
585     MRP_UNUSED(dc);
586     MRP_UNUSED(user_data);
587
588     if (errcode != 0) {
589         ICO_ERR("murphy: exporting data to Murphy failed "
590                 "(%d: %s).", errcode, errmsg);
591     }
592 }
593
594 void
595 ico_syc_mrp_active_app(const char *appid)
596 {
597     mrp_domctl_data_t tables[1];
598     mrp_domctl_value_t values[2];
599
600     ICO_DBG("ico_syc_mrp_active_app: active app '%s'", appid);
601
602     memset(tables, 0, sizeof(tables));
603     memset(values, 0, sizeof(values));
604
605     tables[0].id = 0;
606     tables[0].ncolumn = 2;
607     tables[0].nrow = 1;
608     tables[0].rows = mrp_allocz(sizeof(*tables[0].rows));
609     tables[0].rows[0] = values;
610
611     values[0].type = MRP_DOMCTL_STRING;
612     values[0].str = "driver";
613     values[1].type = MRP_DOMCTL_STRING;
614     values[1].str = appid;
615
616     ICO_DBG("called: mrp_domctl_set_data"
617             "(tables[0].rows[0]={\"%s\",\"%s\"})",
618             values[0].str, values[1].str);
619     if (!mrp_domctl_set_data(mrp_dc, tables, 1,
620                              ico_sys_mrp_export_notify, NULL)) {
621         ICO_DBG("ico_syc_mrp_active_app: "
622                 "failed to export active app data to Murphy");
623     }
624
625     mrp_free(tables[0].rows);
626 }
627 /* vim:set expandtab ts=4 sw=4: */