daemon: remove some unneeded header includes
[ladish.git] / daemon / studio_jack_conf.c
blobe8e32ee6cbb54c1f164de8d90cb0a47a1665c08f
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2009 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains implementation of the studio functionality
9 * related to jack configuration
10 **************************************************************************
12 * LADI Session Handler is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * LADI Session Handler is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
24 * or write to the Free Software Foundation, Inc.,
25 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "common.h"
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <dirent.h>
35 #include <expat.h>
37 #include "studio_internal.h"
39 bool
40 jack_conf_container_create(
41 struct jack_conf_container ** container_ptr_ptr,
42 const char * name)
44 struct jack_conf_container * container_ptr;
46 container_ptr = malloc(sizeof(struct jack_conf_container));
47 if (container_ptr == NULL)
49 log_error("malloc() failed to allocate struct jack_conf_container");
50 goto fail;
53 container_ptr->name = strdup(name);
54 if (container_ptr->name == NULL)
56 log_error("strdup() failed to duplicate \"%s\"", name);
57 goto fail_free;
60 INIT_LIST_HEAD(&container_ptr->children);
61 container_ptr->children_leafs = false;
63 *container_ptr_ptr = container_ptr;
64 return true;
66 fail_free:
67 free(container_ptr);
69 fail:
70 return false;
73 bool
74 jack_conf_parameter_create(
75 struct jack_conf_parameter ** parameter_ptr_ptr,
76 const char * name)
78 struct jack_conf_parameter * parameter_ptr;
80 parameter_ptr = malloc(sizeof(struct jack_conf_parameter));
81 if (parameter_ptr == NULL)
83 log_error("malloc() failed to allocate struct jack_conf_parameter");
84 goto fail;
87 parameter_ptr->name = strdup(name);
88 if (parameter_ptr->name == NULL)
90 log_error("strdup() failed to duplicate \"%s\"", name);
91 goto fail_free;
94 *parameter_ptr_ptr = parameter_ptr;
95 return true;
97 fail_free:
98 free(parameter_ptr);
100 fail:
101 return false;
104 void
105 jack_conf_parameter_destroy(
106 struct jack_conf_parameter * parameter_ptr)
108 #if 0
109 log_info("jack_conf_parameter destroy");
111 switch (parameter_ptr->parameter.type)
113 case jack_boolean:
114 log_info("%s value is %s (boolean)", parameter_ptr->name, parameter_ptr->parameter.value.boolean ? "true" : "false");
115 break;
116 case jack_string:
117 log_info("%s value is %s (string)", parameter_ptr->name, parameter_ptr->parameter.value.string);
118 break;
119 case jack_byte:
120 log_info("%s value is %u/%c (byte/char)", parameter_ptr->name, parameter_ptr->parameter.value.byte, (char)parameter_ptr->parameter.value.byte);
121 break;
122 case jack_uint32:
123 log_info("%s value is %u (uint32)", parameter_ptr->name, (unsigned int)parameter_ptr->parameter.value.uint32);
124 break;
125 case jack_int32:
126 log_info("%s value is %u (int32)", parameter_ptr->name, (signed int)parameter_ptr->parameter.value.int32);
127 break;
128 default:
129 log_error("unknown jack parameter_ptr->parameter type %d (%s)", (int)parameter_ptr->parameter.type, parameter_ptr->name);
130 break;
132 #endif
134 if (parameter_ptr->parameter.type == jack_string)
136 free(parameter_ptr->parameter.value.string);
139 free(parameter_ptr->name);
140 free(parameter_ptr);
143 void
144 jack_conf_container_destroy(
145 struct jack_conf_container * container_ptr)
147 struct list_head * node_ptr;
149 //log_info("\"%s\" jack_conf_parameter destroy", container_ptr->name);
151 if (!container_ptr->children_leafs)
153 while (!list_empty(&container_ptr->children))
155 node_ptr = container_ptr->children.next;
156 list_del(node_ptr);
157 jack_conf_container_destroy(list_entry(node_ptr, struct jack_conf_container, siblings));
160 else
162 while (!list_empty(&container_ptr->children))
164 node_ptr = container_ptr->children.next;
165 list_del(node_ptr);
166 jack_conf_parameter_destroy(list_entry(node_ptr, struct jack_conf_parameter, siblings));
170 free(container_ptr->name);
171 free(container_ptr);
174 #define context_ptr ((struct conf_callback_context *)context)
176 static
177 bool
178 conf_callback(
179 void * context,
180 bool leaf,
181 const char * address,
182 char * child)
184 char path[JACK_CONF_MAX_ADDRESS_SIZE];
185 const char * component;
186 char * dst;
187 size_t len;
188 bool is_set;
189 struct jack_conf_container * parent_ptr;
190 struct jack_conf_container * container_ptr;
191 struct jack_conf_parameter * parameter_ptr;
193 parent_ptr = context_ptr->parent_ptr;
195 if (parent_ptr == NULL && strcmp(child, "drivers") == 0)
197 log_debug("ignoring drivers branch");
198 return true;
201 dst = path;
202 component = address;
203 while (*component != 0)
205 len = strlen(component);
206 memcpy(dst, component, len);
207 dst[len] = ':';
208 component += len + 1;
209 dst += len + 1;
212 strcpy(dst, child);
214 /* address always is same buffer as the one supplied through context pointer */
215 ASSERT(context_ptr->address == address);
216 dst = (char *)component;
218 len = strlen(child) + 1;
219 memcpy(dst, child, len);
220 dst[len] = 0;
222 if (leaf)
224 log_debug("%s (leaf)", path);
226 if (parent_ptr == NULL)
228 log_error("jack conf parameters can't appear in root container");
229 return false;
232 if (!parent_ptr->children_leafs)
234 if (!list_empty(&parent_ptr->children))
236 log_error("jack conf parameters cant be mixed with containers at same hierarchy level");
237 return false;
240 parent_ptr->children_leafs = true;
243 if (!jack_conf_parameter_create(&parameter_ptr, child))
245 log_error("jack_conf_parameter_create() failed");
246 return false;
249 if (!jack_proxy_get_parameter_value(context_ptr->address, &is_set, &parameter_ptr->parameter))
251 log_error("cannot get value of %s", path);
252 return false;
255 if (is_set)
257 #if 0
258 switch (parameter_ptr->parameter.type)
260 case jack_boolean:
261 log_info("%s value is %s (boolean)", path, parameter_ptr->parameter.value.boolean ? "true" : "false");
262 break;
263 case jack_string:
264 log_info("%s value is %s (string)", path, parameter_ptr->parameter.value.string);
265 break;
266 case jack_byte:
267 log_info("%s value is %u/%c (byte/char)", path, parameter_ptr->parameter.value.byte, (char)parameter_ptr->parameter.value.byte);
268 break;
269 case jack_uint32:
270 log_info("%s value is %u (uint32)", path, (unsigned int)parameter_ptr->parameter.value.uint32);
271 break;
272 case jack_int32:
273 log_info("%s value is %u (int32)", path, (signed int)parameter_ptr->parameter.value.int32);
274 break;
275 default:
276 log_error("unknown jack parameter_ptr->parameter type %d (%s)", (int)parameter_ptr->parameter.type, path);
277 jack_conf_parameter_destroy(parameter_ptr);
278 return false;
280 #endif
282 parameter_ptr->parent_ptr = parent_ptr;
283 memcpy(parameter_ptr->address, context_ptr->address, JACK_CONF_MAX_ADDRESS_SIZE);
284 list_add_tail(&parameter_ptr->siblings, &parent_ptr->children);
285 list_add_tail(&parameter_ptr->leaves, &g_studio.jack_params);
287 else
289 jack_conf_parameter_destroy(parameter_ptr);
292 else
294 log_debug("%s (container)", path);
296 if (parent_ptr != NULL && parent_ptr->children_leafs)
298 log_error("jack conf containers cant be mixed with parameters at same hierarchy level");
299 return false;
302 if (!jack_conf_container_create(&container_ptr, child))
304 log_error("jack_conf_container_create() failed");
305 return false;
308 container_ptr->parent_ptr = parent_ptr;
310 if (parent_ptr == NULL)
312 list_add_tail(&container_ptr->siblings, &g_studio.jack_conf);
314 else
316 list_add_tail(&container_ptr->siblings, &parent_ptr->children);
319 context_ptr->parent_ptr = container_ptr;
321 if (!jack_proxy_read_conf_container(context_ptr->address, context, conf_callback))
323 log_error("cannot read container %s", path);
324 return false;
327 context_ptr->parent_ptr = parent_ptr;
330 *dst = 0;
332 return true;
335 #undef context_ptr
337 void jack_conf_clear(void)
339 struct list_head * node_ptr;
341 INIT_LIST_HEAD(&g_studio.jack_params); /* we will destroy the leaves as part of tree destroy traversal */
342 while (!list_empty(&g_studio.jack_conf))
344 node_ptr = g_studio.jack_conf.next;
345 list_del(node_ptr);
346 jack_conf_container_destroy(list_entry(node_ptr, struct jack_conf_container, siblings));
349 g_studio.jack_conf_valid = false;
352 bool studio_fetch_jack_settings(void)
354 struct conf_callback_context context;
356 jack_conf_clear();
358 context.address[0] = 0;
359 context.container_ptr = &g_studio.jack_conf;
360 context.parent_ptr = NULL;
362 if (!jack_proxy_read_conf_container(context.address, &context, conf_callback))
364 log_error("jack_proxy_read_conf_container() failed.");
365 return false;
368 return true;