2 * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
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
10 //==========================================================================
12 * @file ico_syc_mrp_resource.c
16 //==========================================================================
18 #include <murphy/common.h>
19 #include <murphy/common/ecore-glue.h>
20 #include <murphy/domain-control/client.h>
23 #include "ico_syc_error.h"
24 #include "ico_syc_mrp_resource_private.h"
27 static void ico_syc_mrp_resource_cb(mrp_res_context_t *ctx,
28 const mrp_res_resource_set_t *rs,
31 static void ico_syc_mrp_state_cb(mrp_res_context_t *ctx,
35 static void ico_syc_mrp_connect_notify(mrp_domctl_t *dc,int connected,
36 int errcode, const char *errmsg,
39 static void ico_syc_mrp_data_notify(mrp_domctl_t *dc,
40 mrp_domctl_data_t *tables,
41 int ntable, void *user_data);
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);
48 static void ico_syc_mrp_process_input_queue(void);
49 static void ico_syc_mrp_process_display_queue(void);
51 static void ico_syc_mrp_process_sound_queue(void);
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;
59 static mrp_list_hook_t mrp_sound_wait_queue;
61 static mrp_list_hook_t mrp_reqs;
65 * tables for inserting and reading data from Murphy
68 #define ACTIVE_APP_COLUMNS \
69 "zone varchar(128)," \
72 #define ACTIVE_APP_INDEX "zone, appid"
74 #define DISPLAY_OWNER_SELECT "*"
75 #define DISPLAY_OWNER_WHERE NULL
77 mrp_domctl_table_t ico_tables[] = {
78 MRP_DOMCTL_TABLE("active_screen",
83 mrp_domctl_watch_t ico_watches[] = {
84 MRP_DOMCTL_WATCH("display-owner",
86 DISPLAY_OWNER_WHERE, 0),
89 static ico_syc_mrp_enforce_sound_t ico_syc_mrp_enforce_soundCB = NULL;
90 static void *cb_user_data = NULL;
93 /*-------------------------------------------------------------------------*/
97 /*-------------------------------------------------------------------------*/
98 int ico_syc_mrp_init(ico_syc_mrp_enforce_sound_t soundcb, void *user_data)
102 ICO_DBG("ico_syc_mrp_init: Enter");
104 ico_syc_mrp_enforce_soundCB = soundcb;
105 cb_user_data = user_data;
107 mrp_list_init(&mrp_sound_wait_queue);
109 mrp_list_init(&mrp_reqs);
111 ICO_DBG("called: mrp_mainloop_ecore_get()");
112 mrp_ml = mrp_mainloop_ecore_get();
114 ICO_DBG("called: mrp_res_connecte()");
115 mrp_ctx = mrp_res_create(mrp_ml, ico_syc_mrp_state_cb, NULL);
118 ICO_ERR("ico_syc_mrp_init: Leave(mrp_res_create Error)");
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);
129 if (mrp_dc == NULL) {
130 ICO_ERR("ico_syc_mrp_init: Leave(mrp_domctl_create Error)");
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)");
143 void ico_syc_mrp_term(void)
145 if (NULL != mrp_ctx) {
146 mrp_res_destroy(mrp_ctx);
149 if (NULL != mrp_dc) {
150 mrp_domctl_destroy(mrp_dc);
153 if (NULL != mrp_ml) {
154 mrp_mainloop_destroy(mrp_ml);
159 ico_syc_mrp_add_request(resource_request_t *req)
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);
170 ico_syc_mrp_del_request(resource_request_t *req)
176 resource_request_t *findreq = ico_syc_mrp_find_request(req->id,
178 if (NULL != findreq) {
179 if (req->pid != findreq->pid) {
180 ICO_DBG("ico_syc_mrp_del_request: pid not match");
185 ICO_DBG("ico_syc_mrp_del_request: not found in req list");
189 ICO_DBG("ico_syc_mrp_del_request: "
190 "del request %p to mrp_reqs list", req);
191 mrp_list_delete(&req->hook);
193 if (mrp_ctx && req->rset) {
194 mrp_res_release_resource_set(req->rset);
195 mrp_res_delete_resource_set(req->rset);
201 ico_syc_mrp_acquire_sound_resource(resource_request_t *newreq)
203 mrp_res_resource_set_t *rs;
205 ICO_DBG("ico_syc_mrp_acquire_sound_resource: Enter");
207 resource_request_t *req = ico_syc_mrp_find_request(newreq->id,
210 ico_syc_mrp_add_request(newreq);
215 if (!mrp_res_connected) {
216 mrp_res_queue_item_t *item;
218 ICO_DBG("ico_syc_mrp_acquire_sound_resource: "
219 "resource context is not connected yet, queueing");
221 item = ico_syc_mrp_create_queue_item(req);
222 mrp_list_append(&mrp_sound_wait_queue, &item->hook);
224 ICO_DBG("ico_syc_mrp_acquire_sound_resource: Leave(true)");
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;
235 ICO_DBG("ico_syc_mrp_acquire_sound_resource: "
236 "could not create resource for sound");
238 ICO_DBG("called: mrp_res_create_resource_set()");
239 rs = mrp_res_create_resource_set(mrp_ctx,
241 ico_syc_mrp_resource_cb,
245 ICO_ERR("ico_syc_mrp_acquire_sound_resource: "
246 "could not create resource set for audio");
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)");
258 ICO_DBG("called: mrp_res_create_resource");
259 res = mrp_res_create_resource(rs, "audio_playback", TRUE, FALSE);
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)");
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) {
275 ret = snprintf(numbuf, sizeof(numbuf), "%d", req->pid);
277 if (ret > 0 && (size_t)ret < sizeof(numbuf)) {
278 mrp_res_set_attribute_string(attr, numbuf);
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);
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);
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*/);
300 ICO_DBG("called: mrp_res_acquire_resource_set()");
301 mrp_res_acquire_resource_set(req->rset);
304 ICO_DBG("ico_syc_mrp_acquire_sound_resource: Leave(true)");
309 ico_syc_mrp_release_sound_resource(resource_request_t *req)
311 ICO_DBG("ico_syc_mrp_release_sound_resource: Enter");
313 ico_syc_mrp_del_request(req);
315 if (mrp_ctx && req->rset) {
316 if (REQTYPE_APP == req->reqtype) {
317 mrp_res_release_resource_set(mrp_ctx, req->rset);
321 mrp_res_release_resource_set(mrp_ctx, req->rset);
322 mrp_res_delete_resource_set(mrp_ctx, req->rset);
327 ICO_DBG("ico_syc_mrp_release_sound_resource: Leave(true)");
331 /*-------------------------------------------------------------------------*/
335 /*-------------------------------------------------------------------------*/
336 static mrp_res_queue_item_t *
337 ico_syc_mrp_create_queue_item(resource_request_t *req)
339 mrp_res_queue_item_t *item = mrp_allocz(sizeof(mrp_res_queue_item_t));
342 ICO_DBG("ico_syc_mrp_create_queue_item: Enter");
345 ICO_ERR("mrp_allocz failed.");
349 mrp_list_init(&item->hook);
351 if (req->resid | RESID_KIND_SOUND) {
352 item->req_id = req->soundid;
353 item->zone_idx = req->soundzoneid;
356 item->prio = req->prio;
357 item->res_type = req->resid;
359 ret = snprintf(item->appid, MURPHY_APPID_MAXIMUM_LENGTH, "%s", req->appid);
361 if (ret < 0 || ret >= MURPHY_APPID_MAXIMUM_LENGTH) {
363 ICO_DBG("ico_syc_mrp_create_queue_item: Leave(NULL)");
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);
370 ICO_DBG("ico_syc_mrp_create_queue_item: Leave(0x%08x)", item);
374 static resource_request_t *
375 ico_syc_mrp_find_request(int req_id, char *appid)
377 mrp_list_hook_t *p, *n;
378 resource_request_t *req;
380 ICO_DBG("ico_syc_mrp_find_request: Enter");
382 /* go through all mrp_res_queue_item_t structs in the list */
384 mrp_list_foreach(&mrp_reqs, p, n) {
385 req = mrp_list_entry(p, typeof(*req), hook);
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);
395 ICO_DBG("ico_syc_mrp_find_request: Leave(NULL)");
400 ico_syc_mrp_process_sound_queue(void)
402 mrp_list_hook_t *p, *n;
403 mrp_res_queue_item_t *item;
405 ICO_DBG("ico_syc_mrp_process_sound_queue: Enter");
407 /* go through all mrp_res_queue_item_t structs in the list */
409 mrp_list_foreach(&mrp_sound_wait_queue, p, n) {
410 resource_request_t *req;
411 item = mrp_list_entry(p, typeof(*item), hook);
413 req = ico_syc_mrp_find_request(item->req_id, item->appid);
416 ico_syc_mrp_acquire_sound_resource(req);
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);
424 mrp_list_delete(&item->hook);
428 ICO_DBG("ico_syc_mrp_process_sound_queue: Leave");
432 ico_syc_mrp_resource_cb(mrp_res_context_t *ctx,
433 const mrp_res_resource_set_t *rs,
436 resource_request_t *req = NULL;
438 //mrp_res_queue_item_t *item = userdata;
439 resource_request_t *item = userdata;
441 unsigned short state = RES_STATE_ACQUIRED;
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);
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);
459 ICO_ERR("murphy: the request wasn't found!");
460 ICO_DBG("ico_syc_mrp_resource_cb: Leave");
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");
470 /* delete the previous set */
471 ICO_DBG("called: mrp_res_delete_resource");
472 mrp_res_delete_resource_set(req->rset);
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);
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;
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");
488 state = RES_STATE_RELEASED;
491 state = RES_STATE_WAITING;
495 ICO_WRN("ico_syc_mrp_resource_cb: state=UNKNOWN");
496 state = RES_STATE_RELEASED;
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)",
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);
521 ICO_WRN("unknown resource id");
524 ICO_DBG("ico_syc_mrp_resource_cb: Leave");
528 ico_syc_mrp_state_cb(mrp_res_context_t *ctx,
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);
540 case MRP_RES_CONNECTED:
541 ICO_DBG("ico_syc_mrp_state_cb: connected to murphyd");
542 mrp_res_connected = TRUE;
544 /* process the queued resources */
545 ico_syc_mrp_process_sound_queue();
547 case MRP_RES_DISCONNECTED:
548 ICO_DBG("ico_syc_mrp_state_cb: disconnected from murphyd");
550 mrp_res_destroy(ctx);
553 mrp_res_connected = FALSE;
556 ICO_ERR("ico_syc_mrp_state_cb: state error");
560 ICO_DBG("ico_syc_mrp_state_cb: Leave");
564 ico_syc_mrp_connect_notify(mrp_domctl_t *dc,int connected,
565 int errcode, const char *errmsg,
568 ICO_DBG("ico_syc_mrp_connect_notify: Enter");
569 ICO_DBG("ico_syc_mrp_connect_notify: Leave");
573 ico_syc_mrp_data_notify(mrp_domctl_t *dc,
574 mrp_domctl_data_t *tables,
575 int ntable, void *user_data)
577 ICO_DBG("ico_syc_mrp_data_notify: Enter");
578 ICO_DBG("ico_syc_mrp_data_notify: Leave");
582 ico_sys_mrp_export_notify(mrp_domctl_t *dc, int errcode,
583 const char *errmsg, void *user_data)
586 MRP_UNUSED(user_data);
589 ICO_ERR("murphy: exporting data to Murphy failed "
590 "(%d: %s).", errcode, errmsg);
595 ico_syc_mrp_active_app(const char *appid)
597 mrp_domctl_data_t tables[1];
598 mrp_domctl_value_t values[2];
600 ICO_DBG("ico_syc_mrp_active_app: active app '%s'", appid);
602 memset(tables, 0, sizeof(tables));
603 memset(values, 0, sizeof(values));
606 tables[0].ncolumn = 2;
608 tables[0].rows = mrp_allocz(sizeof(*tables[0].rows));
609 tables[0].rows[0] = values;
611 values[0].type = MRP_DOMCTL_STRING;
612 values[0].str = "driver";
613 values[1].type = MRP_DOMCTL_STRING;
614 values[1].str = appid;
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");
625 mrp_free(tables[0].rows);
627 /* vim:set expandtab ts=4 sw=4: */