1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2009, 2010 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 (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
)
69 const char * uuid_str
;
71 const char * uuid2_str
;
73 ladish_port_handle port1
;
74 ladish_port_handle port2
;
78 if (context_ptr
->error
)
83 if (context_ptr
->depth
+ 1 >= MAX_STACK_DEPTH
)
85 log_error("xml parse max stack depth reached");
86 context_ptr
->error
= XML_TRUE
;
90 if (strcmp(el
, "studio") == 0)
92 //log_info("<studio>");
93 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_STUDIO
;
97 if (strcmp(el
, "jack") == 0)
100 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_JACK
;
104 if (strcmp(el
, "conf") == 0)
106 //log_info("<conf>");
107 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_CONF
;
111 if (strcmp(el
, "parameter") == 0)
113 //log_info("<parameter>");
114 path
= ladish_get_string_attribute(attr
, "path");
117 log_error("<parameter> XML element without \"path\" attribute");
118 context_ptr
->error
= XML_TRUE
;
122 context_ptr
->str
= strdup(path
);
123 if (context_ptr
->str
== NULL
)
125 log_error("strdup() failed");
126 context_ptr
->error
= XML_TRUE
;
130 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_PARAMETER
;
131 context_ptr
->data_used
= 0;
135 if (strcmp(el
, "clients") == 0)
137 //log_info("<clients>");
138 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_CLIENTS
;
142 if (strcmp(el
, "rooms") == 0)
144 //log_info("<rooms>");
145 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_ROOMS
;
149 if (strcmp(el
, "room") == 0)
151 //log_info("<room>");
152 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_ROOM
;
154 if (context_ptr
->room
!= NULL
)
156 log_error("nested rooms");
157 context_ptr
->error
= XML_TRUE
;
161 if (context_ptr
->depth
== 2 &&
162 context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
&&
163 context_ptr
->element
[1] == PARSE_CONTEXT_ROOMS
)
165 if (!ladish_get_name_and_uuid_attributes("/studio/rooms/room", attr
, &name
, &uuid_str
, uuid
))
167 context_ptr
->error
= XML_TRUE
;
171 if (!ladish_room_create(uuid
, name
, NULL
, g_studio
.studio_graph
, &context_ptr
->room
))
173 log_error("ladish_room_create() failed.");
174 context_ptr
->error
= XML_TRUE
;
175 ASSERT(context_ptr
->room
== NULL
);
182 log_error("ignoring <room> element in wrong context");
186 if (strcmp(el
, "client") == 0)
188 //log_info("<client>");
189 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_CLIENT
;
191 if (context_ptr
->client
!= NULL
)
193 log_error("nested clients");
194 context_ptr
->error
= XML_TRUE
;
198 if (context_ptr
->depth
== 3 &&
199 context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
&&
200 context_ptr
->element
[1] == PARSE_CONTEXT_JACK
&&
201 context_ptr
->element
[2] == PARSE_CONTEXT_CLIENTS
)
203 if (!ladish_get_name_and_uuid_attributes("/studio/jack/clients/client", attr
, &name
, &uuid_str
, uuid
))
205 context_ptr
->error
= XML_TRUE
;
209 log_info("jack client \"%s\" with uuid %s", name
, uuid_str
);
211 if (!ladish_client_create(uuid
, &context_ptr
->client
))
213 log_error("ladish_client_create() failed.");
214 context_ptr
->error
= XML_TRUE
;
215 ASSERT(context_ptr
->client
== NULL
);
219 if (!ladish_graph_add_client(g_studio
.jack_graph
, context_ptr
->client
, name
, true))
221 log_error("ladish_graph_add_client() failed to add client '%s' to JACK graph", name
);
222 context_ptr
->error
= XML_TRUE
;
223 ladish_client_destroy(context_ptr
->client
);
224 context_ptr
->client
= NULL
;
228 else if (context_ptr
->depth
== 2 &&
229 context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
&&
230 context_ptr
->element
[1] == PARSE_CONTEXT_CLIENTS
)
232 if (!ladish_get_name_and_uuid_attributes("/studio/clients/client", attr
, &name
, &uuid_str
, uuid
))
234 context_ptr
->error
= XML_TRUE
;
238 log_info("studio client \"%s\" with uuid %s", name
, uuid_str
);
240 context_ptr
->client
= ladish_graph_find_client_by_uuid(g_studio
.studio_graph
, uuid
);
241 if (context_ptr
->client
!= NULL
)
243 log_info("Found existing client");
247 if (!ladish_client_create(uuid
, &context_ptr
->client
))
249 log_error("ladish_client_create() failed.");
250 context_ptr
->error
= XML_TRUE
;
251 ASSERT(context_ptr
->client
== NULL
);
255 if (!ladish_graph_add_client(g_studio
.studio_graph
, context_ptr
->client
, name
, true))
257 log_error("ladish_graph_add_client() failed to add client '%s' to studio graph", name
);
258 context_ptr
->error
= XML_TRUE
;
259 ladish_client_destroy(context_ptr
->client
);
260 context_ptr
->client
= NULL
;
268 if (strcmp(el
, "ports") == 0)
270 //log_info("<ports>");
271 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_PORTS
;
275 if (strcmp(el
, "port") == 0)
277 //log_info("<port>");
278 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_PORT
;
280 if (context_ptr
->port
!= NULL
)
282 log_error("nested ports");
283 context_ptr
->error
= XML_TRUE
;
287 if (context_ptr
->depth
>= 3 &&
288 context_ptr
->element
[context_ptr
->depth
- 3] == PARSE_CONTEXT_CLIENTS
&&
289 context_ptr
->element
[context_ptr
->depth
- 2] == PARSE_CONTEXT_CLIENT
&&
290 context_ptr
->element
[context_ptr
->depth
- 1] == PARSE_CONTEXT_PORTS
)
292 //log_info("client port");
293 if (context_ptr
->client
== NULL
)
295 log_error("client-less port");
296 context_ptr
->error
= XML_TRUE
;
300 if (context_ptr
->depth
== 5 && context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
&& context_ptr
->element
[1] == PARSE_CONTEXT_JACK
)
302 if (!ladish_get_name_and_uuid_attributes("/studio/jack/clients/client/ports/port", attr
, &name
, &uuid_str
, uuid
))
304 context_ptr
->error
= XML_TRUE
;
308 log_info("jack port \"%s\" with uuid %s", name
, uuid_str
);
310 if (!ladish_port_create(uuid
, false, &context_ptr
->port
))
312 log_error("ladish_port_create() failed.");
316 if (!ladish_graph_add_port(g_studio
.jack_graph
, context_ptr
->client
, context_ptr
->port
, name
, 0, 0, true))
318 log_error("ladish_graph_add_port() failed.");
319 ladish_port_destroy(context_ptr
->port
);
320 context_ptr
->port
= NULL
;
325 else if (context_ptr
->depth
== 4 && context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
)
327 if (!ladish_get_name_and_uuid_attributes("/studio/clients/client/ports/port", attr
, &name
, &uuid_str
, uuid
))
329 context_ptr
->error
= XML_TRUE
;
333 uuid2_str
= ladish_get_uuid_attribute(attr
, "link_uuid", uuid2
, true);
335 log_info("studio port \"%s\" with uuid %s (%s)", name
, uuid_str
, uuid2_str
== NULL
? "normal" : "room link");
337 if (uuid2_str
== NULL
)
338 { /* normal studio port */
339 context_ptr
->port
= ladish_graph_find_port_by_uuid(g_studio
.jack_graph
, uuid
, false);
340 if (context_ptr
->port
== NULL
)
342 log_error("studio client with non-jack port %s", uuid_str
);
343 context_ptr
->error
= XML_TRUE
;
347 if (!ladish_graph_add_port(g_studio
.studio_graph
, context_ptr
->client
, context_ptr
->port
, name
, 0, 0, true))
349 log_error("ladish_graph_add_port() failed.");
350 ladish_port_destroy(context_ptr
->port
);
351 context_ptr
->port
= NULL
;
359 context_ptr
->port
= ladish_graph_find_client_port_by_uuid(g_studio
.studio_graph
, context_ptr
->client
, uuid2
, false);
360 if (context_ptr
->port
== NULL
)
362 log_error("room link port not found");
363 context_ptr
->error
= XML_TRUE
;
367 ladish_graph_set_link_port_override_uuid(g_studio
.studio_graph
, context_ptr
->port
, uuid
);
371 else if (context_ptr
->depth
== 3 &&
372 context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
&&
373 context_ptr
->element
[1] == PARSE_CONTEXT_ROOMS
&&
374 context_ptr
->element
[2] == PARSE_CONTEXT_ROOM
)
376 ASSERT(context_ptr
->room
!= NULL
);
377 //log_info("room port");
379 if (!ladish_get_name_and_uuid_attributes("/studio/rooms/room/port", attr
, &name
, &uuid_str
, uuid
))
381 context_ptr
->error
= XML_TRUE
;
385 log_info("room port \"%s\" with uuid %s", name
, uuid_str
);
387 if (!ladish_parse_port_type_and_direction_attributes("/studio/rooms/room/port", attr
, &port_type
, &port_flags
))
389 context_ptr
->error
= XML_TRUE
;
393 context_ptr
->port
= ladish_room_add_port(context_ptr
->room
, uuid
, name
, port_type
, port_flags
);
394 if (context_ptr
->port
== NULL
)
396 log_error("ladish_room_add_port() failed.");
397 context_ptr
->port
= NULL
;
403 log_error("port element in wrong place");
404 ladish_dump_element_stack(context_ptr
);
405 context_ptr
->error
= XML_TRUE
;
409 if (strcmp(el
, "connections") == 0)
411 //log_info("<connections>");
412 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_CONNECTIONS
;
416 if (strcmp(el
, "connection") == 0)
418 //log_info("<connection>");
419 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_CONNECTION
;
421 uuid_str
= ladish_get_uuid_attribute(attr
, "port1", uuid
, false);
422 if (uuid_str
== NULL
)
424 log_error("/studio/connections/connection \"port1\" attribute is not available.");
425 context_ptr
->error
= XML_TRUE
;
429 uuid2_str
= ladish_get_uuid_attribute(attr
, "port2", uuid2
, false);
430 if (uuid2_str
== NULL
)
432 log_error("/studio/connections/connection \"port2\" attribute is not available.");
433 context_ptr
->error
= XML_TRUE
;
437 log_info("studio connection between port %s and port %s", uuid_str
, uuid2_str
);
439 port1
= ladish_graph_find_port_by_uuid(g_studio
.studio_graph
, uuid
, true);
442 log_error("studio client with unknown port %s", uuid_str
);
443 context_ptr
->error
= XML_TRUE
;
447 port2
= ladish_graph_find_port_by_uuid(g_studio
.studio_graph
, uuid2
, true);
450 log_error("studio client with unknown port %s", uuid2_str
);
451 context_ptr
->error
= XML_TRUE
;
455 context_ptr
->connection_id
= ladish_graph_add_connection(g_studio
.studio_graph
, port1
, port2
, true);
456 if (context_ptr
->connection_id
== 0)
458 log_error("ladish_graph_add_connection() failed.");
465 if (strcmp(el
, "applications") == 0)
467 //log_info("<applications>");
468 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_APPLICATIONS
;
472 if (strcmp(el
, "application") == 0)
474 //log_info("<application>");
475 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_APPLICATION
;
477 name
= ladish_get_string_attribute(attr
, "name");
480 log_error("application \"name\" attribute is not available.");
481 context_ptr
->error
= XML_TRUE
;
485 if (ladish_get_bool_attribute(attr
, "terminal", &context_ptr
->terminal
) == NULL
)
487 log_error("application \"terminal\" attribute is not available. name=\"%s\"", name
);
488 context_ptr
->error
= XML_TRUE
;
492 if (ladish_get_bool_attribute(attr
, "autorun", &context_ptr
->autorun
) == NULL
)
494 log_error("application \"autorun\" attribute is not available. name=\"%s\"", name
);
495 context_ptr
->error
= XML_TRUE
;
499 if (ladish_get_byte_attribute(attr
, "level", &context_ptr
->level
) == NULL
)
501 log_error("application \"level\" attribute is not available. name=\"%s\"", name
);
502 context_ptr
->error
= XML_TRUE
;
506 context_ptr
->str
= strdup(name
);
507 if (context_ptr
->str
== NULL
)
509 log_error("strdup() failed");
510 context_ptr
->error
= XML_TRUE
;
514 context_ptr
->data_used
= 0;
518 if (strcmp(el
, "dict") == 0)
520 //log_info("<dict>");
521 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_DICT
;
523 if (context_ptr
->dict
!= NULL
)
525 log_error("nested dicts");
526 context_ptr
->error
= XML_TRUE
;
530 if (context_ptr
->depth
== 1 &&
531 context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
)
533 context_ptr
->dict
= ladish_graph_get_dict(g_studio
.studio_graph
);
534 ASSERT(context_ptr
->dict
!= NULL
);
536 else if (context_ptr
->depth
> 0 &&
537 context_ptr
->element
[context_ptr
->depth
- 1] == PARSE_CONTEXT_CLIENT
)
539 ASSERT(context_ptr
->client
!= NULL
);
540 context_ptr
->dict
= ladish_client_get_dict(context_ptr
->client
);
541 ASSERT(context_ptr
->dict
!= NULL
);
543 else if (context_ptr
->depth
> 0 &&
544 context_ptr
->element
[context_ptr
->depth
- 1] == PARSE_CONTEXT_PORT
)
546 ASSERT(context_ptr
->port
!= NULL
);
547 context_ptr
->dict
= ladish_port_get_dict(context_ptr
->port
);
548 ASSERT(context_ptr
->dict
!= NULL
);
550 else if (context_ptr
->depth
> 0 &&
551 context_ptr
->element
[context_ptr
->depth
- 1] == PARSE_CONTEXT_CONNECTION
)
553 ASSERT(context_ptr
->port
!= NULL
);
554 context_ptr
->dict
= ladish_graph_get_connection_dict(g_studio
.studio_graph
, context_ptr
->connection_id
);
555 ASSERT(context_ptr
->dict
!= NULL
);
559 log_error("unexpected dict XML element");
560 context_ptr
->error
= XML_TRUE
;
567 if (strcmp(el
, "key") == 0)
570 context_ptr
->element
[++context_ptr
->depth
] = PARSE_CONTEXT_KEY
;
572 if (context_ptr
->dict
== NULL
)
574 log_error("dict-less key");
575 context_ptr
->error
= XML_TRUE
;
579 name
= ladish_get_string_attribute(attr
, "name");
582 log_error("dict/key \"name\" attribute is not available.");
583 context_ptr
->error
= XML_TRUE
;
587 context_ptr
->str
= strdup(name
);
588 if (context_ptr
->str
== NULL
)
590 log_error("strdup() failed");
591 context_ptr
->error
= XML_TRUE
;
595 context_ptr
->data_used
= 0;
600 log_error("unknown element \"%s\"", el
);
601 context_ptr
->error
= XML_TRUE
;
604 static void callback_elend(void * data
, const char * el
)
612 struct jack_parameter_variant parameter
;
615 if (context_ptr
->error
)
620 //log_info("element end (depth = %d, element = %u)", context_ptr->depth, context_ptr->element[context_ptr->depth]);
622 if (context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_PARAMETER
&&
623 context_ptr
->depth
== 3 &&
624 context_ptr
->element
[0] == PARSE_CONTEXT_STUDIO
&&
625 context_ptr
->element
[1] == PARSE_CONTEXT_JACK
&&
626 context_ptr
->element
[2] == PARSE_CONTEXT_CONF
)
628 context_ptr
->data
[context_ptr
->data_used
] = 0;
630 //log_info("'%s' with value '%s'", context_ptr->str, context_ptr->data);
632 dst
= address
= strdup(context_ptr
->str
);
633 src
= context_ptr
->str
+ 1;
636 sep
= strchr(src
, '/');
639 src_len
= strlen(src
);
646 dst_len
= unescape(src
, src_len
, dst
);
651 ASSERT(*src
== '/' || *src
== 0);
655 src
++; /* skip separator */
662 *dst
= 0; /* ASCIZZ */
664 if (!jack_proxy_get_parameter_value(address
, &is_set
, ¶meter
))
666 log_error("jack_proxy_get_parameter_value() failed");
667 goto fail_free_address
;
670 if (parameter
.type
== jack_string
)
672 free(parameter
.value
.string
);
675 switch (parameter
.type
)
678 log_info("%s value is %s (boolean)", context_ptr
->str
, context_ptr
->data
);
679 if (strcmp(context_ptr
->data
, "true") == 0)
681 parameter
.value
.boolean
= true;
683 else if (strcmp(context_ptr
->data
, "false") == 0)
685 parameter
.value
.boolean
= false;
689 log_error("bad value for a bool jack param");
690 goto fail_free_address
;
694 log_info("%s value is %s (string)", context_ptr
->str
, context_ptr
->data
);
695 parameter
.value
.string
= context_ptr
->data
;
698 log_debug("%s value is %u/%c (byte/char)", context_ptr
->str
, *context_ptr
->data
, *context_ptr
->data
);
699 if (context_ptr
->data
[0] == 0 ||
700 context_ptr
->data
[1] != 0)
702 log_error("bad value for a char jack param");
703 goto fail_free_address
;
705 parameter
.value
.byte
= context_ptr
->data
[0];
708 log_info("%s value is %s (uint32)", context_ptr
->str
, context_ptr
->data
);
709 if (sscanf(context_ptr
->data
, "%" PRIu32
, ¶meter
.value
.uint32
) != 1)
711 log_error("bad value for an uint32 jack param");
712 goto fail_free_address
;
716 log_info("%s value is %s (int32)", context_ptr
->str
, context_ptr
->data
);
717 if (sscanf(context_ptr
->data
, "%" PRIi32
, ¶meter
.value
.int32
) != 1)
719 log_error("bad value for an int32 jack param");
720 goto fail_free_address
;
724 log_error("unknown jack parameter type %d of %s", (int)parameter
.type
, context_ptr
->str
);
725 goto fail_free_address
;
728 if (!jack_proxy_set_parameter_value(address
, ¶meter
))
730 log_error("jack_proxy_set_parameter_value() failed");
731 goto fail_free_address
;
736 else if (context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_KEY
&&
737 context_ptr
->depth
> 0 &&
738 context_ptr
->element
[context_ptr
->depth
- 1] == PARSE_CONTEXT_DICT
)
740 ASSERT(context_ptr
->dict
!= NULL
);
741 context_ptr
->data
[context_ptr
->data_used
] = 0;
742 log_info("dict key '%s' with value '%s'", context_ptr
->str
, context_ptr
->data
);
743 if (!ladish_dict_set(context_ptr
->dict
, context_ptr
->str
, context_ptr
->data
))
745 log_error("ladish_dict_set() failed");
746 context_ptr
->error
= XML_TRUE
;
750 else if (context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_ROOM
)
752 //log_info("</room>");
753 ASSERT(context_ptr
->room
!= NULL
);
754 context_ptr
->room
= NULL
;
756 else if (context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_DICT
)
758 //log_info("</dict>");
759 ASSERT(context_ptr
->dict
!= NULL
);
760 context_ptr
->dict
= NULL
;
762 else if (context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_CLIENT
)
764 //log_info("</client>");
765 ASSERT(context_ptr
->client
!= NULL
);
766 context_ptr
->client
= NULL
;
768 else if (context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_PORT
)
770 //log_info("</port>");
771 ASSERT(context_ptr
->port
!= NULL
);
772 context_ptr
->port
= NULL
;
774 else if (context_ptr
->element
[context_ptr
->depth
] == PARSE_CONTEXT_APPLICATION
)
776 context_ptr
->data
[unescape(context_ptr
->data
, context_ptr
->data_used
, context_ptr
->data
)] = 0;
777 unescape(context_ptr
->str
, strlen(context_ptr
->str
) + 1, context_ptr
->str
);
779 log_info("application '%s' (%s, %s, level %u) with commandline '%s'", context_ptr
->str
, context_ptr
->terminal
? "terminal" : "shell", context_ptr
->autorun
? "autorun" : "stopped", (unsigned int)context_ptr
->level
, context_ptr
->data
);
781 if (ladish_app_supervisor_add(g_studio
.app_supervisor
, context_ptr
->str
, context_ptr
->autorun
, context_ptr
->data
, context_ptr
->terminal
, context_ptr
->level
) == NULL
)
783 log_error("ladish_app_supervisor_add() failed.");
784 context_ptr
->error
= XML_TRUE
;
788 context_ptr
->depth
--;
790 if (context_ptr
->str
!= NULL
)
792 free(context_ptr
->str
);
793 context_ptr
->str
= NULL
;
800 context_ptr
->error
= XML_TRUE
;
806 struct ladish_command_load_studio
808 struct ladish_command command
;
812 #define cmd_ptr ((struct ladish_command_load_studio *)command_context)
814 static bool run(void * command_context
)
822 enum XML_Status xmls
;
823 struct ladish_parse_context parse_context
;
825 ASSERT(cmd_ptr
->command
.state
== LADISH_COMMAND_STATE_PENDING
);
827 if (!ladish_studio_compose_filename(cmd_ptr
->studio_name
, &path
, NULL
))
829 log_error("failed to compose path of studio \%s\" file", cmd_ptr
->studio_name
);
833 log_info("Loading studio... ('%s')", path
);
835 if (stat(path
, &st
) != 0)
837 log_error("failed to stat '%s': %d (%s)", path
, errno
, strerror(errno
));
842 g_studio
.name
= cmd_ptr
->studio_name
;
843 cmd_ptr
->studio_name
= NULL
;
845 g_studio
.filename
= path
;
847 if (!jack_reset_all_params())
849 log_error("jack_reset_all_params() failed");
853 fd
= open(path
, O_RDONLY
);
856 log_error("failed to open '%s': %d (%s)", path
, errno
, strerror(errno
));
860 parser
= XML_ParserCreate(NULL
);
863 log_error("XML_ParserCreate() failed to create parser object.");
868 //log_info("conf file size is %llu bytes", (unsigned long long)st.st_size);
870 /* we are expecting that conf file has small enough size to fit in memory */
872 buffer
= XML_GetBuffer(parser
, st
.st_size
);
875 log_error("XML_GetBuffer() failed.");
876 XML_ParserFree(parser
);
881 bytes_read
= read(fd
, buffer
, st
.st_size
);
882 if (bytes_read
!= st
.st_size
)
884 log_error("read() returned unexpected result.");
885 XML_ParserFree(parser
);
890 parse_context
.error
= XML_FALSE
;
891 parse_context
.depth
= -1;
892 parse_context
.str
= NULL
;
893 parse_context
.client
= NULL
;
894 parse_context
.port
= NULL
;
895 parse_context
.dict
= NULL
;
896 parse_context
.room
= NULL
;
898 XML_SetElementHandler(parser
, callback_elstart
, callback_elend
);
899 XML_SetCharacterDataHandler(parser
, callback_chrdata
);
900 XML_SetUserData(parser
, &parse_context
);
902 if (!ladish_studio_show())
904 log_error("ladish_studio_show() failed.");
905 XML_ParserFree(parser
);
910 xmls
= XML_ParseBuffer(parser
, bytes_read
, XML_TRUE
);
911 if (xmls
== XML_STATUS_ERROR
)
913 if (!parse_context
.error
)
915 log_error("XML_ParseBuffer() failed.");
918 ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH
, "Studio load failed", "Please inspect the ladishd log (~/.ladish/ladish.log) for more info");
919 ladish_studio_clear();
920 XML_ParserFree(parser
);
925 XML_ParserFree(parser
);
928 if (parse_context
.error
)
930 ladish_studio_clear();
931 ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH
, "Studio load failed", "Please inspect the ladishd log (~/.ladish/ladish.log) for more info");
935 ladish_interlink_clients(ladish_studio_get_studio_graph(), ladish_studio_get_studio_app_supervisor());
937 g_studio
.persisted
= true;
938 log_info("Studio loaded. ('%s')", path
);
940 ladish_graph_dump(g_studio
.jack_graph
);
941 ladish_graph_dump(g_studio
.studio_graph
);
943 ladish_studio_announce();
945 cmd_ptr
->command
.state
= LADISH_COMMAND_STATE_DONE
;
949 static void destructor(void * command_context
)
951 log_info("load studio command destructor");
952 if (cmd_ptr
->studio_name
!= NULL
)
954 free(cmd_ptr
->studio_name
);
960 bool ladish_command_load_studio(void * call_ptr
, struct ladish_cqueue
* queue_ptr
, const char * studio_name
, bool autostart
)
962 struct ladish_command_load_studio
* cmd_ptr
;
963 char * studio_name_dup
;
965 studio_name_dup
= strdup(studio_name
);
966 if (studio_name_dup
== NULL
)
968 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_GENERIC
, "strdup('%s') failed.", studio_name
);
972 if (!ladish_command_unload_studio(call_ptr
, queue_ptr
))
977 cmd_ptr
= ladish_command_new(sizeof(struct ladish_command_load_studio
));
980 log_error("ladish_command_new() failed.");
981 goto fail_drop_unload_command
;
984 cmd_ptr
->command
.run
= run
;
985 cmd_ptr
->command
.destructor
= destructor
;
986 cmd_ptr
->studio_name
= studio_name_dup
;
988 if (!ladish_cqueue_add_command(queue_ptr
, &cmd_ptr
->command
))
990 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_GENERIC
, "ladish_cqueue_add_command() failed.");
991 goto fail_destroy_command
;
996 if (!ladish_command_start_studio(call_ptr
, queue_ptr
))
998 goto fail_drop_load_command
;
1004 fail_drop_load_command
:
1005 ladish_cqueue_drop_command(queue_ptr
);
1007 fail_destroy_command
:
1010 fail_drop_unload_command
:
1011 ladish_cqueue_drop_command(queue_ptr
);
1014 free(studio_name_dup
);