Merge branch 'stable' into 'main'
[ladish.git] / daemon / studio_jack_conf.c
blob3127af4b1083d3eef921658ebe31ba90bf9f3361
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2009, 2010 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 static
40 bool
41 ladish_studio_jack_conf_container_create(
42 struct jack_conf_container ** container_ptr_ptr,
43 const char * name)
45 struct jack_conf_container * container_ptr;
47 container_ptr = malloc(sizeof(struct jack_conf_container));
48 if (container_ptr == NULL)
50 log_error("malloc() failed to allocate struct jack_conf_container");
51 goto fail;
54 container_ptr->name = strdup(name);
55 if (container_ptr->name == NULL)
57 log_error("strdup() failed to duplicate \"%s\"", name);
58 goto fail_free;
61 INIT_LIST_HEAD(&container_ptr->children);
62 container_ptr->children_leafs = false;
64 *container_ptr_ptr = container_ptr;
65 return true;
67 fail_free:
68 free(container_ptr);
70 fail:
71 return false;
74 static
75 bool
76 ladish_studio_jack_conf_parameter_create(
77 struct jack_conf_parameter ** parameter_ptr_ptr,
78 const char * name)
80 struct jack_conf_parameter * parameter_ptr;
82 parameter_ptr = malloc(sizeof(struct jack_conf_parameter));
83 if (parameter_ptr == NULL)
85 log_error("malloc() failed to allocate struct jack_conf_parameter");
86 goto fail;
89 parameter_ptr->name = strdup(name);
90 if (parameter_ptr->name == NULL)
92 log_error("strdup() failed to duplicate \"%s\"", name);
93 goto fail_free;
96 *parameter_ptr_ptr = parameter_ptr;
97 return true;
99 fail_free:
100 free(parameter_ptr);
102 fail:
103 return false;
106 static
107 void
108 ladish_studio_jack_conf_parameter_destroy(
109 struct jack_conf_parameter * parameter_ptr)
111 #if 0
112 log_info("jack_conf_parameter destroy");
114 switch (parameter_ptr->parameter.type)
116 case jack_boolean:
117 log_info("%s value is %s (boolean)", parameter_ptr->name, parameter_ptr->parameter.value.boolean ? "true" : "false");
118 break;
119 case jack_string:
120 log_info("%s value is %s (string)", parameter_ptr->name, parameter_ptr->parameter.value.string);
121 break;
122 case jack_byte:
123 log_info("%s value is %u/%c (byte/char)", parameter_ptr->name, parameter_ptr->parameter.value.byte, (char)parameter_ptr->parameter.value.byte);
124 break;
125 case jack_uint32:
126 log_info("%s value is %u (uint32)", parameter_ptr->name, (unsigned int)parameter_ptr->parameter.value.uint32);
127 break;
128 case jack_int32:
129 log_info("%s value is %u (int32)", parameter_ptr->name, (signed int)parameter_ptr->parameter.value.int32);
130 break;
131 default:
132 log_error("unknown jack parameter_ptr->parameter type %d (%s)", (int)parameter_ptr->parameter.type, parameter_ptr->name);
133 break;
135 #endif
137 if (parameter_ptr->parameter.type == jack_string)
139 free(parameter_ptr->parameter.value.string);
142 free(parameter_ptr->name);
143 free(parameter_ptr);
146 static
147 void
148 ladish_studio_jack_conf_container_destroy(
149 struct jack_conf_container * container_ptr)
151 struct list_head * node_ptr;
153 //log_info("\"%s\" jack_conf_parameter destroy", container_ptr->name);
155 if (!container_ptr->children_leafs)
157 while (!list_empty(&container_ptr->children))
159 node_ptr = container_ptr->children.next;
160 list_del(node_ptr);
161 ladish_studio_jack_conf_container_destroy(list_entry(node_ptr, struct jack_conf_container, siblings));
164 else
166 while (!list_empty(&container_ptr->children))
168 node_ptr = container_ptr->children.next;
169 list_del(node_ptr);
170 ladish_studio_jack_conf_parameter_destroy(list_entry(node_ptr, struct jack_conf_parameter, siblings));
174 free(container_ptr->name);
175 free(container_ptr);
178 #define context_ptr ((struct conf_callback_context *)context)
180 static
181 bool
182 ladish_studio_jack_conf_callback(
183 void * context,
184 bool leaf,
185 const char * address,
186 char * child)
188 char path[JACK_CONF_MAX_ADDRESS_SIZE];
189 const char * component;
190 char * dst;
191 size_t len;
192 bool is_set;
193 struct jack_conf_container * parent_ptr;
194 struct jack_conf_container * container_ptr;
195 struct jack_conf_parameter * parameter_ptr;
197 parent_ptr = context_ptr->parent_ptr;
199 if (parent_ptr == NULL && strcmp(child, "drivers") == 0)
201 log_debug("ignoring drivers branch");
202 return true;
205 dst = path;
206 component = address;
207 while (*component != 0)
209 len = strlen(component);
210 memcpy(dst, component, len);
211 dst[len] = ':';
212 component += len + 1;
213 dst += len + 1;
216 strcpy(dst, child);
218 /* address always is same buffer as the one supplied through context pointer */
219 ASSERT(context_ptr->address == address);
220 dst = (char *)component;
222 len = strlen(child) + 1;
223 memcpy(dst, child, len);
224 dst[len] = 0;
226 if (leaf)
228 log_debug("%s (leaf)", path);
230 if (parent_ptr == NULL)
232 log_error("jack conf parameters can't appear in root container");
233 return false;
236 if (!parent_ptr->children_leafs)
238 if (!list_empty(&parent_ptr->children))
240 log_error("jack conf parameters cant be mixed with containers at same hierarchy level");
241 return false;
244 parent_ptr->children_leafs = true;
247 if (!ladish_studio_jack_conf_parameter_create(&parameter_ptr, child))
249 log_error("jack_conf_parameter_create() failed");
250 return false;
253 if (!jack_proxy_get_parameter_value(context_ptr->address, &is_set, &parameter_ptr->parameter))
255 log_error("cannot get value of %s", path);
256 return false;
259 if (is_set)
261 #if 0
262 switch (parameter_ptr->parameter.type)
264 case jack_boolean:
265 log_info("%s value is %s (boolean)", path, parameter_ptr->parameter.value.boolean ? "true" : "false");
266 break;
267 case jack_string:
268 log_info("%s value is %s (string)", path, parameter_ptr->parameter.value.string);
269 break;
270 case jack_byte:
271 log_info("%s value is %u/%c (byte/char)", path, parameter_ptr->parameter.value.byte, (char)parameter_ptr->parameter.value.byte);
272 break;
273 case jack_uint32:
274 log_info("%s value is %u (uint32)", path, (unsigned int)parameter_ptr->parameter.value.uint32);
275 break;
276 case jack_int32:
277 log_info("%s value is %u (int32)", path, (signed int)parameter_ptr->parameter.value.int32);
278 break;
279 default:
280 log_error("unknown jack parameter_ptr->parameter type %d (%s)", (int)parameter_ptr->parameter.type, path);
281 jack_conf_parameter_destroy(parameter_ptr);
282 return false;
284 #endif
286 parameter_ptr->parent_ptr = parent_ptr;
287 memcpy(parameter_ptr->address, context_ptr->address, JACK_CONF_MAX_ADDRESS_SIZE);
288 list_add_tail(&parameter_ptr->siblings, &parent_ptr->children);
289 list_add_tail(&parameter_ptr->leaves, &g_studio.jack_params);
291 else
293 ladish_studio_jack_conf_parameter_destroy(parameter_ptr);
296 else
298 log_debug("%s (container)", path);
300 if (parent_ptr != NULL && parent_ptr->children_leafs)
302 log_error("jack conf containers cant be mixed with parameters at same hierarchy level");
303 return false;
306 if (!ladish_studio_jack_conf_container_create(&container_ptr, child))
308 log_error("jack_conf_container_create() failed");
309 return false;
312 container_ptr->parent_ptr = parent_ptr;
314 if (parent_ptr == NULL)
316 list_add_tail(&container_ptr->siblings, &g_studio.jack_conf);
318 else
320 list_add_tail(&container_ptr->siblings, &parent_ptr->children);
323 context_ptr->parent_ptr = container_ptr;
325 if (!jack_proxy_read_conf_container(context_ptr->address, context, ladish_studio_jack_conf_callback))
327 log_error("cannot read container %s", path);
328 return false;
331 context_ptr->parent_ptr = parent_ptr;
334 *dst = 0;
336 return true;
339 #undef context_ptr
341 void ladish_studio_jack_conf_clear(void)
343 struct list_head * node_ptr;
345 INIT_LIST_HEAD(&g_studio.jack_params); /* we will destroy the leaves as part of tree destroy traversal */
346 while (!list_empty(&g_studio.jack_conf))
348 node_ptr = g_studio.jack_conf.next;
349 list_del(node_ptr);
350 ladish_studio_jack_conf_container_destroy(list_entry(node_ptr, struct jack_conf_container, siblings));
353 g_studio.jack_conf_valid = false;
356 bool ladish_studio_fetch_jack_settings(void)
358 struct conf_callback_context context;
360 ladish_studio_jack_conf_clear();
362 context.address[0] = 0;
363 context.container_ptr = &g_studio.jack_conf;
364 context.parent_ptr = NULL;
366 if (!jack_proxy_read_conf_container(context.address, &context, ladish_studio_jack_conf_callback))
368 log_error("jack_proxy_read_conf_container() failed.");
369 return false;
372 return true;