daemon: improve log
[ladish.git] / daemon / studio_jack_conf.c
blob2b725d58608a01d6a50015de5c10603ad058781b
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 "../jack_proxy.h"
38 #include "../graph_proxy.h"
39 #include "graph.h"
40 #include "../dbus_constants.h"
41 #include "control.h"
42 #include "../catdup.h"
43 #include "../dbus/error.h"
44 #include "dirhelpers.h"
45 #include "graph_dict.h"
46 #include "escape.h"
47 #include "studio_internal.h"
49 bool
50 jack_conf_container_create(
51 struct jack_conf_container ** container_ptr_ptr,
52 const char * name)
54 struct jack_conf_container * container_ptr;
56 container_ptr = malloc(sizeof(struct jack_conf_container));
57 if (container_ptr == NULL)
59 log_error("malloc() failed to allocate struct jack_conf_container");
60 goto fail;
63 container_ptr->name = strdup(name);
64 if (container_ptr->name == NULL)
66 log_error("strdup() failed to duplicate \"%s\"", name);
67 goto fail_free;
70 INIT_LIST_HEAD(&container_ptr->children);
71 container_ptr->children_leafs = false;
73 *container_ptr_ptr = container_ptr;
74 return true;
76 fail_free:
77 free(container_ptr);
79 fail:
80 return false;
83 bool
84 jack_conf_parameter_create(
85 struct jack_conf_parameter ** parameter_ptr_ptr,
86 const char * name)
88 struct jack_conf_parameter * parameter_ptr;
90 parameter_ptr = malloc(sizeof(struct jack_conf_parameter));
91 if (parameter_ptr == NULL)
93 log_error("malloc() failed to allocate struct jack_conf_parameter");
94 goto fail;
97 parameter_ptr->name = strdup(name);
98 if (parameter_ptr->name == NULL)
100 log_error("strdup() failed to duplicate \"%s\"", name);
101 goto fail_free;
104 *parameter_ptr_ptr = parameter_ptr;
105 return true;
107 fail_free:
108 free(parameter_ptr);
110 fail:
111 return false;
114 void
115 jack_conf_parameter_destroy(
116 struct jack_conf_parameter * parameter_ptr)
118 #if 0
119 log_info("jack_conf_parameter destroy");
121 switch (parameter_ptr->parameter.type)
123 case jack_boolean:
124 log_info("%s value is %s (boolean)", parameter_ptr->name, parameter_ptr->parameter.value.boolean ? "true" : "false");
125 break;
126 case jack_string:
127 log_info("%s value is %s (string)", parameter_ptr->name, parameter_ptr->parameter.value.string);
128 break;
129 case jack_byte:
130 log_info("%s value is %u/%c (byte/char)", parameter_ptr->name, parameter_ptr->parameter.value.byte, (char)parameter_ptr->parameter.value.byte);
131 break;
132 case jack_uint32:
133 log_info("%s value is %u (uint32)", parameter_ptr->name, (unsigned int)parameter_ptr->parameter.value.uint32);
134 break;
135 case jack_int32:
136 log_info("%s value is %u (int32)", parameter_ptr->name, (signed int)parameter_ptr->parameter.value.int32);
137 break;
138 default:
139 log_error("unknown jack parameter_ptr->parameter type %d (%s)", (int)parameter_ptr->parameter.type, parameter_ptr->name);
140 break;
142 #endif
144 if (parameter_ptr->parameter.type == jack_string)
146 free(parameter_ptr->parameter.value.string);
149 free(parameter_ptr->name);
150 free(parameter_ptr);
153 void
154 jack_conf_container_destroy(
155 struct jack_conf_container * container_ptr)
157 struct list_head * node_ptr;
159 //log_info("\"%s\" jack_conf_parameter destroy", container_ptr->name);
161 if (!container_ptr->children_leafs)
163 while (!list_empty(&container_ptr->children))
165 node_ptr = container_ptr->children.next;
166 list_del(node_ptr);
167 jack_conf_container_destroy(list_entry(node_ptr, struct jack_conf_container, siblings));
170 else
172 while (!list_empty(&container_ptr->children))
174 node_ptr = container_ptr->children.next;
175 list_del(node_ptr);
176 jack_conf_parameter_destroy(list_entry(node_ptr, struct jack_conf_parameter, siblings));
180 free(container_ptr->name);
181 free(container_ptr);
184 #define context_ptr ((struct conf_callback_context *)context)
186 static
187 bool
188 conf_callback(
189 void * context,
190 bool leaf,
191 const char * address,
192 char * child)
194 char path[JACK_CONF_MAX_ADDRESS_SIZE];
195 const char * component;
196 char * dst;
197 size_t len;
198 bool is_set;
199 struct jack_conf_container * parent_ptr;
200 struct jack_conf_container * container_ptr;
201 struct jack_conf_parameter * parameter_ptr;
203 parent_ptr = context_ptr->parent_ptr;
205 if (parent_ptr == NULL && strcmp(child, "drivers") == 0)
207 log_debug("ignoring drivers branch");
208 return true;
211 dst = path;
212 component = address;
213 while (*component != 0)
215 len = strlen(component);
216 memcpy(dst, component, len);
217 dst[len] = ':';
218 component += len + 1;
219 dst += len + 1;
222 strcpy(dst, child);
224 /* address always is same buffer as the one supplied through context pointer */
225 ASSERT(context_ptr->address == address);
226 dst = (char *)component;
228 len = strlen(child) + 1;
229 memcpy(dst, child, len);
230 dst[len] = 0;
232 if (leaf)
234 log_debug("%s (leaf)", path);
236 if (parent_ptr == NULL)
238 log_error("jack conf parameters can't appear in root container");
239 return false;
242 if (!parent_ptr->children_leafs)
244 if (!list_empty(&parent_ptr->children))
246 log_error("jack conf parameters cant be mixed with containers at same hierarchy level");
247 return false;
250 parent_ptr->children_leafs = true;
253 if (!jack_conf_parameter_create(&parameter_ptr, child))
255 log_error("jack_conf_parameter_create() failed");
256 return false;
259 if (!jack_proxy_get_parameter_value(context_ptr->address, &is_set, &parameter_ptr->parameter))
261 log_error("cannot get value of %s", path);
262 return false;
265 if (is_set)
267 #if 0
268 switch (parameter_ptr->parameter.type)
270 case jack_boolean:
271 log_info("%s value is %s (boolean)", path, parameter_ptr->parameter.value.boolean ? "true" : "false");
272 break;
273 case jack_string:
274 log_info("%s value is %s (string)", path, parameter_ptr->parameter.value.string);
275 break;
276 case jack_byte:
277 log_info("%s value is %u/%c (byte/char)", path, parameter_ptr->parameter.value.byte, (char)parameter_ptr->parameter.value.byte);
278 break;
279 case jack_uint32:
280 log_info("%s value is %u (uint32)", path, (unsigned int)parameter_ptr->parameter.value.uint32);
281 break;
282 case jack_int32:
283 log_info("%s value is %u (int32)", path, (signed int)parameter_ptr->parameter.value.int32);
284 break;
285 default:
286 log_error("unknown jack parameter_ptr->parameter type %d (%s)", (int)parameter_ptr->parameter.type, path);
287 jack_conf_parameter_destroy(parameter_ptr);
288 return false;
290 #endif
292 parameter_ptr->parent_ptr = parent_ptr;
293 memcpy(parameter_ptr->address, context_ptr->address, JACK_CONF_MAX_ADDRESS_SIZE);
294 list_add_tail(&parameter_ptr->siblings, &parent_ptr->children);
295 list_add_tail(&parameter_ptr->leaves, &g_studio.jack_params);
297 else
299 jack_conf_parameter_destroy(parameter_ptr);
302 else
304 log_debug("%s (container)", path);
306 if (parent_ptr != NULL && parent_ptr->children_leafs)
308 log_error("jack conf containers cant be mixed with parameters at same hierarchy level");
309 return false;
312 if (!jack_conf_container_create(&container_ptr, child))
314 log_error("jack_conf_container_create() failed");
315 return false;
318 container_ptr->parent_ptr = parent_ptr;
320 if (parent_ptr == NULL)
322 list_add_tail(&container_ptr->siblings, &g_studio.jack_conf);
324 else
326 list_add_tail(&container_ptr->siblings, &parent_ptr->children);
329 context_ptr->parent_ptr = container_ptr;
331 if (!jack_proxy_read_conf_container(context_ptr->address, context, conf_callback))
333 log_error("cannot read container %s", path);
334 return false;
337 context_ptr->parent_ptr = parent_ptr;
340 *dst = 0;
342 return true;
345 #undef context_ptr
347 void jack_conf_clear(void)
349 struct list_head * node_ptr;
351 INIT_LIST_HEAD(&g_studio.jack_params); /* we will destroy the leaves as part of tree destroy traversal */
352 while (!list_empty(&g_studio.jack_conf))
354 node_ptr = g_studio.jack_conf.next;
355 list_del(node_ptr);
356 jack_conf_container_destroy(list_entry(node_ptr, struct jack_conf_container, siblings));
359 g_studio.jack_conf_valid = false;
362 bool studio_fetch_jack_settings(void)
364 struct conf_callback_context context;
366 jack_conf_clear();
368 context.address[0] = 0;
369 context.container_ptr = &g_studio.jack_conf;
370 context.parent_ptr = NULL;
372 if (!jack_proxy_read_conf_container(context.address, &context, conf_callback))
374 log_error("jack_proxy_read_conf_container() failed.");
375 return false;
378 return true;