2 * module-agl-audio -- PulseAudio module for providing audio routing support
3 * (forked from "module-murphy-ivi" - https://github.com/otcshare )
4 * Copyright (c) 2012, Intel Corporation.
5 * Copyright (c) 2016, IoT.bzh
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU Lesser General Public License,
9 * version 2.1, as published by the Free Software Foundation.
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston,
28 #include <json/json.h>
30 #include <pulsecore/core-util.h>
31 #include <pulsecore/pulsecore-config.h>
33 bool use_default_configuration (struct userdata *);
35 const char *agl_config_file_get_path (const char *dir, const char *file, char *buf, size_t len)
41 snprintf (buf, len, "%s/%s", dir, file);
46 bool agl_config_parse_file (struct userdata *u, const char *path)
55 pa_log_info ("parsing configuration file '%s'", path);
56 success = agl_config_dofile (u, path);
60 pa_log_info ("applying builtin default configuration");
61 success = use_default_configuration (u);
67 bool agl_config_dofile (struct userdata *u, const char *path)
72 struct json_object *fjson, *root, *sct, *elt, *selt;
79 filefd = open (path, O_RDONLY);
81 pa_log_info ("could not find configuration file '%s'", path);
84 fstat (filefd, &filestat);
86 filemap = mmap (NULL, filestat.st_size, PROT_READ, MAP_PRIVATE, filefd, 0);
87 if (filemap == MAP_FAILED) {
88 pa_log_info ("could not map configuration file in memory");
92 /* is the file a JSON file, and if it is, does it have a "config" root ? */
93 fjson = json_tokener_parse (filemap);
94 root = json_object_object_get (fjson, "config");
95 if (!fjson || !root) {
96 pa_log_info ("could not parse JSON configuration file");
100 /* [zones] section */
101 sct = json_object_object_get (root, "zones");
102 if (!sct) return false;
103 len = json_object_array_length (sct);
104 for (i = 0; i < len; i++) {
105 elt = json_object_array_get_idx (sct, i);
106 val = json_object_get_string (elt);
107 agl_zoneset_add_zone (u, val, (uint32_t)i);
110 /* [rtgroups] section */
111 sct = json_object_object_get (root, "rtgroups");
112 if (!sct) return false;
113 len = json_object_array_length (sct);
114 for (i = 0; i < len; i++) {
115 const char *name, *type, *card, *accept_fct, *effect_fct;
116 elt = json_object_array_get_idx (sct, i);
117 name = json_object_get_string (json_object_object_get (elt, "name"));
118 type = json_object_get_string (json_object_object_get (elt, "type"));
119 card = json_object_get_string (json_object_object_get (elt, "card"));
120 accept_fct = json_object_get_string (json_object_object_get (elt, "accept_fct"));
121 effect_fct = json_object_get_string (json_object_object_get (elt, "effect_fct"));
122 agl_router_create_rtgroup (u, pa_streq(type, "OUTPUT") ? agl_output : agl_input,
124 pa_streq(type, "phone") ? agl_router_phone_accept : NULL,
125 pa_streq(type, "phone") ? agl_router_phone_effect : NULL);
128 /* [classmap] section */
129 sct = json_object_object_get (root, "classmap");
130 if (!sct) return false;
131 len = json_object_array_length (sct);
132 for (i = 0; i < len; i++) {
133 const char *class, *type, *rtgroup;
135 elt = json_object_array_get_idx (sct, i);
136 class = json_object_get_string (json_object_object_get (elt, "class"));
137 type = json_object_get_string (json_object_object_get (elt, "type"));
138 zone = json_object_get_int (json_object_object_get (elt, "zone"));
139 rtgroup = json_object_get_string (json_object_object_get (elt, "rtgroup"));
140 agl_router_assign_class_to_rtgroup (u, agl_node_type_from_str (class),
142 pa_streq(type, "OUTPUT") ? agl_output : agl_input,
146 /* [typemap] section */
147 sct = json_object_object_get (root, "typemap");
148 if (!sct) return false;
149 len = json_object_array_length (sct);
150 for (i = 0; i < len; i++) {
151 const char *id, *type;
152 elt = json_object_array_get_idx (sct, i);
153 id = json_object_get_string (json_object_object_get (elt, "id"));
154 type = json_object_get_string (json_object_object_get (elt, "type"));
155 agl_nodeset_add_role (u, id, agl_node_type_from_str (type), NULL);
158 /* [priormap] section */
159 sct = json_object_object_get (root, "priormap");
160 if (!sct) return false;
161 len = json_object_array_length (sct);
162 for (i = 0; i < len; i++) {
165 elt = json_object_array_get_idx (sct, i);
166 class = json_object_get_string (json_object_object_get (elt, "class"));
167 priority = json_object_get_int (json_object_object_get (elt, "priority"));
168 agl_router_assign_class_priority (u, agl_node_type_from_str (class), priority);
171 json_object_object_del (fjson, "");
172 munmap (filemap, filestat.st_size);
179 /* DEFAULT CONFIGURATION PART */
181 static zone_def zones[] = {
190 static rtgroup_def rtgroups[] = {
194 agl_router_phone_accept,
195 agl_router_phone_effect
205 { 0, NULL, NULL, NULL, NULL }
208 static classmap_def classmap[] = {
209 { agl_phone, 0, agl_input, "Phone" },
210 { agl_player, 0, agl_input, "default" },
211 { agl_radio, 0, agl_input, "default" },
212 { agl_navigator,0, agl_input, "default" },
213 { agl_event, 0, agl_input, "default" },
214 { agl_node_type_unknown, 0, agl_direction_unknown, NULL }
217 static typemap_def typemap[] = {
218 { "phone", agl_phone },
219 { "music", agl_player },
220 { "radio", agl_radio },
221 { "navi", agl_navigator },
222 { "event", agl_event },
223 { NULL, agl_node_type_unknown }
226 static prior_def priormap[] = {
229 { agl_navigator, 2 },
232 { agl_node_type_unknown, 0}
235 bool use_default_configuration (struct userdata *u)
245 for (z = zones; z->name; z++)
246 agl_zoneset_add_zone (u, z->name, (uint32_t)(z - zones));
248 for (r = rtgroups; r->name; r++)
249 agl_router_create_rtgroup (u, r->type, r->name, r->node_desc,
250 r->accept, r->effect);
252 for (c = classmap; c->rtgroup; c++)
253 agl_router_assign_class_to_rtgroup (u, c->class, c->zone,
254 c->type, c->rtgroup);
256 for (t = typemap; t->id; t++)
257 agl_nodeset_add_role (u, t->id, t->type, NULL);
259 for (p = priormap; p->class; p++)
260 agl_router_assign_class_priority (u, p->class, p->priority);