1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2009,2010,2011,2012 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains implementation for the load helper functions
9 **************************************************************************
11 * LADI Session Handler is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * LADI Session Handler is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
23 * or write to the Free Software Foundation, Inc.,
24 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include "../proxies/jmcore_proxy.h"
32 void ladish_dump_element_stack(struct ladish_parse_context
* context_ptr
)
37 log_info("depth=%d", context_ptr
->depth
);
39 for (depth
= context_ptr
->depth
; depth
>= 0; depth
--)
41 switch (context_ptr
->element
[depth
])
43 case PARSE_CONTEXT_ROOT
:
46 case PARSE_CONTEXT_STUDIO
:
49 case PARSE_CONTEXT_JACK
:
52 case PARSE_CONTEXT_CONF
:
55 case PARSE_CONTEXT_PARAMETER
:
58 case PARSE_CONTEXT_CLIENTS
:
61 case PARSE_CONTEXT_CLIENT
:
64 case PARSE_CONTEXT_PORTS
:
67 case PARSE_CONTEXT_PORT
:
70 case PARSE_CONTEXT_DICT
:
73 case PARSE_CONTEXT_KEY
:
76 case PARSE_CONTEXT_CONNECTIONS
:
77 descr
= "connections";
79 case PARSE_CONTEXT_CONNECTION
:
82 case PARSE_CONTEXT_APPLICATIONS
:
83 descr
= "applications";
85 case PARSE_CONTEXT_APPLICATION
:
86 descr
= "application";
88 case PARSE_CONTEXT_ROOMS
:
91 case PARSE_CONTEXT_ROOM
:
94 case PARSE_CONTEXT_PROJECT
:
101 log_info("%d - %u (%s)", depth
, context_ptr
->element
[depth
], descr
);
105 static const char * get_string_attribute_internal(const char * const * attr
, const char * key
, bool optional
)
107 while (attr
[0] != NULL
)
109 ASSERT(attr
[1] != NULL
);
110 if (strcmp(attr
[0], key
) == 0)
119 log_error("attribute \"%s\" is missing", key
);
125 const char * ladish_get_string_attribute(const char * const * attr
, const char * key
)
127 return get_string_attribute_internal(attr
, key
, false);
130 const char * ladish_get_uuid_attribute(const char * const * attr
, const char * key
, uuid_t uuid
, bool optional
)
134 value
= get_string_attribute_internal(attr
, key
, optional
);
140 if (uuid_parse(value
, uuid
) != 0)
142 log_error("cannot parse uuid \"%s\"", value
);
149 const char * ladish_get_bool_attribute(const char * const * attr
, const char * key
, bool * bool_value_ptr
)
151 const char * value_str
;
153 value_str
= ladish_get_string_attribute(attr
, key
);
154 if (value_str
== NULL
)
159 if (strcmp(value_str
, "true") == 0)
161 *bool_value_ptr
= true;
165 if (strcmp(value_str
, "false") == 0)
167 *bool_value_ptr
= false;
171 log_error("boolean XML attribute has value of \"%s\" but only \"true\" and \"false\" are valid", value_str
);
175 const char * ladish_get_byte_attribute(const char * const * attr
, const char * key
, uint8_t * byte_value_ptr
)
177 const char * value_str
;
181 value_str
= ladish_get_string_attribute(attr
, key
);
182 if (value_str
== NULL
)
187 errno
= 0; /* To distinguish success/failure after call */
188 li_value
= strtol(value_str
, &end_ptr
, 10);
189 if ((errno
== ERANGE
&& (li_value
== LONG_MAX
|| li_value
== LONG_MIN
)) || (errno
!= 0 && li_value
== 0) || end_ptr
== value_str
)
191 log_error("value '%s' of attribute '%s' is not valid integer.", value_str
, key
);
195 if (li_value
< 0 || li_value
> 255)
197 log_error("value '%s' of attribute '%s' is not valid uint8.", value_str
, key
);
201 *byte_value_ptr
= (uint8_t)li_value
;
206 ladish_get_name_and_uuid_attributes(
207 const char * element_description
,
208 const char * const * attr
,
209 const char ** name_str_ptr
,
210 const char ** uuid_str_ptr
,
213 const char * name_str
;
214 const char * uuid_str
;
216 name_str
= ladish_get_string_attribute(attr
, "name");
217 if (name_str
== NULL
)
219 log_error("%s \"name\" attribute is not available", element_description
);
223 uuid_str
= ladish_get_uuid_attribute(attr
, "uuid", uuid
, false);
224 if (uuid_str
== NULL
)
226 log_error("%s \"uuid\" attribute is not available. name=\"%s\"", element_description
, name_str
);
230 *name_str_ptr
= name_str
;
231 *uuid_str_ptr
= uuid_str
;
236 ladish_parse_port_type_and_direction_attributes(
237 const char * element_description
,
238 const char * const * attr
,
240 uint32_t * flags_ptr
)
242 const char * type_str
;
243 const char * direction_str
;
245 type_str
= ladish_get_string_attribute(attr
, "type");
246 if (type_str
== NULL
)
248 log_error("%s \"type\" attribute is not available", element_description
);
252 direction_str
= ladish_get_string_attribute(attr
, "direction");
253 if (direction_str
== NULL
)
255 log_error("%s \"direction\" attribute is not available", element_description
);
259 if (strcmp(type_str
, "midi") == 0)
261 *type_ptr
= JACKDBUS_PORT_TYPE_MIDI
;
263 else if (strcmp(type_str
, "audio") == 0)
265 *type_ptr
= JACKDBUS_PORT_TYPE_AUDIO
;
269 log_error("%s \"type\" attribute contains unknown value \"%s\"", element_description
, type_str
);
273 if (strcmp(direction_str
, "playback") == 0)
276 JACKDBUS_PORT_SET_INPUT(*flags_ptr
);
278 else if (strcmp(direction_str
, "capture") == 0)
281 JACKDBUS_PORT_SET_OUTPUT(*flags_ptr
);
285 log_error("%s \"direction\" attribute contains unknown value \"%s\"", element_description
, direction_str
);
292 struct interlink_context
294 ladish_graph_handle vgraph
;
295 ladish_app_supervisor_handle app_supervisor
;
298 #define ctx_ptr ((struct interlink_context *)context)
304 ladish_graph_handle
UNUSED(graph_handle
),
306 ladish_client_handle jclient
,
308 void ** UNUSED(client_iteration_context_ptr_ptr
))
311 uuid_t vclient_app_uuid
;
313 ladish_client_handle vclient
;
315 ladish_app_handle app
;
318 ladish_graph_handle vgraph
;
320 ASSERT(ctx_ptr
->vgraph
!= NULL
);
321 vgraph
= ladish_client_get_vgraph(jclient
);
322 if (vgraph
!= NULL
&& ctx_ptr
->vgraph
!= vgraph
)
324 /* skip clients of different vgraphs */
328 if (strcmp(name
, "system") == 0)
333 interlinked
= ladish_client_get_interlink(jclient
, vclient_uuid
);
335 if (ladish_client_has_app(jclient
))
337 ASSERT(interlinked
); /* jclient has app associated but is not interlinked */
340 else if (interlinked
)
342 /* jclient has no app associated but is interlinked */
343 /* this can happen if there is an external app (presumably in a different vgraph) */
344 ASSERT_NO_PASS
; /* if vgraph is different, then we should have skipped the client earlier */
347 ASSERT(!interlinked
);
349 /* XXX: why this is is here is a mystery. interlink is supposed to be called just after load so pid will always be 0 */
350 pid
= ladish_client_get_pid(jclient
);
351 jmcore
= pid
!= 0 && pid
== jmcore_proxy_get_pid_cached();
357 if (ladish_virtualizer_is_a2j_client(jclient
))
362 app
= ladish_app_supervisor_find_app_by_name(ctx_ptr
->app_supervisor
, name
);
365 log_info("JACK client \"%s\" not found in app supervisor", name
);
369 vclient
= ladish_graph_find_client_by_name(ctx_ptr
->vgraph
, name
, false);
372 log_error("JACK client '%s' has no vclient associated", name
);
376 log_info("Interlinking clients of app '%s'", name
);
377 ladish_client_interlink(jclient
, vclient
);
379 ladish_app_get_uuid(app
, app_uuid
);
380 if (ladish_client_get_app(vclient
, vclient_app_uuid
))
382 if (uuid_compare(app_uuid
, vclient_app_uuid
) != 0)
384 log_error("vclient of app '%s' already has a different app uuid", name
);
389 log_info("associating vclient with app '%s'", name
);
390 ladish_client_set_app(vclient
, app_uuid
);
393 ladish_client_set_app(jclient
, app_uuid
);
394 ladish_client_set_vgraph(jclient
, ctx_ptr
->vgraph
);
401 void * UNUSED(context
),
402 ladish_graph_handle
UNUSED(graph_handle
),
404 void * UNUSED(client_iteration_context_ptr
),
405 ladish_client_handle client_handle
,
406 const char * UNUSED(client_name
),
407 ladish_port_handle port_handle
,
408 const char * UNUSED(port_name
),
409 uint32_t UNUSED(port_type
),
410 uint32_t UNUSED(port_flags
))
414 if (ladish_client_get_app(client_handle
, app_uuid
))
416 ladish_port_set_app(port_handle
, app_uuid
);
422 void ladish_interlink(ladish_graph_handle vgraph
, ladish_app_supervisor_handle app_supervisor
)
424 struct interlink_context ctx
;
427 ctx
.app_supervisor
= app_supervisor
;
429 ladish_graph_iterate_nodes(ladish_studio_get_jack_graph(), &ctx
, interlink_client
, NULL
, NULL
);
430 ladish_graph_iterate_nodes(vgraph
, &ctx
, NULL
, interlink_port
, NULL
);