ivi-resource-manager: add appid mapping
[profile/ivi/murphy.git] / src / plugins / ivi-resource-manager / audio.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 <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34
35 #include <murphy/common.h>
36
37 #include <murphy-db/mqi.h>
38
39 #include <murphy/resource/config-api.h>
40 #include <murphy/resource/manager-api.h>
41 #include <murphy/resource/client-api.h>
42
43 #include "audio.h"
44 #include "class.h"
45 #include "appid.h"
46
47 #define RESOURCE_NAME       "audio_playback"
48 #define ACTIVE_SCREEN_TABLE "active_screen"
49
50 #define ACTIVE_SCREEN_MAX   32
51
52 #define BIT(i)               ((uint32_t)1 << (i))
53 #define MASK(w)              (((uint32_t)1 << (w)) - 1)
54
55 #define PRIORITY_BITS       8
56 #define CATEGORY_BITS       8
57 #define ZORDER_BITS         16
58
59 #define PRIORITY_POSITION   0
60 #define CATEGORY_POSITION   (PRIORITY_POSITION + PRIORITY_BITS)
61 #define ZORDER_POSITION     (CATEGORY_POSITION + CATEGORY_BITS)
62
63 #define PRIORITY_MASK       MASK(PRIORITY_BITS)
64 #define CATEGORY_MASK       MASK(CATEGORY_BITS)
65 #define ZORDER_MASK         MASK(ZORDER_BITS)
66
67 #define STAMP_BITS          30
68 #define ACQUIRE_BITS        1
69 #define SHARE_BITS          1
70
71 #define STAMP_POSITION      0
72 #define ACQUIRE_POSITION    (STAMP_POSITION + STAMP_BITS)
73 #define SHARE_POSITION      (ACQUIRE_POSITION + ACQUIRE_BITS)
74
75 #define STAMP_MASK          MASK(STAMP_BITS)
76 #define ACQUIRE_MASK        MASK(ACQUIRE_BITS)
77 #define SHARE_MASK          MASK(SHARE_BITS)
78
79
80 #define ATTRIBUTE(n,t,v)    {n, MRP_RESOURCE_RW, mqi_##t, {.t=v}}
81 #define ATTR_END            {NULL, 0, 0, {.string=NULL}}
82
83 typedef struct audio_resource_s   audio_resource_t;
84 typedef struct active_screen_s    active_screen_t;
85
86 struct active_screen_s {
87     const char *appid;
88 };
89
90 struct mrp_resmgr_audio_s {
91     mrp_resmgr_data_t *data;
92     uint32_t resid;
93     mrp_list_hook_t classes[MRP_ZONE_MAX];
94     int nactive[MRP_ZONE_MAX];
95     active_screen_t actives[MRP_ZONE_MAX][ACTIVE_SCREEN_MAX];
96     mqi_handle_t dbtbl;
97     uint32_t grantids[MRP_ZONE_MAX];
98 };
99
100 struct audio_resource_s {
101     mrp_list_hook_t link;
102     mrp_resource_t *res;
103     mrp_resmgr_audio_t *audio;
104     mrp_resmgr_class_t *class;
105     bool acquire;
106     uint32_t grantid;
107     uint32_t key;
108 };
109
110
111 static audio_resource_t *audio_resource_create(mrp_resmgr_audio_t *,
112                                                  mrp_zone_t *,mrp_resource_t *,
113                                                  mrp_application_class_t *);
114 static void audio_resource_destroy(mrp_resmgr_audio_t *,  mrp_zone_t *,
115                                     mrp_resource_t *);
116 static audio_resource_t *audio_resource_lookup(mrp_resmgr_audio_t *,
117                                                  mrp_resource_t *);
118 static void audio_update_resources(mrp_resmgr_audio_t *, mrp_zone_t *);
119 static void audio_grant_resources(mrp_resmgr_audio_t *, mrp_zone_t *);
120
121 static void resource_class_move_resource(mrp_resmgr_class_t *,
122                                          audio_resource_t *);
123 static uint32_t resource_key(audio_resource_t *);
124 static bool resource_is_active(mrp_resmgr_audio_t *, uint32_t,
125                                audio_resource_t *);
126 static void resource_fix_appid(mrp_resmgr_audio_t *, mrp_resource_t *);
127
128 static void get_active_screens(mrp_resmgr_audio_t *, mrp_zone_t *);
129
130 static void audio_notify(mrp_resource_event_t, mrp_zone_t *,
131                           mrp_application_class_t *, mrp_resource_t *, void *);
132 static void audio_init(mrp_zone_t *, void *);
133 static bool audio_allocate(mrp_zone_t *, mrp_resource_t *, void *);
134 static void audio_free(mrp_zone_t *, mrp_resource_t *, void *);
135 static bool audio_advice(mrp_zone_t *, mrp_resource_t *, void *);
136 static void audio_commit(mrp_zone_t *, void *);
137
138
139 #define PRIORITY_ATTRIDX  0
140 #define CATEGORY_ATTRIDX  1
141 #define APPID_ATTRIDX     2
142 #define ROLE_ATTRIDX      3
143 #define PID_ATTRIDX       4
144 #define POLICY_ATTRIDX    5
145
146 static mrp_attr_def_t audio_attrs[] = {
147     ATTRIBUTE("priority" , integer,       0      ),
148     ATTRIBUTE("cathegory", integer,       0      ),
149     ATTRIBUTE("appid"    , string , "<undefined>"),
150     ATTRIBUTE("role"     , string , "music"      ),
151     ATTRIBUTE("pid"      , string , "<unknown>"  ),
152     ATTRIBUTE("policy"   , string , "relaxed"    ),
153     ATTR_END
154 };
155
156
157 static mrp_resource_mgr_ftbl_t audio_ftbl = {
158     audio_notify,
159     audio_init,
160     audio_allocate,
161     audio_free,
162     audio_advice,
163     audio_commit
164 };
165
166
167 static uint32_t request_stamp;
168
169
170 mrp_resmgr_audio_t *mrp_resmgr_audio_create(mrp_resmgr_data_t *data)
171 {
172     mrp_resmgr_audio_t *audio;
173     uint32_t resid;
174     uint32_t i;
175
176     if ((audio = mrp_allocz(sizeof(*audio)))) {
177         resid = mrp_resource_definition_create(RESOURCE_NAME,true,audio_attrs,
178                                                &audio_ftbl,audio);
179         mrp_lua_resclass_create_from_c(resid);
180
181         audio->data = data;
182         audio->resid = resid;
183         audio->dbtbl = MQI_HANDLE_INVALID;
184
185         for (i = 0;  i < MRP_ZONE_MAX;  i++)
186             mrp_list_init(audio->classes + i);
187
188         mqi_open();
189
190         mrp_resmgr_register_dependency(data, ACTIVE_SCREEN_TABLE);
191     }
192
193     return audio;
194 }
195
196
197 void mrp_resmgr_audio_destroy(mrp_resmgr_audio_t *audio)
198 {
199     if (audio) {
200
201         mrp_free(audio);
202     }
203 }
204
205 int mrp_resmgr_audio_print(mrp_resmgr_audio_t *audio,
206                             uint32_t zoneid,
207                             char *buf, int len)
208 {
209 #define PRINT(...)                              \
210     do {                                        \
211         p += snprintf(p, e-p, __VA_ARGS__);     \
212         if (p >= e)                             \
213             return p - buf;                     \
214     } while (0)
215
216     char *p, *e;
217     mrp_list_hook_t *classes, *centry, *cn;
218     mrp_list_hook_t *resources, *rentry, *rn;
219     mrp_resmgr_class_t *class;
220     audio_resource_t *ar;
221     const char *class_name;
222     mrp_attr_t a;
223     int i;
224
225     MRP_ASSERT(audio && buf && len > 0, "invalid argument");
226
227     e = (p = buf) + len;
228     classes = audio->classes + zoneid;
229
230     PRINT("      Resource 'audio' - grantid:%u\n", audio->grantids[zoneid]);
231
232     if (mrp_list_empty(classes))
233         PRINT("         No resources\n");
234     else {
235         mrp_list_foreach_back(classes, centry, cn) {
236             class = mrp_list_entry(centry, mrp_resmgr_class_t, link);
237             class_name = mrp_application_class_get_name(class->class);
238             resources = &class->resources;
239
240             PRINT("         Class '%s':\n", class_name);
241
242             mrp_list_foreach_back(resources, rentry, rn) {
243                 ar = mrp_list_entry(rentry, audio_resource_t, link);
244
245                 PRINT("            0x%08x %s %u",
246                       ar->key, ar->acquire ? "acquire":"release", ar->grantid);
247
248                 for (i = 0;  i < (int)MRP_ARRAY_SIZE(audio_attrs) - 1;  i++) {
249                     if ((mrp_resource_read_attribute(ar->res, i, &a))) {
250                         PRINT(" %s:", a.name);
251
252                         switch (a.type) {
253                         case mqi_string:   PRINT("'%s'",a.value.string); break;
254                         case mqi_integer:  PRINT("%d",a.value.integer);  break;
255                         case mqi_unsignd:  PRINT("%u",a.value.unsignd);  break;
256                         case mqi_floating: PRINT("%lf",a.value.floating);break;
257                         default:           PRINT("<unsupported type>");  break;
258                         }
259                     }
260                 }
261
262                 PRINT("\n");
263             }
264         }
265     }
266
267     return p - buf;
268
269 #undef PRINT
270 }
271
272 static audio_resource_t *audio_resource_create(mrp_resmgr_audio_t *audio,
273                                                mrp_zone_t *zone,
274                                                mrp_resource_t *res,
275                                                mrp_application_class_t *ac)
276 {
277     mrp_resmgr_data_t *data;
278     uint32_t zone_id;
279     mrp_list_hook_t *classes;
280     mrp_resmgr_class_t *rc;
281     audio_resource_t *ar;
282
283     MRP_ASSERT(audio && zone && res && ac, "invalid argument");
284     MRP_ASSERT(audio->data, "confused with data structures");
285
286     data = audio->data;
287
288     zone_id = mrp_zone_get_id(zone);
289     classes = audio->classes + zone_id;
290
291     if (!(rc = mrp_resmgr_class_find(classes, ac)) &&
292         !(rc = mrp_resmgr_class_create(classes, ac)) )
293     {
294         mrp_log_error("ivi-resource-manager: can't obtain resmgr class");
295     }
296     else {
297         resource_fix_appid(audio, res);
298
299         if ((ar = mrp_allocz(sizeof(*ar)))) {
300             mrp_list_init(&ar->link);
301             ar->res = res;
302             ar->audio = audio;
303             ar->class = rc;
304             ar->key = resource_key(ar);
305
306             resource_class_move_resource(rc, ar);
307
308             mrp_resmgr_insert_resource(data, zone, res, ar);
309         }
310     }
311
312     return ar;
313 }
314
315
316 static void audio_resource_destroy(mrp_resmgr_audio_t *audio,
317                                     mrp_zone_t *zone,
318                                     mrp_resource_t *res)
319 {
320     audio_resource_t *ar;
321
322     MRP_ASSERT(res && audio, "invalid argument");
323     MRP_ASSERT(audio->data, "confused with data structures");
324
325     if ((ar = mrp_resmgr_remove_resource(audio->data, zone, res))) {
326         mrp_list_delete(&ar->link);
327         mrp_free(ar);
328     }
329 }
330
331
332 static audio_resource_t *audio_resource_lookup(mrp_resmgr_audio_t *audio,
333                                                  mrp_resource_t *res)
334 {
335     audio_resource_t *ar;
336
337     MRP_ASSERT(res && audio, "invalid argument");
338     MRP_ASSERT(audio->data, "confused with data structures");
339
340     ar = mrp_resmgr_lookup_resource(audio->data, res);
341
342     return ar;
343 }
344
345 static void audio_update_resources(mrp_resmgr_audio_t *audio,
346                                     mrp_zone_t *zone)
347 {
348     uint32_t zoneid;
349     mrp_list_hook_t *classes, *centry, *cn;
350     mrp_list_hook_t *resources, *rentry, *rn;
351     mrp_resmgr_class_t *class;
352     const char *class_name;
353     audio_resource_t *ar, *ars[4096];
354     int nar;
355     uint32_t zorder;
356     int i;
357
358     zoneid = mrp_zone_get_id(zone);
359     classes = audio->classes + zoneid;
360
361     mrp_list_foreach_back(classes, centry, cn) {
362         class = mrp_list_entry(centry, mrp_resmgr_class_t, link);
363         class_name = mrp_application_class_get_name(class->class);
364         resources = &class->resources;
365
366         if (!strcmp(class_name, "player") || !strcmp(class_name, "base")) {
367             nar = 0;
368
369             mrp_list_foreach_back(resources, rentry, rn) {
370                 ar = mrp_list_entry(rentry, audio_resource_t, link);
371
372                 if (resource_is_active(audio, zoneid, ar)) {
373                     ar->key |= (ZORDER_MASK << ZORDER_POSITION);
374                     if (nar >= (int)MRP_ARRAY_SIZE(ars)) {
375                         mrp_log_error("ivi-resource-manager: "
376                                       "too many active audios");
377                         break;
378                     }
379                     mrp_list_delete(&ar->link);
380                     ars[nar++] = ar;
381                 }
382                 else {
383                     zorder  = (ar->key >> ZORDER_POSITION) & ZORDER_MASK;
384                     zorder -= (zorder > 0) ? 1 : 0;
385
386                     ar->key &= ~(ZORDER_MASK << ZORDER_POSITION);
387                     ar->key |= (zorder << ZORDER_POSITION);
388                 }
389             } /* foreach resource */
390
391             for (i = 0;   i < nar;   i++)
392                 resource_class_move_resource(class, ars[i]);
393         } /* if class is 'player' or 'base' */
394
395     } /* foreach class */
396 }
397
398 static void audio_grant_resources(mrp_resmgr_audio_t *audio,
399                                    mrp_zone_t *zone)
400 {
401     uint32_t zoneid;
402     uint32_t grantid;
403     mrp_list_hook_t *classes, *centry, *cn;
404     mrp_list_hook_t *resources, *rentry, *rn;
405     mrp_resmgr_class_t *class;
406     const char *class_name;
407     bool base_class;
408     audio_resource_t *ar;
409
410     zoneid  = mrp_zone_get_id(zone);
411     classes = audio->classes + zoneid;
412     grantid = ++audio->grantids[zoneid];
413
414     mrp_list_foreach_back(classes, centry, cn) {
415         class = mrp_list_entry(centry, mrp_resmgr_class_t, link);
416         class_name = mrp_application_class_get_name(class->class);
417         resources = &class->resources;
418         base_class = !strcmp(class_name, "player") ||
419             !strcmp(class_name, "base");
420
421         if (!base_class || audio->nactive[zoneid]) {
422             mrp_list_foreach_back(resources, rentry, rn) {
423                 ar = mrp_list_entry(rentry, audio_resource_t, link);
424
425                 if (!ar->acquire)
426                     continue;
427
428                 if (base_class && !resource_is_active(audio,zoneid,ar))
429                     continue;
430
431                 ar->grantid = grantid;
432
433                 if (!mrp_resource_is_shared(ar->res))
434                     return;
435             } /* resources */
436         }
437     }
438 }
439
440 static void resource_class_move_resource(mrp_resmgr_class_t *class,
441                                          audio_resource_t *resource)
442 {
443     mrp_list_hook_t *list, *entry, *n, *insert_before;
444     audio_resource_t *ar;
445
446     mrp_list_delete(&resource->link);
447
448     list = insert_before = &class->resources;
449
450     mrp_list_foreach_back(list, entry, n) {
451         ar = mrp_list_entry(entry, audio_resource_t, link);
452
453         if (resource->key >= ar->key)
454             break;
455
456         insert_before = entry;
457     }
458
459     mrp_list_append(insert_before, &resource->link);
460 }
461
462
463 static uint32_t resource_key(audio_resource_t *ar)
464 {
465     mrp_resmgr_class_t *class;
466     const char *class_name;
467     bool base_class;
468     mrp_resource_t *res;
469     mrp_attr_t a;
470     uint32_t priority;
471     uint32_t category;
472     bool share;
473     bool acquire;
474     uint32_t key = 0;
475
476     do {
477         if (!(class = ar->class))
478             base_class = false;
479         else {
480             class_name = mrp_application_class_get_name(class->class);
481             base_class = !strcmp(class_name, "player") ||
482                          !strcmp(class_name, "base");
483         }
484
485         if (!(res = ar->res))
486             break;
487
488         if (base_class) {
489             if (!mrp_resource_read_attribute(res, PRIORITY_ATTRIDX, &a))
490                 break;
491             if (a.type != mqi_integer || a.value.integer < 0)
492                 break;
493
494             priority = (a.value.integer & PRIORITY_MASK) << PRIORITY_POSITION;
495
496             if (!mrp_resource_read_attribute(res, CATEGORY_ATTRIDX, &a))
497                 break;
498             if (a.type != mqi_integer || a.value.integer < 0)
499                 break;
500
501             category = (a.value.integer & CATEGORY_MASK) << CATEGORY_POSITION;
502
503             key = (priority | category);
504         }
505         else {
506             acquire = ar->acquire;
507             share = mrp_resource_is_shared(res);
508
509             key  = (++request_stamp & STAMP_MASK);
510             key |= (acquire ? (ACQUIRE_BITS << ACQUIRE_POSITION) : 0);
511             key |= (share ? (SHARE_BITS << SHARE_POSITION) : 0);
512         }
513
514     } while(0);
515
516     return key;
517 }
518
519 static bool resource_is_active(mrp_resmgr_audio_t *audio,
520                                uint32_t zoneid,
521                                audio_resource_t *ar)
522 {
523     active_screen_t *as;
524     mrp_attr_t a;
525     const char *appid;
526     int i, n;
527
528     if (mrp_resource_read_attribute(ar->res, APPID_ATTRIDX, &a)) {
529         appid = a.value.string;
530
531         for (i = 0, n = audio->nactive[zoneid];   i < n;   i++) {
532             as = &audio->actives[zoneid][i];
533
534             if (!strcmp(appid, as->appid))
535                 return true;
536         }
537     }
538
539     return false;
540 }
541
542 static void resource_fix_appid(mrp_resmgr_audio_t *audio, mrp_resource_t *res)
543 {
544     mrp_resmgr_data_t *data;
545     mrp_attr_t attr, attrs[2];
546     const char *appid;
547     const char *pid;
548
549     data = audio->data;
550     appid = NULL;
551     pid = 0;
552
553     if (mrp_resource_read_attribute(res, PID_ATTRIDX, &attr)) {
554         if (attr.type == mqi_string) {
555             if (strcmp(attr.value.string, "<unknown>"))
556                 pid = attr.value.string;
557         }
558     }
559
560     if (mrp_resource_read_attribute(res, APPID_ATTRIDX, &attr)) {
561         if (attr.type == mqi_string) {
562             if (strcmp(attr.value.string, "<undefined>"))
563                 appid = attr.value.string;
564         }
565     }
566
567     if (!appid && pid) {
568         appid = mrp_resmgr_appid_find_by_pid(mrp_resmgr_get_appid(data), pid);
569
570         if (appid) {
571             memset(attrs, 0, sizeof(attrs));
572             attrs[0].name = audio_attrs[APPID_ATTRIDX].name;
573             attrs[0].type = mqi_string;
574             attrs[0].value.string = appid;
575
576             mrp_resource_write_attributes(res, attrs);
577         }
578     }
579 }
580
581 static void get_active_screens(mrp_resmgr_audio_t *audio, mrp_zone_t *zone)
582 {
583     static const char *zone_name;
584
585     MQI_COLUMN_SELECTION_LIST(columns,
586         MQI_COLUMN_SELECTOR( 1, active_screen_t, appid )
587     );
588
589     MQI_WHERE_CLAUSE(where,
590         MQI_EQUAL( MQI_COLUMN(0), MQI_STRING_VAR(zone_name) )
591     );
592
593
594     uint32_t zone_id;
595     int n, nrow;
596     active_screen_t rows[MRP_ZONE_MAX * ACTIVE_SCREEN_MAX];
597     active_screen_t *as, *from, *to;
598     int i;
599
600     if (!audio || !zone)
601         return;
602
603     zone_id = mrp_zone_get_id(zone);
604     zone_name = mrp_zone_get_name(zone);
605
606     for (i = 0, n = audio->nactive[zone_id];   i < n;   i++) {
607         as = &audio->actives[zone_id][i];
608         mrp_free((void *)as->appid);
609         as = NULL;
610     }
611
612     audio->nactive[zone_id] = 0;
613
614     if (audio->dbtbl == MQI_HANDLE_INVALID) {
615         audio->dbtbl = mqi_get_table_handle(ACTIVE_SCREEN_TABLE);
616
617         if (audio->dbtbl == MQI_HANDLE_INVALID)
618             return;
619
620         mrp_log_info("ivi-resource-manager: audio resource: "
621                      "'active_screen' table found");
622     }
623
624     if ((size_t)mqi_get_table_size(audio->dbtbl) > MRP_ARRAY_SIZE(rows)) {
625         mrp_log_error("ivi-resource-manager: audio resource: "
626                       "table size exceeds the max.");
627         return;
628     }
629
630     if ((nrow = MQI_SELECT(columns, audio->dbtbl, where, rows)) < 0) {
631         mrp_log_error("ivi-resource-manager: audio resource: "
632                       "DB select failed: %s", strerror(errno));
633         return;
634     }
635
636     if (nrow > ACTIVE_SCREEN_MAX) {
637         mrp_log_error("ivi-resource-manager: audio resource: "
638                       "DB select result is too large (%d). "
639                       "Will be truncated to %d", nrow, ACTIVE_SCREEN_MAX);
640         nrow = ACTIVE_SCREEN_MAX;
641     }
642
643     for (i = 0;  i < nrow;  i++) {
644         from = &rows[i];
645         to = &audio->actives[zone_id][i];
646
647         to->appid = mrp_strdup(from->appid);
648     }
649
650     audio->nactive[zone_id] = nrow;
651 }
652
653
654 static void audio_notify(mrp_resource_event_t event,
655                           mrp_zone_t *zone,
656                           mrp_application_class_t *ac,
657                           mrp_resource_t *res,
658                           void *userdata)
659 {
660     mrp_resmgr_audio_t *audio = (mrp_resmgr_audio_t *)userdata;
661     const char *zone_name = mrp_zone_get_name(zone);
662     audio_resource_t *ar;
663
664     MRP_ASSERT(zone && ac && res && audio, "invalid argument");
665
666     switch (event) {
667
668     case MRP_RESOURCE_EVENT_CREATED:
669         mrp_log_info("audio resource in zone '%s' created", zone_name);
670         audio_resource_create(audio, zone, res, ac);
671         break;
672
673     case MRP_RESOURCE_EVENT_DESTROYED:
674         mrp_log_info("audio resource in zone '%s' destroyed", zone_name);
675         audio_resource_destroy(audio, zone, res);
676         break;
677
678     case MRP_RESOURCE_EVENT_ACQUIRE:
679         mrp_log_info("audio resource in zone '%s' is acquiring", zone_name);
680         if (!(ar = audio_resource_lookup(audio, res)))
681             goto no_audio_resource;
682         else {
683             ar->acquire = true;
684         }
685         break;
686
687     case MRP_RESOURCE_EVENT_RELEASE:
688         mrp_log_info("audio resource in zone '%s' is released", zone_name);
689         if (!(ar = audio_resource_lookup(audio, res)))
690             goto no_audio_resource;
691         else {
692             ar->acquire = false;
693         }
694         break;
695
696     no_audio_resource:
697         mrp_log_error("ivi-resource-manager: can't find audio resource "
698                       "in zone '%s'", zone_name);
699         break;
700
701     default:
702         mrp_log_error("ivi-resource-manager: invalid event %d at audio "
703                       "notification (zone '%s')", event, zone_name);
704         break;
705     }
706 }
707
708 static void audio_init(mrp_zone_t *zone, void *userdata)
709 {
710     mrp_resmgr_audio_t *audio = (mrp_resmgr_audio_t *)userdata;
711     const char *zone_name = mrp_zone_get_name(zone);
712
713     MRP_ASSERT(audio, "invalid argument");
714
715     mrp_log_info("audio init in zone '%s'", zone_name);
716
717     get_active_screens(audio, zone);
718     audio_update_resources(audio, zone);
719
720     audio_grant_resources(audio, zone);
721 }
722
723 static bool audio_allocate(mrp_zone_t *zone,
724                             mrp_resource_t *res,
725                             void *userdata)
726 {
727     mrp_resmgr_audio_t *audio = (mrp_resmgr_audio_t *)userdata;
728     uint32_t zoneid;
729     const char *zonenam = mrp_zone_get_name(zone);
730     audio_resource_t *ar;
731     uint32_t grantid;
732
733     MRP_ASSERT(res && audio, "invalid argument");
734
735     zoneid  = mrp_zone_get_id(zone);
736     zonenam = mrp_zone_get_name(zone);
737     grantid = audio->grantids[zoneid];
738
739     mrp_log_info("audio allocate in zone '%s'", zonenam);
740
741     if ((ar = audio_resource_lookup(audio, res))) {
742         return (ar->grantid == grantid);
743     }
744
745     mrp_log_error("ivi-resource-manager: attempt to allocate "
746                   "untracked resource");
747
748     return FALSE;
749 }
750
751
752 static void audio_free(mrp_zone_t *zone, mrp_resource_t *res, void *userdata)
753 {
754     mrp_resmgr_audio_t *audio = (mrp_resmgr_audio_t *)userdata;
755     const char *zone_name = mrp_zone_get_name(zone);
756
757     MRP_UNUSED(res);
758
759     MRP_ASSERT(audio, "invalid argument");
760
761     mrp_log_info("audio free in zone '%s'", zone_name);
762 }
763
764 static bool audio_advice(mrp_zone_t *zone,mrp_resource_t *res,void *userdata)
765 {
766     mrp_resmgr_audio_t *audio = (mrp_resmgr_audio_t *)userdata;
767     const char *zone_name = mrp_zone_get_name(zone);
768
769     MRP_UNUSED(res);
770
771     MRP_ASSERT(audio, "invalid argument");
772
773     mrp_log_info("audio advice in zone '%s'", zone_name);
774
775     return TRUE;
776 }
777
778 static void audio_commit(mrp_zone_t *zone, void *userdata)
779 {
780     mrp_resmgr_audio_t *audio = (mrp_resmgr_audio_t *)userdata;
781     const char *zone_name = mrp_zone_get_name(zone);
782
783     MRP_ASSERT(audio, "invalid argument");
784
785     mrp_log_info("audio commit in zone '%s'", zone_name);
786 }
787
788
789 /*
790  * Local Variables:
791  * c-basic-offset: 4
792  * indent-tabs-mode: nil
793  * End:
794  *
795  */