gui: update full view name on view name change. Fix for #105
[ladish.git] / daemon / cmd_stop_studio.c
blob34060a12f731cfdc4cd745e1d333a65569cdb348
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains implementation of the "stop studio" command
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.
27 #include <unistd.h>
29 #include "cmd.h"
30 #include "studio_internal.h"
31 #include "loader.h"
32 #include "../common/time.h"
33 #include "studio.h"
35 #define STOP_STATE_WAITING_FOR_ROOM_STOP 1
36 #define STOP_STATE_WAITING_FOR_JACK_CLIENTS_DISAPPEAR 2
37 #define STOP_STATE_WAITING_FOR_CHILDS_TERMINATION 3
38 #define STOP_STATE_WAITING_FOR_JACK_SERVER_STOP 4
40 struct ladish_command_stop_studio
42 struct ladish_command command;
43 uint64_t deadline;
44 unsigned int stop_state;
47 static bool stop_room(void * context, ladish_room_handle room)
49 ladish_room_initiate_stop(room, false);
50 return true;
53 static bool room_stopped(void * context, ladish_room_handle room)
55 return ladish_room_stopped(room);
58 #define cmd_ptr ((struct ladish_command_stop_studio *)context)
60 static bool run(void * context)
62 bool jack_server_started;
63 unsigned int clients_count;
65 switch (cmd_ptr->command.state)
67 case LADISH_COMMAND_STATE_PENDING:
68 if (!ladish_studio_is_started())
70 log_info("Ignoring stop request because studio is already stopped.");
71 /* nothing to do, studio is not running */
72 cmd_ptr->command.state = LADISH_COMMAND_STATE_DONE;
73 return true;
76 ladish_graph_dump(g_studio.jack_graph);
77 ladish_graph_dump(g_studio.studio_graph);
79 ladish_studio_stop_app_supervisors();
81 cmd_ptr->command.state = LADISH_COMMAND_STATE_WAITING;
82 cmd_ptr->stop_state = STOP_STATE_WAITING_FOR_ROOM_STOP;
84 if (!ladish_studio_iterate_rooms(ladish_studio_get_virtualizer(), stop_room))
86 log_error("room stop initiation failed");
87 return false;
90 /* fall through */
91 case LADISH_COMMAND_STATE_WAITING:
92 if (cmd_ptr->stop_state == STOP_STATE_WAITING_FOR_ROOM_STOP)
94 if (!ladish_studio_iterate_rooms(ladish_studio_get_virtualizer(), room_stopped))
96 return true;
99 cmd_ptr->stop_state = STOP_STATE_WAITING_FOR_JACK_CLIENTS_DISAPPEAR;
102 if (cmd_ptr->stop_state == STOP_STATE_WAITING_FOR_JACK_CLIENTS_DISAPPEAR)
104 clients_count = ladish_virtualizer_get_our_clients_count(g_studio.virtualizer);
105 log_info("%u JACK clients started by ladish are visible", clients_count);
106 if (clients_count != 0)
108 return true;
111 cmd_ptr->stop_state = STOP_STATE_WAITING_FOR_CHILDS_TERMINATION;
114 if (cmd_ptr->stop_state == STOP_STATE_WAITING_FOR_CHILDS_TERMINATION)
116 clients_count = loader_get_app_count();
117 log_info("%u child processes are running", clients_count);
118 if (clients_count != 0)
120 return true;
123 log_info("Stopping JACK server...");
125 ladish_graph_dump(g_studio.studio_graph);
127 cmd_ptr->stop_state = STOP_STATE_WAITING_FOR_JACK_SERVER_STOP;
129 if (!jack_proxy_stop_server())
131 log_error("Stopping JACK server failed. Waiting stop for 5 seconds anyway...");
133 /* JACK server stop sometimes fail, even if it actually succeeds after some time */
134 /* Reproducable with yoshimi-0.0.45 */
136 cmd_ptr->deadline = ladish_get_current_microseconds();
137 if (cmd_ptr->deadline != 0)
139 cmd_ptr->deadline += 5000000;
142 return true;
146 ASSERT(cmd_ptr->stop_state == STOP_STATE_WAITING_FOR_JACK_SERVER_STOP);
148 if (cmd_ptr->deadline != 0)
150 if (jack_proxy_is_started(&jack_server_started) && !jack_server_started)
152 ladish_environment_reset_stealth(&g_studio.env_store, ladish_environment_jack_server_started);
153 goto done;
156 if (ladish_get_current_microseconds() >= cmd_ptr->deadline)
158 log_error("JACK server stop wait after stop request expired (5 seconds).");
159 cmd_ptr->command.state = LADISH_COMMAND_STATE_DONE;
160 return false;
163 return true;
166 if (!ladish_environment_consume_change(&g_studio.env_store, ladish_environment_jack_server_started, &jack_server_started))
168 /* we are still waiting for the JACK server stop */
169 ASSERT(ladish_environment_get(&g_studio.env_store, ladish_environment_jack_server_started)); /* someone else consumed the state change? */
170 return true;
173 done:
174 log_info("Wait for JACK server stop complete.");
176 ladish_graph_hide_non_virtual(g_studio.jack_graph);
177 ladish_graph_hide_non_virtual(g_studio.studio_graph);
178 ASSERT(!jack_server_started);
180 ladish_graph_dump(g_studio.studio_graph);
182 ladish_studio_on_event_jack_stopped();
184 cmd_ptr->command.state = LADISH_COMMAND_STATE_DONE;
185 return true;
188 ASSERT_NO_PASS;
189 return false;
192 #undef cmd_ptr
194 bool ladish_command_stop_studio(void * call_ptr, struct ladish_cqueue * queue_ptr)
196 struct ladish_command_stop_studio * cmd_ptr;
198 cmd_ptr = ladish_command_new(sizeof(struct ladish_command_stop_studio));
199 if (cmd_ptr == NULL)
201 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "ladish_command_new() failed.");
202 goto fail;
205 cmd_ptr->command.run = run;
206 cmd_ptr->deadline = 0;
208 if (!ladish_cqueue_add_command(queue_ptr, &cmd_ptr->command))
210 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "ladish_cqueue_add_command() failed.");
211 goto fail_destroy_command;
214 return true;
216 fail_destroy_command:
217 free(cmd_ptr);
219 fail:
220 return false;