1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2010 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains implementation save releated 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.
33 bool ladish_write_string(int fd
, const char * string
)
39 if (write(fd
, string
, len
) != len
)
41 log_error("write() failed to write config file.");
48 bool ladish_write_indented_string(int fd
, int indent
, const char * string
)
53 if (!ladish_write_string(fd
, LADISH_XML_BASE_INDENT
))
59 if (!ladish_write_string(fd
, string
))
67 #define fd (((struct ladish_write_context *)context)->fd)
68 #define indent (((struct ladish_write_context *)context)->indent)
77 if (!ladish_write_indented_string(fd
, indent
, "<key name=\""))
82 if (!ladish_write_string(fd
, key
))
87 if (!ladish_write_string(fd
, "\">"))
92 if (!ladish_write_string(fd
, value
))
97 if (!ladish_write_string(fd
, "</key>\n"))
107 ladish_save_vgraph_client_begin(
109 ladish_graph_handle graph
,
110 ladish_client_handle client_handle
,
111 const char * client_name
,
112 void ** client_iteration_context_ptr_ptr
)
117 ladish_client_get_uuid(client_handle
, uuid
);
118 uuid_unparse(uuid
, str
);
120 log_info("saving vgraph client '%s' (%s)", client_name
, str
);
122 if (!ladish_write_indented_string(fd
, indent
, "<client name=\""))
127 if (!ladish_write_string(fd
, client_name
))
132 if (!ladish_write_string(fd
, "\" uuid=\""))
137 if (!ladish_write_string(fd
, str
))
142 if (!ladish_write_string(fd
, "\">\n"))
147 if (!ladish_write_indented_string(fd
, indent
+ 1, "<ports>\n"))
157 ladish_save_vgraph_client_end(
159 ladish_graph_handle graph
,
160 ladish_client_handle client_handle
,
161 const char * client_name
,
162 void * client_iteration_context_ptr
)
164 if (!ladish_write_indented_string(fd
, indent
+ 1, "</ports>\n"))
169 if (!ladish_write_dict(fd
, indent
+ 1, ladish_client_get_dict(client_handle
)))
174 if (!ladish_write_indented_string(fd
, indent
, "</client>\n"))
182 static bool ladish_get_vgraph_port_uuids(ladish_graph_handle vgraph
, ladish_port_handle port
, uuid_t uuid
, uuid_t link_uuid
)
186 if (vgraph
!= ladish_studio_get_studio_graph())
188 link
= false; /* room ports are saved using their fixed uuids */
192 link
= ladish_port_is_link(port
);
195 /* get the generated port uuid that is used for identification in the virtual graph */
196 ladish_graph_get_port_uuid(vgraph
, port
, uuid
);
200 if (!link
|| link_uuid
!= NULL
)
202 /* get the real port uuid that is same in both room and studio graphs */
203 ladish_port_get_uuid(port
, link
? link_uuid
: uuid
);
211 ladish_save_vgraph_port(
213 ladish_graph_handle graph
,
214 void * client_iteration_context_ptr
,
215 ladish_client_handle client_handle
,
216 const char * client_name
,
217 ladish_port_handle port_handle
,
218 const char * port_name
,
227 ladish_dict_handle dict
;
229 link
= ladish_get_vgraph_port_uuids(graph
, port_handle
, uuid
, link_uuid
);
230 uuid_unparse(uuid
, str
);
233 uuid_unparse(link_uuid
, link_str
);
234 log_info("saving vgraph link port '%s':'%s' (%s link=%s)", client_name
, port_name
, str
, link_str
);
238 log_info("saving vgraph port '%s':'%s' (%s)", client_name
, port_name
, str
);
241 if (!ladish_write_indented_string(fd
, indent
+ 2, "<port name=\""))
246 if (!ladish_write_string(fd
, port_name
))
251 if (!ladish_write_string(fd
, "\" uuid=\""))
256 if (!ladish_write_string(fd
, str
))
263 if (!ladish_write_string(fd
, "\" link_uuid=\""))
268 if (!ladish_write_string(fd
, link_str
))
274 dict
= ladish_port_get_dict(port_handle
);
275 if (ladish_dict_is_empty(dict
))
277 if (!ladish_write_string(fd
, "\" />\n"))
284 if (!ladish_write_string(fd
, "\">\n"))
289 if (!ladish_write_dict(fd
, indent
+ 3, dict
))
294 if (!ladish_write_indented_string(fd
, indent
+ 2, "</port>\n"))
305 ladish_save_vgraph_connection(
307 ladish_graph_handle graph
,
308 ladish_port_handle port1_handle
,
309 ladish_port_handle port2_handle
,
310 ladish_dict_handle dict
)
315 log_info("saving vgraph connection");
317 if (!ladish_write_indented_string(fd
, indent
, "<connection port1=\""))
322 ladish_get_vgraph_port_uuids(graph
, port1_handle
, uuid
, NULL
);
323 uuid_unparse(uuid
, str
);
325 if (!ladish_write_string(fd
, str
))
330 if (!ladish_write_string(fd
, "\" port2=\""))
335 ladish_get_vgraph_port_uuids(graph
, port2_handle
, uuid
, NULL
);
336 uuid_unparse(uuid
, str
);
338 if (!ladish_write_string(fd
, str
))
343 if (ladish_dict_is_empty(dict
))
345 if (!ladish_write_string(fd
, "\" />\n"))
352 if (!ladish_write_string(fd
, "\">\n"))
357 if (!ladish_write_dict(fd
, indent
+ 1, dict
))
362 if (!ladish_write_indented_string(fd
, indent
, "</connection>\n"))
371 static bool ladish_save_app(void * context
, const char * name
, bool running
, const char * command
, bool terminal
, uint8_t level
, pid_t pid
)
374 const char * unescaped_string
;
375 char * escaped_string
;
376 char * escaped_buffer
;
379 log_info("saving app: name='%s', %srunning, %s, level %u, commandline='%s'", name
, running
? "" : "not ", terminal
? "terminal" : "shell", (unsigned int)level
, command
);
383 escaped_buffer
= malloc(ladish_max(strlen(name
), strlen(command
)) * 3 + 1); /* encode each char in three bytes (percent encoding) */
384 if (escaped_buffer
== NULL
)
386 log_error("malloc() failed.");
390 if (!ladish_write_indented_string(fd
, indent
, "<application name=\""))
395 unescaped_string
= name
;
396 escaped_string
= escaped_buffer
;
397 escape(&unescaped_string
, &escaped_string
);
399 if (!ladish_write_string(fd
, escaped_buffer
))
404 if (!ladish_write_string(fd
, "\" terminal=\""))
409 if (!ladish_write_string(fd
, terminal
? "true" : "false"))
414 if (!ladish_write_string(fd
, "\" level=\""))
419 sprintf(buf
, "%u", (unsigned int)level
);
421 if (!ladish_write_string(fd
, buf
))
426 if (!ladish_write_string(fd
, "\" autorun=\""))
431 if (!ladish_write_string(fd
, running
? "true" : "false"))
436 if (!ladish_write_string(fd
, "\">"))
441 unescaped_string
= command
;
442 escaped_string
= escaped_buffer
;
443 escape(&unescaped_string
, &escaped_string
);
445 if (!ladish_write_string(fd
, escaped_buffer
))
450 if (!ladish_write_string(fd
, "</application>\n"))
458 free(escaped_buffer
);
466 ladish_write_room_port(
468 ladish_port_handle port
,
476 const char * type_str
;
478 const char * direction_str
;
479 ladish_dict_handle dict
;
481 ladish_port_get_uuid(port
, uuid
);
482 uuid_unparse(uuid
, str
);
484 playback
= (flags
& JACKDBUS_PORT_FLAG_INPUT
) != 0;
485 ASSERT(playback
|| (flags
& JACKDBUS_PORT_FLAG_OUTPUT
) != 0); /* playback or capture */
486 ASSERT(!(playback
&& (flags
& JACKDBUS_PORT_FLAG_OUTPUT
) != 0)); /* but not both */
487 direction_str
= playback
? "playback" : "capture";
489 midi
= type
== JACKDBUS_PORT_TYPE_MIDI
;
490 ASSERT(midi
|| type
== JACKDBUS_PORT_TYPE_AUDIO
); /* midi or audio */
491 ASSERT(!(midi
&& type
== JACKDBUS_PORT_TYPE_AUDIO
)); /* but not both */
492 type_str
= midi
? "midi" : "audio";
494 log_info("saving room %s %s port '%s' (%s)", direction_str
, type_str
, name
, str
);
496 if (!ladish_write_indented_string(fd
, indent
, "<port name=\""))
501 if (!ladish_write_string(fd
, name
))
506 if (!ladish_write_string(fd
, "\" uuid=\""))
511 if (!ladish_write_string(fd
, str
))
516 if (!ladish_write_string(fd
, "\" type=\""))
521 if (!ladish_write_string(fd
, type_str
))
526 if (!ladish_write_string(fd
, "\" direction=\""))
531 if (!ladish_write_string(fd
, direction_str
))
536 dict
= ladish_port_get_dict(port
);
537 if (ladish_dict_is_empty(dict
))
539 if (!ladish_write_string(fd
, "\" />\n"))
546 if (!ladish_write_string(fd
, "\">\n"))
551 if (!ladish_write_dict(fd
, indent
+ 1, dict
))
556 if (!ladish_write_indented_string(fd
, indent
, "</port>\n"))
567 ladish_save_jack_client_begin(
569 ladish_graph_handle graph_handle
,
570 ladish_client_handle client_handle
,
571 const char * client_name
,
572 void ** client_iteration_context_ptr_ptr
)
577 ladish_client_get_uuid(client_handle
, uuid
);
578 uuid_unparse(uuid
, str
);
580 log_info("saving jack client '%s' (%s)", client_name
, str
);
582 if (!ladish_write_indented_string(fd
, indent
, "<client name=\""))
587 if (!ladish_write_string(fd
, client_name
))
592 if (!ladish_write_string(fd
, "\" uuid=\""))
597 if (!ladish_write_string(fd
, str
))
602 if (!ladish_write_string(fd
, "\">\n"))
607 if (!ladish_write_indented_string(fd
, indent
+ 1, "<ports>\n"))
617 ladish_save_jack_client_end(
619 ladish_graph_handle graph_handle
,
620 ladish_client_handle client_handle
,
621 const char * client_name
,
622 void * client_iteration_context_ptr
)
624 if (!ladish_write_indented_string(fd
, indent
+ 1, "</ports>\n"))
629 if (!ladish_write_indented_string(fd
, indent
, "</client>\n"))
639 ladish_save_jack_port(
641 ladish_graph_handle graph_handle
,
642 void * client_iteration_context_ptr
,
643 ladish_client_handle client_handle
,
644 const char * client_name
,
645 ladish_port_handle port_handle
,
646 const char * port_name
,
653 ladish_port_get_uuid(port_handle
, uuid
);
654 uuid_unparse(uuid
, str
);
656 log_info("saving jack port '%s':'%s' (%s)", client_name
, port_name
, str
);
658 if (!ladish_write_indented_string(fd
, indent
+ 2, "<port name=\""))
663 if (!ladish_write_string(fd
, port_name
))
668 if (!ladish_write_string(fd
, "\" uuid=\""))
673 if (!ladish_write_string(fd
, str
))
678 if (!ladish_write_string(fd
, "\" />\n"))
689 bool ladish_write_dict(int fd
, int indent
, ladish_dict_handle dict
)
691 struct ladish_write_context context
;
693 if (ladish_dict_is_empty(dict
))
699 context
.indent
= indent
+ 1;
701 if (!ladish_write_indented_string(fd
, indent
, "<dict>\n"))
706 if (!ladish_dict_iterate(dict
, &context
, write_dict_entry
))
711 if (!ladish_write_indented_string(fd
, indent
, "</dict>\n"))
719 bool ladish_write_vgraph(int fd
, int indent
, ladish_graph_handle vgraph
, ladish_app_supervisor_handle app_supervisor
)
721 struct ladish_write_context context
;
724 context
.indent
= indent
+ 1;
726 if (!ladish_write_indented_string(fd
, indent
, "<clients>\n"))
731 if (!ladish_graph_iterate_nodes(
736 ladish_save_vgraph_client_begin
,
737 ladish_save_vgraph_port
,
738 ladish_save_vgraph_client_end
))
740 log_error("ladish_graph_iterate_nodes() failed");
744 if (!ladish_write_indented_string(fd
, indent
, "</clients>\n"))
749 if (!ladish_write_indented_string(fd
, indent
, "<connections>\n"))
754 if (!ladish_graph_iterate_connections(vgraph
, true, &context
, ladish_save_vgraph_connection
))
756 log_error("ladish_graph_iterate_connections() failed");
760 if (!ladish_write_indented_string(fd
, indent
, "</connections>\n"))
765 if (!ladish_write_indented_string(fd
, indent
, "<applications>\n"))
770 if (!ladish_app_supervisor_enum(app_supervisor
, &context
, ladish_save_app
))
775 if (!ladish_write_indented_string(fd
, indent
, "</applications>\n"))
783 bool ladish_write_room_link_ports(int fd
, int indent
, ladish_room_handle room
)
785 struct ladish_write_context context
;
788 context
.indent
= indent
;
790 if (!ladish_room_iterate_link_ports(room
, &context
, ladish_write_room_port
))
792 log_error("ladish_room_iterate_link_ports() failed");
799 bool ladish_write_jgraph(int fd
, int indent
, ladish_graph_handle vgraph
)
801 struct ladish_write_context context
;
803 if (!ladish_write_indented_string(fd
, indent
, "<clients>\n"))
809 context
.indent
= indent
+ 1;
811 if (!ladish_graph_iterate_nodes(
812 ladish_studio_get_jack_graph(),
816 ladish_save_jack_client_begin
,
817 ladish_save_jack_port
,
818 ladish_save_jack_client_end
))
820 log_error("ladish_graph_iterate_nodes() failed");
824 if (!ladish_write_indented_string(fd
, indent
, "</clients>\n"))