D-Bus access for jackctl_server_add_slave/jackctl_server_remove_slave API.
[jack2.git] / dbus / controller.c
blobf5c53f69b1c1900219feb7a2fadd8a936cccd273
1 /* -*- Mode: C ; c-basic-offset: 4 -*- */
2 /*
3 Copyright (C) 2007,2008 Nedko Arnaudov
4 Copyright (C) 2007-2008 Juuso Alasuutari
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #if defined(HAVE_CONFIG_H)
22 #include "config.h"
23 #endif
25 #include <stdint.h>
26 #include <string.h>
27 #include <dbus/dbus.h>
29 #include "controller.h"
30 #include "controller_internal.h"
31 #include "xml.h"
33 struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[] =
35 &g_jack_controller_iface_introspectable,
36 &g_jack_controller_iface_control,
37 &g_jack_controller_iface_configure,
38 &g_jack_controller_iface_patchbay,
39 &g_jack_controller_iface_transport,
40 NULL
43 jackctl_driver_t *
44 jack_controller_find_driver(
45 jackctl_server_t *server,
46 const char *driver_name)
48 const JSList * node_ptr;
50 node_ptr = jackctl_server_get_drivers_list(server);
52 while (node_ptr)
54 if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0)
56 return node_ptr->data;
59 node_ptr = jack_slist_next(node_ptr);
62 return NULL;
65 jackctl_internal_t *
66 jack_controller_find_internal(
67 jackctl_server_t *server,
68 const char *internal_name)
70 const JSList * node_ptr;
72 node_ptr = jackctl_server_get_internals_list(server);
74 while (node_ptr)
76 if (strcmp(jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data), internal_name) == 0)
78 return node_ptr->data;
81 node_ptr = jack_slist_next(node_ptr);
84 return NULL;
87 jackctl_parameter_t *
88 jack_controller_find_parameter(
89 const JSList * parameters_list,
90 const char * parameter_name)
92 while (parameters_list)
94 if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0)
96 return parameters_list->data;
99 parameters_list = jack_slist_next(parameters_list);
102 return NULL;
105 bool
106 jack_controller_select_driver(
107 struct jack_controller * controller_ptr,
108 const char * driver_name)
110 jackctl_driver_t *driver;
112 driver = jack_controller_find_driver(controller_ptr->server, driver_name);
113 if (driver == NULL)
115 return false;
118 jack_info("driver \"%s\" selected", driver_name);
120 controller_ptr->driver = driver;
121 controller_ptr->driver_set = true;
123 return true;
126 static
128 jack_controller_xrun(void * arg)
130 ((struct jack_controller *)arg)->xruns++;
132 return 0;
135 bool
136 jack_controller_start_server(
137 struct jack_controller * controller_ptr,
138 void *dbus_call_context_ptr)
140 int ret;
142 jack_info("Starting jack server...");
144 if (controller_ptr->started)
146 jack_info("Already started.");
147 return TRUE;
150 if (controller_ptr->driver == NULL)
152 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Select driver first!");
153 goto fail;
156 controller_ptr->xruns = 0;
158 if (!jackctl_server_start(
159 controller_ptr->server,
160 controller_ptr->driver))
162 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server");
163 goto fail;
166 controller_ptr->client = jack_client_open(
167 "dbusapi",
168 JackNoStartServer,
169 NULL);
170 if (controller_ptr->client == NULL)
172 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to create dbusapi jack client");
174 goto fail_stop_server;
177 ret = jack_set_xrun_callback(controller_ptr->client, jack_controller_xrun, controller_ptr);
178 if (ret != 0)
180 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to set xrun callback. error is %d", ret);
182 goto fail_close_client;
185 if (!jack_controller_patchbay_init(controller_ptr))
187 jack_error("Failed to initialize patchbay district");
188 goto fail_close_client;
191 ret = jack_activate(controller_ptr->client);
192 if (ret != 0)
194 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to activate dbusapi jack client. error is %d", ret);
196 goto fail_patchbay_uninit;
199 controller_ptr->started = true;
201 return TRUE;
203 fail_patchbay_uninit:
204 jack_controller_patchbay_uninit(controller_ptr);
206 fail_close_client:
207 ret = jack_client_close(controller_ptr->client);
208 if (ret != 0)
210 jack_error("jack_client_close() failed with error %d", ret);
213 controller_ptr->client = NULL;
215 fail_stop_server:
216 if (!jackctl_server_stop(controller_ptr->server))
218 jack_error("failed to stop jack server");
221 fail:
222 return FALSE;
225 bool
226 jack_controller_stop_server(
227 struct jack_controller * controller_ptr,
228 void *dbus_call_context_ptr)
230 int ret;
232 jack_info("Stopping jack server...");
234 if (!controller_ptr->started)
236 jack_info("Already stopped.");
237 return TRUE;
240 ret = jack_deactivate(controller_ptr->client);
241 if (ret != 0)
243 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to deactivate dbusapi jack client. error is %d", ret);
246 jack_controller_patchbay_uninit(controller_ptr);
248 ret = jack_client_close(controller_ptr->client);
249 if (ret != 0)
251 jack_error("jack_client_close() failed with error %d", ret);
254 controller_ptr->client = NULL;
256 if (!jackctl_server_stop(controller_ptr->server))
258 return FALSE;
261 controller_ptr->started = false;
263 return TRUE;
266 bool
267 jack_controller_switch_master(
268 struct jack_controller * controller_ptr,
269 void *dbus_call_context_ptr)
271 if (!jackctl_server_switch_master(
272 controller_ptr->server,
273 controller_ptr->driver))
275 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to switch master");
276 return FALSE;
279 return TRUE;
282 void *
283 jack_controller_create(
284 DBusConnection *connection)
286 struct jack_controller *controller_ptr;
287 const JSList * node_ptr;
288 const char ** driver_name_target;
289 const char ** internal_name_target;
290 JSList * drivers;
291 JSList * internals;
292 DBusObjectPathVTable vtable =
294 jack_dbus_message_handler_unregister,
295 jack_dbus_message_handler,
296 NULL
299 controller_ptr = malloc(sizeof(struct jack_controller));
300 if (!controller_ptr)
302 jack_error("Ran out of memory trying to allocate struct jack_controller");
303 goto fail;
306 controller_ptr->server = jackctl_server_create();
307 if (controller_ptr->server == NULL)
309 jack_error("Failed to create server object");
310 goto fail_free;
313 controller_ptr->client = NULL;
314 controller_ptr->started = false;
315 controller_ptr->driver = NULL;
316 controller_ptr->driver_set = false;
318 drivers = (JSList *)jackctl_server_get_drivers_list(controller_ptr->server);
319 controller_ptr->drivers_count = jack_slist_length(drivers);
320 controller_ptr->driver_names = malloc(controller_ptr->drivers_count * sizeof(const char *));
321 if (controller_ptr->driver_names == NULL)
323 jack_error("Ran out of memory trying to allocate driver names array");
324 goto fail_destroy_server;
327 driver_name_target = controller_ptr->driver_names;
328 node_ptr = jackctl_server_get_drivers_list(controller_ptr->server);
329 while (node_ptr != NULL)
331 *driver_name_target = jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data);
333 /* select default driver */
334 if (controller_ptr->driver == NULL && strcmp(*driver_name_target, DEFAULT_DRIVER) == 0)
336 controller_ptr->driver = (jackctl_driver_t *)node_ptr->data;
339 node_ptr = jack_slist_next(node_ptr);
340 driver_name_target++;
343 internals = (JSList *)jackctl_server_get_internals_list(controller_ptr->server);
344 controller_ptr->internals_count = jack_slist_length(internals);
345 controller_ptr->internal_names = malloc(controller_ptr->internals_count * sizeof(const char *));
346 if (controller_ptr->internal_names == NULL)
348 jack_error("Ran out of memory trying to allocate internals names array");
349 goto fail_free_driver_names_array;
352 internal_name_target = controller_ptr->internal_names;
353 node_ptr = jackctl_server_get_internals_list(controller_ptr->server);
354 while (node_ptr != NULL)
356 *internal_name_target = jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data);
357 node_ptr = jack_slist_next(node_ptr);
358 internal_name_target++;
361 controller_ptr->dbus_descriptor.context = controller_ptr;
362 controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces;
364 if (!dbus_connection_register_object_path(
365 connection,
366 JACK_CONTROLLER_OBJECT_PATH,
367 &vtable,
368 &controller_ptr->dbus_descriptor))
370 jack_error("Ran out of memory trying to register D-Bus object path");
371 goto fail_free_internal_names_array;
374 jack_controller_settings_load(controller_ptr);
376 return controller_ptr;
378 fail_free_internal_names_array:
379 free(controller_ptr->internal_names);
381 fail_free_driver_names_array:
382 free(controller_ptr->driver_names);
384 fail_destroy_server:
385 jackctl_server_destroy(controller_ptr->server);
387 fail_free:
388 free(controller_ptr);
390 fail:
391 return NULL;
394 bool
395 jack_controller_add_slave(
396 struct jack_controller *controller_ptr,
397 const char * driver_name)
399 jackctl_driver_t *driver;
401 driver = jack_controller_find_driver(controller_ptr->server, driver_name);
403 if (driver == NULL)
405 return false;
408 jack_info("driver \"%s\" selected", driver_name);
410 return jackctl_server_add_slave(controller_ptr->server, driver);
413 bool
414 jack_controller_remove_slave(
415 struct jack_controller *controller_ptr,
416 const char * driver_name)
418 jackctl_driver_t *driver;
420 driver = jack_controller_find_driver(controller_ptr->server, driver_name);
422 if (driver == NULL)
424 return false;
427 jack_info("driver \"%s\" selected", driver_name);
429 return jackctl_server_remove_slave(controller_ptr->server, driver);
432 bool
433 jack_controller_load_internal(
434 struct jack_controller *controller_ptr,
435 const char * internal_name)
437 jackctl_internal_t *internal;
439 internal = jack_controller_find_internal(controller_ptr->server, internal_name);
440 if (internal == NULL)
442 return false;
445 jack_info("internal \"%s\" selected", internal_name);
447 return jackctl_server_load_internal(controller_ptr->server, internal);
450 bool
451 jack_controller_unload_internal(
452 struct jack_controller *controller_ptr,
453 const char * internal_name)
455 jackctl_internal_t *internal;
457 internal = jack_controller_find_internal(controller_ptr->server, internal_name);
458 if (internal == NULL)
460 return false;
463 jack_info("internal \"%s\" selected", internal_name);
465 return jackctl_server_unload_internal(controller_ptr->server, internal);
468 #define controller_ptr ((struct jack_controller *)context)
470 void
471 jack_controller_destroy(
472 void * context)
474 if (controller_ptr->started)
476 jack_controller_stop_server(controller_ptr, NULL);
479 free(controller_ptr->driver_names);
480 free(controller_ptr->internal_names);
482 jackctl_server_destroy(controller_ptr->server);
484 free(controller_ptr);