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
)
40 ret
= write(fd
, string
, len
);
43 log_error("write(%d, \"%s\", %zu) failed to write config file: %d (%s)", fd
, string
, len
, errno
, strerror(errno
));
46 if ((size_t)ret
!= len
)
48 log_error("write() wrote wrong byte count to config file (%zd != %zu).", ret
, len
);
55 bool ladish_write_indented_string(int fd
, int indent
, const char * string
)
60 if (!ladish_write_string(fd
, LADISH_XML_BASE_INDENT
))
66 if (!ladish_write_string(fd
, string
))
74 #define fd (((struct ladish_write_context *)context)->fd)
75 #define indent (((struct ladish_write_context *)context)->indent)
84 if (!ladish_write_indented_string(fd
, indent
, "<key name=\""))
89 if (!ladish_write_string(fd
, key
))
94 if (!ladish_write_string(fd
, "\">"))
99 if (!ladish_write_string(fd
, value
))
104 if (!ladish_write_string(fd
, "</key>\n"))
114 ladish_save_vgraph_client_begin(
116 ladish_graph_handle graph
,
117 ladish_client_handle client_handle
,
118 const char * client_name
,
119 void ** client_iteration_context_ptr_ptr
)
124 ladish_client_get_uuid(client_handle
, uuid
);
125 uuid_unparse(uuid
, str
);
127 log_info("saving vgraph client '%s' (%s)", client_name
, str
);
129 if (!ladish_write_indented_string(fd
, indent
, "<client name=\""))
134 if (!ladish_write_string(fd
, client_name
))
139 if (!ladish_write_string(fd
, "\" uuid=\""))
144 if (!ladish_write_string(fd
, str
))
149 if (!ladish_write_string(fd
, "\">\n"))
154 if (!ladish_write_indented_string(fd
, indent
+ 1, "<ports>\n"))
164 ladish_save_vgraph_client_end(
166 ladish_graph_handle graph
,
167 ladish_client_handle client_handle
,
168 const char * client_name
,
169 void * client_iteration_context_ptr
)
171 if (!ladish_write_indented_string(fd
, indent
+ 1, "</ports>\n"))
176 if (!ladish_write_dict(fd
, indent
+ 1, ladish_client_get_dict(client_handle
)))
181 if (!ladish_write_indented_string(fd
, indent
, "</client>\n"))
189 static bool ladish_get_vgraph_port_uuids(ladish_graph_handle vgraph
, ladish_port_handle port
, uuid_t uuid
, uuid_t link_uuid
)
193 if (vgraph
!= ladish_studio_get_studio_graph())
195 link
= false; /* room ports are saved using their fixed uuids */
199 link
= ladish_port_is_link(port
);
202 /* get the generated port uuid that is used for identification in the virtual graph */
203 ladish_graph_get_port_uuid(vgraph
, port
, uuid
);
207 if (!link
|| link_uuid
!= NULL
)
209 /* get the real port uuid that is same in both room and studio graphs */
210 ladish_port_get_uuid(port
, link
? link_uuid
: uuid
);
218 ladish_save_vgraph_port(
220 ladish_graph_handle graph
,
221 void * client_iteration_context_ptr
,
222 ladish_client_handle client_handle
,
223 const char * client_name
,
224 ladish_port_handle port_handle
,
225 const char * port_name
,
234 ladish_dict_handle dict
;
236 link
= ladish_get_vgraph_port_uuids(graph
, port_handle
, uuid
, link_uuid
);
237 uuid_unparse(uuid
, str
);
240 uuid_unparse(link_uuid
, link_str
);
241 log_info("saving vgraph link port '%s':'%s' (%s link=%s)", client_name
, port_name
, str
, link_str
);
245 log_info("saving vgraph port '%s':'%s' (%s)", client_name
, port_name
, str
);
248 if (!ladish_write_indented_string(fd
, indent
+ 2, "<port name=\""))
253 if (!ladish_write_string(fd
, port_name
))
258 if (!ladish_write_string(fd
, "\" uuid=\""))
263 if (!ladish_write_string(fd
, str
))
270 if (!ladish_write_string(fd
, "\" link_uuid=\""))
275 if (!ladish_write_string(fd
, link_str
))
281 dict
= ladish_port_get_dict(port_handle
);
282 if (ladish_dict_is_empty(dict
))
284 if (!ladish_write_string(fd
, "\" />\n"))
291 if (!ladish_write_string(fd
, "\">\n"))
296 if (!ladish_write_dict(fd
, indent
+ 3, dict
))
301 if (!ladish_write_indented_string(fd
, indent
+ 2, "</port>\n"))
312 ladish_save_vgraph_connection(
314 ladish_graph_handle graph
,
315 ladish_port_handle port1_handle
,
316 ladish_port_handle port2_handle
,
317 ladish_dict_handle dict
)
322 log_info("saving vgraph connection");
324 if (!ladish_write_indented_string(fd
, indent
, "<connection port1=\""))
329 ladish_get_vgraph_port_uuids(graph
, port1_handle
, uuid
, NULL
);
330 uuid_unparse(uuid
, str
);
332 if (!ladish_write_string(fd
, str
))
337 if (!ladish_write_string(fd
, "\" port2=\""))
342 ladish_get_vgraph_port_uuids(graph
, port2_handle
, uuid
, NULL
);
343 uuid_unparse(uuid
, str
);
345 if (!ladish_write_string(fd
, str
))
350 if (ladish_dict_is_empty(dict
))
352 if (!ladish_write_string(fd
, "\" />\n"))
359 if (!ladish_write_string(fd
, "\">\n"))
364 if (!ladish_write_dict(fd
, indent
+ 1, dict
))
369 if (!ladish_write_indented_string(fd
, indent
, "</connection>\n"))
384 const char * command
,
391 const char * unescaped_string
;
392 char * escaped_string
;
393 char * escaped_buffer
;
396 log_info("saving app: name='%s', %srunning, %s, level %u, commandline='%s'", name
, running
? "" : "not ", terminal
? "terminal" : "shell", (unsigned int)level
, command
);
400 escaped_buffer
= malloc(ladish_max(strlen(name
), strlen(command
)) * 3 + 1); /* encode each char in three bytes (percent encoding) */
401 if (escaped_buffer
== NULL
)
403 log_error("malloc() failed.");
407 if (!ladish_write_indented_string(fd
, indent
, "<application name=\""))
412 unescaped_string
= name
;
413 escaped_string
= escaped_buffer
;
414 escape(&unescaped_string
, &escaped_string
);
416 if (!ladish_write_string(fd
, escaped_buffer
))
421 if (!ladish_write_string(fd
, "\" terminal=\""))
426 if (!ladish_write_string(fd
, terminal
? "true" : "false"))
431 if (!ladish_write_string(fd
, "\" level=\""))
436 sprintf(buf
, "%u", (unsigned int)level
);
438 if (!ladish_write_string(fd
, buf
))
443 if (!ladish_write_string(fd
, "\" autorun=\""))
448 if (!ladish_write_string(fd
, running
? "true" : "false"))
453 if (!ladish_write_string(fd
, "\">"))
458 unescaped_string
= command
;
459 escaped_string
= escaped_buffer
;
460 escape(&unescaped_string
, &escaped_string
);
462 if (!ladish_write_string(fd
, escaped_buffer
))
467 if (!ladish_write_string(fd
, "</application>\n"))
475 free(escaped_buffer
);
483 ladish_write_room_port(
485 ladish_port_handle port
,
493 const char * type_str
;
495 const char * direction_str
;
496 ladish_dict_handle dict
;
498 ladish_port_get_uuid(port
, uuid
);
499 uuid_unparse(uuid
, str
);
501 playback
= (flags
& JACKDBUS_PORT_FLAG_INPUT
) != 0;
502 ASSERT(playback
|| (flags
& JACKDBUS_PORT_FLAG_OUTPUT
) != 0); /* playback or capture */
503 ASSERT(!(playback
&& (flags
& JACKDBUS_PORT_FLAG_OUTPUT
) != 0)); /* but not both */
504 direction_str
= playback
? "playback" : "capture";
506 midi
= type
== JACKDBUS_PORT_TYPE_MIDI
;
507 ASSERT(midi
|| type
== JACKDBUS_PORT_TYPE_AUDIO
); /* midi or audio */
508 ASSERT(!(midi
&& type
== JACKDBUS_PORT_TYPE_AUDIO
)); /* but not both */
509 type_str
= midi
? "midi" : "audio";
511 log_info("saving room %s %s port '%s' (%s)", direction_str
, type_str
, name
, str
);
513 if (!ladish_write_indented_string(fd
, indent
, "<port name=\""))
518 if (!ladish_write_string(fd
, name
))
523 if (!ladish_write_string(fd
, "\" uuid=\""))
528 if (!ladish_write_string(fd
, str
))
533 if (!ladish_write_string(fd
, "\" type=\""))
538 if (!ladish_write_string(fd
, type_str
))
543 if (!ladish_write_string(fd
, "\" direction=\""))
548 if (!ladish_write_string(fd
, direction_str
))
553 dict
= ladish_port_get_dict(port
);
554 if (ladish_dict_is_empty(dict
))
556 if (!ladish_write_string(fd
, "\" />\n"))
563 if (!ladish_write_string(fd
, "\">\n"))
568 if (!ladish_write_dict(fd
, indent
+ 1, dict
))
573 if (!ladish_write_indented_string(fd
, indent
, "</port>\n"))
584 ladish_save_jack_client_begin(
586 ladish_graph_handle graph_handle
,
587 ladish_client_handle client_handle
,
588 const char * client_name
,
589 void ** client_iteration_context_ptr_ptr
)
594 ladish_client_get_uuid(client_handle
, uuid
);
595 uuid_unparse(uuid
, str
);
597 log_info("saving jack client '%s' (%s)", client_name
, str
);
599 if (!ladish_write_indented_string(fd
, indent
, "<client name=\""))
604 if (!ladish_write_string(fd
, client_name
))
609 if (!ladish_write_string(fd
, "\" uuid=\""))
614 if (!ladish_write_string(fd
, str
))
619 if (!ladish_write_string(fd
, "\">\n"))
624 if (!ladish_write_indented_string(fd
, indent
+ 1, "<ports>\n"))
634 ladish_save_jack_client_end(
636 ladish_graph_handle graph_handle
,
637 ladish_client_handle client_handle
,
638 const char * client_name
,
639 void * client_iteration_context_ptr
)
641 if (!ladish_write_indented_string(fd
, indent
+ 1, "</ports>\n"))
646 if (!ladish_write_indented_string(fd
, indent
, "</client>\n"))
656 ladish_save_jack_port(
658 ladish_graph_handle graph_handle
,
659 void * client_iteration_context_ptr
,
660 ladish_client_handle client_handle
,
661 const char * client_name
,
662 ladish_port_handle port_handle
,
663 const char * port_name
,
670 ladish_port_get_uuid(port_handle
, uuid
);
671 uuid_unparse(uuid
, str
);
673 log_info("saving jack port '%s':'%s' (%s)", client_name
, port_name
, str
);
675 if (!ladish_write_indented_string(fd
, indent
+ 2, "<port name=\""))
680 if (!ladish_write_string(fd
, port_name
))
685 if (!ladish_write_string(fd
, "\" uuid=\""))
690 if (!ladish_write_string(fd
, str
))
695 if (!ladish_write_string(fd
, "\" />\n"))
706 bool ladish_write_dict(int fd
, int indent
, ladish_dict_handle dict
)
708 struct ladish_write_context context
;
710 if (ladish_dict_is_empty(dict
))
716 context
.indent
= indent
+ 1;
718 if (!ladish_write_indented_string(fd
, indent
, "<dict>\n"))
723 if (!ladish_dict_iterate(dict
, &context
, write_dict_entry
))
728 if (!ladish_write_indented_string(fd
, indent
, "</dict>\n"))
736 bool ladish_write_vgraph(int fd
, int indent
, ladish_graph_handle vgraph
, ladish_app_supervisor_handle app_supervisor
)
738 struct ladish_write_context context
;
741 context
.indent
= indent
+ 1;
743 if (!ladish_write_indented_string(fd
, indent
, "<clients>\n"))
748 if (!ladish_graph_iterate_nodes(
753 ladish_save_vgraph_client_begin
,
754 ladish_save_vgraph_port
,
755 ladish_save_vgraph_client_end
))
757 log_error("ladish_graph_iterate_nodes() failed");
761 if (!ladish_write_indented_string(fd
, indent
, "</clients>\n"))
766 if (!ladish_write_indented_string(fd
, indent
, "<connections>\n"))
771 if (!ladish_graph_iterate_connections(vgraph
, true, &context
, ladish_save_vgraph_connection
))
773 log_error("ladish_graph_iterate_connections() failed");
777 if (!ladish_write_indented_string(fd
, indent
, "</connections>\n"))
782 if (!ladish_write_indented_string(fd
, indent
, "<applications>\n"))
787 if (!ladish_app_supervisor_enum(app_supervisor
, &context
, ladish_save_app
))
792 if (!ladish_write_indented_string(fd
, indent
, "</applications>\n"))
800 bool ladish_write_room_link_ports(int fd
, int indent
, ladish_room_handle room
)
802 struct ladish_write_context context
;
805 context
.indent
= indent
;
807 if (!ladish_room_iterate_link_ports(room
, &context
, ladish_write_room_port
))
809 log_error("ladish_room_iterate_link_ports() failed");
816 bool ladish_write_jgraph(int fd
, int indent
, ladish_graph_handle vgraph
)
818 struct ladish_write_context context
;
820 if (!ladish_write_indented_string(fd
, indent
, "<clients>\n"))
826 context
.indent
= indent
+ 1;
828 if (!ladish_graph_iterate_nodes(
829 ladish_studio_get_jack_graph(),
833 ladish_save_jack_client_begin
,
834 ladish_save_jack_port
,
835 ladish_save_jack_client_end
))
837 log_error("ladish_graph_iterate_nodes() failed");
841 if (!ladish_write_indented_string(fd
, indent
, "</clients>\n"))