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 of the "load studio" command
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.
29 #include <sys/types.h>
36 #include "studio_internal.h"
37 #include "../proxies/notify_proxy.h"
40 #define context_ptr ((struct ladish_parse_context *)data)
42 static void callback_chrdata(void * data
, const XML_Char
* s
, int len
)
44 if (context_ptr
->error
)
49 if (context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_PARAMETER
||
50 context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_KEY
||
51 context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_APPLICATION
)
53 if ((size_t)(context_ptr
->data_used
+ len
) >= sizeof(context_ptr
->data
))
55 log_error("xml parse max char data length reached");
56 context_ptr
->error
= XML_TRUE
;
60 memcpy(context_ptr
->data
+ context_ptr
->data_used
, s
, len
);
61 context_ptr
->data_used
+= len
;
65 static void callback_elstart(void * data
, const char * el
, const char ** attr
)
71 const char * uuid_str
;
73 const char * uuid2_str
;
75 ladish_port_handle port1
;
76 ladish_port_handle port2
;
83 if (context_ptr
->error
)
88 if (context_ptr
->depth
+ 1 >= MAX_STACK_DEPTH
)
90 log_error("xml parse max stack depth reached");
91 context_ptr
->error
= XML_TRUE
;
95 if (strcmp(el
, "studio") == 0)
97 //log_info("<studio>");
98 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_STUDIO
;
102 if (strcmp(el
, "jack") == 0)
104 //log_info("<jack>");
105 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_JACK
;
109 if (strcmp(el
, "conf") == 0)
111 //log_info("<conf>");
112 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_CONF
;
116 if (strcmp(el
, "parameter") == 0)
118 //log_info("<parameter>");
119 path
= ladish_get_string_attribute(attr
, "path");
122 log_error("<parameter> XML element without \"path\" attribute");
123 context_ptr
->error
= XML_TRUE
;
127 context_ptr
->str
= strdup(path
);
128 if (context_ptr
->str
== NULL
)
130 log_error("strdup() failed");
131 context_ptr
->error
= XML_TRUE
;
135 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_PARAMETER
;
136 context_ptr
->data_used
= 0;
140 if (strcmp(el
, "clients") == 0)
142 //log_info("<clients>");
143 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_CLIENTS
;
147 if (strcmp(el
, "rooms") == 0)
149 //log_info("<rooms>");
150 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_ROOMS
;
154 if (strcmp(el
, "room") == 0)
156 //log_info("<room>");
157 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_ROOM
;
159 if (context_ptr
->room
!= NULL
)
161 log_error("nested rooms");
162 context_ptr
->error
= XML_TRUE
;
166 if (context_ptr
->depth
== 2 &&
167 context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
&&
168 context_ptr
->element
[1] == PARSE_CONTEXT_ROOMS
)
170 if (!ladish_get_name_and_uuid_attributes("/studio/rooms/room", attr
, &name
, &uuid_str
, uuid
))
172 context_ptr
->error
= XML_TRUE
;
176 if (!ladish_room_create(uuid
, name
, NULL
, g_studio
.studio_graph
, &context_ptr
->room
))
178 log_error("ladish_room_create() failed.");
179 context_ptr
->error
= XML_TRUE
;
180 ASSERT(context_ptr
->room
== NULL
);
187 log_error("ignoring <room> element in wrong context");
191 if (strcmp(el
, "client") == 0)
193 //log_info("<client>");
194 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_CLIENT
;
196 if (context_ptr
->client
!= NULL
)
198 log_error("nested clients");
199 context_ptr
->error
= XML_TRUE
;
203 if (context_ptr
->depth
== 3 &&
204 context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
&&
205 context_ptr
->element
[1] == PARSE_CONTEXT_JACK
&&
206 context_ptr
->element
[2] == PARSE_CONTEXT_CLIENTS
)
208 if (!ladish_get_name_and_uuid_attributes("/studio/jack/clients/client", attr
, &name
, &uuid_str
, uuid
))
210 context_ptr
->error
= XML_TRUE
;
214 name_dup
= unescape_dup(name
);
215 if (name_dup
== NULL
)
217 log_error("allocation of memory for unescaped name buffer failed. name = '%s'", name
);
218 context_ptr
->error
= XML_TRUE
;
222 log_info("jack client \"%s\" with uuid %s", name_dup
, uuid_str
);
224 if (!ladish_client_create(uuid
, &context_ptr
->client
))
226 log_error("ladish_client_create() failed.");
227 context_ptr
->error
= XML_TRUE
;
228 ASSERT(context_ptr
->client
== NULL
);
232 if (!ladish_graph_add_client(g_studio
.jack_graph
, context_ptr
->client
, name_dup
, true))
234 log_error("ladish_graph_add_client() failed to add client '%s' to JACK graph", name_dup
);
235 context_ptr
->error
= XML_TRUE
;
236 ladish_client_destroy(context_ptr
->client
);
237 context_ptr
->client
= NULL
;
241 else if (context_ptr
->depth
== 2 &&
242 context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
&&
243 context_ptr
->element
[1] == PARSE_CONTEXT_CLIENTS
)
245 if (!ladish_get_name_and_uuid_attributes("/studio/clients/client", attr
, &name
, &uuid_str
, uuid
))
247 context_ptr
->error
= XML_TRUE
;
251 name_dup
= unescape_dup(name
);
252 if (name_dup
== NULL
)
254 log_error("allocation of memory for unescaped name buffer failed. name = '%s'", name
);
255 context_ptr
->error
= XML_TRUE
;
259 log_info("studio client \"%s\" with uuid %s", name_dup
, uuid_str
);
261 context_ptr
->client
= ladish_graph_find_client_by_uuid(g_studio
.studio_graph
, uuid
);
262 if (context_ptr
->client
!= NULL
)
264 log_info("Found existing client");
268 if (!ladish_client_create(uuid
, &context_ptr
->client
))
270 log_error("ladish_client_create() failed.");
271 context_ptr
->error
= XML_TRUE
;
272 ASSERT(context_ptr
->client
== NULL
);
276 if (ladish_get_uuid_attribute(attr
, "app", context_ptr
->uuid
, true))
278 ladish_client_set_app(context_ptr
->client
, context_ptr
->uuid
);
281 if (!ladish_graph_add_client(g_studio
.studio_graph
, context_ptr
->client
, name_dup
, true))
283 log_error("ladish_graph_add_client() failed to add client '%s' to studio graph", name_dup
);
284 context_ptr
->error
= XML_TRUE
;
285 ladish_client_destroy(context_ptr
->client
);
286 context_ptr
->client
= NULL
;
294 if (strcmp(el
, "ports") == 0)
296 //log_info("<ports>");
297 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_PORTS
;
301 if (strcmp(el
, "port") == 0)
303 //log_info("<port>");
304 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_PORT
;
306 if (context_ptr
->port
!= NULL
)
308 log_error("nested ports");
309 context_ptr
->error
= XML_TRUE
;
313 if (context_ptr
->depth
>= 3 &&
314 context_ptr
->element
[context_ptr
->depth
- 3] == PARSE_CONTEXT_CLIENTS
&&
315 context_ptr
->element
[context_ptr
->depth
- 2] == PARSE_CONTEXT_CLIENT
&&
316 context_ptr
->element
[context_ptr
->depth
- 1] == PARSE_CONTEXT_PORTS
)
318 //log_info("client port");
319 if (context_ptr
->client
== NULL
)
321 log_error("client-less port");
322 context_ptr
->error
= XML_TRUE
;
326 if (context_ptr
->depth
== 5 && context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
&& context_ptr
->element
[1] == PARSE_CONTEXT_JACK
)
328 if (!ladish_get_name_and_uuid_attributes("/studio/jack/clients/client/ports/port", attr
, &name
, &uuid_str
, uuid
))
330 context_ptr
->error
= XML_TRUE
;
334 name_dup
= unescape_dup(name
);
335 if (name_dup
== NULL
)
337 log_error("allocation of memory for unescaped name buffer failed. name = '%s'", name
);
338 context_ptr
->error
= XML_TRUE
;
342 log_info("jack port \"%s\" with uuid %s", name_dup
, uuid_str
);
344 if (!ladish_port_create(uuid
, false, &context_ptr
->port
))
346 log_error("ladish_port_create() failed.");
350 ladish_port_set_vgraph(context_ptr
->port
, g_studio
.studio_graph
);
352 if (!ladish_graph_add_port(g_studio
.jack_graph
, context_ptr
->client
, context_ptr
->port
, name_dup
, 0, 0, true))
354 log_error("ladish_graph_add_port() failed.");
355 ladish_port_destroy(context_ptr
->port
);
356 context_ptr
->port
= NULL
;
361 else if (context_ptr
->depth
== 4 && context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
)
363 if (!ladish_get_name_and_uuid_attributes("/studio/clients/client/ports/port", attr
, &name
, &uuid_str
, uuid
))
365 context_ptr
->error
= XML_TRUE
;
369 name_dup
= unescape_dup(name
);
370 if (name_dup
== NULL
)
372 log_error("allocation of memory for unescaped name buffer failed. name = '%s'", name
);
373 context_ptr
->error
= XML_TRUE
;
377 uuid2_str
= ladish_get_uuid_attribute(attr
, "link_uuid", uuid2
, true);
379 log_info("studio port \"%s\" with uuid %s (%s)", name_dup
, uuid_str
, uuid2_str
== NULL
? "normal" : "room link");
381 if (uuid2_str
== NULL
)
382 { /* normal studio port */
383 context_ptr
->port
= ladish_graph_find_port_by_uuid(g_studio
.jack_graph
, uuid
, false, g_studio
.studio_graph
);
384 if (context_ptr
->port
== NULL
)
386 log_error("studio client with non-jack port %s", uuid_str
);
387 context_ptr
->error
= XML_TRUE
;
391 if (!ladish_graph_add_port(g_studio
.studio_graph
, context_ptr
->client
, context_ptr
->port
, name_dup
, 0, 0, true))
393 log_error("ladish_graph_add_port() failed.");
394 ladish_port_destroy(context_ptr
->port
);
395 context_ptr
->port
= NULL
;
403 context_ptr
->port
= ladish_graph_find_client_port_by_uuid(g_studio
.studio_graph
, context_ptr
->client
, uuid2
, false);
404 if (context_ptr
->port
== NULL
)
406 log_error("room link port not found");
407 context_ptr
->error
= XML_TRUE
;
411 ladish_graph_set_link_port_override_uuid(g_studio
.studio_graph
, context_ptr
->port
, uuid
);
415 else if (context_ptr
->depth
== 3 &&
416 context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
&&
417 context_ptr
->element
[1] == PARSE_CONTEXT_ROOMS
&&
418 context_ptr
->element
[2] == PARSE_CONTEXT_ROOM
)
420 ASSERT(context_ptr
->room
!= NULL
);
421 //log_info("room port");
423 if (!ladish_get_name_and_uuid_attributes("/studio/rooms/room/port", attr
, &name
, &uuid_str
, uuid
))
425 context_ptr
->error
= XML_TRUE
;
429 name_dup
= unescape_dup(name
);
430 if (name_dup
== NULL
)
432 log_error("allocation of memory for unescaped name buffer failed. name = '%s'", name
);
433 context_ptr
->error
= XML_TRUE
;
437 log_info("room port \"%s\" with uuid %s", name_dup
, uuid_str
);
439 if (!ladish_parse_port_type_and_direction_attributes("/studio/rooms/room/port", attr
, &port_type
, &port_flags
))
441 context_ptr
->error
= XML_TRUE
;
445 context_ptr
->port
= ladish_room_add_port(context_ptr
->room
, uuid
, name_dup
, port_type
, port_flags
);
446 if (context_ptr
->port
== NULL
)
448 log_error("ladish_room_add_port() failed.");
449 context_ptr
->port
= NULL
;
455 log_error("port element in wrong place");
456 ladish_dump_element_stack(context_ptr
);
457 context_ptr
->error
= XML_TRUE
;
461 if (strcmp(el
, "connections") == 0)
463 //log_info("<connections>");
464 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_CONNECTIONS
;
468 if (strcmp(el
, "connection") == 0)
470 //log_info("<connection>");
471 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_CONNECTION
;
473 uuid_str
= ladish_get_uuid_attribute(attr
, "port1", uuid
, false);
474 if (uuid_str
== NULL
)
476 log_error("/studio/connections/connection \"port1\" attribute is not available.");
477 context_ptr
->error
= XML_TRUE
;
481 uuid2_str
= ladish_get_uuid_attribute(attr
, "port2", uuid2
, false);
482 if (uuid2_str
== NULL
)
484 log_error("/studio/connections/connection \"port2\" attribute is not available.");
485 context_ptr
->error
= XML_TRUE
;
489 log_info("studio connection between port %s and port %s", uuid_str
, uuid2_str
);
491 port1
= ladish_graph_find_port_by_uuid(g_studio
.studio_graph
, uuid
, true, NULL
);
494 log_error("studio client with unknown port %s", uuid_str
);
495 context_ptr
->error
= XML_TRUE
;
499 port2
= ladish_graph_find_port_by_uuid(g_studio
.studio_graph
, uuid2
, true, NULL
);
502 log_error("studio client with unknown port %s", uuid2_str
);
503 context_ptr
->error
= XML_TRUE
;
507 context_ptr
->connection_id
= ladish_graph_add_connection(g_studio
.studio_graph
, port1
, port2
, true);
508 if (context_ptr
->connection_id
== 0)
510 log_error("ladish_graph_add_connection() failed.");
517 if (strcmp(el
, "applications") == 0)
519 //log_info("<applications>");
520 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_APPLICATIONS
;
524 if (strcmp(el
, "application") == 0)
526 //log_info("<application>");
527 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_APPLICATION
;
529 name
= ladish_get_string_attribute(attr
, "name");
532 log_error("application \"name\" attribute is not available.");
533 context_ptr
->error
= XML_TRUE
;
537 if (!ladish_get_uuid_attribute(attr
, "uuid", context_ptr
->uuid
, true))
539 uuid_clear(context_ptr
->uuid
);
542 if (ladish_get_bool_attribute(attr
, "terminal", &context_ptr
->terminal
) == NULL
)
544 log_error("application \"terminal\" attribute is not available. name=\"%s\"", name
);
545 context_ptr
->error
= XML_TRUE
;
549 if (ladish_get_bool_attribute(attr
, "autorun", &context_ptr
->autorun
) == NULL
)
551 log_error("application \"autorun\" attribute is not available. name=\"%s\"", name
);
552 context_ptr
->error
= XML_TRUE
;
556 level
= ladish_get_string_attribute(attr
, "level");
559 log_error("application \"level\" attribute is not available. name=\"%s\"", name
);
560 context_ptr
->error
= XML_TRUE
;
564 if (!ladish_check_app_level_validity(level
, &len
))
566 log_error("application \"level\" attribute has invalid value \"%s\", name=\"%s\"", level
, name
);
567 context_ptr
->error
= XML_TRUE
;
571 memcpy(context_ptr
->level
, level
, len
+ 1);
573 context_ptr
->str
= strdup(name
);
574 if (context_ptr
->str
== NULL
)
576 log_error("strdup() failed");
577 context_ptr
->error
= XML_TRUE
;
581 context_ptr
->data_used
= 0;
585 if (strcmp(el
, "dict") == 0)
587 //log_info("<dict>");
588 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_DICT
;
590 if (context_ptr
->dict
!= NULL
)
592 log_error("nested dicts");
593 context_ptr
->error
= XML_TRUE
;
597 if (context_ptr
->depth
== 1 &&
598 context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
)
600 context_ptr
->dict
= ladish_graph_get_dict(g_studio
.studio_graph
);
601 ASSERT(context_ptr
->dict
!= NULL
);
603 else if (context_ptr
->depth
> 0 &&
604 context_ptr
->element
[context_ptr
->depth
- 1] == PARSE_CONTEXT_CLIENT
)
606 ASSERT(context_ptr
->client
!= NULL
);
607 context_ptr
->dict
= ladish_client_get_dict(context_ptr
->client
);
608 ASSERT(context_ptr
->dict
!= NULL
);
610 else if (context_ptr
->depth
> 0 &&
611 context_ptr
->element
[context_ptr
->depth
- 1] == PARSE_CONTEXT_PORT
)
613 ASSERT(context_ptr
->port
!= NULL
);
614 context_ptr
->dict
= ladish_port_get_dict(context_ptr
->port
);
615 ASSERT(context_ptr
->dict
!= NULL
);
617 else if (context_ptr
->depth
> 0 &&
618 context_ptr
->element
[context_ptr
->depth
- 1] == PARSE_CONTEXT_CONNECTION
)
620 ASSERT(context_ptr
->port
!= NULL
);
621 context_ptr
->dict
= ladish_graph_get_connection_dict(g_studio
.studio_graph
, context_ptr
->connection_id
);
622 ASSERT(context_ptr
->dict
!= NULL
);
626 log_error("unexpected dict XML element");
627 context_ptr
->error
= XML_TRUE
;
634 if (strcmp(el
, "key") == 0)
637 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_KEY
;
639 if (context_ptr
->dict
== NULL
)
641 log_error("dict-less key");
642 context_ptr
->error
= XML_TRUE
;
646 name
= ladish_get_string_attribute(attr
, "name");
649 log_error("dict/key \"name\" attribute is not available.");
650 context_ptr
->error
= XML_TRUE
;
654 context_ptr
->str
= strdup(name
);
655 if (context_ptr
->str
== NULL
)
657 log_error("strdup() failed");
658 context_ptr
->error
= XML_TRUE
;
662 context_ptr
->data_used
= 0;
667 log_error("unknown element \"%s\"", el
);
668 context_ptr
->error
= XML_TRUE
;
675 static void callback_elend(void * data
, const char * UNUSED(el
))
683 struct jack_parameter_variant parameter
;
686 if (context_ptr
->error
)
691 //log_info("element end (depth = %d, element = %u)", context_ptr->depth, context_ptr->element[context_ptr->depth]);
693 if (context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_PARAMETER
&&
694 context_ptr
->depth
== 3 &&
695 context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
&&
696 context_ptr
->element
[1] == PARSE_CONTEXT_JACK
&&
697 context_ptr
->element
[2] == PARSE_CONTEXT_CONF
)
699 context_ptr
->data
[context_ptr
->data_used
] = 0;
701 //log_info("'%s' with value '%s'", context_ptr->str, context_ptr->data);
703 dst
= address
= strdup(context_ptr
->str
);
704 src
= context_ptr
->str
+ 1;
707 sep
= strchr(src
, '/');
710 src_len
= strlen(src
);
717 dst_len
= unescape(src
, src_len
, dst
);
722 ASSERT(*src
== '/' || *src
== 0);
726 src
++; /* skip separator */
733 *dst
= 0; /* ASCIZZ */
735 if (!jack_proxy_get_parameter_value(address
, &is_set
, ¶meter
))
737 log_error("jack_proxy_get_parameter_value() failed");
738 goto fail_free_address
;
741 if (parameter
.type
== jack_string
)
743 free(parameter
.value
.string
);
746 switch (parameter
.type
)
749 log_info("%s value is %s (boolean)", context_ptr
->str
, context_ptr
->data
);
750 if (strcmp(context_ptr
->data
, "true") == 0)
752 parameter
.value
.boolean
= true;
754 else if (strcmp(context_ptr
->data
, "false") == 0)
756 parameter
.value
.boolean
= false;
760 log_error("bad value for a bool jack param");
761 goto fail_free_address
;
765 log_info("%s value is %s (string)", context_ptr
->str
, context_ptr
->data
);
766 parameter
.value
.string
= context_ptr
->data
;
769 log_debug("%s value is %u/%c (byte/char)", context_ptr
->str
, *context_ptr
->data
, *context_ptr
->data
);
770 if (context_ptr
->data
[0] == 0 ||
771 context_ptr
->data
[1] != 0)
773 log_error("bad value for a char jack param");
774 goto fail_free_address
;
776 parameter
.value
.byte
= context_ptr
->data
[0];
779 log_info("%s value is %s (uint32)", context_ptr
->str
, context_ptr
->data
);
780 if (sscanf(context_ptr
->data
, "%" PRIu32
, ¶meter
.value
.uint32
) != 1)
782 log_error("bad value for an uint32 jack param");
783 goto fail_free_address
;
787 log_info("%s value is %s (int32)", context_ptr
->str
, context_ptr
->data
);
788 if (sscanf(context_ptr
->data
, "%" PRIi32
, ¶meter
.value
.int32
) != 1)
790 log_error("bad value for an int32 jack param");
791 goto fail_free_address
;
795 log_error("unknown jack parameter type %d of %s", (int)parameter
.type
, context_ptr
->str
);
796 goto fail_free_address
;
799 if (!jack_proxy_set_parameter_value(address
, ¶meter
))
801 log_error("jack_proxy_set_parameter_value() failed");
802 goto fail_free_address
;
807 else if (context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_KEY
&&
808 context_ptr
->depth
> 0 &&
809 context_ptr
->element
[context_ptr
->depth
- 1] == PARSE_CONTEXT_DICT
)
811 ASSERT(context_ptr
->dict
!= NULL
);
812 context_ptr
->data
[context_ptr
->data_used
] = 0;
813 log_info("dict key '%s' with value '%s'", context_ptr
->str
, context_ptr
->data
);
814 if (!ladish_dict_set(context_ptr
->dict
, context_ptr
->str
, context_ptr
->data
))
816 log_error("ladish_dict_set() failed");
817 context_ptr
->error
= XML_TRUE
;
821 else if (context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_ROOM
)
823 //log_info("</room>");
824 ASSERT(context_ptr
->room
!= NULL
);
825 context_ptr
->room
= NULL
;
827 else if (context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_DICT
)
829 //log_info("</dict>");
830 ASSERT(context_ptr
->dict
!= NULL
);
831 context_ptr
->dict
= NULL
;
833 else if (context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_CLIENT
)
835 //log_info("</client>");
836 ASSERT(context_ptr
->client
!= NULL
);
837 context_ptr
->client
= NULL
;
839 else if (context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_PORT
)
841 //log_info("</port>");
842 ASSERT(context_ptr
->port
!= NULL
);
843 context_ptr
->port
= NULL
;
845 else if (context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_APPLICATION
)
847 context_ptr
->data
[unescape(context_ptr
->data
, context_ptr
->data_used
, context_ptr
->data
)] = 0;
848 unescape_simple(context_ptr
->str
);
850 log_info("application '%s' (%s, %s, level '%s') with commandline '%s'", context_ptr
->str
, context_ptr
->terminal
? "terminal" : "shell", context_ptr
->autorun
? "autorun" : "stopped", context_ptr
->level
, context_ptr
->data
);
852 if (ladish_app_supervisor_add(
853 g_studio
.app_supervisor
,
856 context_ptr
->autorun
,
858 context_ptr
->terminal
,
859 context_ptr
->level
) == NULL
)
861 log_error("ladish_app_supervisor_add() failed.");
862 context_ptr
->error
= XML_TRUE
;
866 context_ptr
->depth
--;
868 if (context_ptr
->str
!= NULL
)
870 free(context_ptr
->str
);
871 context_ptr
->str
= NULL
;
878 context_ptr
->error
= XML_TRUE
;
884 struct ladish_command_load_studio
886 struct ladish_command command
;
890 #define cmd_ptr ((struct ladish_command_load_studio *)command_context)
892 static bool run(void * command_context
)
900 enum XML_Status xmls
;
901 struct ladish_parse_context parse_context
;
903 ASSERT(cmd_ptr
->command
.state
== LADISH_COMMAND_STATE_PENDING
);
905 if (!ladish_studio_compose_filename(cmd_ptr
->studio_name
, &path
, NULL
))
907 log_error("failed to compose path of studio \%s\" file", cmd_ptr
->studio_name
);
911 log_info("Loading studio... ('%s')", path
);
913 if (stat(path
, &st
) != 0)
915 log_error("failed to stat '%s': %d (%s)", path
, errno
, strerror(errno
));
920 g_studio
.name
= cmd_ptr
->studio_name
;
921 cmd_ptr
->studio_name
= NULL
;
923 g_studio
.filename
= path
;
925 if (!jack_reset_all_params())
927 log_error("jack_reset_all_params() failed");
931 fd
= open(path
, O_RDONLY
);
934 log_error("failed to open '%s': %d (%s)", path
, errno
, strerror(errno
));
938 parser
= XML_ParserCreate(NULL
);
941 log_error("XML_ParserCreate() failed to create parser object.");
946 //log_info("conf file size is %llu bytes", (unsigned long long)st.st_size);
948 /* we are expecting that conf file has small enough size to fit in memory */
950 buffer
= XML_GetBuffer(parser
, st
.st_size
);
953 log_error("XML_GetBuffer() failed.");
954 XML_ParserFree(parser
);
959 bytes_read
= read(fd
, buffer
, st
.st_size
);
960 if (bytes_read
!= st
.st_size
)
962 log_error("read() returned unexpected result.");
963 XML_ParserFree(parser
);
968 parse_context
.error
= XML_FALSE
;
969 parse_context
.depth
= -1;
970 parse_context
.str
= NULL
;
971 parse_context
.client
= NULL
;
972 parse_context
.port
= NULL
;
973 parse_context
.dict
= NULL
;
974 parse_context
.room
= NULL
;
976 XML_SetElementHandler(parser
, callback_elstart
, callback_elend
);
977 XML_SetCharacterDataHandler(parser
, callback_chrdata
);
978 XML_SetUserData(parser
, &parse_context
);
980 if (!ladish_studio_show())
982 log_error("ladish_studio_show() failed.");
983 XML_ParserFree(parser
);
988 xmls
= XML_ParseBuffer(parser
, bytes_read
, XML_TRUE
);
989 if (xmls
== XML_STATUS_ERROR
)
991 if (!parse_context
.error
)
993 log_error("XML_ParseBuffer() failed.");
996 ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH
, "Studio load failed", LADISH_CHECK_LOG_TEXT
);
997 ladish_studio_clear();
998 XML_ParserFree(parser
);
1003 XML_ParserFree(parser
);
1006 if (parse_context
.error
)
1008 ladish_studio_clear();
1009 ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH
, "Studio load failed", LADISH_CHECK_LOG_TEXT
);
1013 ladish_interlink(ladish_studio_get_studio_graph(), ladish_studio_get_studio_app_supervisor());
1015 g_studio
.persisted
= true;
1016 log_info("Studio loaded. ('%s')", path
);
1018 ladish_graph_dump(g_studio
.jack_graph
);
1019 ladish_graph_dump(g_studio
.studio_graph
);
1020 ladish_app_supervisor_dump(g_studio
.app_supervisor
);
1022 ladish_recent_store_use_item(g_studios_recent_store
, g_studio
.name
);
1024 if (!ladish_app_supervisor_set_project_name(ladish_studio_get_studio_app_supervisor(), g_studio
.name
))
1026 ladish_app_supervisor_set_project_name(ladish_studio_get_studio_app_supervisor(), NULL
);
1029 ladish_studio_announce();
1031 cmd_ptr
->command
.state
= LADISH_COMMAND_STATE_DONE
;
1035 static void destructor(void * command_context
)
1037 log_info("load studio command destructor");
1038 if (cmd_ptr
->studio_name
!= NULL
)
1040 free(cmd_ptr
->studio_name
);
1046 bool ladish_command_load_studio(void * call_ptr
, struct ladish_cqueue
* queue_ptr
, const char * studio_name
, bool autostart
)
1048 struct ladish_command_load_studio
* cmd_ptr
;
1049 char * studio_name_dup
;
1051 studio_name_dup
= strdup(studio_name
);
1052 if (studio_name_dup
== NULL
)
1054 cdbus_error(call_ptr
, DBUS_ERROR_FAILED
, "strdup('%s') failed.", studio_name
);
1058 if (!ladish_command_unload_studio(call_ptr
, queue_ptr
))
1060 goto fail_free_name
;
1063 cmd_ptr
= ladish_command_new(sizeof(struct ladish_command_load_studio
));
1064 if (cmd_ptr
== NULL
)
1066 log_error("ladish_command_new() failed.");
1067 goto fail_drop_unload_command
;
1070 cmd_ptr
->command
.run
= run
;
1071 cmd_ptr
->command
.destructor
= destructor
;
1072 cmd_ptr
->studio_name
= studio_name_dup
;
1074 if (!ladish_cqueue_add_command(queue_ptr
, &cmd_ptr
->command
))
1076 cdbus_error(call_ptr
, DBUS_ERROR_FAILED
, "ladish_cqueue_add_command() failed.");
1077 goto fail_destroy_command
;
1082 if (!ladish_command_start_studio(call_ptr
, queue_ptr
))
1084 goto fail_drop_load_command
;
1090 fail_drop_load_command
:
1091 ladish_cqueue_drop_command(queue_ptr
);
1093 fail_destroy_command
:
1096 fail_drop_unload_command
:
1097 ladish_cqueue_drop_command(queue_ptr
);
1100 free(studio_name_dup
);