diff --git a/daemon/app_supervisor.c b/daemon/app_supervisor.c index d2616501..d23d9ad2 100644 --- a/daemon/app_supervisor.c +++ b/daemon/app_supervisor.c @@ -52,6 +52,7 @@ struct ladish_app_supervisor { char * name; char * opath; + char * dir; uint64_t version; uint64_t next_id; struct list_head applist; @@ -93,6 +94,8 @@ ladish_app_supervisor_create( return false; } + supervisor_ptr->dir = NULL; + supervisor_ptr->version = 0; supervisor_ptr->next_id = 1; @@ -273,6 +276,12 @@ void ladish_app_supervisor_clear(ladish_app_supervisor_handle supervisor_handle) struct list_head * safe_node_ptr; struct ladish_app * app_ptr; + if (supervisor_ptr->dir != NULL) + { + free(supervisor_ptr->dir); + supervisor_ptr->dir = NULL; + } + list_for_each_safe(node_ptr, safe_node_ptr, &supervisor_ptr->applist) { app_ptr = list_entry(node_ptr, struct ladish_app, siblings); @@ -299,6 +308,30 @@ void ladish_app_supervisor_destroy(ladish_app_supervisor_handle supervisor_handl free(supervisor_ptr); } +bool +ladish_app_supervisor_set_directory( + ladish_app_supervisor_handle supervisor_handle, + const char * dir) +{ + char * dup; + + dup = strdup(dir); + if (dup == NULL) + { + log_error("strdup(\"%s\") failed", dir); + return false; + } + + if (supervisor_ptr->dir != NULL) + { + free(supervisor_ptr->dir); + } + + supervisor_ptr->dir = dup; + + return true; +} + bool ladish_app_supervisor_child_exit(ladish_app_supervisor_handle supervisor_handle, pid_t pid) { struct list_head * node_ptr; @@ -365,7 +398,13 @@ bool ladish_app_supervisor_start_app(ladish_app_supervisor_handle supervisor_han ASSERT(app_ptr->pid == 0); - if (!loader_execute(supervisor_ptr->name, app_ptr->name, "/", app_ptr->terminal, app_ptr->commandline, &app_ptr->pid)) + if (!loader_execute( + supervisor_ptr->name, + app_ptr->name, + supervisor_ptr->dir != NULL ? supervisor_ptr->dir : "/", + app_ptr->terminal, + app_ptr->commandline, + &app_ptr->pid)) { return false; } diff --git a/daemon/app_supervisor.h b/daemon/app_supervisor.h index bca7d08e..e8ea5066 100644 --- a/daemon/app_supervisor.h +++ b/daemon/app_supervisor.h @@ -107,6 +107,18 @@ void ladish_app_supervisor_destroy( ladish_app_supervisor_handle supervisor_handle); +/** + * Set the directory where apps will be started. If never called, apps will be started in the root directory ("/") + * + * @param[in] supervisor_handle supervisor object handle + * + * @return success status + */ +bool +ladish_app_supervisor_set_directory( + ladish_app_supervisor_handle supervisor_handle, + const char * dir); + /** * Mark that app has quit * diff --git a/daemon/room.c b/daemon/room.c index 1e7c95bd..afdf4352 100644 --- a/daemon/room.c +++ b/daemon/room.c @@ -5,7 +5,7 @@ * Copyright (C) 2010 Nedko Arnaudov * ************************************************************************** - * This file contains implementation of the room object + * This file contains the core parts of room object implementation ************************************************************************** * * LADI Session Handler is free software; you can redistribute it and/or modify @@ -24,7 +24,7 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "room.h" +#include "room_internal.h" #include "../dbus_constants.h" #include "graph_dict.h" #include "../lib/wkports.h" @@ -33,28 +33,6 @@ #include "cmd.h" #include "../dbus/error.h" -struct ladish_room -{ - struct list_head siblings; - uuid_t uuid; - char * name; - bool template; - - /* these are not valid for templates */ - uuid_t template_uuid; - ladish_graph_handle owner; - unsigned int index; - char * object_path; - dbus_object_path dbus_object; - ladish_graph_handle graph; - ladish_app_supervisor_handle app_supervisor; - ladish_client_handle client; - bool started; - - char * project_dir; - char * project_name; -}; - extern const struct dbus_interface_descriptor g_interface_room; /* implemented in studio.c */ @@ -690,112 +668,6 @@ fail: return NULL; } -bool -ladish_room_save_project( - ladish_room_handle room_handle, - const char * project_dir_param, - const char * project_name_param) -{ - bool first_time; - bool dir_supplied; - bool name_supplied; - char * project_dir; - char * project_name; - bool ret; - - ret = false; - project_name = NULL; - project_dir = NULL; - - /* project has either both name and dir no none of them */ - ASSERT((room_ptr->project_dir == NULL && room_ptr->project_name == NULL) || (room_ptr->project_dir != NULL && room_ptr->project_name != NULL)); - first_time = room_ptr->project_dir == NULL; - - dir_supplied = strlen(project_dir_param) != 0; - name_supplied = strlen(project_name_param) != 0; - - if (first_time) - { - if (!dir_supplied && !name_supplied) - { - log_error("Cannot save unnamed project in room '%s'", room_ptr->name); - goto exit; - } - - if (dir_supplied && name_supplied) - { - project_dir = strdup(project_dir_param); - project_name = strdup(project_name_param); - } - else if (dir_supplied) - { - ASSERT(!name_supplied); - /* TODO */ - log_error("Deducing project name from project dir is not implemented yet"); - goto exit; - } - else if (name_supplied) - { - ASSERT(!dir_supplied); - /* TODO */ - log_error("Deducing project dir from project name is not implemented yet"); - goto exit; - } - else - { - ASSERT_NO_PASS; - goto exit; - } - } - else - { - ASSERT(room_ptr->project_name != NULL); - ASSERT(room_ptr->project_dir != NULL); - - project_name = name_supplied ? strdup(project_name_param) : room_ptr->project_name; - project_dir = dir_supplied ? strdup(project_dir_param) : room_ptr->project_dir; - } - - if (project_name == NULL || project_dir == NULL) - { - log_error("strdup() failed for project name or dir"); - goto exit; - } - - log_info("Saving project '%s' in room '%s' to '%s'", project_name, room_ptr->name, project_dir); - log_error("NOT IMPLEMENTED YET"); - ret = true; - -exit: - if (ret) - { - ASSERT(project_name != NULL); - if (project_name != room_ptr->project_name) - { - free(room_ptr->project_name); - room_ptr->project_name = project_name; - } - ASSERT(project_dir != NULL); - if (project_dir != room_ptr->project_dir) - { - free(room_ptr->project_dir); - room_ptr->project_dir = project_dir; - } - } - - /* free strings that are allocated and stored only in the stack */ - if (project_name != NULL && project_name != room_ptr->project_name) - { - free(project_name); - } - if (project_dir != NULL && project_dir != room_ptr->project_dir) - { - free(project_dir); - } - - return ret; -} - #undef room_ptr ladish_room_handle ladish_room_from_list_node(struct list_head * node_ptr) diff --git a/daemon/room_internal.h b/daemon/room_internal.h new file mode 100644 index 00000000..7126f82b --- /dev/null +++ b/daemon/room_internal.h @@ -0,0 +1,57 @@ +/* -*- Mode: C ; c-basic-offset: 2 -*- */ +/* + * LADI Session Handler (ladish) + * + * Copyright (C) 2010 Nedko Arnaudov + * + ************************************************************************** + * This file contains internal declarations used by the room object implementation + ************************************************************************** + * + * LADI Session Handler is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LADI Session Handler is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LADI Session Handler. If not, see + * or write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef ROOM_INTERNAL_H__FAF5B68F_E419_442A_8F9B_C729BAC00422__INCLUDED +#define ROOM_INTERNAL_H__FAF5B68F_E419_442A_8F9B_C729BAC00422__INCLUDED + +#include "room.h" + +#define LADISH_PROJECT_FILENAME "/ladish-project.xml" + +struct ladish_room +{ + struct list_head siblings; + uuid_t uuid; + char * name; + bool template; + + /* these are not valid for templates */ + uuid_t template_uuid; + ladish_graph_handle owner; + unsigned int index; + char * object_path; + dbus_object_path dbus_object; + ladish_graph_handle graph; + ladish_app_supervisor_handle app_supervisor; + ladish_client_handle client; + bool started; + + uuid_t project_uuid; + char * project_dir; + char * project_name; +}; + +#endif /* #ifndef ROOM_INTERNAL_H__FAF5B68F_E419_442A_8F9B_C729BAC00422__INCLUDED */ diff --git a/daemon/room_save.c b/daemon/room_save.c new file mode 100644 index 00000000..25d5d070 --- /dev/null +++ b/daemon/room_save.c @@ -0,0 +1,298 @@ +/* -*- Mode: C ; c-basic-offset: 2 -*- */ +/* + * LADI Session Handler (ladish) + * + * Copyright (C) 2010 Nedko Arnaudov + * + ************************************************************************** + * This file contains the parts of room object implementation + * that are related to project save functionality + ************************************************************************** + * + * LADI Session Handler is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LADI Session Handler is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LADI Session Handler. If not, see + * or write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include + +#include "room_internal.h" +#include "../catdup.h" +#include "save.h" + +#define PROJECT_HEADER_TEXT BASE_NAME " Project.\n" + +static bool ladish_room_save_project_do(struct ladish_room * room_ptr) +{ + bool ret; + time_t timestamp; + char timestamp_str[26]; + char uuid_str[37]; + char * filename; + char * bak_filename; + int fd; + + log_info("Saving project '%s' in room '%s' to '%s'", room_ptr->project_name, room_ptr->name, room_ptr->project_dir); + + time(×tamp); + ctime_r(×tamp, timestamp_str); + timestamp_str[24] = 0; + + ret = false; + + uuid_generate(room_ptr->project_uuid); /* TODO: the uuid should be changed on "save as" but not on "rename" */ + uuid_unparse(room_ptr->project_uuid, uuid_str); + + filename = catdup(room_ptr->project_dir, LADISH_PROJECT_FILENAME); + if (filename == NULL) + { + log_error("catdup() failed to compose project xml filename"); + goto exit; + } + + bak_filename = catdup(filename, ".bak"); + if (bak_filename == NULL) + { + log_error("catdup() failed to compose project xml backup filename"); + goto free_filename; + } + + fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0666); + if (fd == -1) + { + log_error("open(%s) failed: %d (%s)", filename, errno, strerror(errno)); + goto free_bak_filename; + } + + if (!ladish_write_string(fd, "\n")) + { + goto close; + } + + if (!ladish_write_string(fd, "\n")) + { + goto close; + } + + if (!ladish_write_string(fd, "\n")) + { + goto close; + } + + if (!ladish_write_string(fd, "project_name)) /* TODO: escaping */ + { + return false; + } + + if (!ladish_write_string(fd, "\" uuid=\"")) + { + return false; + } + + if (!ladish_write_string(fd, uuid_str)) + { + return false; + } + + if (!ladish_write_string(fd, "\">\n")) + { + goto close; + } + + if (!ladish_write_indented_string(fd, 1, "\n")) + { + goto close; + } + + if (!ladish_write_room_link_ports(fd, 2, (ladish_room_handle)room_ptr)) + { + log_error("ladish_write_room_link_ports() failed"); + return false; + } + + if (!ladish_write_indented_string(fd, 1, "\n")) + { + goto close; + } + + if (!ladish_write_vgraph(fd, 1, room_ptr->graph, room_ptr->app_supervisor)) + { + log_error("ladish_write_vgraph() failed for studio"); + goto close; + } + + if (!ladish_write_dict(fd, 1, ladish_graph_get_dict(room_ptr->graph))) + { + goto close; + } + + if (!ladish_write_string(fd, "\n")) + { + goto close; + } + + ret = true; + +close: + close(fd); +free_bak_filename: + free(bak_filename); +free_filename: + free(filename); +exit: + return ret; +} + +#define room_ptr ((struct ladish_room *)room_handle) + +bool +ladish_room_save_project( + ladish_room_handle room_handle, + const char * project_dir_param, + const char * project_name_param) +{ + bool first_time; + bool dir_supplied; + bool name_supplied; + char * project_dir; + char * project_name; + char * old_project_dir; + char * old_project_name; + bool ret; + + ret = false; + project_name = NULL; + project_dir = NULL; + + /* project has either both name and dir no none of them */ + ASSERT((room_ptr->project_dir == NULL && room_ptr->project_name == NULL) || (room_ptr->project_dir != NULL && room_ptr->project_name != NULL)); + first_time = room_ptr->project_dir == NULL; + + dir_supplied = strlen(project_dir_param) != 0; + name_supplied = strlen(project_name_param) != 0; + + if (first_time) + { + if (!dir_supplied && !name_supplied) + { + log_error("Cannot save unnamed project in room '%s'", room_ptr->name); + goto exit; + } + + if (dir_supplied && name_supplied) + { + project_dir = strdup(project_dir_param); + project_name = strdup(project_name_param); + } + else if (dir_supplied) + { + ASSERT(!name_supplied); + /* TODO */ + log_error("Deducing project name from project dir is not implemented yet"); + goto exit; + } + else if (name_supplied) + { + ASSERT(!dir_supplied); + /* TODO */ + log_error("Deducing project dir from project name is not implemented yet"); + goto exit; + } + else + { + ASSERT_NO_PASS; + goto exit; + } + + ladish_app_supervisor_set_directory(room_ptr->app_supervisor, project_dir); + } + else + { + ASSERT(room_ptr->project_name != NULL); + ASSERT(room_ptr->project_dir != NULL); + + project_name = name_supplied ? strdup(project_name_param) : room_ptr->project_name; + project_dir = dir_supplied ? strdup(project_dir_param) : room_ptr->project_dir; + } + + if (project_name == NULL || project_dir == NULL) + { + log_error("strdup() failed for project name or dir"); + goto exit; + } + + old_project_dir = room_ptr->project_dir; + old_project_name = room_ptr->project_name; + room_ptr->project_name = project_name; + room_ptr->project_dir = project_dir; + ret = ladish_room_save_project_do(room_ptr); + if (!ret) + { + room_ptr->project_name = old_project_name; + room_ptr->project_dir = old_project_dir; + } + +exit: + if (project_name != NULL && project_name != room_ptr->project_name) + { + free(room_ptr->project_name); + } + + if (project_dir != NULL && project_dir != room_ptr->project_dir) + { + free(room_ptr->project_dir); + } + + /* free strings that are allocated and stored only in the stack */ + if (project_name != NULL && project_name != room_ptr->project_name) + { + free(project_name); + } + if (project_dir != NULL && project_dir != room_ptr->project_dir) + { + free(project_dir); + } + + return ret; +} + +#undef room_ptr diff --git a/daemon/save.c b/daemon/save.c index 8fb45b2b..b82a10e7 100644 --- a/daemon/save.c +++ b/daemon/save.c @@ -28,6 +28,7 @@ #include "save.h" #include "escape.h" +#include "studio.h" bool ladish_write_string(int fd, const char * string) { @@ -182,11 +183,18 @@ static bool ladish_get_vgraph_port_uuids(ladish_graph_handle vgraph, ladish_port { bool link; - link = ladish_port_is_link(port); - if (link) + if (vgraph != ladish_studio_get_studio_graph()) { - /* get the generated port uuid that is used for identification in the virtual graph */ - ladish_graph_get_port_uuid(vgraph, port, uuid); + link = false; /* room ports are saved using their fixed uuids */ + } + else + { + link = ladish_port_is_link(port); + if (link) + { + /* get the generated port uuid that is used for identification in the virtual graph */ + ladish_graph_get_port_uuid(vgraph, port, uuid); + } } if (!link || link_uuid != NULL) @@ -483,7 +491,7 @@ ladish_write_room_port( ASSERT(!(midi && type == JACKDBUS_PORT_TYPE_AUDIO)); /* but not both */ type_str = midi ? "midi" : "audio"; - log_info("saving studio room %s %s port '%s' (%s)", direction_str, type_str, name, str); + log_info("saving room %s %s port '%s' (%s)", direction_str, type_str, name, str); if (!ladish_write_indented_string(fd, indent, "