Fix XCode project.
[jack2.git] / dbus / controller.c
blob17b51fdf4c7fe059b934dc996c46d7e5bb813dd2
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"
32 #include "reserve.h"
34 struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[] =
36 &g_jack_controller_iface_introspectable,
37 &g_jack_controller_iface_control,
38 &g_jack_controller_iface_configure,
39 &g_jack_controller_iface_patchbay,
40 &g_jack_controller_iface_transport,
41 NULL
44 jackctl_driver_t *
45 jack_controller_find_driver(
46 jackctl_server_t *server,
47 const char *driver_name)
49 const JSList * node_ptr;
51 node_ptr = jackctl_server_get_drivers_list(server);
53 while (node_ptr)
55 if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0)
57 return node_ptr->data;
60 node_ptr = jack_slist_next(node_ptr);
63 return NULL;
66 jackctl_internal_t *
67 jack_controller_find_internal(
68 jackctl_server_t *server,
69 const char *internal_name)
71 const JSList * node_ptr;
73 node_ptr = jackctl_server_get_internals_list(server);
75 while (node_ptr)
77 if (strcmp(jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data), internal_name) == 0)
79 return node_ptr->data;
82 node_ptr = jack_slist_next(node_ptr);
85 return NULL;
88 jackctl_parameter_t *
89 jack_controller_find_parameter(
90 const JSList * parameters_list,
91 const char * parameter_name)
93 while (parameters_list)
95 if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0)
97 return parameters_list->data;
100 parameters_list = jack_slist_next(parameters_list);
103 return NULL;
106 bool
107 jack_controller_select_driver(
108 struct jack_controller * controller_ptr,
109 const char * driver_name)
111 jackctl_driver_t *driver;
113 driver = jack_controller_find_driver(controller_ptr->server, driver_name);
114 if (driver == NULL)
116 return false;
119 jack_info("driver \"%s\" selected", driver_name);
121 controller_ptr->driver = driver;
122 controller_ptr->driver_set = true;
124 return true;
127 static
129 jack_controller_xrun(void * arg)
131 ((struct jack_controller *)arg)->xruns++;
133 return 0;
136 bool
137 jack_controller_start_server(
138 struct jack_controller * controller_ptr,
139 void *dbus_call_context_ptr)
141 int ret;
143 jack_info("Starting jack server...");
145 if (controller_ptr->started)
147 jack_info("Already started.");
148 return TRUE;
151 if (controller_ptr->driver == NULL)
153 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Select driver first!");
154 goto fail;
157 controller_ptr->xruns = 0;
159 if (!jackctl_server_start(
160 controller_ptr->server,
161 controller_ptr->driver))
163 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server");
164 goto fail;
167 controller_ptr->client = jack_client_open(
168 "dbusapi",
169 JackNoStartServer,
170 NULL);
171 if (controller_ptr->client == NULL)
173 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to create dbusapi jack client");
175 goto fail_stop_server;
178 ret = jack_set_xrun_callback(controller_ptr->client, jack_controller_xrun, controller_ptr);
179 if (ret != 0)
181 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to set xrun callback. error is %d", ret);
183 goto fail_close_client;
186 if (!jack_controller_patchbay_init(controller_ptr))
188 jack_error("Failed to initialize patchbay district");
189 goto fail_close_client;
192 ret = jack_activate(controller_ptr->client);
193 if (ret != 0)
195 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to activate dbusapi jack client. error is %d", ret);
197 goto fail_patchbay_uninit;
200 controller_ptr->started = true;
202 return TRUE;
204 fail_patchbay_uninit:
205 jack_controller_patchbay_uninit(controller_ptr);
207 fail_close_client:
208 ret = jack_client_close(controller_ptr->client);
209 if (ret != 0)
211 jack_error("jack_client_close() failed with error %d", ret);
214 controller_ptr->client = NULL;
216 fail_stop_server:
217 if (!jackctl_server_stop(controller_ptr->server))
219 jack_error("failed to stop jack server");
222 fail:
223 return FALSE;
226 bool
227 jack_controller_stop_server(
228 struct jack_controller * controller_ptr,
229 void *dbus_call_context_ptr)
231 int ret;
233 jack_info("Stopping jack server...");
235 if (!controller_ptr->started)
237 jack_info("Already stopped.");
238 return TRUE;
241 ret = jack_deactivate(controller_ptr->client);
242 if (ret != 0)
244 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to deactivate dbusapi jack client. error is %d", ret);
247 jack_controller_patchbay_uninit(controller_ptr);
249 ret = jack_client_close(controller_ptr->client);
250 if (ret != 0)
252 jack_error("jack_client_close() failed with error %d", ret);
255 controller_ptr->client = NULL;
257 if (!jackctl_server_stop(controller_ptr->server))
259 return FALSE;
262 controller_ptr->started = false;
264 return TRUE;
267 bool
268 jack_controller_switch_master(
269 struct jack_controller * controller_ptr,
270 void *dbus_call_context_ptr)
272 if (!jackctl_server_switch_master(
273 controller_ptr->server,
274 controller_ptr->driver))
276 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to switch master");
277 return FALSE;
280 return TRUE;
283 #define DEVICE_MAX 2
285 typedef struct reserved_audio_device {
287 char device_name[64];
288 rd_device * reserved_device;
290 } reserved_audio_device;
293 int g_device_count = 0;
294 static reserved_audio_device g_reserved_device[DEVICE_MAX];
296 static
297 bool
298 on_device_acquire(const char * device_name)
300 int ret;
301 DBusError error;
303 ret = rd_acquire(
304 &g_reserved_device[g_device_count].reserved_device,
305 g_connection,
306 device_name,
307 "Jack audio server",
308 INT32_MAX,
309 NULL,
310 &error);
311 if (ret < 0)
313 jack_error("Failed to acquire device name : %s error : %s", device_name, (error.message ? error.message : strerror(-ret)));
314 return false;
317 strcpy(g_reserved_device[g_device_count].device_name, device_name);
318 g_device_count++;
319 jack_info("Acquired audio card %s", device_name);
320 return true;
323 static
324 void
325 on_device_release(const char * device_name)
327 int i;
329 // Look for corresponding reserved device
330 for (i = 0; i < DEVICE_MAX; i++) {
331 if (strcmp(g_reserved_device[i].device_name, device_name) == 0)
332 break;
335 if (i < DEVICE_MAX) {
336 jack_info("Released audio card %s", device_name);
337 rd_release(g_reserved_device[i].reserved_device);
338 } else {
339 jack_error("Audio card %s not found!!", device_name);
342 g_device_count--;
345 void *
346 jack_controller_create(
347 DBusConnection *connection)
349 struct jack_controller *controller_ptr;
350 const JSList * node_ptr;
351 const char ** driver_name_target;
352 const char ** internal_name_target;
353 JSList * drivers;
354 JSList * internals;
355 DBusObjectPathVTable vtable =
357 jack_dbus_message_handler_unregister,
358 jack_dbus_message_handler,
359 NULL
362 controller_ptr = malloc(sizeof(struct jack_controller));
363 if (!controller_ptr)
365 jack_error("Ran out of memory trying to allocate struct jack_controller");
366 goto fail;
369 controller_ptr->server = jackctl_server_create(on_device_acquire, on_device_release);
370 if (controller_ptr->server == NULL)
372 jack_error("Failed to create server object");
373 goto fail_free;
376 controller_ptr->client = NULL;
377 controller_ptr->started = false;
378 controller_ptr->driver = NULL;
379 controller_ptr->driver_set = false;
381 drivers = (JSList *)jackctl_server_get_drivers_list(controller_ptr->server);
382 controller_ptr->drivers_count = jack_slist_length(drivers);
383 controller_ptr->driver_names = malloc(controller_ptr->drivers_count * sizeof(const char *));
384 if (controller_ptr->driver_names == NULL)
386 jack_error("Ran out of memory trying to allocate driver names array");
387 goto fail_destroy_server;
390 driver_name_target = controller_ptr->driver_names;
391 node_ptr = jackctl_server_get_drivers_list(controller_ptr->server);
392 while (node_ptr != NULL)
394 *driver_name_target = jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data);
396 /* select default driver */
397 if (controller_ptr->driver == NULL && strcmp(*driver_name_target, DEFAULT_DRIVER) == 0)
399 controller_ptr->driver = (jackctl_driver_t *)node_ptr->data;
402 node_ptr = jack_slist_next(node_ptr);
403 driver_name_target++;
406 internals = (JSList *)jackctl_server_get_internals_list(controller_ptr->server);
407 controller_ptr->internals_count = jack_slist_length(internals);
408 controller_ptr->internal_names = malloc(controller_ptr->internals_count * sizeof(const char *));
409 if (controller_ptr->internal_names == NULL)
411 jack_error("Ran out of memory trying to allocate internals names array");
412 goto fail_free_driver_names_array;
415 internal_name_target = controller_ptr->internal_names;
416 node_ptr = jackctl_server_get_internals_list(controller_ptr->server);
417 while (node_ptr != NULL)
419 *internal_name_target = jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data);
420 node_ptr = jack_slist_next(node_ptr);
421 internal_name_target++;
424 controller_ptr->dbus_descriptor.context = controller_ptr;
425 controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces;
427 if (!dbus_connection_register_object_path(
428 connection,
429 JACK_CONTROLLER_OBJECT_PATH,
430 &vtable,
431 &controller_ptr->dbus_descriptor))
433 jack_error("Ran out of memory trying to register D-Bus object path");
434 goto fail_free_internal_names_array;
437 jack_controller_settings_load(controller_ptr);
439 return controller_ptr;
441 fail_free_internal_names_array:
442 free(controller_ptr->internal_names);
444 fail_free_driver_names_array:
445 free(controller_ptr->driver_names);
447 fail_destroy_server:
448 jackctl_server_destroy(controller_ptr->server);
450 fail_free:
451 free(controller_ptr);
453 fail:
454 return NULL;
457 bool
458 jack_controller_add_slave(
459 struct jack_controller *controller_ptr,
460 const char * driver_name)
462 jackctl_driver_t *driver;
464 driver = jack_controller_find_driver(controller_ptr->server, driver_name);
466 if (driver == NULL)
468 return false;
471 jack_info("driver \"%s\" selected", driver_name);
473 return jackctl_server_add_slave(controller_ptr->server, driver);
476 bool
477 jack_controller_remove_slave(
478 struct jack_controller *controller_ptr,
479 const char * driver_name)
481 jackctl_driver_t *driver;
483 driver = jack_controller_find_driver(controller_ptr->server, driver_name);
485 if (driver == NULL)
487 return false;
490 jack_info("driver \"%s\" selected", driver_name);
492 return jackctl_server_remove_slave(controller_ptr->server, driver);
495 bool
496 jack_controller_load_internal(
497 struct jack_controller *controller_ptr,
498 const char * internal_name)
500 jackctl_internal_t *internal;
502 internal = jack_controller_find_internal(controller_ptr->server, internal_name);
503 if (internal == NULL)
505 return false;
508 jack_info("internal \"%s\" selected", internal_name);
510 return jackctl_server_load_internal(controller_ptr->server, internal);
513 bool
514 jack_controller_unload_internal(
515 struct jack_controller *controller_ptr,
516 const char * internal_name)
518 jackctl_internal_t *internal;
520 internal = jack_controller_find_internal(controller_ptr->server, internal_name);
521 if (internal == NULL)
523 return false;
526 jack_info("internal \"%s\" selected", internal_name);
528 return jackctl_server_unload_internal(controller_ptr->server, internal);
531 #define controller_ptr ((struct jack_controller *)context)
533 void
534 jack_controller_destroy(
535 void * context)
537 if (controller_ptr->started)
539 jack_controller_stop_server(controller_ptr, NULL);
542 free(controller_ptr->driver_names);
543 free(controller_ptr->internal_names);
545 jackctl_server_destroy(controller_ptr->server);
547 free(controller_ptr);