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 the parts of room object implementation
9 * that are related to project save functionality
10 **************************************************************************
12 * LADI Session Handler is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * LADI Session Handler is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
24 * or write to the Free Software Foundation, Inc.,
25 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <sys/types.h>
32 #include <libgen.h> /* POSIX basename() */
34 #include "room_internal.h"
35 #include "../common/catdup.h"
37 #include "../common/dirhelpers.h"
40 #define PROJECT_HEADER_TEXT BASE_NAME " Project.\n"
41 #define DEFAULT_PROJECT_BASE_DIR "/ladish-projects/"
42 #define DEFAULT_PROJECT_BASE_DIR_LEN ((size_t)(sizeof(DEFAULT_PROJECT_BASE_DIR) - 1))
44 static bool ladish_room_save_project_do(struct ladish_room
* room_ptr
)
48 char timestamp_str
[26];
52 char * escaped_project_name
;
55 log_info("Saving project '%s' in room '%s' to '%s'", room_ptr
->project_name
, room_ptr
->name
, room_ptr
->project_dir
);
58 ctime_r(×tamp
, timestamp_str
);
59 timestamp_str
[24] = 0;
63 if (!ensure_dir_exist(room_ptr
->project_dir
, 0777))
68 uuid_generate(room_ptr
->project_uuid
); /* TODO: the uuid should be changed on "save as" but not on "rename" */
69 uuid_unparse(room_ptr
->project_uuid
, uuid_str
);
71 escaped_project_name
= malloc(max_escaped_length(strlen(room_ptr
->project_name
)) + 1);
72 if (escaped_project_name
== NULL
)
74 log_error("malloc() failed to allocate buffer for storing escaped project name");
78 filename
= catdup(room_ptr
->project_dir
, LADISH_PROJECT_FILENAME
);
81 log_error("catdup() failed to compose project xml filename");
82 goto free_escaped_project_name
;
85 escape_simple(room_ptr
->project_name
, escaped_project_name
);
87 bak_filename
= catdup(filename
, ".bak");
88 if (bak_filename
== NULL
)
90 log_error("catdup() failed to compose project xml backup filename");
94 fd
= open(filename
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
97 log_error("open(%s) failed: %d (%s)", filename
, errno
, strerror(errno
));
98 goto free_bak_filename
;
101 if (!ladish_write_string(fd
, "<?xml version=\"1.0\"?>\n"))
106 if (!ladish_write_string(fd
, "<!--\n"))
111 if (!ladish_write_string(fd
, PROJECT_HEADER_TEXT
))
116 if (!ladish_write_string(fd
, "-->\n"))
121 if (!ladish_write_string(fd
, "<!-- "))
126 if (!ladish_write_string(fd
, timestamp_str
))
131 if (!ladish_write_string(fd
, " -->\n"))
136 if (!ladish_write_string(fd
, "<project name=\""))
141 if (!ladish_write_string(fd
, escaped_project_name
))
146 if (!ladish_write_string(fd
, "\" uuid=\""))
151 if (!ladish_write_string(fd
, uuid_str
))
156 if (!ladish_write_string(fd
, "\">\n"))
161 if (!ladish_write_indented_string(fd
, 1, "<room>\n"))
166 if (!ladish_write_room_link_ports(fd
, 2, (ladish_room_handle
)room_ptr
))
168 log_error("ladish_write_room_link_ports() failed");
172 if (!ladish_write_indented_string(fd
, 1, "</room>\n"))
177 if (!ladish_write_indented_string(fd
, 1, "<jack>\n"))
182 if (!ladish_write_jgraph(fd
, 2, room_ptr
->graph
))
184 log_error("ladish_write_jgraph() failed for room graph");
188 if (!ladish_write_indented_string(fd
, 1, "</jack>\n"))
193 if (!ladish_write_vgraph(fd
, 1, room_ptr
->graph
, room_ptr
->app_supervisor
))
195 log_error("ladish_write_vgraph() failed for studio");
199 if (!ladish_write_dict(fd
, 1, ladish_graph_get_dict(room_ptr
->graph
)))
204 if (!ladish_write_string(fd
, "</project>\n"))
209 ladish_app_supervisor_save_L1(room_ptr
->app_supervisor
);
211 ladish_room_emit_project_properties_changed(room_ptr
);
221 free_escaped_project_name
:
222 free(escaped_project_name
);
227 /* TODO: base dir must be a runtime setting */
228 char * compose_project_dir_from_name(const char * project_name
)
230 const char * home_dir
;
234 home_dir
= getenv("HOME");
235 home_dir_len
= strlen(home_dir
);
237 project_dir
= malloc(home_dir_len
+ DEFAULT_PROJECT_BASE_DIR_LEN
+ max_escaped_length(strlen(project_name
)) + 1);
238 if (project_dir
== NULL
)
240 log_error("malloc() failed to allocate buffer for project dir");
244 memcpy(project_dir
, home_dir
, home_dir_len
);
245 memcpy(project_dir
+ home_dir_len
, DEFAULT_PROJECT_BASE_DIR
, DEFAULT_PROJECT_BASE_DIR_LEN
);
246 escape_simple(project_name
, project_dir
+ home_dir_len
+ DEFAULT_PROJECT_BASE_DIR_LEN
);
251 #define room_ptr ((struct ladish_room *)room_handle)
254 ladish_room_save_project(
255 ladish_room_handle room_handle
,
256 const char * project_dir_param
,
257 const char * project_name_param
)
264 char * old_project_dir
;
265 char * old_project_name
;
273 /* project has either both name and dir no none of them */
274 ASSERT((room_ptr
->project_dir
== NULL
&& room_ptr
->project_name
== NULL
) || (room_ptr
->project_dir
!= NULL
&& room_ptr
->project_name
!= NULL
));
275 first_time
= room_ptr
->project_dir
== NULL
;
277 dir_supplied
= strlen(project_dir_param
) != 0;
278 name_supplied
= strlen(project_name_param
) != 0;
282 if (!dir_supplied
&& !name_supplied
)
284 log_error("Cannot save unnamed project in room '%s'", room_ptr
->name
);
288 if (dir_supplied
&& name_supplied
)
290 project_dir
= strdup(project_dir_param
);
291 project_name
= strdup(project_name_param
);
293 else if (dir_supplied
)
295 ASSERT(!name_supplied
);
297 buffer
= strdup(project_dir_param
);
300 log_error("strdup() failed for project dir");
304 project_name
= basename(buffer
);
305 log_info("Project name for dir '%s' will be '%s'", project_dir_param
, project_name
);
306 project_name
= strdup(project_name
);
308 project_dir
= strdup(project_dir_param
); /* buffer cannot be used because it may be modified by basename() */
310 else if (name_supplied
)
312 ASSERT(!dir_supplied
);
314 project_dir
= compose_project_dir_from_name(project_name_param
);
320 log_info("Project dir for name '%s' will be '%s'", project_name_param
, project_dir
);
322 project_name
= strdup(project_name_param
);
330 ladish_app_supervisor_set_directory(room_ptr
->app_supervisor
, project_dir
);
334 ASSERT(room_ptr
->project_name
!= NULL
);
335 ASSERT(room_ptr
->project_dir
!= NULL
);
337 project_name
= name_supplied
? strdup(project_name_param
) : room_ptr
->project_name
;
338 project_dir
= dir_supplied
? strdup(project_dir_param
) : room_ptr
->project_dir
;
341 if (project_name
== NULL
|| project_dir
== NULL
)
343 log_error("strdup() failed for project name or dir");
347 old_project_dir
= room_ptr
->project_dir
;
348 old_project_name
= room_ptr
->project_name
;
349 room_ptr
->project_name
= project_name
;
350 room_ptr
->project_dir
= project_dir
;
351 ret
= ladish_room_save_project_do(room_ptr
);
354 room_ptr
->project_name
= old_project_name
;
355 room_ptr
->project_dir
= old_project_dir
;
359 if (project_name
!= NULL
&& project_name
!= room_ptr
->project_name
)
361 free(room_ptr
->project_name
);
364 if (project_dir
!= NULL
&& project_dir
!= room_ptr
->project_dir
)
366 free(room_ptr
->project_dir
);
369 /* free strings that are allocated and stored only in the stack */
370 if (project_name
!= NULL
&& project_name
!= room_ptr
->project_name
)
374 if (project_dir
!= NULL
&& project_dir
!= room_ptr
->project_dir
)