fix compiler warning
[ladish.git] / daemon / room_save.c
blob763da1535d19295d40071a3742013a92e9fa16ed
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2010,2011 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>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <libgen.h> /* POSIX basename() */
34 #include "room_internal.h"
35 #include "../common/catdup.h"
36 #include "save.h"
37 #include "../common/dirhelpers.h"
38 #include "escape.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)
46 bool ret;
47 time_t timestamp;
48 char timestamp_str[26];
49 char uuid_str[37];
50 char * filename;
51 char * bak_filename;
52 int fd;
54 log_info("Saving project '%s' in room '%s' to '%s'", room_ptr->project_name, room_ptr->name, room_ptr->project_dir);
56 ladish_check_integrity();
58 time(&timestamp);
59 ctime_r(&timestamp, timestamp_str);
60 timestamp_str[24] = 0;
62 ret = false;
64 if (!ensure_dir_exist(room_ptr->project_dir, 0777))
66 goto exit;
69 uuid_generate(room_ptr->project_uuid); /* TODO: the uuid should be changed on "save as" but not on "rename" */
70 uuid_unparse(room_ptr->project_uuid, uuid_str);
72 filename = catdup(room_ptr->project_dir, LADISH_PROJECT_FILENAME);
73 if (filename == NULL)
75 log_error("catdup() failed to compose project xml filename");
76 goto exit;
79 bak_filename = catdup(filename, ".bak");
80 if (bak_filename == NULL)
82 log_error("catdup() failed to compose project xml backup filename");
83 goto free_filename;
86 fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0666);
87 if (fd == -1)
89 log_error("open(%s) failed: %d (%s)", filename, errno, strerror(errno));
90 goto free_bak_filename;
93 if (!ladish_write_string(fd, "<?xml version=\"1.0\"?>\n"))
95 goto close;
98 if (!ladish_write_string(fd, "<!--\n"))
100 goto close;
103 if (!ladish_write_string(fd, PROJECT_HEADER_TEXT))
105 goto close;
108 if (!ladish_write_string(fd, "-->\n"))
110 goto close;
113 if (!ladish_write_string(fd, "<!-- "))
115 goto close;
118 if (!ladish_write_string(fd, timestamp_str))
120 goto close;
123 if (!ladish_write_string(fd, " -->\n"))
125 goto close;
128 if (!ladish_write_string(fd, "<project name=\""))
130 goto close;
133 if (!ladish_write_string_escape(fd, room_ptr->project_name))
135 return false;
138 if (!ladish_write_string(fd, "\" uuid=\""))
140 return false;
143 if (!ladish_write_string(fd, uuid_str))
145 return false;
148 if (!ladish_write_string(fd, "\">\n"))
150 goto close;
153 if (room_ptr->project_description != NULL)
155 if (!ladish_write_indented_string(fd, 1, "<description>"))
157 goto close;
160 if (!ladish_write_string_escape(fd, room_ptr->project_description))
162 goto close;
165 if (!ladish_write_string(fd, "</description>\n"))
167 goto close;
171 if (room_ptr->project_notes != NULL)
173 if (!ladish_write_indented_string(fd, 1, "<notes>"))
175 goto close;
178 if (!ladish_write_string_escape(fd, room_ptr->project_notes))
180 goto close;
183 if (!ladish_write_string(fd, "</notes>\n"))
185 goto close;
189 if (!ladish_write_indented_string(fd, 1, "<room>\n"))
191 goto close;
194 if (!ladish_write_room_link_ports(fd, 2, (ladish_room_handle)room_ptr))
196 log_error("ladish_write_room_link_ports() failed");
197 return false;
200 if (!ladish_write_indented_string(fd, 1, "</room>\n"))
202 goto close;
205 if (!ladish_write_indented_string(fd, 1, "<jack>\n"))
207 goto close;
210 if (!ladish_write_jgraph(fd, 2, room_ptr->graph, room_ptr->app_supervisor))
212 log_error("ladish_write_jgraph() failed for room graph");
213 goto close;
216 if (!ladish_write_indented_string(fd, 1, "</jack>\n"))
218 goto close;
221 if (!ladish_write_vgraph(fd, 1, room_ptr->graph, room_ptr->app_supervisor))
223 log_error("ladish_write_vgraph() failed for studio");
224 goto close;
227 if (!ladish_write_dict(fd, 1, ladish_graph_get_dict(room_ptr->graph)))
229 goto close;
232 if (!ladish_write_string(fd, "</project>\n"))
234 goto close;
237 ladish_app_supervisor_save(room_ptr->app_supervisor);
239 ladish_room_emit_project_properties_changed(room_ptr);
241 ret = true;
243 close:
244 close(fd);
245 free_bak_filename:
246 free(bak_filename);
247 free_filename:
248 free(filename);
249 exit:
250 return ret;
253 /* TODO: base dir must be a runtime setting */
254 char * compose_project_dir_from_name(const char * project_name)
256 const char * home_dir;
257 char * project_dir;
258 size_t home_dir_len;
260 home_dir = getenv("HOME");
261 home_dir_len = strlen(home_dir);
263 project_dir = malloc(home_dir_len + DEFAULT_PROJECT_BASE_DIR_LEN + max_escaped_length(strlen(project_name)) + 1);
264 if (project_dir == NULL)
266 log_error("malloc() failed to allocate buffer for project dir");
267 return NULL;
270 memcpy(project_dir, home_dir, home_dir_len);
271 memcpy(project_dir + home_dir_len, DEFAULT_PROJECT_BASE_DIR, DEFAULT_PROJECT_BASE_DIR_LEN);
272 escape_simple(project_name, project_dir + home_dir_len + DEFAULT_PROJECT_BASE_DIR_LEN, LADISH_ESCAPE_FLAG_ALL);
274 return project_dir;
277 #define room_ptr ((struct ladish_room *)room_handle)
279 bool
280 ladish_room_save_project(
281 ladish_room_handle room_handle,
282 const char * project_dir_param,
283 const char * project_name_param)
285 bool first_time;
286 bool dir_supplied;
287 bool name_supplied;
288 char * project_dir;
289 char * project_name;
290 char * old_project_dir;
291 char * old_project_name;
292 char * buffer;
293 bool ret;
295 ret = false;
296 project_name = NULL;
297 project_dir = NULL;
299 /* project has either both name and dir no none of them */
300 ASSERT((room_ptr->project_dir == NULL && room_ptr->project_name == NULL) || (room_ptr->project_dir != NULL && room_ptr->project_name != NULL));
301 first_time = room_ptr->project_dir == NULL;
303 dir_supplied = strlen(project_dir_param) != 0;
304 name_supplied = strlen(project_name_param) != 0;
306 if (first_time)
308 if (!dir_supplied && !name_supplied)
310 log_error("Cannot save unnamed project in room '%s'", room_ptr->name);
311 goto exit;
314 if (dir_supplied && name_supplied)
316 project_dir = strdup(project_dir_param);
317 project_name = strdup(project_name_param);
319 else if (dir_supplied)
321 ASSERT(!name_supplied);
323 buffer = strdup(project_dir_param);
324 if (buffer == NULL)
326 log_error("strdup() failed for project dir");
327 goto exit;
330 project_name = basename(buffer);
331 log_info("Project name for dir '%s' will be '%s'", project_dir_param, project_name);
332 project_name = strdup(project_name);
333 free(buffer);
334 project_dir = strdup(project_dir_param); /* buffer cannot be used because it may be modified by basename() */
336 else if (name_supplied)
338 ASSERT(!dir_supplied);
340 project_dir = compose_project_dir_from_name(project_name_param);
341 if (!project_dir)
343 goto exit;
346 log_info("Project dir for name '%s' will be '%s'", project_name_param, project_dir);
348 project_name = strdup(project_name_param);
350 else
352 ASSERT_NO_PASS;
353 goto exit;
356 ladish_app_supervisor_set_directory(room_ptr->app_supervisor, project_dir);
358 else
360 ASSERT(room_ptr->project_name != NULL);
361 ASSERT(room_ptr->project_dir != NULL);
363 project_name = name_supplied ? strdup(project_name_param) : room_ptr->project_name;
364 project_dir = dir_supplied ? strdup(project_dir_param) : room_ptr->project_dir;
367 if (project_name == NULL || project_dir == NULL)
369 log_error("strdup() failed for project name or dir");
370 goto exit;
373 old_project_dir = room_ptr->project_dir;
374 old_project_name = room_ptr->project_name;
375 room_ptr->project_name = project_name;
376 room_ptr->project_dir = project_dir;
377 ret = ladish_room_save_project_do(room_ptr);
378 if (!ret)
380 room_ptr->project_name = old_project_name;
381 room_ptr->project_dir = old_project_dir;
383 else
385 room_ptr->project_state = ROOM_PROJECT_STATE_LOADED;
388 exit:
389 if (project_name != NULL && project_name != room_ptr->project_name)
391 free(room_ptr->project_name);
394 if (project_dir != NULL && project_dir != room_ptr->project_dir)
396 free(room_ptr->project_dir);
399 /* free strings that are allocated and stored only in the stack */
400 if (project_name != NULL && project_name != room_ptr->project_name)
402 free(project_name);
404 if (project_dir != NULL && project_dir != room_ptr->project_dir)
406 free(project_dir);
409 return ret;
412 #undef room_ptr