diff --git a/common/JackSocketServerChannel.cpp b/common/JackSocketServerChannel.cpp index de18011f..86a304f9 100644 --- a/common/JackSocketServerChannel.cpp +++ b/common/JackSocketServerChannel.cpp @@ -402,6 +402,15 @@ void JackSocketServerChannel::BuildPoolTable() } } +bool JackSocketServerChannel::Init() +{ + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGPIPE); + pthread_sigmask(SIG_BLOCK, &set, 0); + return true; +} + bool JackSocketServerChannel::Execute() { // Global poll diff --git a/linux/dbus/controller.c b/linux/dbus/controller.c index 42c39387..1aa1d922 100644 --- a/linux/dbus/controller.c +++ b/linux/dbus/controller.c @@ -333,1008 +333,4 @@ jack_controller_destroy( free(controller_ptr); } -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - Copyright (C) 2007-2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include - -#include "controller.h" -#include "controller_internal.h" -#include "xml.h" - -struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[] = -{ - &g_jack_controller_iface_introspectable, - &g_jack_controller_iface_control, - &g_jack_controller_iface_configure, - &g_jack_controller_iface_patchbay, - &g_jack_controller_iface_transport, - NULL -}; - -jackctl_driver_t * -jack_controller_find_driver( - jackctl_server_t *server, - const char *driver_name) -{ - const JSList * node_ptr; - - node_ptr = jackctl_server_get_drivers_list(server); - - while (node_ptr) - { - if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0) - { - return node_ptr->data; - } - - node_ptr = jack_slist_next(node_ptr); - } - - return NULL; -} - -jackctl_parameter_t * -jack_controller_find_parameter( - const JSList * parameters_list, - const char * parameter_name) -{ - while (parameters_list) - { - if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0) - { - return parameters_list->data; - } - - parameters_list = jack_slist_next(parameters_list); - } - - return NULL; -} - -bool -jack_controller_select_driver( - struct jack_controller * controller_ptr, - const char * driver_name) -{ - jackctl_driver_t *driver; - - driver = jack_controller_find_driver(controller_ptr->server, driver_name); - if (driver == NULL) - { - return false; - } - - jack_info("driver \"%s\" selected", driver_name); - - controller_ptr->driver = driver; - - return true; -} - -static -int -jack_controller_xrun(void * arg) -{ - ((struct jack_controller *)arg)->xruns++; - - return 0; -} - -bool -jack_controller_start_server( - struct jack_controller * controller_ptr, - void *dbus_call_context_ptr) -{ - int ret; - - jack_info("Starting jack server..."); - - if (controller_ptr->started) - { - jack_info("Already started."); - return TRUE; - } - - if (controller_ptr->driver == NULL) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Select driver first!"); - goto fail; - } - - controller_ptr->xruns = 0; - - if (!jackctl_server_start( - controller_ptr->server, - controller_ptr->driver)) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server"); - goto fail; - } - - controller_ptr->client = jack_client_open( - "dbusapi", - JackNoStartServer, - NULL); - if (controller_ptr->client == NULL) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to create dbusapi jack client"); - - goto fail_stop_server; - } - - ret = jack_set_xrun_callback(controller_ptr->client, jack_controller_xrun, controller_ptr); - if (ret != 0) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to set xrun callback. error is %d", ret); - - goto fail_close_client; - } - - if (!jack_controller_patchbay_init(controller_ptr)) - { - jack_error("Failed to initialize patchbay district"); - goto fail_close_client; - } - - ret = jack_activate(controller_ptr->client); - if (ret != 0) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to activate dbusapi jack client. error is %d", ret); - - goto fail_patchbay_uninit; - } - - controller_ptr->started = true; - - return TRUE; - -fail_patchbay_uninit: - jack_controller_patchbay_uninit(controller_ptr); - -fail_close_client: - ret = jack_client_close(controller_ptr->client); - if (ret != 0) - { - jack_error("jack_client_close() failed with error %d", ret); - } - - controller_ptr->client = NULL; - -fail_stop_server: - if (!jackctl_server_stop(controller_ptr->server)) - { - jack_error("failed to stop jack server"); - } - -fail: - return FALSE; -} - -bool -jack_controller_stop_server( - struct jack_controller * controller_ptr, - void *dbus_call_context_ptr) -{ - int ret; - - jack_info("Stopping jack server..."); - - if (!controller_ptr->started) - { - jack_info("Already stopped."); - return TRUE; - } - - ret = jack_deactivate(controller_ptr->client); - if (ret != 0) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to deactivate dbusapi jack client. error is %d", ret); - } - - jack_controller_patchbay_uninit(controller_ptr); - - ret = jack_client_close(controller_ptr->client); - if (ret != 0) - { - jack_error("jack_client_close() failed with error %d", ret); - } - - controller_ptr->client = NULL; - - if (!jackctl_server_stop(controller_ptr->server)) - { - return FALSE; - } - - controller_ptr->started = false; - - return TRUE; -} - -void * -jack_controller_create( - DBusConnection *connection) -{ - struct jack_controller *controller_ptr; - const JSList * node_ptr; - const char ** driver_name_target; - JSList * drivers; - DBusObjectPathVTable vtable = - { - jack_dbus_message_handler_unregister, - jack_dbus_message_handler, - NULL - }; - - controller_ptr = malloc(sizeof(struct jack_controller)); - if (!controller_ptr) - { - jack_error("Ran out of memory trying to allocate struct jack_controller"); - goto fail; - } - - controller_ptr->server = jackctl_server_create(); - if (controller_ptr->server == NULL) - { - jack_error("Failed to create server object"); - goto fail_free; - } - - controller_ptr->client = NULL; - controller_ptr->started = false; - - drivers = (JSList *)jackctl_server_get_drivers_list(controller_ptr->server); - controller_ptr->drivers_count = jack_slist_length(drivers); - controller_ptr->driver_names = malloc(controller_ptr->drivers_count * sizeof(const char *)); - if (controller_ptr->driver_names == NULL) - { - jack_error("Ran out of memory trying to allocate driver names array"); - goto fail_destroy_server; - } - - driver_name_target = controller_ptr->driver_names; - node_ptr = jackctl_server_get_drivers_list(controller_ptr->server); - while (node_ptr != NULL) - { - *driver_name_target = jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data); - node_ptr = jack_slist_next(node_ptr); - driver_name_target++; - } - - controller_ptr->dbus_descriptor.context = controller_ptr; - controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces; - - if (!dbus_connection_register_object_path( - connection, - JACK_CONTROLLER_OBJECT_PATH, - &vtable, - &controller_ptr->dbus_descriptor)) - { - jack_error("Ran out of memory trying to register D-Bus object path"); - goto fail_free_driver_names_array; - } - - jack_controller_settings_load(controller_ptr); - - return controller_ptr; - -fail_free_driver_names_array: - free(controller_ptr->driver_names); - -fail_destroy_server: - jackctl_server_destroy(controller_ptr->server); - -fail_free: - free(controller_ptr); - -fail: - return NULL; -} - -#define controller_ptr ((struct jack_controller *)context) - -void -jack_controller_destroy( - void * context) -{ - if (controller_ptr->started) - { - jack_controller_stop_server(controller_ptr, NULL); - } - - free(controller_ptr->driver_names); - - jackctl_server_destroy(controller_ptr->server); - - free(controller_ptr); -} -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - Copyright (C) 2007-2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include - -#include "controller.h" -#include "controller_internal.h" -#include "xml.h" - -struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[] = -{ - &g_jack_controller_iface_introspectable, - &g_jack_controller_iface_control, - &g_jack_controller_iface_configure, - &g_jack_controller_iface_patchbay, - &g_jack_controller_iface_transport, - NULL -}; - -jackctl_driver_t * -jack_controller_find_driver( - jackctl_server_t *server, - const char *driver_name) -{ - const JSList * node_ptr; - - node_ptr = jackctl_server_get_drivers_list(server); - - while (node_ptr) - { - if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0) - { - return node_ptr->data; - } - - node_ptr = jack_slist_next(node_ptr); - } - - return NULL; -} - -jackctl_parameter_t * -jack_controller_find_parameter( - const JSList * parameters_list, - const char * parameter_name) -{ - while (parameters_list) - { - if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0) - { - return parameters_list->data; - } - - parameters_list = jack_slist_next(parameters_list); - } - - return NULL; -} - -bool -jack_controller_select_driver( - struct jack_controller * controller_ptr, - const char * driver_name) -{ - jackctl_driver_t *driver; - - driver = jack_controller_find_driver(controller_ptr->server, driver_name); - if (driver == NULL) - { - return false; - } - - jack_info("driver \"%s\" selected", driver_name); - - controller_ptr->driver = driver; - - return true; -} - -static -int -jack_controller_xrun(void * arg) -{ - ((struct jack_controller *)arg)->xruns++; - - return 0; -} - -bool -jack_controller_start_server( - struct jack_controller * controller_ptr, - void *dbus_call_context_ptr) -{ - int ret; - - jack_info("Starting jack server..."); - - if (controller_ptr->started) - { - jack_info("Already started."); - return TRUE; - } - - if (controller_ptr->driver == NULL) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Select driver first!"); - goto fail; - } - - controller_ptr->xruns = 0; - - if (!jackctl_server_start( - controller_ptr->server, - controller_ptr->driver)) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server"); - goto fail; - } - - controller_ptr->client = jack_client_open( - "dbusapi", - JackNoStartServer, - NULL); - if (controller_ptr->client == NULL) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to create dbusapi jack client"); - - goto fail_stop_server; - } - - ret = jack_set_xrun_callback(controller_ptr->client, jack_controller_xrun, controller_ptr); - if (ret != 0) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to set xrun callback. error is %d", ret); - - goto fail_close_client; - } - - if (!jack_controller_patchbay_init(controller_ptr)) - { - jack_error("Failed to initialize patchbay district"); - goto fail_close_client; - } - - ret = jack_activate(controller_ptr->client); - if (ret != 0) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to activate dbusapi jack client. error is %d", ret); - - goto fail_patchbay_uninit; - } - - controller_ptr->started = true; - - return TRUE; - -fail_patchbay_uninit: - jack_controller_patchbay_uninit(controller_ptr); - -fail_close_client: - ret = jack_client_close(controller_ptr->client); - if (ret != 0) - { - jack_error("jack_client_close() failed with error %d", ret); - } - - controller_ptr->client = NULL; - -fail_stop_server: - if (!jackctl_server_stop(controller_ptr->server)) - { - jack_error("failed to stop jack server"); - } - -fail: - return FALSE; -} - -bool -jack_controller_stop_server( - struct jack_controller * controller_ptr, - void *dbus_call_context_ptr) -{ - int ret; - - jack_info("Stopping jack server..."); - - if (!controller_ptr->started) - { - jack_info("Already stopped."); - return TRUE; - } - - ret = jack_deactivate(controller_ptr->client); - if (ret != 0) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to deactivate dbusapi jack client. error is %d", ret); - } - - jack_controller_patchbay_uninit(controller_ptr); - - ret = jack_client_close(controller_ptr->client); - if (ret != 0) - { - jack_error("jack_client_close() failed with error %d", ret); - } - - controller_ptr->client = NULL; - - if (!jackctl_server_stop(controller_ptr->server)) - { - return FALSE; - } - - controller_ptr->started = false; - - return TRUE; -} - -void * -jack_controller_create( - DBusConnection *connection) -{ - struct jack_controller *controller_ptr; - const JSList * node_ptr; - const char ** driver_name_target; - JSList * drivers; - DBusObjectPathVTable vtable = - { - jack_dbus_message_handler_unregister, - jack_dbus_message_handler, - NULL - }; - - controller_ptr = malloc(sizeof(struct jack_controller)); - if (!controller_ptr) - { - jack_error("Ran out of memory trying to allocate struct jack_controller"); - goto fail; - } - - controller_ptr->server = jackctl_server_create(); - if (controller_ptr->server == NULL) - { - jack_error("Failed to create server object"); - goto fail_free; - } - - controller_ptr->client = NULL; - controller_ptr->started = false; - - drivers = (JSList *)jackctl_server_get_drivers_list(controller_ptr->server); - controller_ptr->drivers_count = jack_slist_length(drivers); - controller_ptr->driver_names = malloc(controller_ptr->drivers_count * sizeof(const char *)); - if (controller_ptr->driver_names == NULL) - { - jack_error("Ran out of memory trying to allocate driver names array"); - goto fail_destroy_server; - } - - driver_name_target = controller_ptr->driver_names; - node_ptr = jackctl_server_get_drivers_list(controller_ptr->server); - while (node_ptr != NULL) - { - *driver_name_target = jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data); - node_ptr = jack_slist_next(node_ptr); - driver_name_target++; - } - - controller_ptr->dbus_descriptor.context = controller_ptr; - controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces; - - if (!dbus_connection_register_object_path( - connection, - JACK_CONTROLLER_OBJECT_PATH, - &vtable, - &controller_ptr->dbus_descriptor)) - { - jack_error("Ran out of memory trying to register D-Bus object path"); - goto fail_free_driver_names_array; - } - - jack_controller_settings_load(controller_ptr); - - return controller_ptr; - -fail_free_driver_names_array: - free(controller_ptr->driver_names); - -fail_destroy_server: - jackctl_server_destroy(controller_ptr->server); - -fail_free: - free(controller_ptr); - -fail: - return NULL; -} - -#define controller_ptr ((struct jack_controller *)context) - -void -jack_controller_destroy( - void * context) -{ - if (controller_ptr->started) - { - jack_controller_stop_server(controller_ptr, NULL); - } - - free(controller_ptr->driver_names); - - jackctl_server_destroy(controller_ptr->server); - - free(controller_ptr); -} -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - Copyright (C) 2007-2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include - -#include "controller.h" -#include "controller_internal.h" -#include "xml.h" - -struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[] = -{ - &g_jack_controller_iface_introspectable, - &g_jack_controller_iface_control, - &g_jack_controller_iface_configure, - &g_jack_controller_iface_patchbay, - &g_jack_controller_iface_transport, - NULL -}; - -jackctl_driver_t * -jack_controller_find_driver( - jackctl_server_t *server, - const char *driver_name) -{ - const JSList * node_ptr; - - node_ptr = jackctl_server_get_drivers_list(server); - - while (node_ptr) - { - if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0) - { - return node_ptr->data; - } - - node_ptr = jack_slist_next(node_ptr); - } - - return NULL; -} - -jackctl_parameter_t * -jack_controller_find_parameter( - const JSList * parameters_list, - const char * parameter_name) -{ - while (parameters_list) - { - if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0) - { - return parameters_list->data; - } - - parameters_list = jack_slist_next(parameters_list); - } - - return NULL; -} - -bool -jack_controller_select_driver( - struct jack_controller * controller_ptr, - const char * driver_name) -{ - jackctl_driver_t *driver; - - driver = jack_controller_find_driver(controller_ptr->server, driver_name); - if (driver == NULL) - { - return false; - } - - jack_info("driver \"%s\" selected", driver_name); - - controller_ptr->driver = driver; - - return true; -} - -static -int -jack_controller_xrun(void * arg) -{ - ((struct jack_controller *)arg)->xruns++; - - return 0; -} - -bool -jack_controller_start_server( - struct jack_controller * controller_ptr, - void *dbus_call_context_ptr) -{ - int ret; - - jack_info("Starting jack server..."); - - if (controller_ptr->started) - { - jack_info("Already started."); - return TRUE; - } - - if (controller_ptr->driver == NULL) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Select driver first!"); - goto fail; - } - - controller_ptr->xruns = 0; - - if (!jackctl_server_start( - controller_ptr->server, - controller_ptr->driver)) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server"); - goto fail; - } - - controller_ptr->client = jack_client_open( - "dbusapi", - JackNoStartServer, - NULL); - if (controller_ptr->client == NULL) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to create dbusapi jack client"); - - goto fail_stop_server; - } - - ret = jack_set_xrun_callback(controller_ptr->client, jack_controller_xrun, controller_ptr); - if (ret != 0) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to set xrun callback. error is %d", ret); - - goto fail_close_client; - } - - if (!jack_controller_patchbay_init(controller_ptr)) - { - jack_error("Failed to initialize patchbay district"); - goto fail_close_client; - } - - ret = jack_activate(controller_ptr->client); - if (ret != 0) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to activate dbusapi jack client. error is %d", ret); - - goto fail_patchbay_uninit; - } - - controller_ptr->started = true; - - return TRUE; - -fail_patchbay_uninit: - jack_controller_patchbay_uninit(controller_ptr); - -fail_close_client: - ret = jack_client_close(controller_ptr->client); - if (ret != 0) - { - jack_error("jack_client_close() failed with error %d", ret); - } - - controller_ptr->client = NULL; - -fail_stop_server: - if (!jackctl_server_stop(controller_ptr->server)) - { - jack_error("failed to stop jack server"); - } - -fail: - return FALSE; -} - -bool -jack_controller_stop_server( - struct jack_controller * controller_ptr, - void *dbus_call_context_ptr) -{ - int ret; - - jack_info("Stopping jack server..."); - - if (!controller_ptr->started) - { - jack_info("Already stopped."); - return TRUE; - } - - ret = jack_deactivate(controller_ptr->client); - if (ret != 0) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to deactivate dbusapi jack client. error is %d", ret); - } - - jack_controller_patchbay_uninit(controller_ptr); - - ret = jack_client_close(controller_ptr->client); - if (ret != 0) - { - jack_error("jack_client_close() failed with error %d", ret); - } - - controller_ptr->client = NULL; - - if (!jackctl_server_stop(controller_ptr->server)) - { - return FALSE; - } - - controller_ptr->started = false; - - return TRUE; -} - -void * -jack_controller_create( - DBusConnection *connection) -{ - struct jack_controller *controller_ptr; - const JSList * node_ptr; - const char ** driver_name_target; - JSList * drivers; - DBusObjectPathVTable vtable = - { - jack_dbus_message_handler_unregister, - jack_dbus_message_handler, - NULL - }; - - controller_ptr = malloc(sizeof(struct jack_controller)); - if (!controller_ptr) - { - jack_error("Ran out of memory trying to allocate struct jack_controller"); - goto fail; - } - - controller_ptr->server = jackctl_server_create(); - if (controller_ptr->server == NULL) - { - jack_error("Failed to create server object"); - goto fail_free; - } - - controller_ptr->client = NULL; - controller_ptr->started = false; - - drivers = (JSList *)jackctl_server_get_drivers_list(controller_ptr->server); - controller_ptr->drivers_count = jack_slist_length(drivers); - controller_ptr->driver_names = malloc(controller_ptr->drivers_count * sizeof(const char *)); - if (controller_ptr->driver_names == NULL) - { - jack_error("Ran out of memory trying to allocate driver names array"); - goto fail_destroy_server; - } - - driver_name_target = controller_ptr->driver_names; - node_ptr = jackctl_server_get_drivers_list(controller_ptr->server); - while (node_ptr != NULL) - { - *driver_name_target = jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data); - node_ptr = jack_slist_next(node_ptr); - driver_name_target++; - } - - controller_ptr->dbus_descriptor.context = controller_ptr; - controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces; - - if (!dbus_connection_register_object_path( - connection, - JACK_CONTROLLER_OBJECT_PATH, - &vtable, - &controller_ptr->dbus_descriptor)) - { - jack_error("Ran out of memory trying to register D-Bus object path"); - goto fail_free_driver_names_array; - } - - jack_controller_settings_load(controller_ptr); - return controller_ptr; - -fail_free_driver_names_array: - free(controller_ptr->driver_names); - -fail_destroy_server: - jackctl_server_destroy(controller_ptr->server); - -fail_free: - free(controller_ptr); - -fail: - return NULL; -} - -#define controller_ptr ((struct jack_controller *)context) - -void -jack_controller_destroy( - void * context) -{ - if (controller_ptr->started) - { - jack_controller_stop_server(controller_ptr, NULL); - } - - free(controller_ptr->driver_names); - - jackctl_server_destroy(controller_ptr->server); - - free(controller_ptr); -} diff --git a/linux/dbus/controller_iface_configure.c b/linux/dbus/controller_iface_configure.c index 36be8d6c..7180f718 100644 --- a/linux/dbus/controller_iface_configure.c +++ b/linux/dbus/controller_iface_configure.c @@ -833,2508 +833,3 @@ JACK_DBUS_METHODS_END JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_configure, "org.jackaudio.JackConfigure") JACK_DBUS_IFACE_EXPOSE_METHODS JACK_DBUS_IFACE_END -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - Copyright (C) 2007-2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include - -#include "jackdbus.h" -#include "controller_internal.h" -#include "xml.h" - -unsigned char jack_controller_dbus_types[JACK_PARAM_MAX] = -{ - [JackParamInt] = DBUS_TYPE_INT32, - [JackParamUInt] = DBUS_TYPE_UINT32, - [JackParamChar] = DBUS_TYPE_BYTE, - [JackParamString] = DBUS_TYPE_STRING, - [JackParamBool] = DBUS_TYPE_BOOLEAN, -}; - -const char *jack_controller_dbus_type_signatures[JACK_PARAM_MAX] = -{ - [JackParamInt] = DBUS_TYPE_INT32_AS_STRING, - [JackParamUInt] = DBUS_TYPE_UINT32_AS_STRING, - [JackParamChar] = DBUS_TYPE_BYTE_AS_STRING, - [JackParamString] = DBUS_TYPE_STRING_AS_STRING, - [JackParamBool] = DBUS_TYPE_BOOLEAN_AS_STRING, -}; - -#define PARAM_TYPE_JACK_TO_DBUS(_) jack_controller_dbus_types[_] -#define PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(_) jack_controller_dbus_type_signatures[_] - -static -bool -jack_controller_jack_to_dbus_variant( - jackctl_param_type_t type, - const union jackctl_parameter_value *value_ptr, - message_arg_t *dbusv_ptr) -{ - switch (type) - { - case JackParamInt: - dbusv_ptr->int32 = (dbus_int32_t)value_ptr->i; - return true; - case JackParamUInt: - dbusv_ptr->uint32 = (dbus_uint32_t)value_ptr->ui; - return true; - case JackParamChar: - dbusv_ptr->byte = value_ptr->c; - return true; - case JackParamString: - dbusv_ptr->string = value_ptr->str; - return true; - case JackParamBool: - dbusv_ptr->boolean = (dbus_bool_t)value_ptr->b; - return true; - } - - jack_error("Unknown JACK parameter type %i", (int)type); - assert(0); - return false; -} - -static -bool -jack_controller_dbus_to_jack_variant( - int type, - const message_arg_t *dbusv_ptr, - union jackctl_parameter_value *value_ptr) -{ - size_t len; - - switch (type) - { - case DBUS_TYPE_INT32: - value_ptr->i = dbusv_ptr->int32; - return true; - case DBUS_TYPE_UINT32: - value_ptr->ui = dbusv_ptr->uint32; - return true; - case DBUS_TYPE_BYTE: - value_ptr->c = dbusv_ptr->byte; - return true; - case DBUS_TYPE_STRING: - len = strlen(dbusv_ptr->string); - if (len > JACK_PARAM_STRING_MAX) - { - jack_error("Parameter string value is too long (%u)", (unsigned int)len); - return false; - } - memcpy(value_ptr->str, dbusv_ptr->string, len + 1); - - return true; - case DBUS_TYPE_BOOLEAN: - value_ptr->b = dbusv_ptr->boolean; - return true; - } - - jack_error("Unknown D-Bus parameter type %i", (int)type); - return false; -} - -/* - * Construct a return message for a Get[Driver|Engine]ParameterValue method call. - * - * The operation can only fail due to lack of memory, in which case - * there's no sense in trying to construct an error return. Instead, - * call->reply will be set to NULL and handled in send_method_return(). - */ -static void -jack_dbus_construct_method_return_parameter( - struct jack_dbus_method_call *call, - dbus_bool_t is_set, - int type, - const char *signature, - message_arg_t default_value, - message_arg_t value) -{ - DBusMessageIter iter; - - /* Create a new method return message. */ - call->reply = dbus_message_new_method_return (call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append (call->reply, &iter); - - /* Append the is_set argument. */ - if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, (const void *) &is_set)) - { - goto fail_unref; - } - - /* Append the 'default' and 'value' arguments. */ - if (!jack_dbus_message_append_variant(&iter, type, signature, &default_value)) - { - goto fail_unref; - } - if (!jack_dbus_message_append_variant(&iter, type, signature, &value)) - { - goto fail_unref; - } - - return; - -fail_unref: - dbus_message_unref (call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -#define controller_ptr ((struct jack_controller *)call->context) - -static -void -jack_controller_dbus_get_available_drivers( - struct jack_dbus_method_call *call) -{ - jack_dbus_construct_method_return_array_of_strings( - call, - controller_ptr->drivers_count, - controller_ptr->driver_names); -} - -static -void -jack_controller_dbus_get_selected_driver( - struct jack_dbus_method_call *call) -{ - message_arg_t arg; - - if (controller_ptr->driver != NULL) - { - arg.string = jackctl_driver_get_name(controller_ptr->driver); - } - else - { - arg.string = NULL; - } - - jack_dbus_construct_method_return_single(call, DBUS_TYPE_STRING, arg); -} - -static -void -jack_controller_dbus_select_driver( - struct jack_dbus_method_call *call) -{ - const char *driver_name; - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &driver_name, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - if (!jack_controller_select_driver(controller_ptr, driver_name)) - { - /* Couldn't find driver with the specified name. */ - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_DRIVER, - "Unknown driver \"%s\"", - driver_name); - return; - } - - jack_controller_settings_save_auto(controller_ptr); - - jack_dbus_construct_method_return_empty(call); -} - -static -void -jack_controller_get_parameters_info( - struct jack_dbus_method_call *call, - const JSList *parameters_list) -{ - DBusMessageIter iter, array_iter, struct_iter; - unsigned char type; - const char *str; - - call->reply = dbus_message_new_method_return (call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append (call->reply, &iter); - - /* Open the array. */ - if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ysss)", &array_iter)) - { - goto fail_unref; - } - - /* Append parameter descriptions to the array. */ - while (parameters_list != NULL) - { - /* Open the struct. */ - if (!dbus_message_iter_open_container (&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)) - { - goto fail_close_unref; - } - - /* Append parameter type. */ - type = PARAM_TYPE_JACK_TO_DBUS(jackctl_parameter_get_type((jackctl_parameter_t *)parameters_list->data)); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_BYTE, - (const void *) &type)) - { - goto fail_close2_unref; - } - - /* Append parameter name. */ - str = jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close2_unref; - } - - /* Append parameter short description. */ - str = jackctl_parameter_get_short_description((jackctl_parameter_t *)parameters_list->data); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close2_unref; - } - - /* Append parameter long description. */ - str = jackctl_parameter_get_long_description((jackctl_parameter_t *)parameters_list->data); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close2_unref; - } - - /* Close the struct. */ - if (!dbus_message_iter_close_container (&array_iter, &struct_iter)) - { - goto fail_close_unref; - } - - parameters_list = jack_slist_next(parameters_list); - } - - /* Close the array. */ - if (!dbus_message_iter_close_container (&iter, &array_iter)) - { - goto fail_unref; - } - - return; - -fail_close2_unref: - dbus_message_iter_close_container (&iter, &struct_iter); - -fail_close_unref: - dbus_message_iter_close_container (&iter, &array_iter); - -fail_unref: - dbus_message_unref (call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -static -void -jack_controller_get_parameter_info( - struct jack_dbus_method_call *call, - jackctl_parameter_t *parameter) -{ - DBusMessageIter iter, struct_iter; - unsigned char type; - const char *str; - - call->reply = dbus_message_new_method_return (call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append (call->reply, &iter); - - /* Open the struct. */ - if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)) - { - goto fail_unref; - } - - /* Append parameter type. */ - type = PARAM_TYPE_JACK_TO_DBUS(jackctl_parameter_get_type(parameter)); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_BYTE, - (const void *) &type)) - { - goto fail_close_unref; - } - - /* Append parameter name. */ - str = jackctl_parameter_get_name(parameter); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close_unref; - } - - /* Append parameter short description. */ - str = jackctl_parameter_get_short_description(parameter); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close_unref; - } - - /* Append parameter long description. */ - str = jackctl_parameter_get_long_description(parameter); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close_unref; - } - - /* Close the struct. */ - if (!dbus_message_iter_close_container (&iter, &struct_iter)) - { - goto fail_unref; - } - - return; - -fail_close_unref: - dbus_message_iter_close_container (&iter, &struct_iter); - -fail_unref: - dbus_message_unref (call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -/* - * Execute GetDriverParametersInfo method call. - */ -static -void -jack_controller_dbus_get_driver_parameters_info( - struct jack_dbus_method_call *call) -{ - if (controller_ptr->driver == NULL) - { - jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, - "No driver selected"); - return; - } - - jack_controller_get_parameters_info( - call, - jackctl_driver_get_parameters(controller_ptr->driver)); -} - -/* - * Execute GetDriverParameterInfo method call. - */ -static -void -jack_controller_dbus_get_driver_parameter_info( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - jackctl_parameter_t *parameter; - - if (controller_ptr->driver == NULL) - { - jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, - "No driver selected"); - return; - } - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, - "Unknown parameter \"%s\" for driver \"%s\"", - parameter_name, - jackctl_driver_get_name(controller_ptr->driver)); - return; - } - - jack_controller_get_parameter_info(call, parameter); -} - - -/* - * Execute GetDriverParameterValue method call. - */ -static void -jack_controller_dbus_get_driver_parameter_value( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - jackctl_parameter_t *parameter; - int type; - union jackctl_parameter_value jackctl_value; - union jackctl_parameter_value jackctl_default_value; - message_arg_t value; - message_arg_t default_value; - - if (controller_ptr->driver == NULL) - { - jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, - "No driver selected"); - return; - } - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * get_method_args() has constructed an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, - "Unknown parameter \"%s\" for driver \"%s\"", - parameter, - jackctl_driver_get_name(controller_ptr->driver)); - return; - } - - type = jackctl_parameter_get_type(parameter); - jackctl_default_value = jackctl_parameter_get_default_value(parameter); - jackctl_value = jackctl_parameter_get_value(parameter); - - jack_controller_jack_to_dbus_variant(type, &jackctl_value, &value); - jack_controller_jack_to_dbus_variant(type, &jackctl_default_value, &default_value); - - /* Construct the reply. */ - jack_dbus_construct_method_return_parameter( - call, - (dbus_bool_t)(jackctl_parameter_is_set(parameter) ? TRUE : FALSE), - PARAM_TYPE_JACK_TO_DBUS(type), - PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), - default_value, - value); -} - -static -void -jack_controller_dbus_set_driver_parameter_value( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - message_arg_t arg; - int arg_type; - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - union jackctl_parameter_value value; - - if (controller_ptr->driver == NULL) - { - jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, - "No driver selected"); - return; - } - - if (!jack_dbus_get_method_args_string_and_variant(call, ¶meter_name, &arg, &arg_type)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args_string_and_variant() has constructed - * an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, - "Unknown parameter \"%s\" for driver \"%s\"", - parameter, - jackctl_driver_get_name(controller_ptr->driver)); - return; - } - - type = jackctl_parameter_get_type(parameter); - - if (PARAM_TYPE_JACK_TO_DBUS(type) != arg_type) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Engine parameter value type mismatch: was expecting '%c', got '%c'", - (char)PARAM_TYPE_JACK_TO_DBUS(type), - (char)arg_type); - return; - } - - if (!jack_controller_dbus_to_jack_variant( - arg_type, - &arg, - &value)) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Cannot convert engine parameter value"); - return; - } - - jackctl_parameter_set_value(parameter, &value); - - jack_controller_settings_save_auto(controller_ptr); - - jack_dbus_construct_method_return_empty(call); -} - -/* - * Execute GetEngineParametersInfo method call. - */ -static -void -jack_controller_dbus_get_engine_parameters_info( - struct jack_dbus_method_call *call) -{ - jack_controller_get_parameters_info( - call, - jackctl_server_get_parameters(controller_ptr->server)); -} - -/* - * Execute GetEngineParameterInfo method call. - */ -static -void -jack_controller_dbus_get_engine_parameter_info( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - jackctl_parameter_t *parameter; - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_ENGINE_PARAMETER, - "Unknown engine parameter \"%s\"", - parameter); - return; - } - - jack_controller_get_parameter_info(call, parameter); -} - -/* - * Execute GetDriverParameterValue method call. - */ -static -void -jack_controller_dbus_get_engine_parameter_value( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - union jackctl_parameter_value jackctl_value; - union jackctl_parameter_value jackctl_default_value; - message_arg_t value; - message_arg_t default_value; - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_ENGINE_PARAMETER, - "Unknown engine parameter \"%s\"", - parameter); - return; - } - - type = jackctl_parameter_get_type(parameter); - jackctl_default_value = jackctl_parameter_get_default_value(parameter); - jackctl_value = jackctl_parameter_get_value(parameter); - - jack_controller_jack_to_dbus_variant(type, &jackctl_value, &value); - jack_controller_jack_to_dbus_variant(type, &jackctl_default_value, &default_value); - - /* Construct the reply. */ - jack_dbus_construct_method_return_parameter( - call, - (dbus_bool_t)(jackctl_parameter_is_set(parameter) ? TRUE : FALSE), - PARAM_TYPE_JACK_TO_DBUS(type), - PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), - default_value, - value); -} - -static -void -jack_controller_dbus_set_engine_parameter_value( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - message_arg_t arg; - int arg_type; - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - union jackctl_parameter_value value; - - if (!jack_dbus_get_method_args_string_and_variant (call, ¶meter_name, &arg, &arg_type)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args_string_and_variant() has constructed - * an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_ENGINE_PARAMETER, - "Unknown engine parameter \"%s\"", - parameter); - return; - } - - type = jackctl_parameter_get_type(parameter); - - if (PARAM_TYPE_JACK_TO_DBUS(type) != arg_type) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Engine parameter value type mismatch: was expecting '%c', got '%c'", - (char)PARAM_TYPE_JACK_TO_DBUS(type), - (char)arg_type); - return; - } - - if (!jack_controller_dbus_to_jack_variant( - arg_type, - &arg, - &value)) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Cannot convert engine parameter value"); - return; - } - - jackctl_parameter_set_value(parameter, &value); - - jack_controller_settings_save_auto(controller_ptr); - - jack_dbus_construct_method_return_empty(call); -} - -#undef controller_ptr - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetAvailableDrivers) - JACK_DBUS_METHOD_ARGUMENT("drivers_list", "as", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetSelectedDriver) - JACK_DBUS_METHOD_ARGUMENT("driver", "s", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SelectDriver) - JACK_DBUS_METHOD_ARGUMENT("driver", "s", false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetDriverParametersInfo) - JACK_DBUS_METHOD_ARGUMENT("parameter_info_array", "a(ysss)", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetDriverParameterInfo) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("parameter_info", "(ysss)", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetDriverParameterValue) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("is_set", "b", true) - JACK_DBUS_METHOD_ARGUMENT("default", "v", true) - JACK_DBUS_METHOD_ARGUMENT("value", "v", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SetDriverParameterValue) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("value", "v", false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetEngineParametersInfo) - JACK_DBUS_METHOD_ARGUMENT("parameter_info_array", "a(ysss)", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetEngineParameterInfo) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("parameter_info", "(ysss)", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetEngineParameterValue) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("is_set", "b", true) - JACK_DBUS_METHOD_ARGUMENT("default", "v", true) - JACK_DBUS_METHOD_ARGUMENT("value", "v", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SetEngineParameterValue) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("value", "v", false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHODS_BEGIN - JACK_DBUS_METHOD_DESCRIBE(GetAvailableDrivers, jack_controller_dbus_get_available_drivers) - JACK_DBUS_METHOD_DESCRIBE(GetSelectedDriver, jack_controller_dbus_get_selected_driver) - JACK_DBUS_METHOD_DESCRIBE(SelectDriver, jack_controller_dbus_select_driver) - JACK_DBUS_METHOD_DESCRIBE(GetDriverParametersInfo, jack_controller_dbus_get_driver_parameters_info) - JACK_DBUS_METHOD_DESCRIBE(GetDriverParameterInfo, jack_controller_dbus_get_driver_parameter_info) - JACK_DBUS_METHOD_DESCRIBE(GetDriverParameterValue, jack_controller_dbus_get_driver_parameter_value) - JACK_DBUS_METHOD_DESCRIBE(SetDriverParameterValue, jack_controller_dbus_set_driver_parameter_value) - JACK_DBUS_METHOD_DESCRIBE(GetEngineParametersInfo, jack_controller_dbus_get_engine_parameters_info) - JACK_DBUS_METHOD_DESCRIBE(GetEngineParameterInfo, jack_controller_dbus_get_engine_parameter_info) - JACK_DBUS_METHOD_DESCRIBE(GetEngineParameterValue, jack_controller_dbus_get_engine_parameter_value) - JACK_DBUS_METHOD_DESCRIBE(SetEngineParameterValue, jack_controller_dbus_set_engine_parameter_value) -JACK_DBUS_METHODS_END - -JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_configure, "org.jackaudio.JackConfigure") - JACK_DBUS_IFACE_EXPOSE_METHODS -JACK_DBUS_IFACE_END -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - Copyright (C) 2007-2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include - -#include "jackdbus.h" -#include "controller_internal.h" -#include "xml.h" - -unsigned char jack_controller_dbus_types[JACK_PARAM_MAX] = -{ - [JackParamInt] = DBUS_TYPE_INT32, - [JackParamUInt] = DBUS_TYPE_UINT32, - [JackParamChar] = DBUS_TYPE_BYTE, - [JackParamString] = DBUS_TYPE_STRING, - [JackParamBool] = DBUS_TYPE_BOOLEAN, -}; - -const char *jack_controller_dbus_type_signatures[JACK_PARAM_MAX] = -{ - [JackParamInt] = DBUS_TYPE_INT32_AS_STRING, - [JackParamUInt] = DBUS_TYPE_UINT32_AS_STRING, - [JackParamChar] = DBUS_TYPE_BYTE_AS_STRING, - [JackParamString] = DBUS_TYPE_STRING_AS_STRING, - [JackParamBool] = DBUS_TYPE_BOOLEAN_AS_STRING, -}; - -#define PARAM_TYPE_JACK_TO_DBUS(_) jack_controller_dbus_types[_] -#define PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(_) jack_controller_dbus_type_signatures[_] - -static -bool -jack_controller_jack_to_dbus_variant( - jackctl_param_type_t type, - const union jackctl_parameter_value *value_ptr, - message_arg_t *dbusv_ptr) -{ - switch (type) - { - case JackParamInt: - dbusv_ptr->int32 = (dbus_int32_t)value_ptr->i; - return true; - case JackParamUInt: - dbusv_ptr->uint32 = (dbus_uint32_t)value_ptr->ui; - return true; - case JackParamChar: - dbusv_ptr->byte = value_ptr->c; - return true; - case JackParamString: - dbusv_ptr->string = value_ptr->str; - return true; - case JackParamBool: - dbusv_ptr->boolean = (dbus_bool_t)value_ptr->b; - return true; - } - - jack_error("Unknown JACK parameter type %i", (int)type); - assert(0); - return false; -} - -static -bool -jack_controller_dbus_to_jack_variant( - int type, - const message_arg_t *dbusv_ptr, - union jackctl_parameter_value *value_ptr) -{ - size_t len; - - switch (type) - { - case DBUS_TYPE_INT32: - value_ptr->i = dbusv_ptr->int32; - return true; - case DBUS_TYPE_UINT32: - value_ptr->ui = dbusv_ptr->uint32; - return true; - case DBUS_TYPE_BYTE: - value_ptr->c = dbusv_ptr->byte; - return true; - case DBUS_TYPE_STRING: - len = strlen(dbusv_ptr->string); - if (len > JACK_PARAM_STRING_MAX) - { - jack_error("Parameter string value is too long (%u)", (unsigned int)len); - return false; - } - memcpy(value_ptr->str, dbusv_ptr->string, len + 1); - - return true; - case DBUS_TYPE_BOOLEAN: - value_ptr->b = dbusv_ptr->boolean; - return true; - } - - jack_error("Unknown D-Bus parameter type %i", (int)type); - return false; -} - -/* - * Construct a return message for a Get[Driver|Engine]ParameterValue method call. - * - * The operation can only fail due to lack of memory, in which case - * there's no sense in trying to construct an error return. Instead, - * call->reply will be set to NULL and handled in send_method_return(). - */ -static void -jack_dbus_construct_method_return_parameter( - struct jack_dbus_method_call *call, - dbus_bool_t is_set, - int type, - const char *signature, - message_arg_t default_value, - message_arg_t value) -{ - DBusMessageIter iter; - - /* Create a new method return message. */ - call->reply = dbus_message_new_method_return (call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append (call->reply, &iter); - - /* Append the is_set argument. */ - if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, (const void *) &is_set)) - { - goto fail_unref; - } - - /* Append the 'default' and 'value' arguments. */ - if (!jack_dbus_message_append_variant(&iter, type, signature, &default_value)) - { - goto fail_unref; - } - if (!jack_dbus_message_append_variant(&iter, type, signature, &value)) - { - goto fail_unref; - } - - return; - -fail_unref: - dbus_message_unref (call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -#define controller_ptr ((struct jack_controller *)call->context) - -static -void -jack_controller_dbus_get_available_drivers( - struct jack_dbus_method_call *call) -{ - jack_dbus_construct_method_return_array_of_strings( - call, - controller_ptr->drivers_count, - controller_ptr->driver_names); -} - -static -void -jack_controller_dbus_get_selected_driver( - struct jack_dbus_method_call *call) -{ - message_arg_t arg; - - if (controller_ptr->driver != NULL) - { - arg.string = jackctl_driver_get_name(controller_ptr->driver); - } - else - { - arg.string = NULL; - } - - jack_dbus_construct_method_return_single(call, DBUS_TYPE_STRING, arg); -} - -static -void -jack_controller_dbus_select_driver( - struct jack_dbus_method_call *call) -{ - const char *driver_name; - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &driver_name, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - if (!jack_controller_select_driver(controller_ptr, driver_name)) - { - /* Couldn't find driver with the specified name. */ - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_DRIVER, - "Unknown driver \"%s\"", - driver_name); - return; - } - - jack_controller_settings_save_auto(controller_ptr); - - jack_dbus_construct_method_return_empty(call); -} - -static -void -jack_controller_get_parameters_info( - struct jack_dbus_method_call *call, - const JSList *parameters_list) -{ - DBusMessageIter iter, array_iter, struct_iter; - unsigned char type; - const char *str; - - call->reply = dbus_message_new_method_return (call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append (call->reply, &iter); - - /* Open the array. */ - if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ysss)", &array_iter)) - { - goto fail_unref; - } - - /* Append parameter descriptions to the array. */ - while (parameters_list != NULL) - { - /* Open the struct. */ - if (!dbus_message_iter_open_container (&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)) - { - goto fail_close_unref; - } - - /* Append parameter type. */ - type = PARAM_TYPE_JACK_TO_DBUS(jackctl_parameter_get_type((jackctl_parameter_t *)parameters_list->data)); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_BYTE, - (const void *) &type)) - { - goto fail_close2_unref; - } - - /* Append parameter name. */ - str = jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close2_unref; - } - - /* Append parameter short description. */ - str = jackctl_parameter_get_short_description((jackctl_parameter_t *)parameters_list->data); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close2_unref; - } - - /* Append parameter long description. */ - str = jackctl_parameter_get_long_description((jackctl_parameter_t *)parameters_list->data); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close2_unref; - } - - /* Close the struct. */ - if (!dbus_message_iter_close_container (&array_iter, &struct_iter)) - { - goto fail_close_unref; - } - - parameters_list = jack_slist_next(parameters_list); - } - - /* Close the array. */ - if (!dbus_message_iter_close_container (&iter, &array_iter)) - { - goto fail_unref; - } - - return; - -fail_close2_unref: - dbus_message_iter_close_container (&iter, &struct_iter); - -fail_close_unref: - dbus_message_iter_close_container (&iter, &array_iter); - -fail_unref: - dbus_message_unref (call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -static -void -jack_controller_get_parameter_info( - struct jack_dbus_method_call *call, - jackctl_parameter_t *parameter) -{ - DBusMessageIter iter, struct_iter; - unsigned char type; - const char *str; - - call->reply = dbus_message_new_method_return (call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append (call->reply, &iter); - - /* Open the struct. */ - if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)) - { - goto fail_unref; - } - - /* Append parameter type. */ - type = PARAM_TYPE_JACK_TO_DBUS(jackctl_parameter_get_type(parameter)); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_BYTE, - (const void *) &type)) - { - goto fail_close_unref; - } - - /* Append parameter name. */ - str = jackctl_parameter_get_name(parameter); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close_unref; - } - - /* Append parameter short description. */ - str = jackctl_parameter_get_short_description(parameter); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close_unref; - } - - /* Append parameter long description. */ - str = jackctl_parameter_get_long_description(parameter); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close_unref; - } - - /* Close the struct. */ - if (!dbus_message_iter_close_container (&iter, &struct_iter)) - { - goto fail_unref; - } - - return; - -fail_close_unref: - dbus_message_iter_close_container (&iter, &struct_iter); - -fail_unref: - dbus_message_unref (call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -/* - * Execute GetDriverParametersInfo method call. - */ -static -void -jack_controller_dbus_get_driver_parameters_info( - struct jack_dbus_method_call *call) -{ - if (controller_ptr->driver == NULL) - { - jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, - "No driver selected"); - return; - } - - jack_controller_get_parameters_info( - call, - jackctl_driver_get_parameters(controller_ptr->driver)); -} - -/* - * Execute GetDriverParameterInfo method call. - */ -static -void -jack_controller_dbus_get_driver_parameter_info( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - jackctl_parameter_t *parameter; - - if (controller_ptr->driver == NULL) - { - jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, - "No driver selected"); - return; - } - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, - "Unknown parameter \"%s\" for driver \"%s\"", - parameter_name, - jackctl_driver_get_name(controller_ptr->driver)); - return; - } - - jack_controller_get_parameter_info(call, parameter); -} - - -/* - * Execute GetDriverParameterValue method call. - */ -static void -jack_controller_dbus_get_driver_parameter_value( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - jackctl_parameter_t *parameter; - int type; - union jackctl_parameter_value jackctl_value; - union jackctl_parameter_value jackctl_default_value; - message_arg_t value; - message_arg_t default_value; - - if (controller_ptr->driver == NULL) - { - jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, - "No driver selected"); - return; - } - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * get_method_args() has constructed an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, - "Unknown parameter \"%s\" for driver \"%s\"", - parameter, - jackctl_driver_get_name(controller_ptr->driver)); - return; - } - - type = jackctl_parameter_get_type(parameter); - jackctl_default_value = jackctl_parameter_get_default_value(parameter); - jackctl_value = jackctl_parameter_get_value(parameter); - - jack_controller_jack_to_dbus_variant(type, &jackctl_value, &value); - jack_controller_jack_to_dbus_variant(type, &jackctl_default_value, &default_value); - - /* Construct the reply. */ - jack_dbus_construct_method_return_parameter( - call, - (dbus_bool_t)(jackctl_parameter_is_set(parameter) ? TRUE : FALSE), - PARAM_TYPE_JACK_TO_DBUS(type), - PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), - default_value, - value); -} - -static -void -jack_controller_dbus_set_driver_parameter_value( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - message_arg_t arg; - int arg_type; - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - union jackctl_parameter_value value; - - if (controller_ptr->driver == NULL) - { - jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, - "No driver selected"); - return; - } - - if (!jack_dbus_get_method_args_string_and_variant(call, ¶meter_name, &arg, &arg_type)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args_string_and_variant() has constructed - * an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, - "Unknown parameter \"%s\" for driver \"%s\"", - parameter, - jackctl_driver_get_name(controller_ptr->driver)); - return; - } - - type = jackctl_parameter_get_type(parameter); - - if (PARAM_TYPE_JACK_TO_DBUS(type) != arg_type) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Engine parameter value type mismatch: was expecting '%c', got '%c'", - (char)PARAM_TYPE_JACK_TO_DBUS(type), - (char)arg_type); - return; - } - - if (!jack_controller_dbus_to_jack_variant( - arg_type, - &arg, - &value)) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Cannot convert engine parameter value"); - return; - } - - jackctl_parameter_set_value(parameter, &value); - - jack_controller_settings_save_auto(controller_ptr); - - jack_dbus_construct_method_return_empty(call); -} - -/* - * Execute GetEngineParametersInfo method call. - */ -static -void -jack_controller_dbus_get_engine_parameters_info( - struct jack_dbus_method_call *call) -{ - jack_controller_get_parameters_info( - call, - jackctl_server_get_parameters(controller_ptr->server)); -} - -/* - * Execute GetEngineParameterInfo method call. - */ -static -void -jack_controller_dbus_get_engine_parameter_info( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - jackctl_parameter_t *parameter; - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_ENGINE_PARAMETER, - "Unknown engine parameter \"%s\"", - parameter); - return; - } - - jack_controller_get_parameter_info(call, parameter); -} - -/* - * Execute GetDriverParameterValue method call. - */ -static -void -jack_controller_dbus_get_engine_parameter_value( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - union jackctl_parameter_value jackctl_value; - union jackctl_parameter_value jackctl_default_value; - message_arg_t value; - message_arg_t default_value; - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_ENGINE_PARAMETER, - "Unknown engine parameter \"%s\"", - parameter); - return; - } - - type = jackctl_parameter_get_type(parameter); - jackctl_default_value = jackctl_parameter_get_default_value(parameter); - jackctl_value = jackctl_parameter_get_value(parameter); - - jack_controller_jack_to_dbus_variant(type, &jackctl_value, &value); - jack_controller_jack_to_dbus_variant(type, &jackctl_default_value, &default_value); - - /* Construct the reply. */ - jack_dbus_construct_method_return_parameter( - call, - (dbus_bool_t)(jackctl_parameter_is_set(parameter) ? TRUE : FALSE), - PARAM_TYPE_JACK_TO_DBUS(type), - PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), - default_value, - value); -} - -static -void -jack_controller_dbus_set_engine_parameter_value( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - message_arg_t arg; - int arg_type; - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - union jackctl_parameter_value value; - - if (!jack_dbus_get_method_args_string_and_variant (call, ¶meter_name, &arg, &arg_type)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args_string_and_variant() has constructed - * an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_ENGINE_PARAMETER, - "Unknown engine parameter \"%s\"", - parameter); - return; - } - - type = jackctl_parameter_get_type(parameter); - - if (PARAM_TYPE_JACK_TO_DBUS(type) != arg_type) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Engine parameter value type mismatch: was expecting '%c', got '%c'", - (char)PARAM_TYPE_JACK_TO_DBUS(type), - (char)arg_type); - return; - } - - if (!jack_controller_dbus_to_jack_variant( - arg_type, - &arg, - &value)) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Cannot convert engine parameter value"); - return; - } - - jackctl_parameter_set_value(parameter, &value); - - jack_controller_settings_save_auto(controller_ptr); - - jack_dbus_construct_method_return_empty(call); -} - -#undef controller_ptr - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetAvailableDrivers) - JACK_DBUS_METHOD_ARGUMENT("drivers_list", "as", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetSelectedDriver) - JACK_DBUS_METHOD_ARGUMENT("driver", "s", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SelectDriver) - JACK_DBUS_METHOD_ARGUMENT("driver", "s", false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetDriverParametersInfo) - JACK_DBUS_METHOD_ARGUMENT("parameter_info_array", "a(ysss)", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetDriverParameterInfo) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("parameter_info", "(ysss)", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetDriverParameterValue) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("is_set", "b", true) - JACK_DBUS_METHOD_ARGUMENT("default", "v", true) - JACK_DBUS_METHOD_ARGUMENT("value", "v", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SetDriverParameterValue) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("value", "v", false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetEngineParametersInfo) - JACK_DBUS_METHOD_ARGUMENT("parameter_info_array", "a(ysss)", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetEngineParameterInfo) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("parameter_info", "(ysss)", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetEngineParameterValue) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("is_set", "b", true) - JACK_DBUS_METHOD_ARGUMENT("default", "v", true) - JACK_DBUS_METHOD_ARGUMENT("value", "v", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SetEngineParameterValue) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("value", "v", false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHODS_BEGIN - JACK_DBUS_METHOD_DESCRIBE(GetAvailableDrivers, jack_controller_dbus_get_available_drivers) - JACK_DBUS_METHOD_DESCRIBE(GetSelectedDriver, jack_controller_dbus_get_selected_driver) - JACK_DBUS_METHOD_DESCRIBE(SelectDriver, jack_controller_dbus_select_driver) - JACK_DBUS_METHOD_DESCRIBE(GetDriverParametersInfo, jack_controller_dbus_get_driver_parameters_info) - JACK_DBUS_METHOD_DESCRIBE(GetDriverParameterInfo, jack_controller_dbus_get_driver_parameter_info) - JACK_DBUS_METHOD_DESCRIBE(GetDriverParameterValue, jack_controller_dbus_get_driver_parameter_value) - JACK_DBUS_METHOD_DESCRIBE(SetDriverParameterValue, jack_controller_dbus_set_driver_parameter_value) - JACK_DBUS_METHOD_DESCRIBE(GetEngineParametersInfo, jack_controller_dbus_get_engine_parameters_info) - JACK_DBUS_METHOD_DESCRIBE(GetEngineParameterInfo, jack_controller_dbus_get_engine_parameter_info) - JACK_DBUS_METHOD_DESCRIBE(GetEngineParameterValue, jack_controller_dbus_get_engine_parameter_value) - JACK_DBUS_METHOD_DESCRIBE(SetEngineParameterValue, jack_controller_dbus_set_engine_parameter_value) -JACK_DBUS_METHODS_END - -JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_configure, "org.jackaudio.JackConfigure") - JACK_DBUS_IFACE_EXPOSE_METHODS -JACK_DBUS_IFACE_END -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - Copyright (C) 2007-2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include - -#include "jackdbus.h" -#include "controller_internal.h" -#include "xml.h" - -unsigned char jack_controller_dbus_types[JACK_PARAM_MAX] = -{ - [JackParamInt] = DBUS_TYPE_INT32, - [JackParamUInt] = DBUS_TYPE_UINT32, - [JackParamChar] = DBUS_TYPE_BYTE, - [JackParamString] = DBUS_TYPE_STRING, - [JackParamBool] = DBUS_TYPE_BOOLEAN, -}; - -const char *jack_controller_dbus_type_signatures[JACK_PARAM_MAX] = -{ - [JackParamInt] = DBUS_TYPE_INT32_AS_STRING, - [JackParamUInt] = DBUS_TYPE_UINT32_AS_STRING, - [JackParamChar] = DBUS_TYPE_BYTE_AS_STRING, - [JackParamString] = DBUS_TYPE_STRING_AS_STRING, - [JackParamBool] = DBUS_TYPE_BOOLEAN_AS_STRING, -}; - -#define PARAM_TYPE_JACK_TO_DBUS(_) jack_controller_dbus_types[_] -#define PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(_) jack_controller_dbus_type_signatures[_] - -static -bool -jack_controller_jack_to_dbus_variant( - jackctl_param_type_t type, - const union jackctl_parameter_value *value_ptr, - message_arg_t *dbusv_ptr) -{ - switch (type) - { - case JackParamInt: - dbusv_ptr->int32 = (dbus_int32_t)value_ptr->i; - return true; - case JackParamUInt: - dbusv_ptr->uint32 = (dbus_uint32_t)value_ptr->ui; - return true; - case JackParamChar: - dbusv_ptr->byte = value_ptr->c; - return true; - case JackParamString: - dbusv_ptr->string = value_ptr->str; - return true; - case JackParamBool: - dbusv_ptr->boolean = (dbus_bool_t)value_ptr->b; - return true; - } - - jack_error("Unknown JACK parameter type %i", (int)type); - assert(0); - return false; -} - -static -bool -jack_controller_dbus_to_jack_variant( - int type, - const message_arg_t *dbusv_ptr, - union jackctl_parameter_value *value_ptr) -{ - size_t len; - - switch (type) - { - case DBUS_TYPE_INT32: - value_ptr->i = dbusv_ptr->int32; - return true; - case DBUS_TYPE_UINT32: - value_ptr->ui = dbusv_ptr->uint32; - return true; - case DBUS_TYPE_BYTE: - value_ptr->c = dbusv_ptr->byte; - return true; - case DBUS_TYPE_STRING: - len = strlen(dbusv_ptr->string); - if (len > JACK_PARAM_STRING_MAX) - { - jack_error("Parameter string value is too long (%u)", (unsigned int)len); - return false; - } - memcpy(value_ptr->str, dbusv_ptr->string, len + 1); - - return true; - case DBUS_TYPE_BOOLEAN: - value_ptr->b = dbusv_ptr->boolean; - return true; - } - - jack_error("Unknown D-Bus parameter type %i", (int)type); - return false; -} - -/* - * Construct a return message for a Get[Driver|Engine]ParameterValue method call. - * - * The operation can only fail due to lack of memory, in which case - * there's no sense in trying to construct an error return. Instead, - * call->reply will be set to NULL and handled in send_method_return(). - */ -static void -jack_dbus_construct_method_return_parameter( - struct jack_dbus_method_call *call, - dbus_bool_t is_set, - int type, - const char *signature, - message_arg_t default_value, - message_arg_t value) -{ - DBusMessageIter iter; - - /* Create a new method return message. */ - call->reply = dbus_message_new_method_return (call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append (call->reply, &iter); - - /* Append the is_set argument. */ - if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, (const void *) &is_set)) - { - goto fail_unref; - } - - /* Append the 'default' and 'value' arguments. */ - if (!jack_dbus_message_append_variant(&iter, type, signature, &default_value)) - { - goto fail_unref; - } - if (!jack_dbus_message_append_variant(&iter, type, signature, &value)) - { - goto fail_unref; - } - - return; - -fail_unref: - dbus_message_unref (call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -#define controller_ptr ((struct jack_controller *)call->context) - -static -void -jack_controller_dbus_get_available_drivers( - struct jack_dbus_method_call *call) -{ - jack_dbus_construct_method_return_array_of_strings( - call, - controller_ptr->drivers_count, - controller_ptr->driver_names); -} - -static -void -jack_controller_dbus_get_selected_driver( - struct jack_dbus_method_call *call) -{ - message_arg_t arg; - - if (controller_ptr->driver != NULL) - { - arg.string = jackctl_driver_get_name(controller_ptr->driver); - } - else - { - arg.string = NULL; - } - - jack_dbus_construct_method_return_single(call, DBUS_TYPE_STRING, arg); -} - -static -void -jack_controller_dbus_select_driver( - struct jack_dbus_method_call *call) -{ - const char *driver_name; - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &driver_name, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - if (!jack_controller_select_driver(controller_ptr, driver_name)) - { - /* Couldn't find driver with the specified name. */ - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_DRIVER, - "Unknown driver \"%s\"", - driver_name); - return; - } - - jack_controller_settings_save_auto(controller_ptr); - - jack_dbus_construct_method_return_empty(call); -} - -static -void -jack_controller_get_parameters_info( - struct jack_dbus_method_call *call, - const JSList *parameters_list) -{ - DBusMessageIter iter, array_iter, struct_iter; - unsigned char type; - const char *str; - - call->reply = dbus_message_new_method_return (call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append (call->reply, &iter); - - /* Open the array. */ - if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ysss)", &array_iter)) - { - goto fail_unref; - } - - /* Append parameter descriptions to the array. */ - while (parameters_list != NULL) - { - /* Open the struct. */ - if (!dbus_message_iter_open_container (&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)) - { - goto fail_close_unref; - } - - /* Append parameter type. */ - type = PARAM_TYPE_JACK_TO_DBUS(jackctl_parameter_get_type((jackctl_parameter_t *)parameters_list->data)); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_BYTE, - (const void *) &type)) - { - goto fail_close2_unref; - } - - /* Append parameter name. */ - str = jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close2_unref; - } - - /* Append parameter short description. */ - str = jackctl_parameter_get_short_description((jackctl_parameter_t *)parameters_list->data); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close2_unref; - } - - /* Append parameter long description. */ - str = jackctl_parameter_get_long_description((jackctl_parameter_t *)parameters_list->data); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close2_unref; - } - - /* Close the struct. */ - if (!dbus_message_iter_close_container (&array_iter, &struct_iter)) - { - goto fail_close_unref; - } - - parameters_list = jack_slist_next(parameters_list); - } - - /* Close the array. */ - if (!dbus_message_iter_close_container (&iter, &array_iter)) - { - goto fail_unref; - } - - return; - -fail_close2_unref: - dbus_message_iter_close_container (&iter, &struct_iter); - -fail_close_unref: - dbus_message_iter_close_container (&iter, &array_iter); - -fail_unref: - dbus_message_unref (call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -static -void -jack_controller_get_parameter_info( - struct jack_dbus_method_call *call, - jackctl_parameter_t *parameter) -{ - DBusMessageIter iter, struct_iter; - unsigned char type; - const char *str; - - call->reply = dbus_message_new_method_return (call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append (call->reply, &iter); - - /* Open the struct. */ - if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)) - { - goto fail_unref; - } - - /* Append parameter type. */ - type = PARAM_TYPE_JACK_TO_DBUS(jackctl_parameter_get_type(parameter)); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_BYTE, - (const void *) &type)) - { - goto fail_close_unref; - } - - /* Append parameter name. */ - str = jackctl_parameter_get_name(parameter); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close_unref; - } - - /* Append parameter short description. */ - str = jackctl_parameter_get_short_description(parameter); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close_unref; - } - - /* Append parameter long description. */ - str = jackctl_parameter_get_long_description(parameter); - if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, - (const void *) &str)) - { - goto fail_close_unref; - } - - /* Close the struct. */ - if (!dbus_message_iter_close_container (&iter, &struct_iter)) - { - goto fail_unref; - } - - return; - -fail_close_unref: - dbus_message_iter_close_container (&iter, &struct_iter); - -fail_unref: - dbus_message_unref (call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -/* - * Execute GetDriverParametersInfo method call. - */ -static -void -jack_controller_dbus_get_driver_parameters_info( - struct jack_dbus_method_call *call) -{ - if (controller_ptr->driver == NULL) - { - jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, - "No driver selected"); - return; - } - - jack_controller_get_parameters_info( - call, - jackctl_driver_get_parameters(controller_ptr->driver)); -} - -/* - * Execute GetDriverParameterInfo method call. - */ -static -void -jack_controller_dbus_get_driver_parameter_info( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - jackctl_parameter_t *parameter; - - if (controller_ptr->driver == NULL) - { - jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, - "No driver selected"); - return; - } - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, - "Unknown parameter \"%s\" for driver \"%s\"", - parameter_name, - jackctl_driver_get_name(controller_ptr->driver)); - return; - } - - jack_controller_get_parameter_info(call, parameter); -} - - -/* - * Execute GetDriverParameterValue method call. - */ -static void -jack_controller_dbus_get_driver_parameter_value( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - jackctl_parameter_t *parameter; - int type; - union jackctl_parameter_value jackctl_value; - union jackctl_parameter_value jackctl_default_value; - message_arg_t value; - message_arg_t default_value; - - if (controller_ptr->driver == NULL) - { - jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, - "No driver selected"); - return; - } - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * get_method_args() has constructed an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, - "Unknown parameter \"%s\" for driver \"%s\"", - parameter, - jackctl_driver_get_name(controller_ptr->driver)); - return; - } - - type = jackctl_parameter_get_type(parameter); - jackctl_default_value = jackctl_parameter_get_default_value(parameter); - jackctl_value = jackctl_parameter_get_value(parameter); - - jack_controller_jack_to_dbus_variant(type, &jackctl_value, &value); - jack_controller_jack_to_dbus_variant(type, &jackctl_default_value, &default_value); - - /* Construct the reply. */ - jack_dbus_construct_method_return_parameter( - call, - (dbus_bool_t)(jackctl_parameter_is_set(parameter) ? TRUE : FALSE), - PARAM_TYPE_JACK_TO_DBUS(type), - PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), - default_value, - value); -} - -static -void -jack_controller_dbus_set_driver_parameter_value( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - message_arg_t arg; - int arg_type; - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - union jackctl_parameter_value value; - - if (controller_ptr->driver == NULL) - { - jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, - "No driver selected"); - return; - } - - if (!jack_dbus_get_method_args_string_and_variant(call, ¶meter_name, &arg, &arg_type)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args_string_and_variant() has constructed - * an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, - "Unknown parameter \"%s\" for driver \"%s\"", - parameter, - jackctl_driver_get_name(controller_ptr->driver)); - return; - } - - type = jackctl_parameter_get_type(parameter); - - if (PARAM_TYPE_JACK_TO_DBUS(type) != arg_type) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Engine parameter value type mismatch: was expecting '%c', got '%c'", - (char)PARAM_TYPE_JACK_TO_DBUS(type), - (char)arg_type); - return; - } - - if (!jack_controller_dbus_to_jack_variant( - arg_type, - &arg, - &value)) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Cannot convert engine parameter value"); - return; - } - - jackctl_parameter_set_value(parameter, &value); - - jack_controller_settings_save_auto(controller_ptr); - - jack_dbus_construct_method_return_empty(call); -} - -/* - * Execute GetEngineParametersInfo method call. - */ -static -void -jack_controller_dbus_get_engine_parameters_info( - struct jack_dbus_method_call *call) -{ - jack_controller_get_parameters_info( - call, - jackctl_server_get_parameters(controller_ptr->server)); -} - -/* - * Execute GetEngineParameterInfo method call. - */ -static -void -jack_controller_dbus_get_engine_parameter_info( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - jackctl_parameter_t *parameter; - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_ENGINE_PARAMETER, - "Unknown engine parameter \"%s\"", - parameter); - return; - } - - jack_controller_get_parameter_info(call, parameter); -} - -/* - * Execute GetDriverParameterValue method call. - */ -static -void -jack_controller_dbus_get_engine_parameter_value( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - union jackctl_parameter_value jackctl_value; - union jackctl_parameter_value jackctl_default_value; - message_arg_t value; - message_arg_t default_value; - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_ENGINE_PARAMETER, - "Unknown engine parameter \"%s\"", - parameter); - return; - } - - type = jackctl_parameter_get_type(parameter); - jackctl_default_value = jackctl_parameter_get_default_value(parameter); - jackctl_value = jackctl_parameter_get_value(parameter); - - jack_controller_jack_to_dbus_variant(type, &jackctl_value, &value); - jack_controller_jack_to_dbus_variant(type, &jackctl_default_value, &default_value); - - /* Construct the reply. */ - jack_dbus_construct_method_return_parameter( - call, - (dbus_bool_t)(jackctl_parameter_is_set(parameter) ? TRUE : FALSE), - PARAM_TYPE_JACK_TO_DBUS(type), - PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), - default_value, - value); -} - -static -void -jack_controller_dbus_set_engine_parameter_value( - struct jack_dbus_method_call *call) -{ - const char *parameter_name; - message_arg_t arg; - int arg_type; - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - union jackctl_parameter_value value; - - if (!jack_dbus_get_method_args_string_and_variant (call, ¶meter_name, &arg, &arg_type)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args_string_and_variant() has constructed - * an error for us. - */ - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), parameter_name); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_ENGINE_PARAMETER, - "Unknown engine parameter \"%s\"", - parameter); - return; - } - - type = jackctl_parameter_get_type(parameter); - - if (PARAM_TYPE_JACK_TO_DBUS(type) != arg_type) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Engine parameter value type mismatch: was expecting '%c', got '%c'", - (char)PARAM_TYPE_JACK_TO_DBUS(type), - (char)arg_type); - return; - } - - if (!jack_controller_dbus_to_jack_variant( - arg_type, - &arg, - &value)) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Cannot convert engine parameter value"); - return; - } - - jackctl_parameter_set_value(parameter, &value); - - jack_controller_settings_save_auto(controller_ptr); - - jack_dbus_construct_method_return_empty(call); -} - -#undef controller_ptr - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetAvailableDrivers) - JACK_DBUS_METHOD_ARGUMENT("drivers_list", "as", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetSelectedDriver) - JACK_DBUS_METHOD_ARGUMENT("driver", "s", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SelectDriver) - JACK_DBUS_METHOD_ARGUMENT("driver", "s", false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetDriverParametersInfo) - JACK_DBUS_METHOD_ARGUMENT("parameter_info_array", "a(ysss)", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetDriverParameterInfo) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("parameter_info", "(ysss)", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetDriverParameterValue) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("is_set", "b", true) - JACK_DBUS_METHOD_ARGUMENT("default", "v", true) - JACK_DBUS_METHOD_ARGUMENT("value", "v", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SetDriverParameterValue) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("value", "v", false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetEngineParametersInfo) - JACK_DBUS_METHOD_ARGUMENT("parameter_info_array", "a(ysss)", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetEngineParameterInfo) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("parameter_info", "(ysss)", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetEngineParameterValue) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("is_set", "b", true) - JACK_DBUS_METHOD_ARGUMENT("default", "v", true) - JACK_DBUS_METHOD_ARGUMENT("value", "v", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SetEngineParameterValue) - JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) - JACK_DBUS_METHOD_ARGUMENT("value", "v", false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHODS_BEGIN - JACK_DBUS_METHOD_DESCRIBE(GetAvailableDrivers, jack_controller_dbus_get_available_drivers) - JACK_DBUS_METHOD_DESCRIBE(GetSelectedDriver, jack_controller_dbus_get_selected_driver) - JACK_DBUS_METHOD_DESCRIBE(SelectDriver, jack_controller_dbus_select_driver) - JACK_DBUS_METHOD_DESCRIBE(GetDriverParametersInfo, jack_controller_dbus_get_driver_parameters_info) - JACK_DBUS_METHOD_DESCRIBE(GetDriverParameterInfo, jack_controller_dbus_get_driver_parameter_info) - JACK_DBUS_METHOD_DESCRIBE(GetDriverParameterValue, jack_controller_dbus_get_driver_parameter_value) - JACK_DBUS_METHOD_DESCRIBE(SetDriverParameterValue, jack_controller_dbus_set_driver_parameter_value) - JACK_DBUS_METHOD_DESCRIBE(GetEngineParametersInfo, jack_controller_dbus_get_engine_parameters_info) - JACK_DBUS_METHOD_DESCRIBE(GetEngineParameterInfo, jack_controller_dbus_get_engine_parameter_info) - JACK_DBUS_METHOD_DESCRIBE(GetEngineParameterValue, jack_controller_dbus_get_engine_parameter_value) - JACK_DBUS_METHOD_DESCRIBE(SetEngineParameterValue, jack_controller_dbus_set_engine_parameter_value) -JACK_DBUS_METHODS_END - -JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_configure, "org.jackaudio.JackConfigure") - JACK_DBUS_IFACE_EXPOSE_METHODS -JACK_DBUS_IFACE_END diff --git a/linux/dbus/controller_iface_control.c b/linux/dbus/controller_iface_control.c index 435b7e68..4cac9473 100644 --- a/linux/dbus/controller_iface_control.c +++ b/linux/dbus/controller_iface_control.c @@ -227,690 +227,3 @@ JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_control, "org.jackaudio.JackContro JACK_DBUS_IFACE_HANDLER(jack_control_run_method) JACK_DBUS_IFACE_EXPOSE_METHODS JACK_DBUS_IFACE_END -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - Copyright (C) 2007-2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include - -#include "jackdbus.h" -#include "controller_internal.h" - -#define controller_ptr ((struct jack_controller *)call->context) - -/* - * Check if the supplied method name exists in org.jackaudio.JackControl, - * if it does execute it and return true. Otherwise return false. - */ -static -bool -jack_control_run_method( - struct jack_dbus_method_call * call, - const struct jack_dbus_interface_method_descriptor * methods) -{ - int ret; - int type; - message_arg_t arg; - - /* use empty reply if not overriden in the code that follows */ - type = DBUS_TYPE_INVALID; - - if (strcmp (call->method_name, "Exit") == 0) - { - g_exit_command = TRUE; - } - else if (strcmp (call->method_name, "IsStarted") == 0) - { - type = DBUS_TYPE_BOOLEAN; - arg.boolean = (dbus_bool_t) (controller_ptr->started ? TRUE : FALSE); - } - else if (strcmp (call->method_name, "StartServer") == 0) - { - if (!jack_controller_start_server(controller_ptr, call)) - { - jack_error ("Failed to start server"); - } - } - else if (strcmp (call->method_name, "StopServer") == 0) - { - if (!jack_controller_stop_server(controller_ptr, call)) - { - jack_error ("Failed to stop server"); - } - } - else if (strcmp (call->method_name, "GetLoad") == 0) - { - if (!controller_ptr->started) - { - goto not_started; - } - - type = DBUS_TYPE_DOUBLE; - arg.doubl = jack_cpu_load(controller_ptr->client); - } - else if (strcmp (call->method_name, "GetXruns") == 0) - { - type = DBUS_TYPE_UINT32; - arg.uint32 = controller_ptr->xruns; - } - else if (strcmp (call->method_name, "GetSampleRate") == 0) - { - if (!controller_ptr->started) - { - goto not_started; - } - - type = DBUS_TYPE_UINT32; - arg.uint32 = jack_get_sample_rate(controller_ptr->client); - } - else if (strcmp (call->method_name, "GetLatency") == 0) - { - if (!controller_ptr->started) - { - goto not_started; - } - - type = DBUS_TYPE_DOUBLE; - arg.doubl = ((float)jack_get_buffer_size(controller_ptr->client) / (float)jack_get_sample_rate(controller_ptr->client)) * 1000.0f; - } - else if (strcmp (call->method_name, "GetBufferSize") == 0) - { - if (!controller_ptr->started) - { - goto not_started; - } - - type = DBUS_TYPE_UINT32; - arg.uint32 = jack_get_buffer_size(controller_ptr->client); - } - else if (strcmp (call->method_name, "SetBufferSize") == 0) - { - dbus_uint32_t buffer_size; - - if (!controller_ptr->started) - { - goto not_started; - } - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_UINT32, &buffer_size, DBUS_TYPE_INVALID)) - { - /* jack_dbus_get_method_args() has set reply for us */ - goto exit; - } - - ret = jack_set_buffer_size(controller_ptr->client, buffer_size); - if (ret != 0) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_GENERIC, - "jack_set_buffer_size(%u) failed with error %d", (unsigned int)buffer_size, ret); - - goto exit; - } - } - else if (strcmp (call->method_name, "IsRealtime") == 0) - { - type = DBUS_TYPE_BOOLEAN; - arg.boolean = jack_is_realtime(controller_ptr->client) ? TRUE : FALSE; - } - else if (strcmp (call->method_name, "ResetXruns") == 0) - { - controller_ptr->xruns = 0; - } - else - { - return false; - } - - jack_dbus_construct_method_return_single(call, type, arg); - - return true; - -not_started: - jack_dbus_error (call, JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute method '%s' with stopped JACK server", call->method_name); - -exit: - return true; -} - -#undef controller_ptr - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(IsStarted) - JACK_DBUS_METHOD_ARGUMENT("started", "b", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(StartServer) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(StopServer) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetLoad) - JACK_DBUS_METHOD_ARGUMENT("load", "d", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetXruns) - JACK_DBUS_METHOD_ARGUMENT("xruns_count", "u", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetSampleRate) - JACK_DBUS_METHOD_ARGUMENT("sample_rate", "u", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetLatency) - JACK_DBUS_METHOD_ARGUMENT("latency_ms", "d", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetBufferSize) - JACK_DBUS_METHOD_ARGUMENT("buffer_size_frames", "u", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SetBufferSize) - JACK_DBUS_METHOD_ARGUMENT("buffer_size_frames", "u", false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(IsRealtime) - JACK_DBUS_METHOD_ARGUMENT("realtime", "b", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ResetXruns) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHODS_BEGIN - JACK_DBUS_METHOD_DESCRIBE(IsStarted, NULL) - JACK_DBUS_METHOD_DESCRIBE(StartServer, NULL) - JACK_DBUS_METHOD_DESCRIBE(StopServer, NULL) - JACK_DBUS_METHOD_DESCRIBE(GetLoad, NULL) - JACK_DBUS_METHOD_DESCRIBE(GetXruns, NULL) - JACK_DBUS_METHOD_DESCRIBE(GetSampleRate, NULL) - JACK_DBUS_METHOD_DESCRIBE(GetLatency, NULL) - JACK_DBUS_METHOD_DESCRIBE(GetBufferSize, NULL) - JACK_DBUS_METHOD_DESCRIBE(SetBufferSize, NULL) - JACK_DBUS_METHOD_DESCRIBE(IsRealtime, NULL) - JACK_DBUS_METHOD_DESCRIBE(ResetXruns, NULL) -JACK_DBUS_METHODS_END - -JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_control, "org.jackaudio.JackControl") - JACK_DBUS_IFACE_HANDLER(jack_control_run_method) - JACK_DBUS_IFACE_EXPOSE_METHODS -JACK_DBUS_IFACE_END -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - Copyright (C) 2007-2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include - -#include "jackdbus.h" -#include "controller_internal.h" - -#define controller_ptr ((struct jack_controller *)call->context) - -/* - * Check if the supplied method name exists in org.jackaudio.JackControl, - * if it does execute it and return true. Otherwise return false. - */ -static -bool -jack_control_run_method( - struct jack_dbus_method_call * call, - const struct jack_dbus_interface_method_descriptor * methods) -{ - int ret; - int type; - message_arg_t arg; - - /* use empty reply if not overriden in the code that follows */ - type = DBUS_TYPE_INVALID; - - if (strcmp (call->method_name, "Exit") == 0) - { - g_exit_command = TRUE; - } - else if (strcmp (call->method_name, "IsStarted") == 0) - { - type = DBUS_TYPE_BOOLEAN; - arg.boolean = (dbus_bool_t) (controller_ptr->started ? TRUE : FALSE); - } - else if (strcmp (call->method_name, "StartServer") == 0) - { - if (!jack_controller_start_server(controller_ptr, call)) - { - jack_error ("Failed to start server"); - } - } - else if (strcmp (call->method_name, "StopServer") == 0) - { - if (!jack_controller_stop_server(controller_ptr, call)) - { - jack_error ("Failed to stop server"); - } - } - else if (strcmp (call->method_name, "GetLoad") == 0) - { - if (!controller_ptr->started) - { - goto not_started; - } - - type = DBUS_TYPE_DOUBLE; - arg.doubl = jack_cpu_load(controller_ptr->client); - } - else if (strcmp (call->method_name, "GetXruns") == 0) - { - type = DBUS_TYPE_UINT32; - arg.uint32 = controller_ptr->xruns; - } - else if (strcmp (call->method_name, "GetSampleRate") == 0) - { - if (!controller_ptr->started) - { - goto not_started; - } - - type = DBUS_TYPE_UINT32; - arg.uint32 = jack_get_sample_rate(controller_ptr->client); - } - else if (strcmp (call->method_name, "GetLatency") == 0) - { - if (!controller_ptr->started) - { - goto not_started; - } - - type = DBUS_TYPE_DOUBLE; - arg.doubl = ((float)jack_get_buffer_size(controller_ptr->client) / (float)jack_get_sample_rate(controller_ptr->client)) * 1000.0f; - } - else if (strcmp (call->method_name, "GetBufferSize") == 0) - { - if (!controller_ptr->started) - { - goto not_started; - } - - type = DBUS_TYPE_UINT32; - arg.uint32 = jack_get_buffer_size(controller_ptr->client); - } - else if (strcmp (call->method_name, "SetBufferSize") == 0) - { - dbus_uint32_t buffer_size; - - if (!controller_ptr->started) - { - goto not_started; - } - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_UINT32, &buffer_size, DBUS_TYPE_INVALID)) - { - /* jack_dbus_get_method_args() has set reply for us */ - goto exit; - } - - ret = jack_set_buffer_size(controller_ptr->client, buffer_size); - if (ret != 0) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_GENERIC, - "jack_set_buffer_size(%u) failed with error %d", (unsigned int)buffer_size, ret); - - goto exit; - } - } - else if (strcmp (call->method_name, "IsRealtime") == 0) - { - type = DBUS_TYPE_BOOLEAN; - arg.boolean = jack_is_realtime(controller_ptr->client) ? TRUE : FALSE; - } - else if (strcmp (call->method_name, "ResetXruns") == 0) - { - controller_ptr->xruns = 0; - } - else - { - return false; - } - - jack_dbus_construct_method_return_single(call, type, arg); - - return true; - -not_started: - jack_dbus_error (call, JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute method '%s' with stopped JACK server", call->method_name); - -exit: - return true; -} - -#undef controller_ptr - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(IsStarted) - JACK_DBUS_METHOD_ARGUMENT("started", "b", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(StartServer) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(StopServer) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetLoad) - JACK_DBUS_METHOD_ARGUMENT("load", "d", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetXruns) - JACK_DBUS_METHOD_ARGUMENT("xruns_count", "u", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetSampleRate) - JACK_DBUS_METHOD_ARGUMENT("sample_rate", "u", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetLatency) - JACK_DBUS_METHOD_ARGUMENT("latency_ms", "d", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetBufferSize) - JACK_DBUS_METHOD_ARGUMENT("buffer_size_frames", "u", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SetBufferSize) - JACK_DBUS_METHOD_ARGUMENT("buffer_size_frames", "u", false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(IsRealtime) - JACK_DBUS_METHOD_ARGUMENT("realtime", "b", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ResetXruns) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHODS_BEGIN - JACK_DBUS_METHOD_DESCRIBE(IsStarted, NULL) - JACK_DBUS_METHOD_DESCRIBE(StartServer, NULL) - JACK_DBUS_METHOD_DESCRIBE(StopServer, NULL) - JACK_DBUS_METHOD_DESCRIBE(GetLoad, NULL) - JACK_DBUS_METHOD_DESCRIBE(GetXruns, NULL) - JACK_DBUS_METHOD_DESCRIBE(GetSampleRate, NULL) - JACK_DBUS_METHOD_DESCRIBE(GetLatency, NULL) - JACK_DBUS_METHOD_DESCRIBE(GetBufferSize, NULL) - JACK_DBUS_METHOD_DESCRIBE(SetBufferSize, NULL) - JACK_DBUS_METHOD_DESCRIBE(IsRealtime, NULL) - JACK_DBUS_METHOD_DESCRIBE(ResetXruns, NULL) -JACK_DBUS_METHODS_END - -JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_control, "org.jackaudio.JackControl") - JACK_DBUS_IFACE_HANDLER(jack_control_run_method) - JACK_DBUS_IFACE_EXPOSE_METHODS -JACK_DBUS_IFACE_END -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - Copyright (C) 2007-2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include - -#include "jackdbus.h" -#include "controller_internal.h" - -#define controller_ptr ((struct jack_controller *)call->context) - -/* - * Check if the supplied method name exists in org.jackaudio.JackControl, - * if it does execute it and return true. Otherwise return false. - */ -static -bool -jack_control_run_method( - struct jack_dbus_method_call * call, - const struct jack_dbus_interface_method_descriptor * methods) -{ - int ret; - int type; - message_arg_t arg; - - /* use empty reply if not overriden in the code that follows */ - type = DBUS_TYPE_INVALID; - - if (strcmp (call->method_name, "Exit") == 0) - { - g_exit_command = TRUE; - } - else if (strcmp (call->method_name, "IsStarted") == 0) - { - type = DBUS_TYPE_BOOLEAN; - arg.boolean = (dbus_bool_t) (controller_ptr->started ? TRUE : FALSE); - } - else if (strcmp (call->method_name, "StartServer") == 0) - { - if (!jack_controller_start_server(controller_ptr, call)) - { - jack_error ("Failed to start server"); - } - } - else if (strcmp (call->method_name, "StopServer") == 0) - { - if (!jack_controller_stop_server(controller_ptr, call)) - { - jack_error ("Failed to stop server"); - } - } - else if (strcmp (call->method_name, "GetLoad") == 0) - { - if (!controller_ptr->started) - { - goto not_started; - } - - type = DBUS_TYPE_DOUBLE; - arg.doubl = jack_cpu_load(controller_ptr->client); - } - else if (strcmp (call->method_name, "GetXruns") == 0) - { - type = DBUS_TYPE_UINT32; - arg.uint32 = controller_ptr->xruns; - } - else if (strcmp (call->method_name, "GetSampleRate") == 0) - { - if (!controller_ptr->started) - { - goto not_started; - } - - type = DBUS_TYPE_UINT32; - arg.uint32 = jack_get_sample_rate(controller_ptr->client); - } - else if (strcmp (call->method_name, "GetLatency") == 0) - { - if (!controller_ptr->started) - { - goto not_started; - } - - type = DBUS_TYPE_DOUBLE; - arg.doubl = ((float)jack_get_buffer_size(controller_ptr->client) / (float)jack_get_sample_rate(controller_ptr->client)) * 1000.0f; - } - else if (strcmp (call->method_name, "GetBufferSize") == 0) - { - if (!controller_ptr->started) - { - goto not_started; - } - - type = DBUS_TYPE_UINT32; - arg.uint32 = jack_get_buffer_size(controller_ptr->client); - } - else if (strcmp (call->method_name, "SetBufferSize") == 0) - { - dbus_uint32_t buffer_size; - - if (!controller_ptr->started) - { - goto not_started; - } - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_UINT32, &buffer_size, DBUS_TYPE_INVALID)) - { - /* jack_dbus_get_method_args() has set reply for us */ - goto exit; - } - - ret = jack_set_buffer_size(controller_ptr->client, buffer_size); - if (ret != 0) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_GENERIC, - "jack_set_buffer_size(%u) failed with error %d", (unsigned int)buffer_size, ret); - - goto exit; - } - } - else if (strcmp (call->method_name, "IsRealtime") == 0) - { - type = DBUS_TYPE_BOOLEAN; - arg.boolean = jack_is_realtime(controller_ptr->client) ? TRUE : FALSE; - } - else if (strcmp (call->method_name, "ResetXruns") == 0) - { - controller_ptr->xruns = 0; - } - else - { - return false; - } - - jack_dbus_construct_method_return_single(call, type, arg); - - return true; - -not_started: - jack_dbus_error (call, JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute method '%s' with stopped JACK server", call->method_name); - -exit: - return true; -} - -#undef controller_ptr - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(IsStarted) - JACK_DBUS_METHOD_ARGUMENT("started", "b", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(StartServer) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(StopServer) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetLoad) - JACK_DBUS_METHOD_ARGUMENT("load", "d", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetXruns) - JACK_DBUS_METHOD_ARGUMENT("xruns_count", "u", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetSampleRate) - JACK_DBUS_METHOD_ARGUMENT("sample_rate", "u", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetLatency) - JACK_DBUS_METHOD_ARGUMENT("latency_ms", "d", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetBufferSize) - JACK_DBUS_METHOD_ARGUMENT("buffer_size_frames", "u", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SetBufferSize) - JACK_DBUS_METHOD_ARGUMENT("buffer_size_frames", "u", false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(IsRealtime) - JACK_DBUS_METHOD_ARGUMENT("realtime", "b", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ResetXruns) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHODS_BEGIN - JACK_DBUS_METHOD_DESCRIBE(IsStarted, NULL) - JACK_DBUS_METHOD_DESCRIBE(StartServer, NULL) - JACK_DBUS_METHOD_DESCRIBE(StopServer, NULL) - JACK_DBUS_METHOD_DESCRIBE(GetLoad, NULL) - JACK_DBUS_METHOD_DESCRIBE(GetXruns, NULL) - JACK_DBUS_METHOD_DESCRIBE(GetSampleRate, NULL) - JACK_DBUS_METHOD_DESCRIBE(GetLatency, NULL) - JACK_DBUS_METHOD_DESCRIBE(GetBufferSize, NULL) - JACK_DBUS_METHOD_DESCRIBE(SetBufferSize, NULL) - JACK_DBUS_METHOD_DESCRIBE(IsRealtime, NULL) - JACK_DBUS_METHOD_DESCRIBE(ResetXruns, NULL) -JACK_DBUS_METHODS_END - -JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_control, "org.jackaudio.JackControl") - JACK_DBUS_IFACE_HANDLER(jack_control_run_method) - JACK_DBUS_IFACE_EXPOSE_METHODS -JACK_DBUS_IFACE_END diff --git a/linux/dbus/controller_iface_introspectable.c b/linux/dbus/controller_iface_introspectable.c index 84072ffc..1392a656 100644 --- a/linux/dbus/controller_iface_introspectable.c +++ b/linux/dbus/controller_iface_introspectable.c @@ -150,459 +150,3 @@ jack_controller_introspect_init() *g_buffer_ptr = 0; } -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007-2008 Nedko Arnaudov - Copyright (C) 2007-2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include - -#include "jackdbus.h" - -static char g_xml_data[102400]; - -static -void -jack_controller_dbus_introspect( - struct jack_dbus_method_call * call) -{ - jack_dbus_construct_method_return_single( - call, - DBUS_TYPE_STRING, - (message_arg_t)(const char *)g_xml_data); -} - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(Introspect) - JACK_DBUS_METHOD_ARGUMENT("xml_data", "s", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHODS_BEGIN - JACK_DBUS_METHOD_DESCRIBE(Introspect, jack_controller_dbus_introspect) -JACK_DBUS_METHODS_END - -JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_introspectable, "org.freedesktop.DBus.Introspectable") - JACK_DBUS_IFACE_EXPOSE_METHODS -JACK_DBUS_IFACE_END - -static char * g_buffer_ptr; - -static -void -write_line_format(const char * format, ...) -{ - va_list ap; - - va_start(ap, format); - g_buffer_ptr += vsprintf(g_buffer_ptr, format, ap); - va_end(ap); -} - -static -void -write_line(const char * line) -{ - write_line_format("%s\n", line); -} - -void jack_controller_introspect_init() __attribute__((constructor)); - -void -jack_controller_introspect_init() -{ - struct jack_dbus_interface_descriptor ** interface_ptr_ptr; - const struct jack_dbus_interface_method_descriptor * method_ptr; - const struct jack_dbus_interface_method_argument_descriptor * method_argument_ptr; - const struct jack_dbus_interface_signal_descriptor * signal_ptr; - const struct jack_dbus_interface_signal_argument_descriptor * signal_argument_ptr; - - g_buffer_ptr = g_xml_data; - - write_line(""); - - write_line(""); - - interface_ptr_ptr = g_jackcontroller_interfaces; - - while (*interface_ptr_ptr != NULL) - { - write_line_format(" \n", (*interface_ptr_ptr)->name); - - if ((*interface_ptr_ptr)->methods != NULL) - { - method_ptr = (*interface_ptr_ptr)->methods; - while (method_ptr->name != NULL) - { - write_line_format(" \n", method_ptr->name); - - method_argument_ptr = method_ptr->arguments; - - while (method_argument_ptr->name != NULL) - { - write_line_format( - " \n", - method_argument_ptr->name, - method_argument_ptr->type, - method_argument_ptr->direction_out ? "out" : "in"); - method_argument_ptr++; - } - - write_line(" "); - method_ptr++; - } - } - - if ((*interface_ptr_ptr)->signals != NULL) - { - signal_ptr = (*interface_ptr_ptr)->signals; - while (signal_ptr->name != NULL) - { - write_line_format(" \n", signal_ptr->name); - - signal_argument_ptr = signal_ptr->arguments; - - while (signal_argument_ptr->name != NULL) - { - write_line_format( - " \n", - signal_argument_ptr->name, - signal_argument_ptr->type); - signal_argument_ptr++; - } - - write_line(" "); - signal_ptr++; - } - } - - write_line(" "); - interface_ptr_ptr++; - } - - write_line(""); - - *g_buffer_ptr = 0; -} -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007-2008 Nedko Arnaudov - Copyright (C) 2007-2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include - -#include "jackdbus.h" - -static char g_xml_data[102400]; - -static -void -jack_controller_dbus_introspect( - struct jack_dbus_method_call * call) -{ - jack_dbus_construct_method_return_single( - call, - DBUS_TYPE_STRING, - (message_arg_t)(const char *)g_xml_data); -} - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(Introspect) - JACK_DBUS_METHOD_ARGUMENT("xml_data", "s", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHODS_BEGIN - JACK_DBUS_METHOD_DESCRIBE(Introspect, jack_controller_dbus_introspect) -JACK_DBUS_METHODS_END - -JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_introspectable, "org.freedesktop.DBus.Introspectable") - JACK_DBUS_IFACE_EXPOSE_METHODS -JACK_DBUS_IFACE_END - -static char * g_buffer_ptr; - -static -void -write_line_format(const char * format, ...) -{ - va_list ap; - - va_start(ap, format); - g_buffer_ptr += vsprintf(g_buffer_ptr, format, ap); - va_end(ap); -} - -static -void -write_line(const char * line) -{ - write_line_format("%s\n", line); -} - -void jack_controller_introspect_init() __attribute__((constructor)); - -void -jack_controller_introspect_init() -{ - struct jack_dbus_interface_descriptor ** interface_ptr_ptr; - const struct jack_dbus_interface_method_descriptor * method_ptr; - const struct jack_dbus_interface_method_argument_descriptor * method_argument_ptr; - const struct jack_dbus_interface_signal_descriptor * signal_ptr; - const struct jack_dbus_interface_signal_argument_descriptor * signal_argument_ptr; - - g_buffer_ptr = g_xml_data; - - write_line(""); - - write_line(""); - - interface_ptr_ptr = g_jackcontroller_interfaces; - - while (*interface_ptr_ptr != NULL) - { - write_line_format(" \n", (*interface_ptr_ptr)->name); - - if ((*interface_ptr_ptr)->methods != NULL) - { - method_ptr = (*interface_ptr_ptr)->methods; - while (method_ptr->name != NULL) - { - write_line_format(" \n", method_ptr->name); - - method_argument_ptr = method_ptr->arguments; - - while (method_argument_ptr->name != NULL) - { - write_line_format( - " \n", - method_argument_ptr->name, - method_argument_ptr->type, - method_argument_ptr->direction_out ? "out" : "in"); - method_argument_ptr++; - } - - write_line(" "); - method_ptr++; - } - } - - if ((*interface_ptr_ptr)->signals != NULL) - { - signal_ptr = (*interface_ptr_ptr)->signals; - while (signal_ptr->name != NULL) - { - write_line_format(" \n", signal_ptr->name); - - signal_argument_ptr = signal_ptr->arguments; - - while (signal_argument_ptr->name != NULL) - { - write_line_format( - " \n", - signal_argument_ptr->name, - signal_argument_ptr->type); - signal_argument_ptr++; - } - - write_line(" "); - signal_ptr++; - } - } - - write_line(" "); - interface_ptr_ptr++; - } - - write_line(""); - - *g_buffer_ptr = 0; -} -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007-2008 Nedko Arnaudov - Copyright (C) 2007-2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include - -#include "jackdbus.h" - -static char g_xml_data[102400]; - -static -void -jack_controller_dbus_introspect( - struct jack_dbus_method_call * call) -{ - jack_dbus_construct_method_return_single( - call, - DBUS_TYPE_STRING, - (message_arg_t)(const char *)g_xml_data); -} - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(Introspect) - JACK_DBUS_METHOD_ARGUMENT("xml_data", "s", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHODS_BEGIN - JACK_DBUS_METHOD_DESCRIBE(Introspect, jack_controller_dbus_introspect) -JACK_DBUS_METHODS_END - -JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_introspectable, "org.freedesktop.DBus.Introspectable") - JACK_DBUS_IFACE_EXPOSE_METHODS -JACK_DBUS_IFACE_END - -static char * g_buffer_ptr; - -static -void -write_line_format(const char * format, ...) -{ - va_list ap; - - va_start(ap, format); - g_buffer_ptr += vsprintf(g_buffer_ptr, format, ap); - va_end(ap); -} - -static -void -write_line(const char * line) -{ - write_line_format("%s\n", line); -} - -void jack_controller_introspect_init() __attribute__((constructor)); - -void -jack_controller_introspect_init() -{ - struct jack_dbus_interface_descriptor ** interface_ptr_ptr; - const struct jack_dbus_interface_method_descriptor * method_ptr; - const struct jack_dbus_interface_method_argument_descriptor * method_argument_ptr; - const struct jack_dbus_interface_signal_descriptor * signal_ptr; - const struct jack_dbus_interface_signal_argument_descriptor * signal_argument_ptr; - - g_buffer_ptr = g_xml_data; - - write_line(""); - - write_line(""); - - interface_ptr_ptr = g_jackcontroller_interfaces; - - while (*interface_ptr_ptr != NULL) - { - write_line_format(" \n", (*interface_ptr_ptr)->name); - - if ((*interface_ptr_ptr)->methods != NULL) - { - method_ptr = (*interface_ptr_ptr)->methods; - while (method_ptr->name != NULL) - { - write_line_format(" \n", method_ptr->name); - - method_argument_ptr = method_ptr->arguments; - - while (method_argument_ptr->name != NULL) - { - write_line_format( - " \n", - method_argument_ptr->name, - method_argument_ptr->type, - method_argument_ptr->direction_out ? "out" : "in"); - method_argument_ptr++; - } - - write_line(" "); - method_ptr++; - } - } - - if ((*interface_ptr_ptr)->signals != NULL) - { - signal_ptr = (*interface_ptr_ptr)->signals; - while (signal_ptr->name != NULL) - { - write_line_format(" \n", signal_ptr->name); - - signal_argument_ptr = signal_ptr->arguments; - - while (signal_argument_ptr->name != NULL) - { - write_line_format( - " \n", - signal_argument_ptr->name, - signal_argument_ptr->type); - signal_argument_ptr++; - } - - write_line(" "); - signal_ptr++; - } - } - - write_line(" "); - interface_ptr_ptr++; - } - - write_line(""); - - *g_buffer_ptr = 0; -} diff --git a/linux/dbus/controller_iface_patchbay.c b/linux/dbus/controller_iface_patchbay.c index aa7990a9..7fe7a130 100644 --- a/linux/dbus/controller_iface_patchbay.c +++ b/linux/dbus/controller_iface_patchbay.c @@ -1843,5538 +1843,3 @@ JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_patchbay, JACK_DBUS_IFACE_NAME) JACK_DBUS_IFACE_EXPOSE_METHODS JACK_DBUS_IFACE_EXPOSE_SIGNALS JACK_DBUS_IFACE_END -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2008 Nedko Arnaudov - Copyright (C) 2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#define _GNU_SOURCE /* PTHREAD_MUTEX_RECURSIVE */ - -#include -#include -#include -#include -#include -#include -#include - -#include "jackdbus.h" -#include "controller_internal.h" -#include "list.h" - -#define JACK_DBUS_IFACE_NAME "org.jackaudio.JackPatchbay" - -/* FIXME: these need to be retrieved from common headers */ -#define JACK_CLIENT_NAME_SIZE 64 -#define JACK_PORT_NAME_SIZE 256 - -struct jack_graph -{ - uint64_t version; - struct list_head clients; - struct list_head ports; - struct list_head connections; -}; - -struct jack_graph_client -{ - uint64_t id; - char * name; - int pid; - struct list_head siblings; - struct list_head ports; -}; - -struct jack_graph_port -{ - uint64_t id; - char * name; - uint32_t flags; - uint32_t type; - struct list_head siblings_graph; - struct list_head siblings_client; - struct jack_graph_client * client; -}; - -struct jack_graph_connection -{ - uint64_t id; - struct jack_graph_port * port1; - struct jack_graph_port * port2; - struct list_head siblings; -}; - -struct jack_controller_patchbay -{ - pthread_mutex_t lock; - struct jack_graph graph; - uint64_t next_client_id; - uint64_t next_port_id; - uint64_t next_connection_id; -}; - -void -jack_controller_patchbay_send_signal_graph_changed( - dbus_uint64_t new_graph_version) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "GraphChanged", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_client_appeared( - dbus_uint64_t new_graph_version, - dbus_uint64_t client_id, - const char * client_name) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "ClientAppeared", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_client_disappeared( - dbus_uint64_t new_graph_version, - dbus_uint64_t client_id, - const char * client_name) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "ClientDisappeared", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_port_appeared( - dbus_uint64_t new_graph_version, - dbus_uint64_t client_id, - const char * client_name, - dbus_uint64_t port_id, - const char * port_name, - dbus_uint32_t port_flags, - dbus_uint32_t port_type) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "PortAppeared", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_UINT64, - &port_id, - DBUS_TYPE_STRING, - &port_name, - DBUS_TYPE_UINT32, - &port_flags, - DBUS_TYPE_UINT32, - &port_type, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_port_disappeared( - dbus_uint64_t new_graph_version, - dbus_uint64_t client_id, - const char * client_name, - dbus_uint64_t port_id, - const char * port_name) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "PortDisappeared", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_UINT64, - &port_id, - DBUS_TYPE_STRING, - &port_name, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_ports_connected( - dbus_uint64_t new_graph_version, - dbus_uint64_t client1_id, - const char * client1_name, - dbus_uint64_t port1_id, - const char * port1_name, - dbus_uint64_t client2_id, - const char * client2_name, - dbus_uint64_t port2_id, - const char * port2_name, - dbus_uint64_t connection_id) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "PortsConnected", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client1_id, - DBUS_TYPE_STRING, - &client1_name, - DBUS_TYPE_UINT64, - &port1_id, - DBUS_TYPE_STRING, - &port1_name, - DBUS_TYPE_UINT64, - &client2_id, - DBUS_TYPE_STRING, - &client2_name, - DBUS_TYPE_UINT64, - &port2_id, - DBUS_TYPE_STRING, - &port2_name, - DBUS_TYPE_UINT64, - &connection_id, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_ports_disconnected( - dbus_uint64_t new_graph_version, - dbus_uint64_t client1_id, - const char * client1_name, - dbus_uint64_t port1_id, - const char * port1_name, - dbus_uint64_t client2_id, - const char * client2_name, - dbus_uint64_t port2_id, - const char * port2_name, - dbus_uint64_t connection_id) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "PortsDisconnected", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client1_id, - DBUS_TYPE_STRING, - &client1_name, - DBUS_TYPE_UINT64, - &port1_id, - DBUS_TYPE_STRING, - &port1_name, - DBUS_TYPE_UINT64, - &client2_id, - DBUS_TYPE_STRING, - &client2_name, - DBUS_TYPE_UINT64, - &port2_id, - DBUS_TYPE_STRING, - &port2_name, - DBUS_TYPE_UINT64, - &connection_id, - DBUS_TYPE_INVALID); -} - -static -struct jack_graph_client * -jack_controller_patchbay_find_client( - struct jack_controller_patchbay *patchbay_ptr, - const char *client_name, /* not '\0' terminated */ - size_t client_name_len) /* without terminating '\0' */ -{ - struct list_head *node_ptr; - struct jack_graph_client *client_ptr; - - list_for_each(node_ptr, &patchbay_ptr->graph.clients) - { - client_ptr = list_entry(node_ptr, struct jack_graph_client, siblings); - if (strncmp(client_ptr->name, client_name, client_name_len) == 0) - { - return client_ptr; - } - } - - return NULL; -} - -static -struct jack_graph_client * -jack_controller_patchbay_find_client_by_id( - struct jack_controller_patchbay *patchbay_ptr, - uint64_t id) -{ - struct list_head *node_ptr; - struct jack_graph_client *client_ptr; - - list_for_each(node_ptr, &patchbay_ptr->graph.clients) - { - client_ptr = list_entry(node_ptr, struct jack_graph_client, siblings); - if (client_ptr->id == id) - { - return client_ptr; - } - } - - return NULL; -} - -static -struct jack_graph_client * -jack_controller_patchbay_create_client( - struct jack_controller_patchbay *patchbay_ptr, - const char *client_name, /* not '\0' terminated */ - size_t client_name_len) /* without terminating '\0' */ -{ - struct jack_graph_client * client_ptr; - - client_ptr = malloc(sizeof(struct jack_graph_client)); - if (client_ptr == NULL) - { - jack_error("Memory allocation of jack_graph_client structure failed."); - goto fail; - } - - client_ptr->name = malloc(client_name_len + 1); - if (client_ptr->name == NULL) - { - jack_error("malloc() failed to allocate memory for client name."); - goto fail_free_client; - } - - memcpy(client_ptr->name, client_name, client_name_len); - client_ptr->name[client_name_len] = 0; - - client_ptr->pid = jack_get_client_pid(client_ptr->name); - jack_info("New client '%s' with PID %d", client_ptr->name, client_ptr->pid); - - client_ptr->id = patchbay_ptr->next_client_id++; - INIT_LIST_HEAD(&client_ptr->ports); - - - pthread_mutex_lock(&patchbay_ptr->lock); - list_add_tail(&client_ptr->siblings, &patchbay_ptr->graph.clients); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_client_appeared(patchbay_ptr->graph.version, client_ptr->id, client_ptr->name); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - - return client_ptr; - -fail_free_client: - free(client_ptr); - -fail: - return NULL; -} - -static -void -jack_controller_patchbay_destroy_client( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_client *client_ptr) -{ - pthread_mutex_lock(&patchbay_ptr->lock); - list_del(&client_ptr->siblings); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_client_disappeared(patchbay_ptr->graph.version, client_ptr->id, client_ptr->name); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - - free(client_ptr->name); - free(client_ptr); -} - -static -void -jack_controller_patchbay_destroy_client_by_name( - struct jack_controller_patchbay *patchbay_ptr, - const char *client_name) /* '\0' terminated */ -{ - struct jack_graph_client *client_ptr; - - client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, client_name, strlen(client_name)); - if (client_ptr == NULL) - { - jack_error("Cannot destroy unknown client '%s'", client_name); - return; - } - - jack_controller_patchbay_destroy_client(patchbay_ptr, client_ptr); -} - -static -void -jack_controller_patchbay_new_port( - struct jack_controller_patchbay *patchbay_ptr, - const char *port_full_name, - uint32_t port_flags, - uint32_t port_type) -{ - struct jack_graph_client *client_ptr; - struct jack_graph_port *port_ptr; - const char *port_short_name; - size_t client_name_len; - - //jack_info("name: %s", port_full_name); - - port_short_name = strchr(port_full_name, ':'); - if (port_short_name == NULL) - { - jack_error("port name '%s' does not contain ':' separator char", port_full_name); - return; - } - - port_short_name++; /* skip ':' separator char */ - - client_name_len = port_short_name - port_full_name - 1; /* without terminating '\0' */ - - client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, port_full_name, client_name_len); - if (client_ptr == NULL) - { - client_ptr = jack_controller_patchbay_create_client(patchbay_ptr, port_full_name, client_name_len); - if (client_ptr == NULL) - { - jack_error("Creation of new jack_graph client failed."); - return; - } - } - - port_ptr = malloc(sizeof(struct jack_graph_port)); - if (port_ptr == NULL) - { - jack_error("Memory allocation of jack_graph_port structure failed."); - return; - } - - port_ptr->name = strdup(port_short_name); - if (port_ptr->name == NULL) - { - jack_error("strdup() call for port name '%s' failed.", port_short_name); - free(port_ptr); - return; - } - - port_ptr->id = patchbay_ptr->next_port_id++; - port_ptr->flags = port_flags; - port_ptr->type = port_type; - port_ptr->client = client_ptr; - - pthread_mutex_lock(&patchbay_ptr->lock); - list_add_tail(&port_ptr->siblings_client, &client_ptr->ports); - list_add_tail(&port_ptr->siblings_graph, &patchbay_ptr->graph.ports); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_port_appeared( - patchbay_ptr->graph.version, - client_ptr->id, - client_ptr->name, - port_ptr->id, - port_ptr->name, - port_ptr->flags, - port_ptr->type); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_patchbay_remove_port( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_port *port_ptr) -{ - pthread_mutex_lock(&patchbay_ptr->lock); - list_del(&port_ptr->siblings_client); - list_del(&port_ptr->siblings_graph); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_port_disappeared(patchbay_ptr->graph.version, port_ptr->client->id, port_ptr->client->name, port_ptr->id, port_ptr->name); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - - free(port_ptr->name); - free(port_ptr); -} - -static -struct jack_graph_port * -jack_controller_patchbay_find_port_by_id( - struct jack_controller_patchbay *patchbay_ptr, - uint64_t port_id) -{ - struct list_head *node_ptr; - struct jack_graph_port *port_ptr; - - list_for_each(node_ptr, &patchbay_ptr->graph.ports) - { - port_ptr = list_entry(node_ptr, struct jack_graph_port, siblings_graph); - if (port_ptr->id == port_id) - { - return port_ptr; - } - } - - return NULL; -} - -static -struct jack_graph_port * -jack_controller_patchbay_find_client_port_by_name( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_client *client_ptr, - const char *port_name) -{ - struct list_head *node_ptr; - struct jack_graph_port *port_ptr; - - list_for_each(node_ptr, &client_ptr->ports) - { - port_ptr = list_entry(node_ptr, struct jack_graph_port, siblings_client); - if (strcmp(port_ptr->name, port_name) == 0) - { - return port_ptr; - } - } - - return NULL; -} - -static -struct jack_graph_port * -jack_controller_patchbay_find_port_by_full_name( - struct jack_controller_patchbay *patchbay_ptr, - const char *port_full_name) -{ - const char *port_short_name; - size_t client_name_len; - struct jack_graph_client *client_ptr; - - //jack_info("name: %s", port_full_name); - - port_short_name = strchr(port_full_name, ':'); - if (port_short_name == NULL) - { - jack_error("port name '%s' does not contain ':' separator char", port_full_name); - return NULL; - } - - port_short_name++; /* skip ':' separator char */ - - client_name_len = port_short_name - port_full_name - 1; /* without terminating '\0' */ - - client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, port_full_name, client_name_len); - if (client_ptr == NULL) - { - jack_error("cannot find client of port '%s'", port_full_name); - return NULL; - } - - return jack_controller_patchbay_find_client_port_by_name(patchbay_ptr, client_ptr, port_short_name); -} - -static -struct jack_graph_port * -jack_controller_patchbay_find_port_by_names( - struct jack_controller_patchbay *patchbay_ptr, - const char *client_name, - const char *port_name) -{ - struct jack_graph_client *client_ptr; - - client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, client_name, strlen(client_name)); - if (client_ptr == NULL) - { - jack_error("cannot find client '%s'", client_name); - return NULL; - } - - return jack_controller_patchbay_find_client_port_by_name(patchbay_ptr, client_ptr, port_name); -} - -static -struct jack_graph_connection * -jack_controller_patchbay_create_connection( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_port *port1_ptr, - struct jack_graph_port *port2_ptr) -{ - struct jack_graph_connection * connection_ptr; - - connection_ptr = malloc(sizeof(struct jack_graph_connection)); - if (connection_ptr == NULL) - { - jack_error("Memory allocation of jack_graph_connection structure failed."); - return NULL; - } - - connection_ptr->id = patchbay_ptr->next_connection_id++; - connection_ptr->port1 = port1_ptr; - connection_ptr->port2 = port2_ptr; - - pthread_mutex_lock(&patchbay_ptr->lock); - list_add_tail(&connection_ptr->siblings, &patchbay_ptr->graph.connections); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_ports_connected( - patchbay_ptr->graph.version, - port1_ptr->client->id, - port1_ptr->client->name, - port1_ptr->id, - port1_ptr->name, - port2_ptr->client->id, - port2_ptr->client->name, - port2_ptr->id, - port2_ptr->name, - connection_ptr->id); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - - return connection_ptr; -} - -static -void -jack_controller_patchbay_destroy_connection( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_connection *connection_ptr) -{ - pthread_mutex_lock(&patchbay_ptr->lock); - list_del(&connection_ptr->siblings); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_ports_disconnected( - patchbay_ptr->graph.version, - connection_ptr->port1->client->id, - connection_ptr->port1->client->name, - connection_ptr->port1->id, - connection_ptr->port1->name, - connection_ptr->port2->client->id, - connection_ptr->port2->client->name, - connection_ptr->port2->id, - connection_ptr->port2->name, - connection_ptr->id); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - - free(connection_ptr); -} - -static -struct jack_graph_connection * -jack_controller_patchbay_find_connection( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_port *port1_ptr, - struct jack_graph_port *port2_ptr) -{ - struct list_head *node_ptr; - struct jack_graph_connection *connection_ptr; - - list_for_each(node_ptr, &patchbay_ptr->graph.connections) - { - connection_ptr = list_entry(node_ptr, struct jack_graph_connection, siblings); - if ((connection_ptr->port1 == port1_ptr && - connection_ptr->port2 == port2_ptr) || - (connection_ptr->port1 == port2_ptr && - connection_ptr->port2 == port1_ptr)) - { - return connection_ptr; - } - } - - return NULL; -} - -static -struct jack_graph_connection * -jack_controller_patchbay_find_connection_by_id( - struct jack_controller_patchbay *patchbay_ptr, - uint64_t connection_id) -{ - struct list_head *node_ptr; - struct jack_graph_connection *connection_ptr; - - list_for_each(node_ptr, &patchbay_ptr->graph.connections) - { - connection_ptr = list_entry(node_ptr, struct jack_graph_connection, siblings); - if (connection_ptr->id == connection_id) - { - return connection_ptr; - } - } - - return NULL; -} - -static -bool -jack_controller_patchbay_connect( - struct jack_dbus_method_call *dbus_call_ptr, - struct jack_controller *controller_ptr, - struct jack_graph_port *port1_ptr, - struct jack_graph_port *port2_ptr) -{ - int ret; - char port1_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - char port2_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - - sprintf(port1_name, "%s:%s", port1_ptr->client->name, port1_ptr->name); - sprintf(port2_name, "%s:%s", port2_ptr->client->name, port2_ptr->name); - - ret = jack_connect(controller_ptr->client, port1_name, port2_name); - if (ret != 0) - { - jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_connect() failed with %d", ret); - return false; - } - - return true; -} - -static -bool -jack_controller_patchbay_disconnect( - struct jack_dbus_method_call *dbus_call_ptr, - struct jack_controller *controller_ptr, - struct jack_graph_port *port1_ptr, - struct jack_graph_port *port2_ptr) -{ - int ret; - char port1_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - char port2_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - - sprintf(port1_name, "%s:%s", port1_ptr->client->name, port1_ptr->name); - sprintf(port2_name, "%s:%s", port2_ptr->client->name, port2_ptr->name); - - ret = jack_disconnect(controller_ptr->client, port1_name, port2_name); - if (ret != 0) - { - jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_connect() failed with %d", ret); - return false; - } - - return true; -} - -#define controller_ptr ((struct jack_controller *)call->context) -#define patchbay_ptr ((struct jack_controller_patchbay *)controller_ptr->patchbay_context) - -static -void -jack_controller_dbus_get_all_ports( - struct jack_dbus_method_call * call) -{ - struct list_head * client_node_ptr; - struct list_head * port_node_ptr; - struct jack_graph_client * client_ptr; - struct jack_graph_port * port_ptr; - DBusMessageIter iter, sub_iter; - char fullname[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - char *fullname_var = fullname; - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - call->reply = dbus_message_new_method_return (call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append (call->reply, &iter); - - if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter)) - { - goto fail_unref; - } - - pthread_mutex_lock(&patchbay_ptr->lock); - - list_for_each(client_node_ptr, &patchbay_ptr->graph.clients) - { - client_ptr = list_entry(client_node_ptr, struct jack_graph_client, siblings); - - list_for_each(port_node_ptr, &client_ptr->ports) - { - port_ptr = list_entry(port_node_ptr, struct jack_graph_port, siblings_client); - - jack_info("%s:%s", client_ptr->name, port_ptr->name); - sprintf(fullname, "%s:%s", client_ptr->name, port_ptr->name); - if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, &fullname_var)) - { - pthread_mutex_unlock(&patchbay_ptr->lock); - dbus_message_iter_close_container (&iter, &sub_iter); - goto fail_unref; - } - } - } - - pthread_mutex_unlock(&patchbay_ptr->lock); - - if (!dbus_message_iter_close_container (&iter, &sub_iter)) - { - goto fail_unref; - } - - return; - -fail_unref: - dbus_message_unref (call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -static -void -jack_controller_dbus_get_graph( - struct jack_dbus_method_call * call) -{ - struct list_head * client_node_ptr; - struct list_head * port_node_ptr; - struct list_head * connection_node_ptr; - struct jack_graph_client * client_ptr; - struct jack_graph_port * port_ptr; - struct jack_graph_connection * connection_ptr; - DBusMessageIter iter; - DBusMessageIter clients_array_iter; - DBusMessageIter client_struct_iter; - DBusMessageIter ports_array_iter; - DBusMessageIter port_struct_iter; - dbus_uint64_t version; - DBusMessageIter connections_array_iter; - DBusMessageIter connection_struct_iter; - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_UINT64, &version, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - goto exit; - } - - //jack_info("Getting graph, know version is %" PRIu32, version); - - call->reply = dbus_message_new_method_return(call->message); - if (!call->reply) - { - jack_error("Ran out of memory trying to construct method return"); - goto exit; - } - - dbus_message_iter_init_append (call->reply, &iter); - - pthread_mutex_lock(&patchbay_ptr->lock); - - if (version > patchbay_ptr->graph.version) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "known graph version %" PRIu64 " is newer than actual version %" PRIu64, - version, - patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - goto exit; - } - - if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT64, &patchbay_ptr->graph.version)) - { - goto nomem_unlock; - } - - if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tsa(tsuu))", &clients_array_iter)) - { - goto nomem_unlock; - } - - if (version < patchbay_ptr->graph.version) - { - list_for_each(client_node_ptr, &patchbay_ptr->graph.clients) - { - client_ptr = list_entry(client_node_ptr, struct jack_graph_client, siblings); - - if (!dbus_message_iter_open_container (&clients_array_iter, DBUS_TYPE_STRUCT, NULL, &client_struct_iter)) - { - goto nomem_close_clients_array; - } - - if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_UINT64, &client_ptr->id)) - { - goto nomem_close_client_struct; - } - - if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_STRING, &client_ptr->name)) - { - goto nomem_close_client_struct; - } - - if (!dbus_message_iter_open_container(&client_struct_iter, DBUS_TYPE_ARRAY, "(tsuu)", &ports_array_iter)) - { - goto nomem_close_client_struct; - } - - list_for_each(port_node_ptr, &client_ptr->ports) - { - port_ptr = list_entry(port_node_ptr, struct jack_graph_port, siblings_client); - - if (!dbus_message_iter_open_container(&ports_array_iter, DBUS_TYPE_STRUCT, NULL, &port_struct_iter)) - { - goto nomem_close_ports_array; - } - - if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT64, &port_ptr->id)) - { - goto nomem_close_port_struct; - } - - if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_STRING, &port_ptr->name)) - { - goto nomem_close_port_struct; - } - - if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->flags)) - { - goto nomem_close_port_struct; - } - - if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->type)) - { - goto nomem_close_port_struct; - } - - if (!dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter)) - { - goto nomem_close_ports_array; - } - } - - if (!dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter)) - { - goto nomem_close_client_struct; - } - - if (!dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter)) - { - goto nomem_close_clients_array; - } - } - } - - if (!dbus_message_iter_close_container(&iter, &clients_array_iter)) - { - goto nomem_unlock; - } - - if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tstststst)", &connections_array_iter)) - { - goto nomem_unlock; - } - - if (version < patchbay_ptr->graph.version) - { - list_for_each(connection_node_ptr, &patchbay_ptr->graph.connections) - { - connection_ptr = list_entry(connection_node_ptr, struct jack_graph_connection, siblings); - - if (!dbus_message_iter_open_container(&connections_array_iter, DBUS_TYPE_STRUCT, NULL, &connection_struct_iter)) - { - goto nomem_close_connections_array; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1->client->id)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1->client->name)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1->id)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1->name)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2->client->id)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2->client->name)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2->id)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2->name)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->id)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter)) - { - goto nomem_close_connections_array; - } - } - } - - if (!dbus_message_iter_close_container(&iter, &connections_array_iter)) - { - goto nomem_unlock; - } - - pthread_mutex_unlock(&patchbay_ptr->lock); - - return; - -nomem_close_connection_struct: - dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter); - -nomem_close_connections_array: - dbus_message_iter_close_container(&iter, &connections_array_iter); - goto nomem_unlock; - -nomem_close_port_struct: - dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter); - -nomem_close_ports_array: - dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter); - -nomem_close_client_struct: - dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter); - -nomem_close_clients_array: - dbus_message_iter_close_container(&iter, &clients_array_iter); - -nomem_unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); - -//nomem: - dbus_message_unref(call->reply); - call->reply = NULL; - jack_error("Ran out of memory trying to construct method return"); - -exit: - return; -} - -static -void -jack_controller_dbus_connect_ports_by_name( - struct jack_dbus_method_call * call) -{ - const char * client1_name; - const char * port1_name; - const char * client2_name; - const char * port2_name; - struct jack_graph_port *port1_ptr; - struct jack_graph_port *port2_ptr; - -/* jack_info("jack_controller_dbus_connect_ports_by_name() called."); */ - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_STRING, - &client1_name, - DBUS_TYPE_STRING, - &port1_name, - DBUS_TYPE_STRING, - &client2_name, - DBUS_TYPE_STRING, - &port2_name, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - -/* jack_info("connecting %s:%s and %s:%s", client1_name, port1_name, client2_name, port2_name); */ - - pthread_mutex_lock(&patchbay_ptr->lock); - - port1_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client1_name, port1_name); - if (port1_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client1_name, port1_name); - goto unlock; - } - - port2_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client2_name, port2_name); - if (port2_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client2_name, port2_name); - goto unlock; - } - - if (!jack_controller_patchbay_connect( - call, - controller_ptr, - port1_ptr, - port2_ptr)) - { - /* jack_controller_patchbay_connect() constructed error reply */ - goto unlock; - } - - jack_dbus_construct_method_return_empty(call); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_dbus_connect_ports_by_id( - struct jack_dbus_method_call * call) -{ - dbus_uint64_t port1_id; - dbus_uint64_t port2_id; - struct jack_graph_port *port1_ptr; - struct jack_graph_port *port2_ptr; - -/* jack_info("jack_controller_dbus_connect_ports_by_id() called."); */ - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_UINT64, - &port1_id, - DBUS_TYPE_UINT64, - &port2_id, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - pthread_mutex_lock(&patchbay_ptr->lock); - - port1_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port1_id); - if (port1_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port1_id); - goto unlock; - } - - port2_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port2_id); - if (port2_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port2_id); - goto unlock; - } - - if (!jack_controller_patchbay_connect( - call, - controller_ptr, - port1_ptr, - port2_ptr)) - { - /* jack_controller_patchbay_connect() constructed error reply */ - goto unlock; - } - - jack_dbus_construct_method_return_empty(call); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_dbus_disconnect_ports_by_name( - struct jack_dbus_method_call * call) -{ - const char * client1_name; - const char * port1_name; - const char * client2_name; - const char * port2_name; - struct jack_graph_port *port1_ptr; - struct jack_graph_port *port2_ptr; - -/* jack_info("jack_controller_dbus_disconnect_ports_by_name() called."); */ - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_STRING, - &client1_name, - DBUS_TYPE_STRING, - &port1_name, - DBUS_TYPE_STRING, - &client2_name, - DBUS_TYPE_STRING, - &port2_name, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - -/* jack_info("disconnecting %s:%s and %s:%s", client1_name, port1_name, client2_name, port2_name); */ - - pthread_mutex_lock(&patchbay_ptr->lock); - - port1_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client1_name, port1_name); - if (port1_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client1_name, port1_name); - goto unlock; - } - - port2_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client2_name, port2_name); - if (port2_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client2_name, port2_name); - goto unlock; - } - - if (!jack_controller_patchbay_disconnect( - call, - controller_ptr, - port1_ptr, - port2_ptr)) - { - /* jack_controller_patchbay_connect() constructed error reply */ - goto unlock; - } - - jack_dbus_construct_method_return_empty(call); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_dbus_disconnect_ports_by_id( - struct jack_dbus_method_call * call) -{ - dbus_uint64_t port1_id; - dbus_uint64_t port2_id; - struct jack_graph_port *port1_ptr; - struct jack_graph_port *port2_ptr; - -/* jack_info("jack_controller_dbus_disconnect_ports_by_id() called."); */ - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_UINT64, - &port1_id, - DBUS_TYPE_UINT64, - &port2_id, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - pthread_mutex_lock(&patchbay_ptr->lock); - - port1_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port1_id); - if (port1_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port1_id); - return; - } - - port2_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port2_id); - if (port2_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port2_id); - return; - } - - if (!jack_controller_patchbay_disconnect( - call, - controller_ptr, - port1_ptr, - port2_ptr)) - { - /* jack_controller_patchbay_connect() constructed error reply */ - goto unlock; - } - - jack_dbus_construct_method_return_empty(call); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_dbus_disconnect_ports_by_connection_id( - struct jack_dbus_method_call * call) -{ - dbus_uint64_t connection_id; - struct jack_graph_connection *connection_ptr; - -/* jack_info("jack_controller_dbus_disconnect_ports_by_id() called."); */ - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_UINT64, - &connection_id, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - pthread_mutex_lock(&patchbay_ptr->lock); - - connection_ptr = jack_controller_patchbay_find_connection_by_id(patchbay_ptr, connection_id); - if (connection_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find connection %" PRIu64, connection_id); - goto unlock; - } - - if (!jack_controller_patchbay_disconnect( - call, - controller_ptr, - connection_ptr->port1, - connection_ptr->port2)) - { - /* jack_controller_patchbay_connect() constructed error reply */ - goto unlock; - } - - jack_dbus_construct_method_return_empty(call); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_dbus_get_client_pid( - struct jack_dbus_method_call * call) -{ - dbus_uint64_t client_id; - struct jack_graph_client *client_ptr; - message_arg_t arg; - -/* jack_info("jack_controller_dbus_get_client_pid() called."); */ - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - pthread_mutex_lock(&patchbay_ptr->lock); - - client_ptr = jack_controller_patchbay_find_client_by_id(patchbay_ptr, client_id); - if (client_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find client %" PRIu64, client_id); - goto unlock; - } - - arg.int64 = client_ptr->pid; - - jack_dbus_construct_method_return_single(call, DBUS_TYPE_INT64, arg); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -#undef controller_ptr -#define controller_ptr ((struct jack_controller *)context) - -static -int -jack_controller_graph_order_callback( - void *context) -{ - const char **ports; - int i; - jack_port_t *port_ptr; - - if (patchbay_ptr->graph.version > 1) - { - /* we use this only for initial catchup */ - return 0; - } - - ports = jack_get_ports(controller_ptr->client, NULL, NULL, 0); - if (ports) - { - for (i = 0; ports[i]; ++i) - { - jack_info("graph reorder: new port '%s'", ports[i]); - port_ptr = jack_port_by_name(controller_ptr->client, ports[i]);; - jack_controller_patchbay_new_port(patchbay_ptr, ports[i], jack_port_flags(port_ptr), jack_port_type_id(port_ptr)); - } - - free(ports); - } - - if (patchbay_ptr->graph.version == 1) - { - /* we have empty initial graph, increment graph version, - so we dont do jack_get_ports() again, - on next next graph change */ - patchbay_ptr->graph.version++; - } - - return 0; -} - -void -jack_controller_client_registration_callback( - const char *client_name, - int created, - void *context) -{ - if (created) - { - jack_log("client '%s' created", client_name); - jack_controller_patchbay_create_client(patchbay_ptr, client_name, strlen(client_name)); - } - else - { - jack_log("client '%s' destroyed", client_name); - jack_controller_patchbay_destroy_client_by_name(patchbay_ptr, client_name); - } -} - -void -jack_controller_port_registration_callback( - jack_port_id_t port_id, - int created, - void *context) -{ - jack_port_t *port_ptr; - struct jack_graph_port *graph_port_ptr; - const char *port_name; - - port_ptr = jack_port_by_id(controller_ptr->client, port_id); - port_name = jack_port_name(port_ptr); - - if (created) - { - jack_log("port '%s' created", port_name); - jack_controller_patchbay_new_port(patchbay_ptr, port_name, jack_port_flags(port_ptr), jack_port_type_id(port_ptr)); - } - else - { - jack_log("port '%s' destroyed", port_name); - graph_port_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port_name); - if (graph_port_ptr == NULL) - { - jack_error("Failed to find port '%s' to destroy", port_name); - return; - } - - jack_controller_patchbay_remove_port(patchbay_ptr, graph_port_ptr); - } -} - -void -jack_controller_port_connect_callback( - jack_port_id_t port1_id, - jack_port_id_t port2_id, - int connect, - void *context) -{ - jack_port_t *port1; - jack_port_t *port2; - const char *port1_name; - const char *port2_name; - struct jack_graph_port *port1_ptr; - struct jack_graph_port *port2_ptr; - struct jack_graph_connection *connection_ptr; - - port1 = jack_port_by_id(controller_ptr->client, port1_id); - port2 = jack_port_by_id(controller_ptr->client, port2_id); - - port1_name = jack_port_name(port1); - port2_name = jack_port_name(port2); - - port1_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port1_name); - if (port1_ptr == NULL) - { - jack_error("Failed to find port '%s' to [dis]connect", port1_name); - return; - } - - port2_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port2_name); - if (port2_ptr == NULL) - { - jack_error("Failed to find port '%s' to [dis]connect", port2_name); - return; - } - - if (connect) - { - jack_info("Connecting '%s' to '%s'", port1_name, port2_name); - connection_ptr = jack_controller_patchbay_find_connection(patchbay_ptr, port1_ptr, port2_ptr); - if (connection_ptr != NULL) - { - jack_error("'%s' and '%s' are already connected", port1_name, port2_name); - return; - } - - jack_controller_patchbay_create_connection(patchbay_ptr, port1_ptr, port2_ptr); - } - else - { - jack_info("Disonnecting '%s' from '%s'", port1_name, port2_name); - connection_ptr = jack_controller_patchbay_find_connection(patchbay_ptr, port1_ptr, port2_ptr); - if (connection_ptr == NULL) - { - jack_error("Cannot find connection being removed"); - return; - } - - jack_controller_patchbay_destroy_connection(patchbay_ptr, connection_ptr); - } -} - -#undef controller_ptr - -void -jack_controller_patchbay_uninit( - struct jack_controller * controller_ptr) -{ - struct jack_graph_client *client_ptr; - struct jack_graph_port *port_ptr; - -/* jack_info("jack_controller_patchbay_uninit() called"); */ - - while (!list_empty(&patchbay_ptr->graph.ports)) - { - port_ptr = list_entry(patchbay_ptr->graph.ports.next, struct jack_graph_port, siblings_graph); - jack_controller_patchbay_remove_port(patchbay_ptr, port_ptr); - } - - while (!list_empty(&patchbay_ptr->graph.clients)) - { - client_ptr = list_entry(patchbay_ptr->graph.clients.next, struct jack_graph_client, siblings); - jack_controller_patchbay_destroy_client(patchbay_ptr, client_ptr); - } - - pthread_mutex_destroy(&patchbay_ptr->lock); -} - -#undef patchbay_ptr - -bool -jack_controller_patchbay_init( - struct jack_controller * controller_ptr) -{ - int ret; - struct jack_controller_patchbay * patchbay_ptr; - pthread_mutexattr_t attr; - -/* jack_info("jack_controller_patchbay_init() called"); */ - - patchbay_ptr = malloc(sizeof(struct jack_controller_patchbay)); - if (patchbay_ptr == NULL) - { - jack_error("Memory allocation of jack_controller_patchbay structure failed."); - goto fail; - } - - ret = pthread_mutexattr_init(&attr); - if (ret != 0) - { - goto fail; - } - - ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - if (ret != 0) - { - goto fail; - } - - pthread_mutex_init(&patchbay_ptr->lock, &attr); - INIT_LIST_HEAD(&patchbay_ptr->graph.clients); - INIT_LIST_HEAD(&patchbay_ptr->graph.ports); - INIT_LIST_HEAD(&patchbay_ptr->graph.connections); - patchbay_ptr->graph.version = 1; - patchbay_ptr->next_client_id = 1; - patchbay_ptr->next_port_id = 1; - patchbay_ptr->next_connection_id = 1; - - controller_ptr->patchbay_context = patchbay_ptr; - - ret = jack_set_graph_order_callback(controller_ptr->client, jack_controller_graph_order_callback, controller_ptr); - if (ret != 0) - { - jack_error("jack_set_graph_order_callback() failed with error %d", ret); - goto fail_uninit_mutex; - } - - ret = jack_set_client_registration_callback(controller_ptr->client, jack_controller_client_registration_callback, controller_ptr); - if (ret != 0) - { - jack_error("jack_set_client_registration_callback() failed with error %d", ret); - goto fail_uninit_mutex; - } - - ret = jack_set_port_registration_callback(controller_ptr->client, jack_controller_port_registration_callback, controller_ptr); - if (ret != 0) - { - jack_error("jack_set_port_registration_callback() failed with error %d", ret); - goto fail_uninit_mutex; - } - - ret = jack_set_port_connect_callback(controller_ptr->client, jack_controller_port_connect_callback, controller_ptr); - if (ret != 0) - { - jack_error("jack_set_port_connect_callback() failed with error %d", ret); - goto fail_uninit_mutex; - } - - return true; - -fail_uninit_mutex: - pthread_mutex_destroy(&patchbay_ptr->lock); - -fail: - return false; -} - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetAllPorts) - JACK_DBUS_METHOD_ARGUMENT("ports_list", "as", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetGraph) - JACK_DBUS_METHOD_ARGUMENT("known_graph_version", DBUS_TYPE_UINT64_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("current_graph_version", DBUS_TYPE_UINT64_AS_STRING, true) - JACK_DBUS_METHOD_ARGUMENT("clients_and_ports", "a(tsa(tsuu))", true) - JACK_DBUS_METHOD_ARGUMENT("connections", "a(tstststst)", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ConnectPortsByName) - JACK_DBUS_METHOD_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ConnectPortsByID) - JACK_DBUS_METHOD_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByName) - JACK_DBUS_METHOD_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByID) - JACK_DBUS_METHOD_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByConnectionID) - JACK_DBUS_METHOD_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetClientPID) - JACK_DBUS_METHOD_ARGUMENT("client_id", DBUS_TYPE_INT64_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHODS_BEGIN - JACK_DBUS_METHOD_DESCRIBE(GetAllPorts, jack_controller_dbus_get_all_ports) - JACK_DBUS_METHOD_DESCRIBE(GetGraph, jack_controller_dbus_get_graph) - JACK_DBUS_METHOD_DESCRIBE(ConnectPortsByName, jack_controller_dbus_connect_ports_by_name) - JACK_DBUS_METHOD_DESCRIBE(ConnectPortsByID, jack_controller_dbus_connect_ports_by_id) - JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByName, jack_controller_dbus_disconnect_ports_by_name) - JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByID, jack_controller_dbus_disconnect_ports_by_id) - JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByConnectionID, jack_controller_dbus_disconnect_ports_by_connection_id) - JACK_DBUS_METHOD_DESCRIBE(GetClientPID, jack_controller_dbus_get_client_pid) -JACK_DBUS_METHODS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(GraphChanged) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ClientAppeared) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ClientDisappeared) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortAppeared) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_flags", DBUS_TYPE_UINT32_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_type", DBUS_TYPE_UINT32_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortDisappeared) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_name", DBUS_TYPE_STRING_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortsConnected) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client1_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client2_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortsDisconnected) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client1_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client2_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNALS_BEGIN - JACK_DBUS_SIGNAL_DESCRIBE(GraphChanged) - JACK_DBUS_SIGNAL_DESCRIBE(ClientAppeared) - JACK_DBUS_SIGNAL_DESCRIBE(ClientDisappeared) - JACK_DBUS_SIGNAL_DESCRIBE(PortAppeared) - JACK_DBUS_SIGNAL_DESCRIBE(PortDisappeared) - JACK_DBUS_SIGNAL_DESCRIBE(PortsConnected) - JACK_DBUS_SIGNAL_DESCRIBE(PortsDisconnected) -JACK_DBUS_SIGNALS_END - -JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_patchbay, JACK_DBUS_IFACE_NAME) - JACK_DBUS_IFACE_EXPOSE_METHODS - JACK_DBUS_IFACE_EXPOSE_SIGNALS -JACK_DBUS_IFACE_END -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2008 Nedko Arnaudov - Copyright (C) 2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#define _GNU_SOURCE /* PTHREAD_MUTEX_RECURSIVE */ - -#include -#include -#include -#include -#include -#include -#include - -#include "jackdbus.h" -#include "controller_internal.h" -#include "list.h" - -#define JACK_DBUS_IFACE_NAME "org.jackaudio.JackPatchbay" - -/* FIXME: these need to be retrieved from common headers */ -#define JACK_CLIENT_NAME_SIZE 64 -#define JACK_PORT_NAME_SIZE 256 - -struct jack_graph -{ - uint64_t version; - struct list_head clients; - struct list_head ports; - struct list_head connections; -}; - -struct jack_graph_client -{ - uint64_t id; - char * name; - int pid; - struct list_head siblings; - struct list_head ports; -}; - -struct jack_graph_port -{ - uint64_t id; - char * name; - uint32_t flags; - uint32_t type; - struct list_head siblings_graph; - struct list_head siblings_client; - struct jack_graph_client * client; -}; - -struct jack_graph_connection -{ - uint64_t id; - struct jack_graph_port * port1; - struct jack_graph_port * port2; - struct list_head siblings; -}; - -struct jack_controller_patchbay -{ - pthread_mutex_t lock; - struct jack_graph graph; - uint64_t next_client_id; - uint64_t next_port_id; - uint64_t next_connection_id; -}; - -void -jack_controller_patchbay_send_signal_graph_changed( - dbus_uint64_t new_graph_version) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "GraphChanged", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_client_appeared( - dbus_uint64_t new_graph_version, - dbus_uint64_t client_id, - const char * client_name) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "ClientAppeared", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_client_disappeared( - dbus_uint64_t new_graph_version, - dbus_uint64_t client_id, - const char * client_name) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "ClientDisappeared", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_port_appeared( - dbus_uint64_t new_graph_version, - dbus_uint64_t client_id, - const char * client_name, - dbus_uint64_t port_id, - const char * port_name, - dbus_uint32_t port_flags, - dbus_uint32_t port_type) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "PortAppeared", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_UINT64, - &port_id, - DBUS_TYPE_STRING, - &port_name, - DBUS_TYPE_UINT32, - &port_flags, - DBUS_TYPE_UINT32, - &port_type, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_port_disappeared( - dbus_uint64_t new_graph_version, - dbus_uint64_t client_id, - const char * client_name, - dbus_uint64_t port_id, - const char * port_name) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "PortDisappeared", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_UINT64, - &port_id, - DBUS_TYPE_STRING, - &port_name, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_ports_connected( - dbus_uint64_t new_graph_version, - dbus_uint64_t client1_id, - const char * client1_name, - dbus_uint64_t port1_id, - const char * port1_name, - dbus_uint64_t client2_id, - const char * client2_name, - dbus_uint64_t port2_id, - const char * port2_name, - dbus_uint64_t connection_id) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "PortsConnected", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client1_id, - DBUS_TYPE_STRING, - &client1_name, - DBUS_TYPE_UINT64, - &port1_id, - DBUS_TYPE_STRING, - &port1_name, - DBUS_TYPE_UINT64, - &client2_id, - DBUS_TYPE_STRING, - &client2_name, - DBUS_TYPE_UINT64, - &port2_id, - DBUS_TYPE_STRING, - &port2_name, - DBUS_TYPE_UINT64, - &connection_id, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_ports_disconnected( - dbus_uint64_t new_graph_version, - dbus_uint64_t client1_id, - const char * client1_name, - dbus_uint64_t port1_id, - const char * port1_name, - dbus_uint64_t client2_id, - const char * client2_name, - dbus_uint64_t port2_id, - const char * port2_name, - dbus_uint64_t connection_id) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "PortsDisconnected", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client1_id, - DBUS_TYPE_STRING, - &client1_name, - DBUS_TYPE_UINT64, - &port1_id, - DBUS_TYPE_STRING, - &port1_name, - DBUS_TYPE_UINT64, - &client2_id, - DBUS_TYPE_STRING, - &client2_name, - DBUS_TYPE_UINT64, - &port2_id, - DBUS_TYPE_STRING, - &port2_name, - DBUS_TYPE_UINT64, - &connection_id, - DBUS_TYPE_INVALID); -} - -static -struct jack_graph_client * -jack_controller_patchbay_find_client( - struct jack_controller_patchbay *patchbay_ptr, - const char *client_name, /* not '\0' terminated */ - size_t client_name_len) /* without terminating '\0' */ -{ - struct list_head *node_ptr; - struct jack_graph_client *client_ptr; - - list_for_each(node_ptr, &patchbay_ptr->graph.clients) - { - client_ptr = list_entry(node_ptr, struct jack_graph_client, siblings); - if (strncmp(client_ptr->name, client_name, client_name_len) == 0) - { - return client_ptr; - } - } - - return NULL; -} - -static -struct jack_graph_client * -jack_controller_patchbay_find_client_by_id( - struct jack_controller_patchbay *patchbay_ptr, - uint64_t id) -{ - struct list_head *node_ptr; - struct jack_graph_client *client_ptr; - - list_for_each(node_ptr, &patchbay_ptr->graph.clients) - { - client_ptr = list_entry(node_ptr, struct jack_graph_client, siblings); - if (client_ptr->id == id) - { - return client_ptr; - } - } - - return NULL; -} - -static -struct jack_graph_client * -jack_controller_patchbay_create_client( - struct jack_controller_patchbay *patchbay_ptr, - const char *client_name, /* not '\0' terminated */ - size_t client_name_len) /* without terminating '\0' */ -{ - struct jack_graph_client * client_ptr; - - client_ptr = malloc(sizeof(struct jack_graph_client)); - if (client_ptr == NULL) - { - jack_error("Memory allocation of jack_graph_client structure failed."); - goto fail; - } - - client_ptr->name = malloc(client_name_len + 1); - if (client_ptr->name == NULL) - { - jack_error("malloc() failed to allocate memory for client name."); - goto fail_free_client; - } - - memcpy(client_ptr->name, client_name, client_name_len); - client_ptr->name[client_name_len] = 0; - - client_ptr->pid = jack_get_client_pid(client_ptr->name); - jack_info("New client '%s' with PID %d", client_ptr->name, client_ptr->pid); - - client_ptr->id = patchbay_ptr->next_client_id++; - INIT_LIST_HEAD(&client_ptr->ports); - - - pthread_mutex_lock(&patchbay_ptr->lock); - list_add_tail(&client_ptr->siblings, &patchbay_ptr->graph.clients); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_client_appeared(patchbay_ptr->graph.version, client_ptr->id, client_ptr->name); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - - return client_ptr; - -fail_free_client: - free(client_ptr); - -fail: - return NULL; -} - -static -void -jack_controller_patchbay_destroy_client( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_client *client_ptr) -{ - pthread_mutex_lock(&patchbay_ptr->lock); - list_del(&client_ptr->siblings); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_client_disappeared(patchbay_ptr->graph.version, client_ptr->id, client_ptr->name); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - - free(client_ptr->name); - free(client_ptr); -} - -static -void -jack_controller_patchbay_destroy_client_by_name( - struct jack_controller_patchbay *patchbay_ptr, - const char *client_name) /* '\0' terminated */ -{ - struct jack_graph_client *client_ptr; - - client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, client_name, strlen(client_name)); - if (client_ptr == NULL) - { - jack_error("Cannot destroy unknown client '%s'", client_name); - return; - } - - jack_controller_patchbay_destroy_client(patchbay_ptr, client_ptr); -} - -static -void -jack_controller_patchbay_new_port( - struct jack_controller_patchbay *patchbay_ptr, - const char *port_full_name, - uint32_t port_flags, - uint32_t port_type) -{ - struct jack_graph_client *client_ptr; - struct jack_graph_port *port_ptr; - const char *port_short_name; - size_t client_name_len; - - //jack_info("name: %s", port_full_name); - - port_short_name = strchr(port_full_name, ':'); - if (port_short_name == NULL) - { - jack_error("port name '%s' does not contain ':' separator char", port_full_name); - return; - } - - port_short_name++; /* skip ':' separator char */ - - client_name_len = port_short_name - port_full_name - 1; /* without terminating '\0' */ - - client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, port_full_name, client_name_len); - if (client_ptr == NULL) - { - client_ptr = jack_controller_patchbay_create_client(patchbay_ptr, port_full_name, client_name_len); - if (client_ptr == NULL) - { - jack_error("Creation of new jack_graph client failed."); - return; - } - } - - port_ptr = malloc(sizeof(struct jack_graph_port)); - if (port_ptr == NULL) - { - jack_error("Memory allocation of jack_graph_port structure failed."); - return; - } - - port_ptr->name = strdup(port_short_name); - if (port_ptr->name == NULL) - { - jack_error("strdup() call for port name '%s' failed.", port_short_name); - free(port_ptr); - return; - } - - port_ptr->id = patchbay_ptr->next_port_id++; - port_ptr->flags = port_flags; - port_ptr->type = port_type; - port_ptr->client = client_ptr; - - pthread_mutex_lock(&patchbay_ptr->lock); - list_add_tail(&port_ptr->siblings_client, &client_ptr->ports); - list_add_tail(&port_ptr->siblings_graph, &patchbay_ptr->graph.ports); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_port_appeared( - patchbay_ptr->graph.version, - client_ptr->id, - client_ptr->name, - port_ptr->id, - port_ptr->name, - port_ptr->flags, - port_ptr->type); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_patchbay_remove_port( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_port *port_ptr) -{ - pthread_mutex_lock(&patchbay_ptr->lock); - list_del(&port_ptr->siblings_client); - list_del(&port_ptr->siblings_graph); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_port_disappeared(patchbay_ptr->graph.version, port_ptr->client->id, port_ptr->client->name, port_ptr->id, port_ptr->name); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - - free(port_ptr->name); - free(port_ptr); -} - -static -struct jack_graph_port * -jack_controller_patchbay_find_port_by_id( - struct jack_controller_patchbay *patchbay_ptr, - uint64_t port_id) -{ - struct list_head *node_ptr; - struct jack_graph_port *port_ptr; - - list_for_each(node_ptr, &patchbay_ptr->graph.ports) - { - port_ptr = list_entry(node_ptr, struct jack_graph_port, siblings_graph); - if (port_ptr->id == port_id) - { - return port_ptr; - } - } - - return NULL; -} - -static -struct jack_graph_port * -jack_controller_patchbay_find_client_port_by_name( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_client *client_ptr, - const char *port_name) -{ - struct list_head *node_ptr; - struct jack_graph_port *port_ptr; - - list_for_each(node_ptr, &client_ptr->ports) - { - port_ptr = list_entry(node_ptr, struct jack_graph_port, siblings_client); - if (strcmp(port_ptr->name, port_name) == 0) - { - return port_ptr; - } - } - - return NULL; -} - -static -struct jack_graph_port * -jack_controller_patchbay_find_port_by_full_name( - struct jack_controller_patchbay *patchbay_ptr, - const char *port_full_name) -{ - const char *port_short_name; - size_t client_name_len; - struct jack_graph_client *client_ptr; - - //jack_info("name: %s", port_full_name); - - port_short_name = strchr(port_full_name, ':'); - if (port_short_name == NULL) - { - jack_error("port name '%s' does not contain ':' separator char", port_full_name); - return NULL; - } - - port_short_name++; /* skip ':' separator char */ - - client_name_len = port_short_name - port_full_name - 1; /* without terminating '\0' */ - - client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, port_full_name, client_name_len); - if (client_ptr == NULL) - { - jack_error("cannot find client of port '%s'", port_full_name); - return NULL; - } - - return jack_controller_patchbay_find_client_port_by_name(patchbay_ptr, client_ptr, port_short_name); -} - -static -struct jack_graph_port * -jack_controller_patchbay_find_port_by_names( - struct jack_controller_patchbay *patchbay_ptr, - const char *client_name, - const char *port_name) -{ - struct jack_graph_client *client_ptr; - - client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, client_name, strlen(client_name)); - if (client_ptr == NULL) - { - jack_error("cannot find client '%s'", client_name); - return NULL; - } - - return jack_controller_patchbay_find_client_port_by_name(patchbay_ptr, client_ptr, port_name); -} - -static -struct jack_graph_connection * -jack_controller_patchbay_create_connection( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_port *port1_ptr, - struct jack_graph_port *port2_ptr) -{ - struct jack_graph_connection * connection_ptr; - - connection_ptr = malloc(sizeof(struct jack_graph_connection)); - if (connection_ptr == NULL) - { - jack_error("Memory allocation of jack_graph_connection structure failed."); - return NULL; - } - - connection_ptr->id = patchbay_ptr->next_connection_id++; - connection_ptr->port1 = port1_ptr; - connection_ptr->port2 = port2_ptr; - - pthread_mutex_lock(&patchbay_ptr->lock); - list_add_tail(&connection_ptr->siblings, &patchbay_ptr->graph.connections); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_ports_connected( - patchbay_ptr->graph.version, - port1_ptr->client->id, - port1_ptr->client->name, - port1_ptr->id, - port1_ptr->name, - port2_ptr->client->id, - port2_ptr->client->name, - port2_ptr->id, - port2_ptr->name, - connection_ptr->id); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - - return connection_ptr; -} - -static -void -jack_controller_patchbay_destroy_connection( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_connection *connection_ptr) -{ - pthread_mutex_lock(&patchbay_ptr->lock); - list_del(&connection_ptr->siblings); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_ports_disconnected( - patchbay_ptr->graph.version, - connection_ptr->port1->client->id, - connection_ptr->port1->client->name, - connection_ptr->port1->id, - connection_ptr->port1->name, - connection_ptr->port2->client->id, - connection_ptr->port2->client->name, - connection_ptr->port2->id, - connection_ptr->port2->name, - connection_ptr->id); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - - free(connection_ptr); -} - -static -struct jack_graph_connection * -jack_controller_patchbay_find_connection( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_port *port1_ptr, - struct jack_graph_port *port2_ptr) -{ - struct list_head *node_ptr; - struct jack_graph_connection *connection_ptr; - - list_for_each(node_ptr, &patchbay_ptr->graph.connections) - { - connection_ptr = list_entry(node_ptr, struct jack_graph_connection, siblings); - if ((connection_ptr->port1 == port1_ptr && - connection_ptr->port2 == port2_ptr) || - (connection_ptr->port1 == port2_ptr && - connection_ptr->port2 == port1_ptr)) - { - return connection_ptr; - } - } - - return NULL; -} - -static -struct jack_graph_connection * -jack_controller_patchbay_find_connection_by_id( - struct jack_controller_patchbay *patchbay_ptr, - uint64_t connection_id) -{ - struct list_head *node_ptr; - struct jack_graph_connection *connection_ptr; - - list_for_each(node_ptr, &patchbay_ptr->graph.connections) - { - connection_ptr = list_entry(node_ptr, struct jack_graph_connection, siblings); - if (connection_ptr->id == connection_id) - { - return connection_ptr; - } - } - - return NULL; -} - -static -bool -jack_controller_patchbay_connect( - struct jack_dbus_method_call *dbus_call_ptr, - struct jack_controller *controller_ptr, - struct jack_graph_port *port1_ptr, - struct jack_graph_port *port2_ptr) -{ - int ret; - char port1_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - char port2_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - - sprintf(port1_name, "%s:%s", port1_ptr->client->name, port1_ptr->name); - sprintf(port2_name, "%s:%s", port2_ptr->client->name, port2_ptr->name); - - ret = jack_connect(controller_ptr->client, port1_name, port2_name); - if (ret != 0) - { - jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_connect() failed with %d", ret); - return false; - } - - return true; -} - -static -bool -jack_controller_patchbay_disconnect( - struct jack_dbus_method_call *dbus_call_ptr, - struct jack_controller *controller_ptr, - struct jack_graph_port *port1_ptr, - struct jack_graph_port *port2_ptr) -{ - int ret; - char port1_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - char port2_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - - sprintf(port1_name, "%s:%s", port1_ptr->client->name, port1_ptr->name); - sprintf(port2_name, "%s:%s", port2_ptr->client->name, port2_ptr->name); - - ret = jack_disconnect(controller_ptr->client, port1_name, port2_name); - if (ret != 0) - { - jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_connect() failed with %d", ret); - return false; - } - - return true; -} - -#define controller_ptr ((struct jack_controller *)call->context) -#define patchbay_ptr ((struct jack_controller_patchbay *)controller_ptr->patchbay_context) - -static -void -jack_controller_dbus_get_all_ports( - struct jack_dbus_method_call * call) -{ - struct list_head * client_node_ptr; - struct list_head * port_node_ptr; - struct jack_graph_client * client_ptr; - struct jack_graph_port * port_ptr; - DBusMessageIter iter, sub_iter; - char fullname[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - char *fullname_var = fullname; - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - call->reply = dbus_message_new_method_return (call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append (call->reply, &iter); - - if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter)) - { - goto fail_unref; - } - - pthread_mutex_lock(&patchbay_ptr->lock); - - list_for_each(client_node_ptr, &patchbay_ptr->graph.clients) - { - client_ptr = list_entry(client_node_ptr, struct jack_graph_client, siblings); - - list_for_each(port_node_ptr, &client_ptr->ports) - { - port_ptr = list_entry(port_node_ptr, struct jack_graph_port, siblings_client); - - jack_info("%s:%s", client_ptr->name, port_ptr->name); - sprintf(fullname, "%s:%s", client_ptr->name, port_ptr->name); - if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, &fullname_var)) - { - pthread_mutex_unlock(&patchbay_ptr->lock); - dbus_message_iter_close_container (&iter, &sub_iter); - goto fail_unref; - } - } - } - - pthread_mutex_unlock(&patchbay_ptr->lock); - - if (!dbus_message_iter_close_container (&iter, &sub_iter)) - { - goto fail_unref; - } - - return; - -fail_unref: - dbus_message_unref (call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -static -void -jack_controller_dbus_get_graph( - struct jack_dbus_method_call * call) -{ - struct list_head * client_node_ptr; - struct list_head * port_node_ptr; - struct list_head * connection_node_ptr; - struct jack_graph_client * client_ptr; - struct jack_graph_port * port_ptr; - struct jack_graph_connection * connection_ptr; - DBusMessageIter iter; - DBusMessageIter clients_array_iter; - DBusMessageIter client_struct_iter; - DBusMessageIter ports_array_iter; - DBusMessageIter port_struct_iter; - dbus_uint64_t version; - DBusMessageIter connections_array_iter; - DBusMessageIter connection_struct_iter; - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_UINT64, &version, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - goto exit; - } - - //jack_info("Getting graph, know version is %" PRIu32, version); - - call->reply = dbus_message_new_method_return(call->message); - if (!call->reply) - { - jack_error("Ran out of memory trying to construct method return"); - goto exit; - } - - dbus_message_iter_init_append (call->reply, &iter); - - pthread_mutex_lock(&patchbay_ptr->lock); - - if (version > patchbay_ptr->graph.version) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "known graph version %" PRIu64 " is newer than actual version %" PRIu64, - version, - patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - goto exit; - } - - if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT64, &patchbay_ptr->graph.version)) - { - goto nomem_unlock; - } - - if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tsa(tsuu))", &clients_array_iter)) - { - goto nomem_unlock; - } - - if (version < patchbay_ptr->graph.version) - { - list_for_each(client_node_ptr, &patchbay_ptr->graph.clients) - { - client_ptr = list_entry(client_node_ptr, struct jack_graph_client, siblings); - - if (!dbus_message_iter_open_container (&clients_array_iter, DBUS_TYPE_STRUCT, NULL, &client_struct_iter)) - { - goto nomem_close_clients_array; - } - - if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_UINT64, &client_ptr->id)) - { - goto nomem_close_client_struct; - } - - if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_STRING, &client_ptr->name)) - { - goto nomem_close_client_struct; - } - - if (!dbus_message_iter_open_container(&client_struct_iter, DBUS_TYPE_ARRAY, "(tsuu)", &ports_array_iter)) - { - goto nomem_close_client_struct; - } - - list_for_each(port_node_ptr, &client_ptr->ports) - { - port_ptr = list_entry(port_node_ptr, struct jack_graph_port, siblings_client); - - if (!dbus_message_iter_open_container(&ports_array_iter, DBUS_TYPE_STRUCT, NULL, &port_struct_iter)) - { - goto nomem_close_ports_array; - } - - if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT64, &port_ptr->id)) - { - goto nomem_close_port_struct; - } - - if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_STRING, &port_ptr->name)) - { - goto nomem_close_port_struct; - } - - if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->flags)) - { - goto nomem_close_port_struct; - } - - if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->type)) - { - goto nomem_close_port_struct; - } - - if (!dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter)) - { - goto nomem_close_ports_array; - } - } - - if (!dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter)) - { - goto nomem_close_client_struct; - } - - if (!dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter)) - { - goto nomem_close_clients_array; - } - } - } - - if (!dbus_message_iter_close_container(&iter, &clients_array_iter)) - { - goto nomem_unlock; - } - - if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tstststst)", &connections_array_iter)) - { - goto nomem_unlock; - } - - if (version < patchbay_ptr->graph.version) - { - list_for_each(connection_node_ptr, &patchbay_ptr->graph.connections) - { - connection_ptr = list_entry(connection_node_ptr, struct jack_graph_connection, siblings); - - if (!dbus_message_iter_open_container(&connections_array_iter, DBUS_TYPE_STRUCT, NULL, &connection_struct_iter)) - { - goto nomem_close_connections_array; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1->client->id)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1->client->name)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1->id)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1->name)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2->client->id)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2->client->name)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2->id)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2->name)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->id)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter)) - { - goto nomem_close_connections_array; - } - } - } - - if (!dbus_message_iter_close_container(&iter, &connections_array_iter)) - { - goto nomem_unlock; - } - - pthread_mutex_unlock(&patchbay_ptr->lock); - - return; - -nomem_close_connection_struct: - dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter); - -nomem_close_connections_array: - dbus_message_iter_close_container(&iter, &connections_array_iter); - goto nomem_unlock; - -nomem_close_port_struct: - dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter); - -nomem_close_ports_array: - dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter); - -nomem_close_client_struct: - dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter); - -nomem_close_clients_array: - dbus_message_iter_close_container(&iter, &clients_array_iter); - -nomem_unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); - -//nomem: - dbus_message_unref(call->reply); - call->reply = NULL; - jack_error("Ran out of memory trying to construct method return"); - -exit: - return; -} - -static -void -jack_controller_dbus_connect_ports_by_name( - struct jack_dbus_method_call * call) -{ - const char * client1_name; - const char * port1_name; - const char * client2_name; - const char * port2_name; - struct jack_graph_port *port1_ptr; - struct jack_graph_port *port2_ptr; - -/* jack_info("jack_controller_dbus_connect_ports_by_name() called."); */ - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_STRING, - &client1_name, - DBUS_TYPE_STRING, - &port1_name, - DBUS_TYPE_STRING, - &client2_name, - DBUS_TYPE_STRING, - &port2_name, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - -/* jack_info("connecting %s:%s and %s:%s", client1_name, port1_name, client2_name, port2_name); */ - - pthread_mutex_lock(&patchbay_ptr->lock); - - port1_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client1_name, port1_name); - if (port1_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client1_name, port1_name); - goto unlock; - } - - port2_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client2_name, port2_name); - if (port2_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client2_name, port2_name); - goto unlock; - } - - if (!jack_controller_patchbay_connect( - call, - controller_ptr, - port1_ptr, - port2_ptr)) - { - /* jack_controller_patchbay_connect() constructed error reply */ - goto unlock; - } - - jack_dbus_construct_method_return_empty(call); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_dbus_connect_ports_by_id( - struct jack_dbus_method_call * call) -{ - dbus_uint64_t port1_id; - dbus_uint64_t port2_id; - struct jack_graph_port *port1_ptr; - struct jack_graph_port *port2_ptr; - -/* jack_info("jack_controller_dbus_connect_ports_by_id() called."); */ - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_UINT64, - &port1_id, - DBUS_TYPE_UINT64, - &port2_id, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - pthread_mutex_lock(&patchbay_ptr->lock); - - port1_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port1_id); - if (port1_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port1_id); - goto unlock; - } - - port2_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port2_id); - if (port2_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port2_id); - goto unlock; - } - - if (!jack_controller_patchbay_connect( - call, - controller_ptr, - port1_ptr, - port2_ptr)) - { - /* jack_controller_patchbay_connect() constructed error reply */ - goto unlock; - } - - jack_dbus_construct_method_return_empty(call); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_dbus_disconnect_ports_by_name( - struct jack_dbus_method_call * call) -{ - const char * client1_name; - const char * port1_name; - const char * client2_name; - const char * port2_name; - struct jack_graph_port *port1_ptr; - struct jack_graph_port *port2_ptr; - -/* jack_info("jack_controller_dbus_disconnect_ports_by_name() called."); */ - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_STRING, - &client1_name, - DBUS_TYPE_STRING, - &port1_name, - DBUS_TYPE_STRING, - &client2_name, - DBUS_TYPE_STRING, - &port2_name, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - -/* jack_info("disconnecting %s:%s and %s:%s", client1_name, port1_name, client2_name, port2_name); */ - - pthread_mutex_lock(&patchbay_ptr->lock); - - port1_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client1_name, port1_name); - if (port1_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client1_name, port1_name); - goto unlock; - } - - port2_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client2_name, port2_name); - if (port2_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client2_name, port2_name); - goto unlock; - } - - if (!jack_controller_patchbay_disconnect( - call, - controller_ptr, - port1_ptr, - port2_ptr)) - { - /* jack_controller_patchbay_connect() constructed error reply */ - goto unlock; - } - - jack_dbus_construct_method_return_empty(call); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_dbus_disconnect_ports_by_id( - struct jack_dbus_method_call * call) -{ - dbus_uint64_t port1_id; - dbus_uint64_t port2_id; - struct jack_graph_port *port1_ptr; - struct jack_graph_port *port2_ptr; - -/* jack_info("jack_controller_dbus_disconnect_ports_by_id() called."); */ - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_UINT64, - &port1_id, - DBUS_TYPE_UINT64, - &port2_id, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - pthread_mutex_lock(&patchbay_ptr->lock); - - port1_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port1_id); - if (port1_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port1_id); - return; - } - - port2_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port2_id); - if (port2_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port2_id); - return; - } - - if (!jack_controller_patchbay_disconnect( - call, - controller_ptr, - port1_ptr, - port2_ptr)) - { - /* jack_controller_patchbay_connect() constructed error reply */ - goto unlock; - } - - jack_dbus_construct_method_return_empty(call); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_dbus_disconnect_ports_by_connection_id( - struct jack_dbus_method_call * call) -{ - dbus_uint64_t connection_id; - struct jack_graph_connection *connection_ptr; - -/* jack_info("jack_controller_dbus_disconnect_ports_by_id() called."); */ - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_UINT64, - &connection_id, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - pthread_mutex_lock(&patchbay_ptr->lock); - - connection_ptr = jack_controller_patchbay_find_connection_by_id(patchbay_ptr, connection_id); - if (connection_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find connection %" PRIu64, connection_id); - goto unlock; - } - - if (!jack_controller_patchbay_disconnect( - call, - controller_ptr, - connection_ptr->port1, - connection_ptr->port2)) - { - /* jack_controller_patchbay_connect() constructed error reply */ - goto unlock; - } - - jack_dbus_construct_method_return_empty(call); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_dbus_get_client_pid( - struct jack_dbus_method_call * call) -{ - dbus_uint64_t client_id; - struct jack_graph_client *client_ptr; - message_arg_t arg; - -/* jack_info("jack_controller_dbus_get_client_pid() called."); */ - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - pthread_mutex_lock(&patchbay_ptr->lock); - - client_ptr = jack_controller_patchbay_find_client_by_id(patchbay_ptr, client_id); - if (client_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find client %" PRIu64, client_id); - goto unlock; - } - - arg.int64 = client_ptr->pid; - - jack_dbus_construct_method_return_single(call, DBUS_TYPE_INT64, arg); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -#undef controller_ptr -#define controller_ptr ((struct jack_controller *)context) - -static -int -jack_controller_graph_order_callback( - void *context) -{ - const char **ports; - int i; - jack_port_t *port_ptr; - - if (patchbay_ptr->graph.version > 1) - { - /* we use this only for initial catchup */ - return 0; - } - - ports = jack_get_ports(controller_ptr->client, NULL, NULL, 0); - if (ports) - { - for (i = 0; ports[i]; ++i) - { - jack_info("graph reorder: new port '%s'", ports[i]); - port_ptr = jack_port_by_name(controller_ptr->client, ports[i]);; - jack_controller_patchbay_new_port(patchbay_ptr, ports[i], jack_port_flags(port_ptr), jack_port_type_id(port_ptr)); - } - - free(ports); - } - - if (patchbay_ptr->graph.version == 1) - { - /* we have empty initial graph, increment graph version, - so we dont do jack_get_ports() again, - on next next graph change */ - patchbay_ptr->graph.version++; - } - - return 0; -} - -void -jack_controller_client_registration_callback( - const char *client_name, - int created, - void *context) -{ - if (created) - { - jack_log("client '%s' created", client_name); - jack_controller_patchbay_create_client(patchbay_ptr, client_name, strlen(client_name)); - } - else - { - jack_log("client '%s' destroyed", client_name); - jack_controller_patchbay_destroy_client_by_name(patchbay_ptr, client_name); - } -} - -void -jack_controller_port_registration_callback( - jack_port_id_t port_id, - int created, - void *context) -{ - jack_port_t *port_ptr; - struct jack_graph_port *graph_port_ptr; - const char *port_name; - - port_ptr = jack_port_by_id(controller_ptr->client, port_id); - port_name = jack_port_name(port_ptr); - - if (created) - { - jack_log("port '%s' created", port_name); - jack_controller_patchbay_new_port(patchbay_ptr, port_name, jack_port_flags(port_ptr), jack_port_type_id(port_ptr)); - } - else - { - jack_log("port '%s' destroyed", port_name); - graph_port_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port_name); - if (graph_port_ptr == NULL) - { - jack_error("Failed to find port '%s' to destroy", port_name); - return; - } - - jack_controller_patchbay_remove_port(patchbay_ptr, graph_port_ptr); - } -} - -void -jack_controller_port_connect_callback( - jack_port_id_t port1_id, - jack_port_id_t port2_id, - int connect, - void *context) -{ - jack_port_t *port1; - jack_port_t *port2; - const char *port1_name; - const char *port2_name; - struct jack_graph_port *port1_ptr; - struct jack_graph_port *port2_ptr; - struct jack_graph_connection *connection_ptr; - - port1 = jack_port_by_id(controller_ptr->client, port1_id); - port2 = jack_port_by_id(controller_ptr->client, port2_id); - - port1_name = jack_port_name(port1); - port2_name = jack_port_name(port2); - - port1_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port1_name); - if (port1_ptr == NULL) - { - jack_error("Failed to find port '%s' to [dis]connect", port1_name); - return; - } - - port2_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port2_name); - if (port2_ptr == NULL) - { - jack_error("Failed to find port '%s' to [dis]connect", port2_name); - return; - } - - if (connect) - { - jack_info("Connecting '%s' to '%s'", port1_name, port2_name); - connection_ptr = jack_controller_patchbay_find_connection(patchbay_ptr, port1_ptr, port2_ptr); - if (connection_ptr != NULL) - { - jack_error("'%s' and '%s' are already connected", port1_name, port2_name); - return; - } - - jack_controller_patchbay_create_connection(patchbay_ptr, port1_ptr, port2_ptr); - } - else - { - jack_info("Disonnecting '%s' from '%s'", port1_name, port2_name); - connection_ptr = jack_controller_patchbay_find_connection(patchbay_ptr, port1_ptr, port2_ptr); - if (connection_ptr == NULL) - { - jack_error("Cannot find connection being removed"); - return; - } - - jack_controller_patchbay_destroy_connection(patchbay_ptr, connection_ptr); - } -} - -#undef controller_ptr - -void -jack_controller_patchbay_uninit( - struct jack_controller * controller_ptr) -{ - struct jack_graph_client *client_ptr; - struct jack_graph_port *port_ptr; - -/* jack_info("jack_controller_patchbay_uninit() called"); */ - - while (!list_empty(&patchbay_ptr->graph.ports)) - { - port_ptr = list_entry(patchbay_ptr->graph.ports.next, struct jack_graph_port, siblings_graph); - jack_controller_patchbay_remove_port(patchbay_ptr, port_ptr); - } - - while (!list_empty(&patchbay_ptr->graph.clients)) - { - client_ptr = list_entry(patchbay_ptr->graph.clients.next, struct jack_graph_client, siblings); - jack_controller_patchbay_destroy_client(patchbay_ptr, client_ptr); - } - - pthread_mutex_destroy(&patchbay_ptr->lock); -} - -#undef patchbay_ptr - -bool -jack_controller_patchbay_init( - struct jack_controller * controller_ptr) -{ - int ret; - struct jack_controller_patchbay * patchbay_ptr; - pthread_mutexattr_t attr; - -/* jack_info("jack_controller_patchbay_init() called"); */ - - patchbay_ptr = malloc(sizeof(struct jack_controller_patchbay)); - if (patchbay_ptr == NULL) - { - jack_error("Memory allocation of jack_controller_patchbay structure failed."); - goto fail; - } - - ret = pthread_mutexattr_init(&attr); - if (ret != 0) - { - goto fail; - } - - ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - if (ret != 0) - { - goto fail; - } - - pthread_mutex_init(&patchbay_ptr->lock, &attr); - INIT_LIST_HEAD(&patchbay_ptr->graph.clients); - INIT_LIST_HEAD(&patchbay_ptr->graph.ports); - INIT_LIST_HEAD(&patchbay_ptr->graph.connections); - patchbay_ptr->graph.version = 1; - patchbay_ptr->next_client_id = 1; - patchbay_ptr->next_port_id = 1; - patchbay_ptr->next_connection_id = 1; - - controller_ptr->patchbay_context = patchbay_ptr; - - ret = jack_set_graph_order_callback(controller_ptr->client, jack_controller_graph_order_callback, controller_ptr); - if (ret != 0) - { - jack_error("jack_set_graph_order_callback() failed with error %d", ret); - goto fail_uninit_mutex; - } - - ret = jack_set_client_registration_callback(controller_ptr->client, jack_controller_client_registration_callback, controller_ptr); - if (ret != 0) - { - jack_error("jack_set_client_registration_callback() failed with error %d", ret); - goto fail_uninit_mutex; - } - - ret = jack_set_port_registration_callback(controller_ptr->client, jack_controller_port_registration_callback, controller_ptr); - if (ret != 0) - { - jack_error("jack_set_port_registration_callback() failed with error %d", ret); - goto fail_uninit_mutex; - } - - ret = jack_set_port_connect_callback(controller_ptr->client, jack_controller_port_connect_callback, controller_ptr); - if (ret != 0) - { - jack_error("jack_set_port_connect_callback() failed with error %d", ret); - goto fail_uninit_mutex; - } - - return true; - -fail_uninit_mutex: - pthread_mutex_destroy(&patchbay_ptr->lock); - -fail: - return false; -} - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetAllPorts) - JACK_DBUS_METHOD_ARGUMENT("ports_list", "as", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetGraph) - JACK_DBUS_METHOD_ARGUMENT("known_graph_version", DBUS_TYPE_UINT64_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("current_graph_version", DBUS_TYPE_UINT64_AS_STRING, true) - JACK_DBUS_METHOD_ARGUMENT("clients_and_ports", "a(tsa(tsuu))", true) - JACK_DBUS_METHOD_ARGUMENT("connections", "a(tstststst)", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ConnectPortsByName) - JACK_DBUS_METHOD_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ConnectPortsByID) - JACK_DBUS_METHOD_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByName) - JACK_DBUS_METHOD_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByID) - JACK_DBUS_METHOD_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByConnectionID) - JACK_DBUS_METHOD_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetClientPID) - JACK_DBUS_METHOD_ARGUMENT("client_id", DBUS_TYPE_INT64_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHODS_BEGIN - JACK_DBUS_METHOD_DESCRIBE(GetAllPorts, jack_controller_dbus_get_all_ports) - JACK_DBUS_METHOD_DESCRIBE(GetGraph, jack_controller_dbus_get_graph) - JACK_DBUS_METHOD_DESCRIBE(ConnectPortsByName, jack_controller_dbus_connect_ports_by_name) - JACK_DBUS_METHOD_DESCRIBE(ConnectPortsByID, jack_controller_dbus_connect_ports_by_id) - JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByName, jack_controller_dbus_disconnect_ports_by_name) - JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByID, jack_controller_dbus_disconnect_ports_by_id) - JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByConnectionID, jack_controller_dbus_disconnect_ports_by_connection_id) - JACK_DBUS_METHOD_DESCRIBE(GetClientPID, jack_controller_dbus_get_client_pid) -JACK_DBUS_METHODS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(GraphChanged) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ClientAppeared) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ClientDisappeared) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortAppeared) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_flags", DBUS_TYPE_UINT32_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_type", DBUS_TYPE_UINT32_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortDisappeared) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_name", DBUS_TYPE_STRING_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortsConnected) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client1_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client2_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortsDisconnected) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client1_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client2_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNALS_BEGIN - JACK_DBUS_SIGNAL_DESCRIBE(GraphChanged) - JACK_DBUS_SIGNAL_DESCRIBE(ClientAppeared) - JACK_DBUS_SIGNAL_DESCRIBE(ClientDisappeared) - JACK_DBUS_SIGNAL_DESCRIBE(PortAppeared) - JACK_DBUS_SIGNAL_DESCRIBE(PortDisappeared) - JACK_DBUS_SIGNAL_DESCRIBE(PortsConnected) - JACK_DBUS_SIGNAL_DESCRIBE(PortsDisconnected) -JACK_DBUS_SIGNALS_END - -JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_patchbay, JACK_DBUS_IFACE_NAME) - JACK_DBUS_IFACE_EXPOSE_METHODS - JACK_DBUS_IFACE_EXPOSE_SIGNALS -JACK_DBUS_IFACE_END -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2008 Nedko Arnaudov - Copyright (C) 2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#define _GNU_SOURCE /* PTHREAD_MUTEX_RECURSIVE */ - -#include -#include -#include -#include -#include -#include -#include - -#include "jackdbus.h" -#include "controller_internal.h" -#include "list.h" - -#define JACK_DBUS_IFACE_NAME "org.jackaudio.JackPatchbay" - -/* FIXME: these need to be retrieved from common headers */ -#define JACK_CLIENT_NAME_SIZE 64 -#define JACK_PORT_NAME_SIZE 256 - -struct jack_graph -{ - uint64_t version; - struct list_head clients; - struct list_head ports; - struct list_head connections; -}; - -struct jack_graph_client -{ - uint64_t id; - char * name; - int pid; - struct list_head siblings; - struct list_head ports; -}; - -struct jack_graph_port -{ - uint64_t id; - char * name; - uint32_t flags; - uint32_t type; - struct list_head siblings_graph; - struct list_head siblings_client; - struct jack_graph_client * client; -}; - -struct jack_graph_connection -{ - uint64_t id; - struct jack_graph_port * port1; - struct jack_graph_port * port2; - struct list_head siblings; -}; - -struct jack_controller_patchbay -{ - pthread_mutex_t lock; - struct jack_graph graph; - uint64_t next_client_id; - uint64_t next_port_id; - uint64_t next_connection_id; -}; - -void -jack_controller_patchbay_send_signal_graph_changed( - dbus_uint64_t new_graph_version) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "GraphChanged", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_client_appeared( - dbus_uint64_t new_graph_version, - dbus_uint64_t client_id, - const char * client_name) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "ClientAppeared", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_client_disappeared( - dbus_uint64_t new_graph_version, - dbus_uint64_t client_id, - const char * client_name) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "ClientDisappeared", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_port_appeared( - dbus_uint64_t new_graph_version, - dbus_uint64_t client_id, - const char * client_name, - dbus_uint64_t port_id, - const char * port_name, - dbus_uint32_t port_flags, - dbus_uint32_t port_type) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "PortAppeared", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_UINT64, - &port_id, - DBUS_TYPE_STRING, - &port_name, - DBUS_TYPE_UINT32, - &port_flags, - DBUS_TYPE_UINT32, - &port_type, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_port_disappeared( - dbus_uint64_t new_graph_version, - dbus_uint64_t client_id, - const char * client_name, - dbus_uint64_t port_id, - const char * port_name) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "PortDisappeared", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_UINT64, - &port_id, - DBUS_TYPE_STRING, - &port_name, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_ports_connected( - dbus_uint64_t new_graph_version, - dbus_uint64_t client1_id, - const char * client1_name, - dbus_uint64_t port1_id, - const char * port1_name, - dbus_uint64_t client2_id, - const char * client2_name, - dbus_uint64_t port2_id, - const char * port2_name, - dbus_uint64_t connection_id) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "PortsConnected", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client1_id, - DBUS_TYPE_STRING, - &client1_name, - DBUS_TYPE_UINT64, - &port1_id, - DBUS_TYPE_STRING, - &port1_name, - DBUS_TYPE_UINT64, - &client2_id, - DBUS_TYPE_STRING, - &client2_name, - DBUS_TYPE_UINT64, - &port2_id, - DBUS_TYPE_STRING, - &port2_name, - DBUS_TYPE_UINT64, - &connection_id, - DBUS_TYPE_INVALID); -} - -void -jack_controller_patchbay_send_signal_ports_disconnected( - dbus_uint64_t new_graph_version, - dbus_uint64_t client1_id, - const char * client1_name, - dbus_uint64_t port1_id, - const char * port1_name, - dbus_uint64_t client2_id, - const char * client2_name, - dbus_uint64_t port2_id, - const char * port2_name, - dbus_uint64_t connection_id) -{ - - jack_dbus_send_signal( - JACK_CONTROLLER_OBJECT_PATH, - JACK_DBUS_IFACE_NAME, - "PortsDisconnected", - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client1_id, - DBUS_TYPE_STRING, - &client1_name, - DBUS_TYPE_UINT64, - &port1_id, - DBUS_TYPE_STRING, - &port1_name, - DBUS_TYPE_UINT64, - &client2_id, - DBUS_TYPE_STRING, - &client2_name, - DBUS_TYPE_UINT64, - &port2_id, - DBUS_TYPE_STRING, - &port2_name, - DBUS_TYPE_UINT64, - &connection_id, - DBUS_TYPE_INVALID); -} - -static -struct jack_graph_client * -jack_controller_patchbay_find_client( - struct jack_controller_patchbay *patchbay_ptr, - const char *client_name, /* not '\0' terminated */ - size_t client_name_len) /* without terminating '\0' */ -{ - struct list_head *node_ptr; - struct jack_graph_client *client_ptr; - - list_for_each(node_ptr, &patchbay_ptr->graph.clients) - { - client_ptr = list_entry(node_ptr, struct jack_graph_client, siblings); - if (strncmp(client_ptr->name, client_name, client_name_len) == 0) - { - return client_ptr; - } - } - - return NULL; -} - -static -struct jack_graph_client * -jack_controller_patchbay_find_client_by_id( - struct jack_controller_patchbay *patchbay_ptr, - uint64_t id) -{ - struct list_head *node_ptr; - struct jack_graph_client *client_ptr; - - list_for_each(node_ptr, &patchbay_ptr->graph.clients) - { - client_ptr = list_entry(node_ptr, struct jack_graph_client, siblings); - if (client_ptr->id == id) - { - return client_ptr; - } - } - - return NULL; -} - -static -struct jack_graph_client * -jack_controller_patchbay_create_client( - struct jack_controller_patchbay *patchbay_ptr, - const char *client_name, /* not '\0' terminated */ - size_t client_name_len) /* without terminating '\0' */ -{ - struct jack_graph_client * client_ptr; - - client_ptr = malloc(sizeof(struct jack_graph_client)); - if (client_ptr == NULL) - { - jack_error("Memory allocation of jack_graph_client structure failed."); - goto fail; - } - - client_ptr->name = malloc(client_name_len + 1); - if (client_ptr->name == NULL) - { - jack_error("malloc() failed to allocate memory for client name."); - goto fail_free_client; - } - - memcpy(client_ptr->name, client_name, client_name_len); - client_ptr->name[client_name_len] = 0; - - client_ptr->pid = jack_get_client_pid(client_ptr->name); - jack_info("New client '%s' with PID %d", client_ptr->name, client_ptr->pid); - - client_ptr->id = patchbay_ptr->next_client_id++; - INIT_LIST_HEAD(&client_ptr->ports); - - - pthread_mutex_lock(&patchbay_ptr->lock); - list_add_tail(&client_ptr->siblings, &patchbay_ptr->graph.clients); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_client_appeared(patchbay_ptr->graph.version, client_ptr->id, client_ptr->name); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - - return client_ptr; - -fail_free_client: - free(client_ptr); - -fail: - return NULL; -} - -static -void -jack_controller_patchbay_destroy_client( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_client *client_ptr) -{ - pthread_mutex_lock(&patchbay_ptr->lock); - list_del(&client_ptr->siblings); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_client_disappeared(patchbay_ptr->graph.version, client_ptr->id, client_ptr->name); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - - free(client_ptr->name); - free(client_ptr); -} - -static -void -jack_controller_patchbay_destroy_client_by_name( - struct jack_controller_patchbay *patchbay_ptr, - const char *client_name) /* '\0' terminated */ -{ - struct jack_graph_client *client_ptr; - - client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, client_name, strlen(client_name)); - if (client_ptr == NULL) - { - jack_error("Cannot destroy unknown client '%s'", client_name); - return; - } - - jack_controller_patchbay_destroy_client(patchbay_ptr, client_ptr); -} - -static -void -jack_controller_patchbay_new_port( - struct jack_controller_patchbay *patchbay_ptr, - const char *port_full_name, - uint32_t port_flags, - uint32_t port_type) -{ - struct jack_graph_client *client_ptr; - struct jack_graph_port *port_ptr; - const char *port_short_name; - size_t client_name_len; - - //jack_info("name: %s", port_full_name); - - port_short_name = strchr(port_full_name, ':'); - if (port_short_name == NULL) - { - jack_error("port name '%s' does not contain ':' separator char", port_full_name); - return; - } - - port_short_name++; /* skip ':' separator char */ - - client_name_len = port_short_name - port_full_name - 1; /* without terminating '\0' */ - - client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, port_full_name, client_name_len); - if (client_ptr == NULL) - { - client_ptr = jack_controller_patchbay_create_client(patchbay_ptr, port_full_name, client_name_len); - if (client_ptr == NULL) - { - jack_error("Creation of new jack_graph client failed."); - return; - } - } - - port_ptr = malloc(sizeof(struct jack_graph_port)); - if (port_ptr == NULL) - { - jack_error("Memory allocation of jack_graph_port structure failed."); - return; - } - - port_ptr->name = strdup(port_short_name); - if (port_ptr->name == NULL) - { - jack_error("strdup() call for port name '%s' failed.", port_short_name); - free(port_ptr); - return; - } - - port_ptr->id = patchbay_ptr->next_port_id++; - port_ptr->flags = port_flags; - port_ptr->type = port_type; - port_ptr->client = client_ptr; - - pthread_mutex_lock(&patchbay_ptr->lock); - list_add_tail(&port_ptr->siblings_client, &client_ptr->ports); - list_add_tail(&port_ptr->siblings_graph, &patchbay_ptr->graph.ports); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_port_appeared( - patchbay_ptr->graph.version, - client_ptr->id, - client_ptr->name, - port_ptr->id, - port_ptr->name, - port_ptr->flags, - port_ptr->type); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_patchbay_remove_port( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_port *port_ptr) -{ - pthread_mutex_lock(&patchbay_ptr->lock); - list_del(&port_ptr->siblings_client); - list_del(&port_ptr->siblings_graph); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_port_disappeared(patchbay_ptr->graph.version, port_ptr->client->id, port_ptr->client->name, port_ptr->id, port_ptr->name); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - - free(port_ptr->name); - free(port_ptr); -} - -static -struct jack_graph_port * -jack_controller_patchbay_find_port_by_id( - struct jack_controller_patchbay *patchbay_ptr, - uint64_t port_id) -{ - struct list_head *node_ptr; - struct jack_graph_port *port_ptr; - - list_for_each(node_ptr, &patchbay_ptr->graph.ports) - { - port_ptr = list_entry(node_ptr, struct jack_graph_port, siblings_graph); - if (port_ptr->id == port_id) - { - return port_ptr; - } - } - - return NULL; -} - -static -struct jack_graph_port * -jack_controller_patchbay_find_client_port_by_name( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_client *client_ptr, - const char *port_name) -{ - struct list_head *node_ptr; - struct jack_graph_port *port_ptr; - - list_for_each(node_ptr, &client_ptr->ports) - { - port_ptr = list_entry(node_ptr, struct jack_graph_port, siblings_client); - if (strcmp(port_ptr->name, port_name) == 0) - { - return port_ptr; - } - } - - return NULL; -} - -static -struct jack_graph_port * -jack_controller_patchbay_find_port_by_full_name( - struct jack_controller_patchbay *patchbay_ptr, - const char *port_full_name) -{ - const char *port_short_name; - size_t client_name_len; - struct jack_graph_client *client_ptr; - - //jack_info("name: %s", port_full_name); - - port_short_name = strchr(port_full_name, ':'); - if (port_short_name == NULL) - { - jack_error("port name '%s' does not contain ':' separator char", port_full_name); - return NULL; - } - - port_short_name++; /* skip ':' separator char */ - - client_name_len = port_short_name - port_full_name - 1; /* without terminating '\0' */ - - client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, port_full_name, client_name_len); - if (client_ptr == NULL) - { - jack_error("cannot find client of port '%s'", port_full_name); - return NULL; - } - - return jack_controller_patchbay_find_client_port_by_name(patchbay_ptr, client_ptr, port_short_name); -} - -static -struct jack_graph_port * -jack_controller_patchbay_find_port_by_names( - struct jack_controller_patchbay *patchbay_ptr, - const char *client_name, - const char *port_name) -{ - struct jack_graph_client *client_ptr; - - client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, client_name, strlen(client_name)); - if (client_ptr == NULL) - { - jack_error("cannot find client '%s'", client_name); - return NULL; - } - - return jack_controller_patchbay_find_client_port_by_name(patchbay_ptr, client_ptr, port_name); -} - -static -struct jack_graph_connection * -jack_controller_patchbay_create_connection( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_port *port1_ptr, - struct jack_graph_port *port2_ptr) -{ - struct jack_graph_connection * connection_ptr; - - connection_ptr = malloc(sizeof(struct jack_graph_connection)); - if (connection_ptr == NULL) - { - jack_error("Memory allocation of jack_graph_connection structure failed."); - return NULL; - } - - connection_ptr->id = patchbay_ptr->next_connection_id++; - connection_ptr->port1 = port1_ptr; - connection_ptr->port2 = port2_ptr; - - pthread_mutex_lock(&patchbay_ptr->lock); - list_add_tail(&connection_ptr->siblings, &patchbay_ptr->graph.connections); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_ports_connected( - patchbay_ptr->graph.version, - port1_ptr->client->id, - port1_ptr->client->name, - port1_ptr->id, - port1_ptr->name, - port2_ptr->client->id, - port2_ptr->client->name, - port2_ptr->id, - port2_ptr->name, - connection_ptr->id); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - - return connection_ptr; -} - -static -void -jack_controller_patchbay_destroy_connection( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_connection *connection_ptr) -{ - pthread_mutex_lock(&patchbay_ptr->lock); - list_del(&connection_ptr->siblings); - patchbay_ptr->graph.version++; - jack_controller_patchbay_send_signal_ports_disconnected( - patchbay_ptr->graph.version, - connection_ptr->port1->client->id, - connection_ptr->port1->client->name, - connection_ptr->port1->id, - connection_ptr->port1->name, - connection_ptr->port2->client->id, - connection_ptr->port2->client->name, - connection_ptr->port2->id, - connection_ptr->port2->name, - connection_ptr->id); - jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - - free(connection_ptr); -} - -static -struct jack_graph_connection * -jack_controller_patchbay_find_connection( - struct jack_controller_patchbay *patchbay_ptr, - struct jack_graph_port *port1_ptr, - struct jack_graph_port *port2_ptr) -{ - struct list_head *node_ptr; - struct jack_graph_connection *connection_ptr; - - list_for_each(node_ptr, &patchbay_ptr->graph.connections) - { - connection_ptr = list_entry(node_ptr, struct jack_graph_connection, siblings); - if ((connection_ptr->port1 == port1_ptr && - connection_ptr->port2 == port2_ptr) || - (connection_ptr->port1 == port2_ptr && - connection_ptr->port2 == port1_ptr)) - { - return connection_ptr; - } - } - - return NULL; -} - -static -struct jack_graph_connection * -jack_controller_patchbay_find_connection_by_id( - struct jack_controller_patchbay *patchbay_ptr, - uint64_t connection_id) -{ - struct list_head *node_ptr; - struct jack_graph_connection *connection_ptr; - - list_for_each(node_ptr, &patchbay_ptr->graph.connections) - { - connection_ptr = list_entry(node_ptr, struct jack_graph_connection, siblings); - if (connection_ptr->id == connection_id) - { - return connection_ptr; - } - } - - return NULL; -} - -static -bool -jack_controller_patchbay_connect( - struct jack_dbus_method_call *dbus_call_ptr, - struct jack_controller *controller_ptr, - struct jack_graph_port *port1_ptr, - struct jack_graph_port *port2_ptr) -{ - int ret; - char port1_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - char port2_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - - sprintf(port1_name, "%s:%s", port1_ptr->client->name, port1_ptr->name); - sprintf(port2_name, "%s:%s", port2_ptr->client->name, port2_ptr->name); - - ret = jack_connect(controller_ptr->client, port1_name, port2_name); - if (ret != 0) - { - jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_connect() failed with %d", ret); - return false; - } - - return true; -} - -static -bool -jack_controller_patchbay_disconnect( - struct jack_dbus_method_call *dbus_call_ptr, - struct jack_controller *controller_ptr, - struct jack_graph_port *port1_ptr, - struct jack_graph_port *port2_ptr) -{ - int ret; - char port1_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - char port2_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - - sprintf(port1_name, "%s:%s", port1_ptr->client->name, port1_ptr->name); - sprintf(port2_name, "%s:%s", port2_ptr->client->name, port2_ptr->name); - - ret = jack_disconnect(controller_ptr->client, port1_name, port2_name); - if (ret != 0) - { - jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_connect() failed with %d", ret); - return false; - } - - return true; -} - -#define controller_ptr ((struct jack_controller *)call->context) -#define patchbay_ptr ((struct jack_controller_patchbay *)controller_ptr->patchbay_context) - -static -void -jack_controller_dbus_get_all_ports( - struct jack_dbus_method_call * call) -{ - struct list_head * client_node_ptr; - struct list_head * port_node_ptr; - struct jack_graph_client * client_ptr; - struct jack_graph_port * port_ptr; - DBusMessageIter iter, sub_iter; - char fullname[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - char *fullname_var = fullname; - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - call->reply = dbus_message_new_method_return (call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append (call->reply, &iter); - - if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter)) - { - goto fail_unref; - } - - pthread_mutex_lock(&patchbay_ptr->lock); - - list_for_each(client_node_ptr, &patchbay_ptr->graph.clients) - { - client_ptr = list_entry(client_node_ptr, struct jack_graph_client, siblings); - - list_for_each(port_node_ptr, &client_ptr->ports) - { - port_ptr = list_entry(port_node_ptr, struct jack_graph_port, siblings_client); - - jack_info("%s:%s", client_ptr->name, port_ptr->name); - sprintf(fullname, "%s:%s", client_ptr->name, port_ptr->name); - if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, &fullname_var)) - { - pthread_mutex_unlock(&patchbay_ptr->lock); - dbus_message_iter_close_container (&iter, &sub_iter); - goto fail_unref; - } - } - } - - pthread_mutex_unlock(&patchbay_ptr->lock); - - if (!dbus_message_iter_close_container (&iter, &sub_iter)) - { - goto fail_unref; - } - - return; - -fail_unref: - dbus_message_unref (call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -static -void -jack_controller_dbus_get_graph( - struct jack_dbus_method_call * call) -{ - struct list_head * client_node_ptr; - struct list_head * port_node_ptr; - struct list_head * connection_node_ptr; - struct jack_graph_client * client_ptr; - struct jack_graph_port * port_ptr; - struct jack_graph_connection * connection_ptr; - DBusMessageIter iter; - DBusMessageIter clients_array_iter; - DBusMessageIter client_struct_iter; - DBusMessageIter ports_array_iter; - DBusMessageIter port_struct_iter; - dbus_uint64_t version; - DBusMessageIter connections_array_iter; - DBusMessageIter connection_struct_iter; - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - if (!jack_dbus_get_method_args(call, DBUS_TYPE_UINT64, &version, DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - goto exit; - } - - //jack_info("Getting graph, know version is %" PRIu32, version); - - call->reply = dbus_message_new_method_return(call->message); - if (!call->reply) - { - jack_error("Ran out of memory trying to construct method return"); - goto exit; - } - - dbus_message_iter_init_append (call->reply, &iter); - - pthread_mutex_lock(&patchbay_ptr->lock); - - if (version > patchbay_ptr->graph.version) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "known graph version %" PRIu64 " is newer than actual version %" PRIu64, - version, - patchbay_ptr->graph.version); - pthread_mutex_unlock(&patchbay_ptr->lock); - goto exit; - } - - if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT64, &patchbay_ptr->graph.version)) - { - goto nomem_unlock; - } - - if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tsa(tsuu))", &clients_array_iter)) - { - goto nomem_unlock; - } - - if (version < patchbay_ptr->graph.version) - { - list_for_each(client_node_ptr, &patchbay_ptr->graph.clients) - { - client_ptr = list_entry(client_node_ptr, struct jack_graph_client, siblings); - - if (!dbus_message_iter_open_container (&clients_array_iter, DBUS_TYPE_STRUCT, NULL, &client_struct_iter)) - { - goto nomem_close_clients_array; - } - - if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_UINT64, &client_ptr->id)) - { - goto nomem_close_client_struct; - } - - if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_STRING, &client_ptr->name)) - { - goto nomem_close_client_struct; - } - - if (!dbus_message_iter_open_container(&client_struct_iter, DBUS_TYPE_ARRAY, "(tsuu)", &ports_array_iter)) - { - goto nomem_close_client_struct; - } - - list_for_each(port_node_ptr, &client_ptr->ports) - { - port_ptr = list_entry(port_node_ptr, struct jack_graph_port, siblings_client); - - if (!dbus_message_iter_open_container(&ports_array_iter, DBUS_TYPE_STRUCT, NULL, &port_struct_iter)) - { - goto nomem_close_ports_array; - } - - if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT64, &port_ptr->id)) - { - goto nomem_close_port_struct; - } - - if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_STRING, &port_ptr->name)) - { - goto nomem_close_port_struct; - } - - if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->flags)) - { - goto nomem_close_port_struct; - } - - if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->type)) - { - goto nomem_close_port_struct; - } - - if (!dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter)) - { - goto nomem_close_ports_array; - } - } - - if (!dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter)) - { - goto nomem_close_client_struct; - } - - if (!dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter)) - { - goto nomem_close_clients_array; - } - } - } - - if (!dbus_message_iter_close_container(&iter, &clients_array_iter)) - { - goto nomem_unlock; - } - - if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tstststst)", &connections_array_iter)) - { - goto nomem_unlock; - } - - if (version < patchbay_ptr->graph.version) - { - list_for_each(connection_node_ptr, &patchbay_ptr->graph.connections) - { - connection_ptr = list_entry(connection_node_ptr, struct jack_graph_connection, siblings); - - if (!dbus_message_iter_open_container(&connections_array_iter, DBUS_TYPE_STRUCT, NULL, &connection_struct_iter)) - { - goto nomem_close_connections_array; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1->client->id)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1->client->name)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1->id)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1->name)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2->client->id)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2->client->name)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2->id)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2->name)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->id)) - { - goto nomem_close_connection_struct; - } - - if (!dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter)) - { - goto nomem_close_connections_array; - } - } - } - - if (!dbus_message_iter_close_container(&iter, &connections_array_iter)) - { - goto nomem_unlock; - } - - pthread_mutex_unlock(&patchbay_ptr->lock); - - return; - -nomem_close_connection_struct: - dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter); - -nomem_close_connections_array: - dbus_message_iter_close_container(&iter, &connections_array_iter); - goto nomem_unlock; - -nomem_close_port_struct: - dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter); - -nomem_close_ports_array: - dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter); - -nomem_close_client_struct: - dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter); - -nomem_close_clients_array: - dbus_message_iter_close_container(&iter, &clients_array_iter); - -nomem_unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); - -//nomem: - dbus_message_unref(call->reply); - call->reply = NULL; - jack_error("Ran out of memory trying to construct method return"); - -exit: - return; -} - -static -void -jack_controller_dbus_connect_ports_by_name( - struct jack_dbus_method_call * call) -{ - const char * client1_name; - const char * port1_name; - const char * client2_name; - const char * port2_name; - struct jack_graph_port *port1_ptr; - struct jack_graph_port *port2_ptr; - -/* jack_info("jack_controller_dbus_connect_ports_by_name() called."); */ - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_STRING, - &client1_name, - DBUS_TYPE_STRING, - &port1_name, - DBUS_TYPE_STRING, - &client2_name, - DBUS_TYPE_STRING, - &port2_name, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - -/* jack_info("connecting %s:%s and %s:%s", client1_name, port1_name, client2_name, port2_name); */ - - pthread_mutex_lock(&patchbay_ptr->lock); - - port1_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client1_name, port1_name); - if (port1_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client1_name, port1_name); - goto unlock; - } - - port2_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client2_name, port2_name); - if (port2_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client2_name, port2_name); - goto unlock; - } - - if (!jack_controller_patchbay_connect( - call, - controller_ptr, - port1_ptr, - port2_ptr)) - { - /* jack_controller_patchbay_connect() constructed error reply */ - goto unlock; - } - - jack_dbus_construct_method_return_empty(call); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_dbus_connect_ports_by_id( - struct jack_dbus_method_call * call) -{ - dbus_uint64_t port1_id; - dbus_uint64_t port2_id; - struct jack_graph_port *port1_ptr; - struct jack_graph_port *port2_ptr; - -/* jack_info("jack_controller_dbus_connect_ports_by_id() called."); */ - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_UINT64, - &port1_id, - DBUS_TYPE_UINT64, - &port2_id, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - pthread_mutex_lock(&patchbay_ptr->lock); - - port1_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port1_id); - if (port1_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port1_id); - goto unlock; - } - - port2_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port2_id); - if (port2_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port2_id); - goto unlock; - } - - if (!jack_controller_patchbay_connect( - call, - controller_ptr, - port1_ptr, - port2_ptr)) - { - /* jack_controller_patchbay_connect() constructed error reply */ - goto unlock; - } - - jack_dbus_construct_method_return_empty(call); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_dbus_disconnect_ports_by_name( - struct jack_dbus_method_call * call) -{ - const char * client1_name; - const char * port1_name; - const char * client2_name; - const char * port2_name; - struct jack_graph_port *port1_ptr; - struct jack_graph_port *port2_ptr; - -/* jack_info("jack_controller_dbus_disconnect_ports_by_name() called."); */ - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_STRING, - &client1_name, - DBUS_TYPE_STRING, - &port1_name, - DBUS_TYPE_STRING, - &client2_name, - DBUS_TYPE_STRING, - &port2_name, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - -/* jack_info("disconnecting %s:%s and %s:%s", client1_name, port1_name, client2_name, port2_name); */ - - pthread_mutex_lock(&patchbay_ptr->lock); - - port1_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client1_name, port1_name); - if (port1_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client1_name, port1_name); - goto unlock; - } - - port2_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client2_name, port2_name); - if (port2_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client2_name, port2_name); - goto unlock; - } - - if (!jack_controller_patchbay_disconnect( - call, - controller_ptr, - port1_ptr, - port2_ptr)) - { - /* jack_controller_patchbay_connect() constructed error reply */ - goto unlock; - } - - jack_dbus_construct_method_return_empty(call); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_dbus_disconnect_ports_by_id( - struct jack_dbus_method_call * call) -{ - dbus_uint64_t port1_id; - dbus_uint64_t port2_id; - struct jack_graph_port *port1_ptr; - struct jack_graph_port *port2_ptr; - -/* jack_info("jack_controller_dbus_disconnect_ports_by_id() called."); */ - - if (!controller_ptr->started) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_SERVER_NOT_RUNNING, - "Can't execute this method with stopped JACK server"); - return; - } - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_UINT64, - &port1_id, - DBUS_TYPE_UINT64, - &port2_id, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - pthread_mutex_lock(&patchbay_ptr->lock); - - port1_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port1_id); - if (port1_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port1_id); - return; - } - - port2_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port2_id); - if (port2_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port2_id); - return; - } - - if (!jack_controller_patchbay_disconnect( - call, - controller_ptr, - port1_ptr, - port2_ptr)) - { - /* jack_controller_patchbay_connect() constructed error reply */ - goto unlock; - } - - jack_dbus_construct_method_return_empty(call); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_dbus_disconnect_ports_by_connection_id( - struct jack_dbus_method_call * call) -{ - dbus_uint64_t connection_id; - struct jack_graph_connection *connection_ptr; - -/* jack_info("jack_controller_dbus_disconnect_ports_by_id() called."); */ - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_UINT64, - &connection_id, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - pthread_mutex_lock(&patchbay_ptr->lock); - - connection_ptr = jack_controller_patchbay_find_connection_by_id(patchbay_ptr, connection_id); - if (connection_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find connection %" PRIu64, connection_id); - goto unlock; - } - - if (!jack_controller_patchbay_disconnect( - call, - controller_ptr, - connection_ptr->port1, - connection_ptr->port2)) - { - /* jack_controller_patchbay_connect() constructed error reply */ - goto unlock; - } - - jack_dbus_construct_method_return_empty(call); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -static -void -jack_controller_dbus_get_client_pid( - struct jack_dbus_method_call * call) -{ - dbus_uint64_t client_id; - struct jack_graph_client *client_ptr; - message_arg_t arg; - -/* jack_info("jack_controller_dbus_get_client_pid() called."); */ - - if (!jack_dbus_get_method_args( - call, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_INVALID)) - { - /* The method call had invalid arguments meaning that - * jack_dbus_get_method_args() has constructed an error for us. - */ - return; - } - - pthread_mutex_lock(&patchbay_ptr->lock); - - client_ptr = jack_controller_patchbay_find_client_by_id(patchbay_ptr, client_id); - if (client_ptr == NULL) - { - jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find client %" PRIu64, client_id); - goto unlock; - } - - arg.int64 = client_ptr->pid; - - jack_dbus_construct_method_return_single(call, DBUS_TYPE_INT64, arg); - -unlock: - pthread_mutex_unlock(&patchbay_ptr->lock); -} - -#undef controller_ptr -#define controller_ptr ((struct jack_controller *)context) - -static -int -jack_controller_graph_order_callback( - void *context) -{ - const char **ports; - int i; - jack_port_t *port_ptr; - - if (patchbay_ptr->graph.version > 1) - { - /* we use this only for initial catchup */ - return 0; - } - - ports = jack_get_ports(controller_ptr->client, NULL, NULL, 0); - if (ports) - { - for (i = 0; ports[i]; ++i) - { - jack_info("graph reorder: new port '%s'", ports[i]); - port_ptr = jack_port_by_name(controller_ptr->client, ports[i]);; - jack_controller_patchbay_new_port(patchbay_ptr, ports[i], jack_port_flags(port_ptr), jack_port_type_id(port_ptr)); - } - - free(ports); - } - - if (patchbay_ptr->graph.version == 1) - { - /* we have empty initial graph, increment graph version, - so we dont do jack_get_ports() again, - on next next graph change */ - patchbay_ptr->graph.version++; - } - - return 0; -} - -void -jack_controller_client_registration_callback( - const char *client_name, - int created, - void *context) -{ - if (created) - { - jack_log("client '%s' created", client_name); - jack_controller_patchbay_create_client(patchbay_ptr, client_name, strlen(client_name)); - } - else - { - jack_log("client '%s' destroyed", client_name); - jack_controller_patchbay_destroy_client_by_name(patchbay_ptr, client_name); - } -} - -void -jack_controller_port_registration_callback( - jack_port_id_t port_id, - int created, - void *context) -{ - jack_port_t *port_ptr; - struct jack_graph_port *graph_port_ptr; - const char *port_name; - - port_ptr = jack_port_by_id(controller_ptr->client, port_id); - port_name = jack_port_name(port_ptr); - - if (created) - { - jack_log("port '%s' created", port_name); - jack_controller_patchbay_new_port(patchbay_ptr, port_name, jack_port_flags(port_ptr), jack_port_type_id(port_ptr)); - } - else - { - jack_log("port '%s' destroyed", port_name); - graph_port_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port_name); - if (graph_port_ptr == NULL) - { - jack_error("Failed to find port '%s' to destroy", port_name); - return; - } - - jack_controller_patchbay_remove_port(patchbay_ptr, graph_port_ptr); - } -} - -void -jack_controller_port_connect_callback( - jack_port_id_t port1_id, - jack_port_id_t port2_id, - int connect, - void *context) -{ - jack_port_t *port1; - jack_port_t *port2; - const char *port1_name; - const char *port2_name; - struct jack_graph_port *port1_ptr; - struct jack_graph_port *port2_ptr; - struct jack_graph_connection *connection_ptr; - - port1 = jack_port_by_id(controller_ptr->client, port1_id); - port2 = jack_port_by_id(controller_ptr->client, port2_id); - - port1_name = jack_port_name(port1); - port2_name = jack_port_name(port2); - - port1_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port1_name); - if (port1_ptr == NULL) - { - jack_error("Failed to find port '%s' to [dis]connect", port1_name); - return; - } - - port2_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port2_name); - if (port2_ptr == NULL) - { - jack_error("Failed to find port '%s' to [dis]connect", port2_name); - return; - } - - if (connect) - { - jack_info("Connecting '%s' to '%s'", port1_name, port2_name); - connection_ptr = jack_controller_patchbay_find_connection(patchbay_ptr, port1_ptr, port2_ptr); - if (connection_ptr != NULL) - { - jack_error("'%s' and '%s' are already connected", port1_name, port2_name); - return; - } - - jack_controller_patchbay_create_connection(patchbay_ptr, port1_ptr, port2_ptr); - } - else - { - jack_info("Disonnecting '%s' from '%s'", port1_name, port2_name); - connection_ptr = jack_controller_patchbay_find_connection(patchbay_ptr, port1_ptr, port2_ptr); - if (connection_ptr == NULL) - { - jack_error("Cannot find connection being removed"); - return; - } - - jack_controller_patchbay_destroy_connection(patchbay_ptr, connection_ptr); - } -} - -#undef controller_ptr - -void -jack_controller_patchbay_uninit( - struct jack_controller * controller_ptr) -{ - struct jack_graph_client *client_ptr; - struct jack_graph_port *port_ptr; - -/* jack_info("jack_controller_patchbay_uninit() called"); */ - - while (!list_empty(&patchbay_ptr->graph.ports)) - { - port_ptr = list_entry(patchbay_ptr->graph.ports.next, struct jack_graph_port, siblings_graph); - jack_controller_patchbay_remove_port(patchbay_ptr, port_ptr); - } - - while (!list_empty(&patchbay_ptr->graph.clients)) - { - client_ptr = list_entry(patchbay_ptr->graph.clients.next, struct jack_graph_client, siblings); - jack_controller_patchbay_destroy_client(patchbay_ptr, client_ptr); - } - - pthread_mutex_destroy(&patchbay_ptr->lock); -} - -#undef patchbay_ptr - -bool -jack_controller_patchbay_init( - struct jack_controller * controller_ptr) -{ - int ret; - struct jack_controller_patchbay * patchbay_ptr; - pthread_mutexattr_t attr; - -/* jack_info("jack_controller_patchbay_init() called"); */ - - patchbay_ptr = malloc(sizeof(struct jack_controller_patchbay)); - if (patchbay_ptr == NULL) - { - jack_error("Memory allocation of jack_controller_patchbay structure failed."); - goto fail; - } - - ret = pthread_mutexattr_init(&attr); - if (ret != 0) - { - goto fail; - } - - ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - if (ret != 0) - { - goto fail; - } - - pthread_mutex_init(&patchbay_ptr->lock, &attr); - INIT_LIST_HEAD(&patchbay_ptr->graph.clients); - INIT_LIST_HEAD(&patchbay_ptr->graph.ports); - INIT_LIST_HEAD(&patchbay_ptr->graph.connections); - patchbay_ptr->graph.version = 1; - patchbay_ptr->next_client_id = 1; - patchbay_ptr->next_port_id = 1; - patchbay_ptr->next_connection_id = 1; - - controller_ptr->patchbay_context = patchbay_ptr; - - ret = jack_set_graph_order_callback(controller_ptr->client, jack_controller_graph_order_callback, controller_ptr); - if (ret != 0) - { - jack_error("jack_set_graph_order_callback() failed with error %d", ret); - goto fail_uninit_mutex; - } - - ret = jack_set_client_registration_callback(controller_ptr->client, jack_controller_client_registration_callback, controller_ptr); - if (ret != 0) - { - jack_error("jack_set_client_registration_callback() failed with error %d", ret); - goto fail_uninit_mutex; - } - - ret = jack_set_port_registration_callback(controller_ptr->client, jack_controller_port_registration_callback, controller_ptr); - if (ret != 0) - { - jack_error("jack_set_port_registration_callback() failed with error %d", ret); - goto fail_uninit_mutex; - } - - ret = jack_set_port_connect_callback(controller_ptr->client, jack_controller_port_connect_callback, controller_ptr); - if (ret != 0) - { - jack_error("jack_set_port_connect_callback() failed with error %d", ret); - goto fail_uninit_mutex; - } - - return true; - -fail_uninit_mutex: - pthread_mutex_destroy(&patchbay_ptr->lock); - -fail: - return false; -} - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetAllPorts) - JACK_DBUS_METHOD_ARGUMENT("ports_list", "as", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetGraph) - JACK_DBUS_METHOD_ARGUMENT("known_graph_version", DBUS_TYPE_UINT64_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("current_graph_version", DBUS_TYPE_UINT64_AS_STRING, true) - JACK_DBUS_METHOD_ARGUMENT("clients_and_ports", "a(tsa(tsuu))", true) - JACK_DBUS_METHOD_ARGUMENT("connections", "a(tstststst)", true) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ConnectPortsByName) - JACK_DBUS_METHOD_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ConnectPortsByID) - JACK_DBUS_METHOD_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByName) - JACK_DBUS_METHOD_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByID) - JACK_DBUS_METHOD_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING, false) - JACK_DBUS_METHOD_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByConnectionID) - JACK_DBUS_METHOD_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetClientPID) - JACK_DBUS_METHOD_ARGUMENT("client_id", DBUS_TYPE_INT64_AS_STRING, false) -JACK_DBUS_METHOD_ARGUMENTS_END - -JACK_DBUS_METHODS_BEGIN - JACK_DBUS_METHOD_DESCRIBE(GetAllPorts, jack_controller_dbus_get_all_ports) - JACK_DBUS_METHOD_DESCRIBE(GetGraph, jack_controller_dbus_get_graph) - JACK_DBUS_METHOD_DESCRIBE(ConnectPortsByName, jack_controller_dbus_connect_ports_by_name) - JACK_DBUS_METHOD_DESCRIBE(ConnectPortsByID, jack_controller_dbus_connect_ports_by_id) - JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByName, jack_controller_dbus_disconnect_ports_by_name) - JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByID, jack_controller_dbus_disconnect_ports_by_id) - JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByConnectionID, jack_controller_dbus_disconnect_ports_by_connection_id) - JACK_DBUS_METHOD_DESCRIBE(GetClientPID, jack_controller_dbus_get_client_pid) -JACK_DBUS_METHODS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(GraphChanged) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ClientAppeared) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ClientDisappeared) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortAppeared) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_flags", DBUS_TYPE_UINT32_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_type", DBUS_TYPE_UINT32_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortDisappeared) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port_name", DBUS_TYPE_STRING_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortsConnected) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client1_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client2_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortsDisconnected) - JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client1_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client2_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING) - JACK_DBUS_SIGNAL_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING) -JACK_DBUS_SIGNAL_ARGUMENTS_END - -JACK_DBUS_SIGNALS_BEGIN - JACK_DBUS_SIGNAL_DESCRIBE(GraphChanged) - JACK_DBUS_SIGNAL_DESCRIBE(ClientAppeared) - JACK_DBUS_SIGNAL_DESCRIBE(ClientDisappeared) - JACK_DBUS_SIGNAL_DESCRIBE(PortAppeared) - JACK_DBUS_SIGNAL_DESCRIBE(PortDisappeared) - JACK_DBUS_SIGNAL_DESCRIBE(PortsConnected) - JACK_DBUS_SIGNAL_DESCRIBE(PortsDisconnected) -JACK_DBUS_SIGNALS_END - -JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_patchbay, JACK_DBUS_IFACE_NAME) - JACK_DBUS_IFACE_EXPOSE_METHODS - JACK_DBUS_IFACE_EXPOSE_SIGNALS -JACK_DBUS_IFACE_END diff --git a/linux/dbus/controller_iface_transport.c b/linux/dbus/controller_iface_transport.c index bef2b941..f5680a1c 100644 --- a/linux/dbus/controller_iface_transport.c +++ b/linux/dbus/controller_iface_transport.c @@ -32,105 +32,3 @@ JACK_DBUS_METHODS_END JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_transport, "org.jackaudio.JackTransport") JACK_DBUS_IFACE_EXPOSE_METHODS JACK_DBUS_IFACE_END -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2008 Nedko Arnaudov - Copyright (C) 2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include - -#include "jackdbus.h" - -JACK_DBUS_METHODS_BEGIN -JACK_DBUS_METHODS_END - -JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_transport, "org.jackaudio.JackTransport") - JACK_DBUS_IFACE_EXPOSE_METHODS -JACK_DBUS_IFACE_END -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2008 Nedko Arnaudov - Copyright (C) 2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include - -#include "jackdbus.h" - -JACK_DBUS_METHODS_BEGIN -JACK_DBUS_METHODS_END - -JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_transport, "org.jackaudio.JackTransport") - JACK_DBUS_IFACE_EXPOSE_METHODS -JACK_DBUS_IFACE_END -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2008 Nedko Arnaudov - Copyright (C) 2008 Juuso Alasuutari - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include - -#include "jackdbus.h" - -JACK_DBUS_METHODS_BEGIN -JACK_DBUS_METHODS_END - -JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_transport, "org.jackaudio.JackTransport") - JACK_DBUS_IFACE_EXPOSE_METHODS -JACK_DBUS_IFACE_END diff --git a/linux/dbus/jackdbus.c b/linux/dbus/jackdbus.c index d3fc38ce..39d58a0f 100644 --- a/linux/dbus/jackdbus.c +++ b/linux/dbus/jackdbus.c @@ -811,2442 +811,3 @@ fail_uninit_xml: fail: return ret; } -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - Copyright (C) 2007-2008 Juuso Alasuutari - Copyright (C) 2008 Marc-Olivier Barre - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" - -#include "jackdbus.h" -#include "controller.h" -#include "jack/jack.h" -#include "jack/jslist.h" -#include "jack/control.h" - -FILE *g_logfile; -char *g_jackdbus_config_dir; -size_t g_jackdbus_config_dir_len; /* without terminating '\0' char */ -char *g_jackdbus_log_dir; -size_t g_jackdbus_log_dir_len; /* without terminating '\0' char */ -int g_exit_command; -DBusConnection *g_connection; - -void -jack_dbus_send_signal( - const char *sender_object_path, - const char *iface, - const char *signal_name, - int first_arg_type, - ...) -{ - DBusMessage *message_ptr; - va_list ap; - - va_start(ap, first_arg_type); - - message_ptr = dbus_message_new_signal(sender_object_path, iface, signal_name); - if (message_ptr == NULL) - { - jack_error("dbus_message_new_signal() failed."); - goto exit; - } - - if (!dbus_message_append_args_valist(message_ptr, first_arg_type, ap)) - { - jack_error("dbus_message_append_args_valist() failed."); - goto unref; - } - - /* Add message to outgoing message queue */ - if (!dbus_connection_send(g_connection, message_ptr, NULL)) - { - jack_error("dbus_connection_send() failed."); - goto unref; - } - -unref: - dbus_message_unref(message_ptr); - -exit: - va_end(ap); -} - -/* - * Send a method return. - * - * If call->reply is NULL (i.e. a message construct method failed - * due to lack of memory) attempt to send a void method return. - */ -static -void -jack_dbus_send_method_return( - struct jack_dbus_method_call * call) -{ - if (call->reply) - { - retry_send: - if (!dbus_connection_send (call->connection, call->reply, NULL)) - { - jack_error ("Ran out of memory trying to queue method return"); - } - - dbus_connection_flush (call->connection); - dbus_message_unref (call->reply); - call->reply = NULL; - } - else - { - jack_error ("send_method_return() called with a NULL message," - " trying to construct a void return..."); - - if ((call->reply = dbus_message_new_method_return (call->message))) - { - goto retry_send; - } - else - { - jack_error ("Failed to construct method return!"); - } - } -} - -#define object_ptr ((struct jack_dbus_object_descriptor *)data) - -/* - * The D-Bus message handler for object path /org/jackaudio/Controller. - */ -DBusHandlerResult -jack_dbus_message_handler( - DBusConnection *connection, - DBusMessage *message, - void *data) -{ - struct jack_dbus_method_call call; - const char *interface_name; - struct jack_dbus_interface_descriptor ** interface_ptr_ptr; - - /* Check if the message is a method call. If not, ignore it. */ - if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL) - { - goto handled; - } - - /* Get the invoked method's name and make sure it's non-NULL. */ - if (!(call.method_name = dbus_message_get_member (message))) - { - jack_dbus_error( - &call, - JACK_DBUS_ERROR_UNKNOWN_METHOD, - "Received method call with empty method name"); - goto send_return; - } - - /* Initialize our data. */ - call.context = object_ptr->context; - call.connection = connection; - call.message = message; - call.reply = NULL; - - /* Check if there's an interface specified for this method call. */ - interface_name = dbus_message_get_interface (message); - if (interface_name != NULL) - { - /* Check if we can match the interface and method. - * The inteface handler functions only return false if the - * method name was unknown, otherwise they run the specified - * method and return TRUE. - */ - - interface_ptr_ptr = object_ptr->interfaces; - - while (*interface_ptr_ptr != NULL) - { - if (strcmp(interface_name, (*interface_ptr_ptr)->name) == 0) - { - if (!(*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods)) - { - break; - } - - goto send_return; - } - - interface_ptr_ptr++; - } - } - else - { - /* No interface was specified so we have to try them all. This is - * dictated by the D-Bus specification which states that method calls - * omitting the interface must never be rejected. - */ - - interface_ptr_ptr = object_ptr->interfaces; - - while (*interface_ptr_ptr != NULL) - { - if ((*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods)) - { - goto send_return; - } - - interface_ptr_ptr++; - } - } - - jack_dbus_error( - &call, - JACK_DBUS_ERROR_UNKNOWN_METHOD, - "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist", - call.method_name, - dbus_message_get_signature(message), - interface_name); - -send_return: - jack_dbus_send_method_return(&call); - -handled: - return DBUS_HANDLER_RESULT_HANDLED; -} - -void -jack_dbus_message_handler_unregister( - DBusConnection *connection, - void *data) -{ - jack_info ("Message handler was unregistered"); -} - -#undef object_ptr - -/* - * Check if the supplied method name exists in org.jackaudio.JackConfigure, - * if it does execute it and return TRUE. Otherwise return FALSE. - */ -bool -jack_dbus_run_method( - struct jack_dbus_method_call *call, - const struct jack_dbus_interface_method_descriptor * methods) -{ - const struct jack_dbus_interface_method_descriptor * method_ptr; - - method_ptr = methods; - - while (method_ptr->name != NULL) - { - if (strcmp(call->method_name, method_ptr->name) == 0) - { - method_ptr->handler(call); - return TRUE; - } - - method_ptr++; - } - - return FALSE; -} - -/* - * Read arguments from a method call. - * If the operation fails construct an error and return false, - * otherwise return true. - */ -bool -jack_dbus_get_method_args( - struct jack_dbus_method_call *call, - int type, - ...) -{ - va_list args; - DBusError error; - bool retval = true; - - va_start (args, type); - dbus_error_init (&error); - - if (!dbus_message_get_args_valist (call->message, &error, type, args)) - { - jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS, - "Invalid arguments to method \"%s\"", - call->method_name); - retval = false; - } - - dbus_error_free (&error); - va_end (args); - - return retval; -} - -/* - * Read a string and a variant argument from a method call. - * If the operation fails construct an error and return false, - * otherwise return true. - */ -bool -jack_dbus_get_method_args_string_and_variant( - struct jack_dbus_method_call *call, - const char **arg1, - message_arg_t *arg2, - int *type_ptr) -{ - DBusMessageIter iter, sub_iter; - - /* First we want a string... */ - if (dbus_message_iter_init (call->message, &iter) - && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING) - { - dbus_message_iter_get_basic (&iter, arg1); - dbus_message_iter_next (&iter); - - /* ...and then a variant. */ - if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_VARIANT) - { - dbus_message_iter_recurse (&iter, &sub_iter); - dbus_message_iter_get_basic (&sub_iter, arg2); - *type_ptr = dbus_message_iter_get_arg_type (&sub_iter); - - /* Got what we wanted. */ - return true; - } - } - - jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS, - "Invalid arguments to method \"%s\"", - call->method_name); - - return false; -} - -/* - * Append a variant type to a D-Bus message. - * Return false if something fails, true otherwise. - */ -bool -jack_dbus_message_append_variant( - DBusMessageIter *iter, - int type, - const char *signature, - message_arg_t *arg) -{ - DBusMessageIter sub_iter; - - /* Open a variant container. */ - if (!dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, signature, &sub_iter)) - { - goto fail; - } - - /* Append the supplied value. */ - if (!dbus_message_iter_append_basic (&sub_iter, type, (const void *) arg)) - { - dbus_message_iter_close_container (iter, &sub_iter); - goto fail; - } - - /* Close the container. */ - if (!dbus_message_iter_close_container (iter, &sub_iter)) - { - goto fail; - } - - return true; - -fail: - return false; -} - -/* - * Construct an empty method return message. - * - * The operation can only fail due to lack of memory, in which case - * there's no sense in trying to construct an error return. Instead, - * call->reply will be set to NULL and handled in send_method_return(). - */ -void -jack_dbus_construct_method_return_empty( - struct jack_dbus_method_call * call) -{ - call->reply = dbus_message_new_method_return (call->message); - - if (call->reply == NULL) - { - jack_error ("Ran out of memory trying to construct method return"); - } -} - -/* - * Construct a method return which holds a single argument or, if - * the type parameter is DBUS_TYPE_INVALID, no arguments at all - * (a void message). - * - * The operation can only fail due to lack of memory, in which case - * there's no sense in trying to construct an error return. Instead, - * call->reply will be set to NULL and handled in send_method_return(). - */ -void -jack_dbus_construct_method_return_single( - struct jack_dbus_method_call *call, - int type, - message_arg_t arg) -{ - DBusMessageIter iter; - call->reply = dbus_message_new_method_return (call->message); - - if (call->reply == NULL) - { - goto fail_no_mem; - } - - /* Void method return requested by caller. */ - if (type == DBUS_TYPE_INVALID) - { - return; - } - - /* Prevent crash on NULL input string. */ - else if (type == DBUS_TYPE_STRING && arg.string == NULL) - { - arg.string = ""; - } - - dbus_message_iter_init_append (call->reply, &iter); - - if (!dbus_message_iter_append_basic (&iter, type, (const void *) &arg)) - { - dbus_message_unref (call->reply); - call->reply = NULL; - goto fail_no_mem; - } - - return; - -fail_no_mem: - jack_error ("Ran out of memory trying to construct method return"); -} - -/* - * Construct a method return which holds an array of strings. - * - * The operation can only fail due to lack of memory, in which case - * there's no sense in trying to construct an error return. Instead, - * call->reply will be set to NULL and handled in send_method_return(). - */ -void -jack_dbus_construct_method_return_array_of_strings( - struct jack_dbus_method_call *call, - unsigned int num_members, - const char **array) -{ - DBusMessageIter iter, sub_iter; - unsigned int i; - - call->reply = dbus_message_new_method_return (call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append (call->reply, &iter); - - if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter)) - { - goto fail_unref; - } - - for (i = 0; i < num_members; ++i) - { - if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, (const void *) &array[i])) - { - dbus_message_iter_close_container (&iter, &sub_iter); - goto fail_unref; - } - } - - if (!dbus_message_iter_close_container (&iter, &sub_iter)) - { - goto fail_unref; - } - - return; - -fail_unref: - dbus_message_unref (call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -void -jack_dbus_info_callback(const char *msg) -{ - time_t timestamp; - char timestamp_str[26]; - - time(×tamp); - ctime_r(×tamp, timestamp_str); - timestamp_str[24] = 0; - - fprintf(g_logfile, "%s: %s\n", timestamp_str, msg); - fflush(g_logfile); -} - -void -jack_dbus_error_callback(const char *msg) -{ - time_t timestamp; - char timestamp_str[26]; - - time(×tamp); - ctime_r(×tamp, timestamp_str); - timestamp_str[24] = 0; - - fprintf(g_logfile, "%s: ERROR: %s\n", timestamp_str, msg); - fflush(g_logfile); -} - -bool -ensure_dir_exist(const char *dirname, int mode) -{ - struct stat st; - if (stat(dirname, &st) != 0) - { - if (errno == ENOENT) - { - printf("Directory \"%s\" does not exist. Creating...\n", dirname); - if (mkdir(dirname, mode) != 0) - { - fprintf(stderr, "Failed to create \"%s\" directory: %d (%s)\n", dirname, errno, strerror(errno)); - return false; - } - } - else - { - fprintf(stderr, "Failed to stat \"%s\": %d (%s)\n", dirname, errno, strerror(errno)); - return false; - } - } - else - { - if (!S_ISDIR(st.st_mode)) - { - fprintf(stderr, "\"%s\" exists but is not directory.\n", dirname); - return false; - } - } - return true; -} - -char * -pathname_cat(const char *pathname_a, const char *pathname_b) -{ - char *pathname; - int pathname_a_len, pathname_b_len, pathname_len; - pathname_a_len = strlen(pathname_a); - pathname_b_len = strlen(pathname_b); - pathname = malloc(pathname_a_len + pathname_b_len + 1); - if (pathname == NULL) - { - fprintf(stderr, "Out of memory\n"); - return NULL; - } - memcpy(pathname, pathname_a, pathname_a_len); - memcpy(pathname + pathname_a_len, pathname_b, pathname_b_len); - pathname_len = pathname_a_len + pathname_b_len; - pathname[pathname_len] = 0; - return pathname; -} - -bool -paths_init() -{ - const char *home_dir, *xdg_config_home, *xdg_log_home; - - home_dir = getenv("HOME"); - if (home_dir == NULL) - { - fprintf(stderr, "Environment variable HOME not set\n"); - goto fail; - } - - xdg_config_home = getenv("XDG_CONFIG_HOME"); - if (xdg_config_home == NULL) - { - if (!(xdg_config_home = pathname_cat(home_dir, DEFAULT_XDG_CONFIG))) goto fail; - } - - if (!(xdg_log_home = pathname_cat(home_dir, DEFAULT_XDG_LOG))) goto fail; - - if (!(g_jackdbus_config_dir = pathname_cat(xdg_config_home, JACKDBUS_DIR))) goto fail; - if (!(g_jackdbus_log_dir = pathname_cat(xdg_log_home, JACKDBUS_DIR))) goto fail; - - if (!ensure_dir_exist(xdg_config_home, 0700)) - { - goto fail; - } - - if (!ensure_dir_exist(xdg_log_home, 0700)) - { - goto fail; - } - - if (!ensure_dir_exist(g_jackdbus_config_dir, 0700)) - { - free(g_jackdbus_config_dir); - goto fail; - } - g_jackdbus_config_dir_len = strlen(g_jackdbus_config_dir); - - if (!ensure_dir_exist(g_jackdbus_log_dir, 0700)) - { - free(g_jackdbus_log_dir); - goto fail; - } - g_jackdbus_log_dir_len = strlen(g_jackdbus_log_dir); - - return true; - -fail: - return false; -} - -void -paths_uninit() -{ - free(g_jackdbus_config_dir); - free(g_jackdbus_log_dir); -} - -int -log_init() -{ - char *log_filename; - size_t log_len; - - log_len = strlen(JACKDBUS_LOG); - - log_filename = malloc(g_jackdbus_log_dir_len + log_len + 1); - if (log_filename == NULL) - { - fprintf(stderr, "Out of memory\n"); - return FALSE; - } - - memcpy(log_filename, g_jackdbus_log_dir, g_jackdbus_log_dir_len); - memcpy(log_filename + g_jackdbus_log_dir_len, JACKDBUS_LOG, log_len); - log_filename[g_jackdbus_log_dir_len + log_len] = 0; - - g_logfile = fopen(log_filename, "a"); - if (g_logfile == NULL) - { - fprintf(stderr, "Cannot open jackdbus log file \"%s\": %d (%s)\n", log_filename, errno, strerror(errno)); - free(log_filename); - return FALSE; - } - - free(log_filename); - - return TRUE; -} - -void -log_uninit() -{ - fclose(g_logfile); -} - -void -jack_dbus_error( - void *dbus_call_context_ptr, - const char *error_name, - const char *format, - ...) -{ - va_list ap; - char buffer[300]; - - va_start(ap, format); - - vsnprintf(buffer, sizeof(buffer), format, ap); - - jack_error_callback(buffer); - if (dbus_call_context_ptr != NULL) - { - ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = dbus_message_new_error( - ((struct jack_dbus_method_call *)dbus_call_context_ptr)->message, - error_name, - buffer); - } - - va_end(ap); -} - -int -main (int argc, char **argv) -{ - DBusError error; - int ret; - void *controller_ptr; - - if (!jack_controller_settings_init()) - { - ret = 1; - goto fail; - } - - if (argc != 2 || strcmp(argv[1], "auto") != 0) - { - ret = 0; - fprintf( - stderr, - "jackdbus should be auto-executed by D-Bus message bus daemon.\n" - "If you want to run it manually anyway, specify \"auto\" as only parameter\n"); - goto fail_uninit_xml; - } - - if (!paths_init()) - { - ret = 1; - goto fail_uninit_xml; - } - - if (!log_init()) - { - ret = 1; - goto fail_uninit_paths; - } - -#if !defined(DISABLE_SIGNAL_MAGIC) - jackctl_setup_signals(0); -#endif - - jack_set_error_function(jack_dbus_error_callback); - jack_set_info_function(jack_dbus_info_callback); - - jack_info("------------------"); - jack_info("Controller activated. Version %s (%s)", jack_get_version_string(), JACK_SVNREVISION); - - if (!dbus_threads_init_default()) - { - jack_error("dbus_threads_init_default() failed"); - ret = 1; - goto fail_uninit_log; - } - - dbus_error_init (&error); - g_connection = dbus_bus_get (DBUS_BUS_SESSION, &error); - if (dbus_error_is_set (&error)) - { - jack_error("Cannot connect to D-Bus session bus: %s", error.message); - ret = 1; - goto fail_uninit_log; - } - - ret = dbus_bus_request_name( - g_connection, - "org.jackaudio.service", - DBUS_NAME_FLAG_DO_NOT_QUEUE, - &error); - if (ret == -1) - { - jack_error("Cannot request service name: %s", error.message); - dbus_error_free(&error); - ret = 1; - goto fail_unref_connection; - } - else if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS) - { - jack_error("Requested D-Bus service name already exists"); - ret = 1; - goto fail_unref_connection; - } - - controller_ptr = jack_controller_create(g_connection); - - if (controller_ptr == NULL) - { - ret = 1; - goto fail_unref_connection; - } - - jack_info("Listening for D-Bus messages"); - - g_exit_command = FALSE; - while (!g_exit_command && dbus_connection_read_write_dispatch (g_connection, 200)); - - jack_controller_destroy(controller_ptr); - - jack_info("Controller deactivated."); - - ret = 0; - -fail_unref_connection: - dbus_connection_unref(g_connection); - -fail_uninit_log: - log_uninit(); - -fail_uninit_paths: - paths_uninit(); - -fail_uninit_xml: - jack_controller_settings_uninit(); - -fail: - return ret; -} -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - Copyright (C) 2007-2008 Juuso Alasuutari - Copyright (C) 2008 Marc-Olivier Barre - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" - -#include "jackdbus.h" -#include "controller.h" -#include "jack/jack.h" -#include "jack/jslist.h" -#include "jack/control.h" - -FILE *g_logfile; -char *g_jackdbus_config_dir; -size_t g_jackdbus_config_dir_len; /* without terminating '\0' char */ -char *g_jackdbus_log_dir; -size_t g_jackdbus_log_dir_len; /* without terminating '\0' char */ -int g_exit_command; -DBusConnection *g_connection; - -void -jack_dbus_send_signal( - const char *sender_object_path, - const char *iface, - const char *signal_name, - int first_arg_type, - ...) -{ - DBusMessage *message_ptr; - va_list ap; - - va_start(ap, first_arg_type); - - message_ptr = dbus_message_new_signal(sender_object_path, iface, signal_name); - if (message_ptr == NULL) - { - jack_error("dbus_message_new_signal() failed."); - goto exit; - } - - if (!dbus_message_append_args_valist(message_ptr, first_arg_type, ap)) - { - jack_error("dbus_message_append_args_valist() failed."); - goto unref; - } - - /* Add message to outgoing message queue */ - if (!dbus_connection_send(g_connection, message_ptr, NULL)) - { - jack_error("dbus_connection_send() failed."); - goto unref; - } - -unref: - dbus_message_unref(message_ptr); - -exit: - va_end(ap); -} - -/* - * Send a method return. - * - * If call->reply is NULL (i.e. a message construct method failed - * due to lack of memory) attempt to send a void method return. - */ -static -void -jack_dbus_send_method_return( - struct jack_dbus_method_call * call) -{ - if (call->reply) - { - retry_send: - if (!dbus_connection_send (call->connection, call->reply, NULL)) - { - jack_error ("Ran out of memory trying to queue method return"); - } - - dbus_connection_flush (call->connection); - dbus_message_unref (call->reply); - call->reply = NULL; - } - else - { - jack_error ("send_method_return() called with a NULL message," - " trying to construct a void return..."); - - if ((call->reply = dbus_message_new_method_return (call->message))) - { - goto retry_send; - } - else - { - jack_error ("Failed to construct method return!"); - } - } -} - -#define object_ptr ((struct jack_dbus_object_descriptor *)data) - -/* - * The D-Bus message handler for object path /org/jackaudio/Controller. - */ -DBusHandlerResult -jack_dbus_message_handler( - DBusConnection *connection, - DBusMessage *message, - void *data) -{ - struct jack_dbus_method_call call; - const char *interface_name; - struct jack_dbus_interface_descriptor ** interface_ptr_ptr; - - /* Check if the message is a method call. If not, ignore it. */ - if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL) - { - goto handled; - } - - /* Get the invoked method's name and make sure it's non-NULL. */ - if (!(call.method_name = dbus_message_get_member (message))) - { - jack_dbus_error( - &call, - JACK_DBUS_ERROR_UNKNOWN_METHOD, - "Received method call with empty method name"); - goto send_return; - } - - /* Initialize our data. */ - call.context = object_ptr->context; - call.connection = connection; - call.message = message; - call.reply = NULL; - - /* Check if there's an interface specified for this method call. */ - interface_name = dbus_message_get_interface (message); - if (interface_name != NULL) - { - /* Check if we can match the interface and method. - * The inteface handler functions only return false if the - * method name was unknown, otherwise they run the specified - * method and return TRUE. - */ - - interface_ptr_ptr = object_ptr->interfaces; - - while (*interface_ptr_ptr != NULL) - { - if (strcmp(interface_name, (*interface_ptr_ptr)->name) == 0) - { - if (!(*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods)) - { - break; - } - - goto send_return; - } - - interface_ptr_ptr++; - } - } - else - { - /* No interface was specified so we have to try them all. This is - * dictated by the D-Bus specification which states that method calls - * omitting the interface must never be rejected. - */ - - interface_ptr_ptr = object_ptr->interfaces; - - while (*interface_ptr_ptr != NULL) - { - if ((*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods)) - { - goto send_return; - } - - interface_ptr_ptr++; - } - } - - jack_dbus_error( - &call, - JACK_DBUS_ERROR_UNKNOWN_METHOD, - "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist", - call.method_name, - dbus_message_get_signature(message), - interface_name); - -send_return: - jack_dbus_send_method_return(&call); - -handled: - return DBUS_HANDLER_RESULT_HANDLED; -} - -void -jack_dbus_message_handler_unregister( - DBusConnection *connection, - void *data) -{ - jack_info ("Message handler was unregistered"); -} - -#undef object_ptr - -/* - * Check if the supplied method name exists in org.jackaudio.JackConfigure, - * if it does execute it and return TRUE. Otherwise return FALSE. - */ -bool -jack_dbus_run_method( - struct jack_dbus_method_call *call, - const struct jack_dbus_interface_method_descriptor * methods) -{ - const struct jack_dbus_interface_method_descriptor * method_ptr; - - method_ptr = methods; - - while (method_ptr->name != NULL) - { - if (strcmp(call->method_name, method_ptr->name) == 0) - { - method_ptr->handler(call); - return TRUE; - } - - method_ptr++; - } - - return FALSE; -} - -/* - * Read arguments from a method call. - * If the operation fails construct an error and return false, - * otherwise return true. - */ -bool -jack_dbus_get_method_args( - struct jack_dbus_method_call *call, - int type, - ...) -{ - va_list args; - DBusError error; - bool retval = true; - - va_start (args, type); - dbus_error_init (&error); - - if (!dbus_message_get_args_valist (call->message, &error, type, args)) - { - jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS, - "Invalid arguments to method \"%s\"", - call->method_name); - retval = false; - } - - dbus_error_free (&error); - va_end (args); - - return retval; -} - -/* - * Read a string and a variant argument from a method call. - * If the operation fails construct an error and return false, - * otherwise return true. - */ -bool -jack_dbus_get_method_args_string_and_variant( - struct jack_dbus_method_call *call, - const char **arg1, - message_arg_t *arg2, - int *type_ptr) -{ - DBusMessageIter iter, sub_iter; - - /* First we want a string... */ - if (dbus_message_iter_init (call->message, &iter) - && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING) - { - dbus_message_iter_get_basic (&iter, arg1); - dbus_message_iter_next (&iter); - - /* ...and then a variant. */ - if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_VARIANT) - { - dbus_message_iter_recurse (&iter, &sub_iter); - dbus_message_iter_get_basic (&sub_iter, arg2); - *type_ptr = dbus_message_iter_get_arg_type (&sub_iter); - - /* Got what we wanted. */ - return true; - } - } - - jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS, - "Invalid arguments to method \"%s\"", - call->method_name); - - return false; -} - -/* - * Append a variant type to a D-Bus message. - * Return false if something fails, true otherwise. - */ -bool -jack_dbus_message_append_variant( - DBusMessageIter *iter, - int type, - const char *signature, - message_arg_t *arg) -{ - DBusMessageIter sub_iter; - - /* Open a variant container. */ - if (!dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, signature, &sub_iter)) - { - goto fail; - } - - /* Append the supplied value. */ - if (!dbus_message_iter_append_basic (&sub_iter, type, (const void *) arg)) - { - dbus_message_iter_close_container (iter, &sub_iter); - goto fail; - } - - /* Close the container. */ - if (!dbus_message_iter_close_container (iter, &sub_iter)) - { - goto fail; - } - - return true; - -fail: - return false; -} - -/* - * Construct an empty method return message. - * - * The operation can only fail due to lack of memory, in which case - * there's no sense in trying to construct an error return. Instead, - * call->reply will be set to NULL and handled in send_method_return(). - */ -void -jack_dbus_construct_method_return_empty( - struct jack_dbus_method_call * call) -{ - call->reply = dbus_message_new_method_return (call->message); - - if (call->reply == NULL) - { - jack_error ("Ran out of memory trying to construct method return"); - } -} - -/* - * Construct a method return which holds a single argument or, if - * the type parameter is DBUS_TYPE_INVALID, no arguments at all - * (a void message). - * - * The operation can only fail due to lack of memory, in which case - * there's no sense in trying to construct an error return. Instead, - * call->reply will be set to NULL and handled in send_method_return(). - */ -void -jack_dbus_construct_method_return_single( - struct jack_dbus_method_call *call, - int type, - message_arg_t arg) -{ - DBusMessageIter iter; - call->reply = dbus_message_new_method_return (call->message); - - if (call->reply == NULL) - { - goto fail_no_mem; - } - - /* Void method return requested by caller. */ - if (type == DBUS_TYPE_INVALID) - { - return; - } - - /* Prevent crash on NULL input string. */ - else if (type == DBUS_TYPE_STRING && arg.string == NULL) - { - arg.string = ""; - } - - dbus_message_iter_init_append (call->reply, &iter); - - if (!dbus_message_iter_append_basic (&iter, type, (const void *) &arg)) - { - dbus_message_unref (call->reply); - call->reply = NULL; - goto fail_no_mem; - } - - return; - -fail_no_mem: - jack_error ("Ran out of memory trying to construct method return"); -} - -/* - * Construct a method return which holds an array of strings. - * - * The operation can only fail due to lack of memory, in which case - * there's no sense in trying to construct an error return. Instead, - * call->reply will be set to NULL and handled in send_method_return(). - */ -void -jack_dbus_construct_method_return_array_of_strings( - struct jack_dbus_method_call *call, - unsigned int num_members, - const char **array) -{ - DBusMessageIter iter, sub_iter; - unsigned int i; - - call->reply = dbus_message_new_method_return (call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append (call->reply, &iter); - - if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter)) - { - goto fail_unref; - } - - for (i = 0; i < num_members; ++i) - { - if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, (const void *) &array[i])) - { - dbus_message_iter_close_container (&iter, &sub_iter); - goto fail_unref; - } - } - - if (!dbus_message_iter_close_container (&iter, &sub_iter)) - { - goto fail_unref; - } - - return; - -fail_unref: - dbus_message_unref (call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -void -jack_dbus_info_callback(const char *msg) -{ - time_t timestamp; - char timestamp_str[26]; - - time(×tamp); - ctime_r(×tamp, timestamp_str); - timestamp_str[24] = 0; - - fprintf(g_logfile, "%s: %s\n", timestamp_str, msg); - fflush(g_logfile); -} - -void -jack_dbus_error_callback(const char *msg) -{ - time_t timestamp; - char timestamp_str[26]; - - time(×tamp); - ctime_r(×tamp, timestamp_str); - timestamp_str[24] = 0; - - fprintf(g_logfile, "%s: ERROR: %s\n", timestamp_str, msg); - fflush(g_logfile); -} - -bool -ensure_dir_exist(const char *dirname, int mode) -{ - struct stat st; - if (stat(dirname, &st) != 0) - { - if (errno == ENOENT) - { - printf("Directory \"%s\" does not exist. Creating...\n", dirname); - if (mkdir(dirname, mode) != 0) - { - fprintf(stderr, "Failed to create \"%s\" directory: %d (%s)\n", dirname, errno, strerror(errno)); - return false; - } - } - else - { - fprintf(stderr, "Failed to stat \"%s\": %d (%s)\n", dirname, errno, strerror(errno)); - return false; - } - } - else - { - if (!S_ISDIR(st.st_mode)) - { - fprintf(stderr, "\"%s\" exists but is not directory.\n", dirname); - return false; - } - } - return true; -} - -char * -pathname_cat(const char *pathname_a, const char *pathname_b) -{ - char *pathname; - int pathname_a_len, pathname_b_len, pathname_len; - pathname_a_len = strlen(pathname_a); - pathname_b_len = strlen(pathname_b); - pathname = malloc(pathname_a_len + pathname_b_len + 1); - if (pathname == NULL) - { - fprintf(stderr, "Out of memory\n"); - return NULL; - } - memcpy(pathname, pathname_a, pathname_a_len); - memcpy(pathname + pathname_a_len, pathname_b, pathname_b_len); - pathname_len = pathname_a_len + pathname_b_len; - pathname[pathname_len] = 0; - return pathname; -} - -bool -paths_init() -{ - const char *home_dir, *xdg_config_home, *xdg_log_home; - - home_dir = getenv("HOME"); - if (home_dir == NULL) - { - fprintf(stderr, "Environment variable HOME not set\n"); - goto fail; - } - - xdg_config_home = getenv("XDG_CONFIG_HOME"); - if (xdg_config_home == NULL) - { - if (!(xdg_config_home = pathname_cat(home_dir, DEFAULT_XDG_CONFIG))) goto fail; - } - - if (!(xdg_log_home = pathname_cat(home_dir, DEFAULT_XDG_LOG))) goto fail; - - if (!(g_jackdbus_config_dir = pathname_cat(xdg_config_home, JACKDBUS_DIR))) goto fail; - if (!(g_jackdbus_log_dir = pathname_cat(xdg_log_home, JACKDBUS_DIR))) goto fail; - - if (!ensure_dir_exist(xdg_config_home, 0700)) - { - goto fail; - } - - if (!ensure_dir_exist(xdg_log_home, 0700)) - { - goto fail; - } - - if (!ensure_dir_exist(g_jackdbus_config_dir, 0700)) - { - free(g_jackdbus_config_dir); - goto fail; - } - g_jackdbus_config_dir_len = strlen(g_jackdbus_config_dir); - - if (!ensure_dir_exist(g_jackdbus_log_dir, 0700)) - { - free(g_jackdbus_log_dir); - goto fail; - } - g_jackdbus_log_dir_len = strlen(g_jackdbus_log_dir); - - return true; - -fail: - return false; -} - -void -paths_uninit() -{ - free(g_jackdbus_config_dir); - free(g_jackdbus_log_dir); -} - -int -log_init() -{ - char *log_filename; - size_t log_len; - - log_len = strlen(JACKDBUS_LOG); - - log_filename = malloc(g_jackdbus_log_dir_len + log_len + 1); - if (log_filename == NULL) - { - fprintf(stderr, "Out of memory\n"); - return FALSE; - } - - memcpy(log_filename, g_jackdbus_log_dir, g_jackdbus_log_dir_len); - memcpy(log_filename + g_jackdbus_log_dir_len, JACKDBUS_LOG, log_len); - log_filename[g_jackdbus_log_dir_len + log_len] = 0; - - g_logfile = fopen(log_filename, "a"); - if (g_logfile == NULL) - { - fprintf(stderr, "Cannot open jackdbus log file \"%s\": %d (%s)\n", log_filename, errno, strerror(errno)); - free(log_filename); - return FALSE; - } - - free(log_filename); - - return TRUE; -} - -void -log_uninit() -{ - fclose(g_logfile); -} - -void -jack_dbus_error( - void *dbus_call_context_ptr, - const char *error_name, - const char *format, - ...) -{ - va_list ap; - char buffer[300]; - - va_start(ap, format); - - vsnprintf(buffer, sizeof(buffer), format, ap); - - jack_error_callback(buffer); - if (dbus_call_context_ptr != NULL) - { - ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = dbus_message_new_error( - ((struct jack_dbus_method_call *)dbus_call_context_ptr)->message, - error_name, - buffer); - } - - va_end(ap); -} - -int -main (int argc, char **argv) -{ - DBusError error; - int ret; - void *controller_ptr; - - if (!jack_controller_settings_init()) - { - ret = 1; - goto fail; - } - - if (argc != 2 || strcmp(argv[1], "auto") != 0) - { - ret = 0; - fprintf( - stderr, - "jackdbus should be auto-executed by D-Bus message bus daemon.\n" - "If you want to run it manually anyway, specify \"auto\" as only parameter\n"); - goto fail_uninit_xml; - } - - if (!paths_init()) - { - ret = 1; - goto fail_uninit_xml; - } - - if (!log_init()) - { - ret = 1; - goto fail_uninit_paths; - } - -#if !defined(DISABLE_SIGNAL_MAGIC) - jackctl_setup_signals(0); -#endif - - jack_set_error_function(jack_dbus_error_callback); - jack_set_info_function(jack_dbus_info_callback); - - jack_info("------------------"); - jack_info("Controller activated. Version %s (%s)", jack_get_version_string(), JACK_SVNREVISION); - - if (!dbus_threads_init_default()) - { - jack_error("dbus_threads_init_default() failed"); - ret = 1; - goto fail_uninit_log; - } - - dbus_error_init (&error); - g_connection = dbus_bus_get (DBUS_BUS_SESSION, &error); - if (dbus_error_is_set (&error)) - { - jack_error("Cannot connect to D-Bus session bus: %s", error.message); - ret = 1; - goto fail_uninit_log; - } - - ret = dbus_bus_request_name( - g_connection, - "org.jackaudio.service", - DBUS_NAME_FLAG_DO_NOT_QUEUE, - &error); - if (ret == -1) - { - jack_error("Cannot request service name: %s", error.message); - dbus_error_free(&error); - ret = 1; - goto fail_unref_connection; - } - else if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS) - { - jack_error("Requested D-Bus service name already exists"); - ret = 1; - goto fail_unref_connection; - } - - controller_ptr = jack_controller_create(g_connection); - - if (controller_ptr == NULL) - { - ret = 1; - goto fail_unref_connection; - } - - jack_info("Listening for D-Bus messages"); - - g_exit_command = FALSE; - while (!g_exit_command && dbus_connection_read_write_dispatch (g_connection, 200)); - - jack_controller_destroy(controller_ptr); - - jack_info("Controller deactivated."); - - ret = 0; - -fail_unref_connection: - dbus_connection_unref(g_connection); - -fail_uninit_log: - log_uninit(); - -fail_uninit_paths: - paths_uninit(); - -fail_uninit_xml: - jack_controller_settings_uninit(); - -fail: - return ret; -} -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - Copyright (C) 2007-2008 Juuso Alasuutari - Copyright (C) 2008 Marc-Olivier Barre - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" - -#include "jackdbus.h" -#include "controller.h" -#include "jack/jack.h" -#include "jack/jslist.h" -#include "jack/control.h" - -FILE *g_logfile; -char *g_jackdbus_config_dir; -size_t g_jackdbus_config_dir_len; /* without terminating '\0' char */ -char *g_jackdbus_log_dir; -size_t g_jackdbus_log_dir_len; /* without terminating '\0' char */ -int g_exit_command; -DBusConnection *g_connection; - -void -jack_dbus_send_signal( - const char *sender_object_path, - const char *iface, - const char *signal_name, - int first_arg_type, - ...) -{ - DBusMessage *message_ptr; - va_list ap; - - va_start(ap, first_arg_type); - - message_ptr = dbus_message_new_signal(sender_object_path, iface, signal_name); - if (message_ptr == NULL) - { - jack_error("dbus_message_new_signal() failed."); - goto exit; - } - - if (!dbus_message_append_args_valist(message_ptr, first_arg_type, ap)) - { - jack_error("dbus_message_append_args_valist() failed."); - goto unref; - } - - /* Add message to outgoing message queue */ - if (!dbus_connection_send(g_connection, message_ptr, NULL)) - { - jack_error("dbus_connection_send() failed."); - goto unref; - } - -unref: - dbus_message_unref(message_ptr); - -exit: - va_end(ap); -} - -/* - * Send a method return. - * - * If call->reply is NULL (i.e. a message construct method failed - * due to lack of memory) attempt to send a void method return. - */ -static -void -jack_dbus_send_method_return( - struct jack_dbus_method_call * call) -{ - if (call->reply) - { - retry_send: - if (!dbus_connection_send (call->connection, call->reply, NULL)) - { - jack_error ("Ran out of memory trying to queue method return"); - } - - dbus_connection_flush (call->connection); - dbus_message_unref (call->reply); - call->reply = NULL; - } - else - { - jack_error ("send_method_return() called with a NULL message," - " trying to construct a void return..."); - - if ((call->reply = dbus_message_new_method_return (call->message))) - { - goto retry_send; - } - else - { - jack_error ("Failed to construct method return!"); - } - } -} - -#define object_ptr ((struct jack_dbus_object_descriptor *)data) - -/* - * The D-Bus message handler for object path /org/jackaudio/Controller. - */ -DBusHandlerResult -jack_dbus_message_handler( - DBusConnection *connection, - DBusMessage *message, - void *data) -{ - struct jack_dbus_method_call call; - const char *interface_name; - struct jack_dbus_interface_descriptor ** interface_ptr_ptr; - - /* Check if the message is a method call. If not, ignore it. */ - if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL) - { - goto handled; - } - - /* Get the invoked method's name and make sure it's non-NULL. */ - if (!(call.method_name = dbus_message_get_member (message))) - { - jack_dbus_error( - &call, - JACK_DBUS_ERROR_UNKNOWN_METHOD, - "Received method call with empty method name"); - goto send_return; - } - - /* Initialize our data. */ - call.context = object_ptr->context; - call.connection = connection; - call.message = message; - call.reply = NULL; - - /* Check if there's an interface specified for this method call. */ - interface_name = dbus_message_get_interface (message); - if (interface_name != NULL) - { - /* Check if we can match the interface and method. - * The inteface handler functions only return false if the - * method name was unknown, otherwise they run the specified - * method and return TRUE. - */ - - interface_ptr_ptr = object_ptr->interfaces; - - while (*interface_ptr_ptr != NULL) - { - if (strcmp(interface_name, (*interface_ptr_ptr)->name) == 0) - { - if (!(*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods)) - { - break; - } - - goto send_return; - } - - interface_ptr_ptr++; - } - } - else - { - /* No interface was specified so we have to try them all. This is - * dictated by the D-Bus specification which states that method calls - * omitting the interface must never be rejected. - */ - - interface_ptr_ptr = object_ptr->interfaces; - - while (*interface_ptr_ptr != NULL) - { - if ((*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods)) - { - goto send_return; - } - - interface_ptr_ptr++; - } - } - - jack_dbus_error( - &call, - JACK_DBUS_ERROR_UNKNOWN_METHOD, - "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist", - call.method_name, - dbus_message_get_signature(message), - interface_name); - -send_return: - jack_dbus_send_method_return(&call); - -handled: - return DBUS_HANDLER_RESULT_HANDLED; -} - -void -jack_dbus_message_handler_unregister( - DBusConnection *connection, - void *data) -{ - jack_info ("Message handler was unregistered"); -} - -#undef object_ptr - -/* - * Check if the supplied method name exists in org.jackaudio.JackConfigure, - * if it does execute it and return TRUE. Otherwise return FALSE. - */ -bool -jack_dbus_run_method( - struct jack_dbus_method_call *call, - const struct jack_dbus_interface_method_descriptor * methods) -{ - const struct jack_dbus_interface_method_descriptor * method_ptr; - - method_ptr = methods; - - while (method_ptr->name != NULL) - { - if (strcmp(call->method_name, method_ptr->name) == 0) - { - method_ptr->handler(call); - return TRUE; - } - - method_ptr++; - } - - return FALSE; -} - -/* - * Read arguments from a method call. - * If the operation fails construct an error and return false, - * otherwise return true. - */ -bool -jack_dbus_get_method_args( - struct jack_dbus_method_call *call, - int type, - ...) -{ - va_list args; - DBusError error; - bool retval = true; - - va_start (args, type); - dbus_error_init (&error); - - if (!dbus_message_get_args_valist (call->message, &error, type, args)) - { - jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS, - "Invalid arguments to method \"%s\"", - call->method_name); - retval = false; - } - - dbus_error_free (&error); - va_end (args); - - return retval; -} - -/* - * Read a string and a variant argument from a method call. - * If the operation fails construct an error and return false, - * otherwise return true. - */ -bool -jack_dbus_get_method_args_string_and_variant( - struct jack_dbus_method_call *call, - const char **arg1, - message_arg_t *arg2, - int *type_ptr) -{ - DBusMessageIter iter, sub_iter; - - /* First we want a string... */ - if (dbus_message_iter_init (call->message, &iter) - && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING) - { - dbus_message_iter_get_basic (&iter, arg1); - dbus_message_iter_next (&iter); - - /* ...and then a variant. */ - if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_VARIANT) - { - dbus_message_iter_recurse (&iter, &sub_iter); - dbus_message_iter_get_basic (&sub_iter, arg2); - *type_ptr = dbus_message_iter_get_arg_type (&sub_iter); - - /* Got what we wanted. */ - return true; - } - } - - jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS, - "Invalid arguments to method \"%s\"", - call->method_name); - - return false; -} - -/* - * Append a variant type to a D-Bus message. - * Return false if something fails, true otherwise. - */ -bool -jack_dbus_message_append_variant( - DBusMessageIter *iter, - int type, - const char *signature, - message_arg_t *arg) -{ - DBusMessageIter sub_iter; - - /* Open a variant container. */ - if (!dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, signature, &sub_iter)) - { - goto fail; - } - - /* Append the supplied value. */ - if (!dbus_message_iter_append_basic (&sub_iter, type, (const void *) arg)) - { - dbus_message_iter_close_container (iter, &sub_iter); - goto fail; - } - - /* Close the container. */ - if (!dbus_message_iter_close_container (iter, &sub_iter)) - { - goto fail; - } - - return true; - -fail: - return false; -} - -/* - * Construct an empty method return message. - * - * The operation can only fail due to lack of memory, in which case - * there's no sense in trying to construct an error return. Instead, - * call->reply will be set to NULL and handled in send_method_return(). - */ -void -jack_dbus_construct_method_return_empty( - struct jack_dbus_method_call * call) -{ - call->reply = dbus_message_new_method_return (call->message); - - if (call->reply == NULL) - { - jack_error ("Ran out of memory trying to construct method return"); - } -} - -/* - * Construct a method return which holds a single argument or, if - * the type parameter is DBUS_TYPE_INVALID, no arguments at all - * (a void message). - * - * The operation can only fail due to lack of memory, in which case - * there's no sense in trying to construct an error return. Instead, - * call->reply will be set to NULL and handled in send_method_return(). - */ -void -jack_dbus_construct_method_return_single( - struct jack_dbus_method_call *call, - int type, - message_arg_t arg) -{ - DBusMessageIter iter; - call->reply = dbus_message_new_method_return (call->message); - - if (call->reply == NULL) - { - goto fail_no_mem; - } - - /* Void method return requested by caller. */ - if (type == DBUS_TYPE_INVALID) - { - return; - } - - /* Prevent crash on NULL input string. */ - else if (type == DBUS_TYPE_STRING && arg.string == NULL) - { - arg.string = ""; - } - - dbus_message_iter_init_append (call->reply, &iter); - - if (!dbus_message_iter_append_basic (&iter, type, (const void *) &arg)) - { - dbus_message_unref (call->reply); - call->reply = NULL; - goto fail_no_mem; - } - - return; - -fail_no_mem: - jack_error ("Ran out of memory trying to construct method return"); -} - -/* - * Construct a method return which holds an array of strings. - * - * The operation can only fail due to lack of memory, in which case - * there's no sense in trying to construct an error return. Instead, - * call->reply will be set to NULL and handled in send_method_return(). - */ -void -jack_dbus_construct_method_return_array_of_strings( - struct jack_dbus_method_call *call, - unsigned int num_members, - const char **array) -{ - DBusMessageIter iter, sub_iter; - unsigned int i; - - call->reply = dbus_message_new_method_return (call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append (call->reply, &iter); - - if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter)) - { - goto fail_unref; - } - - for (i = 0; i < num_members; ++i) - { - if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, (const void *) &array[i])) - { - dbus_message_iter_close_container (&iter, &sub_iter); - goto fail_unref; - } - } - - if (!dbus_message_iter_close_container (&iter, &sub_iter)) - { - goto fail_unref; - } - - return; - -fail_unref: - dbus_message_unref (call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -void -jack_dbus_info_callback(const char *msg) -{ - time_t timestamp; - char timestamp_str[26]; - - time(×tamp); - ctime_r(×tamp, timestamp_str); - timestamp_str[24] = 0; - - fprintf(g_logfile, "%s: %s\n", timestamp_str, msg); - fflush(g_logfile); -} - -void -jack_dbus_error_callback(const char *msg) -{ - time_t timestamp; - char timestamp_str[26]; - - time(×tamp); - ctime_r(×tamp, timestamp_str); - timestamp_str[24] = 0; - - fprintf(g_logfile, "%s: ERROR: %s\n", timestamp_str, msg); - fflush(g_logfile); -} - -bool -ensure_dir_exist(const char *dirname, int mode) -{ - struct stat st; - if (stat(dirname, &st) != 0) - { - if (errno == ENOENT) - { - printf("Directory \"%s\" does not exist. Creating...\n", dirname); - if (mkdir(dirname, mode) != 0) - { - fprintf(stderr, "Failed to create \"%s\" directory: %d (%s)\n", dirname, errno, strerror(errno)); - return false; - } - } - else - { - fprintf(stderr, "Failed to stat \"%s\": %d (%s)\n", dirname, errno, strerror(errno)); - return false; - } - } - else - { - if (!S_ISDIR(st.st_mode)) - { - fprintf(stderr, "\"%s\" exists but is not directory.\n", dirname); - return false; - } - } - return true; -} - -char * -pathname_cat(const char *pathname_a, const char *pathname_b) -{ - char *pathname; - int pathname_a_len, pathname_b_len, pathname_len; - pathname_a_len = strlen(pathname_a); - pathname_b_len = strlen(pathname_b); - pathname = malloc(pathname_a_len + pathname_b_len + 1); - if (pathname == NULL) - { - fprintf(stderr, "Out of memory\n"); - return NULL; - } - memcpy(pathname, pathname_a, pathname_a_len); - memcpy(pathname + pathname_a_len, pathname_b, pathname_b_len); - pathname_len = pathname_a_len + pathname_b_len; - pathname[pathname_len] = 0; - return pathname; -} - -bool -paths_init() -{ - const char *home_dir, *xdg_config_home, *xdg_log_home; - - home_dir = getenv("HOME"); - if (home_dir == NULL) - { - fprintf(stderr, "Environment variable HOME not set\n"); - goto fail; - } - - xdg_config_home = getenv("XDG_CONFIG_HOME"); - if (xdg_config_home == NULL) - { - if (!(xdg_config_home = pathname_cat(home_dir, DEFAULT_XDG_CONFIG))) goto fail; - } - - if (!(xdg_log_home = pathname_cat(home_dir, DEFAULT_XDG_LOG))) goto fail; - - if (!(g_jackdbus_config_dir = pathname_cat(xdg_config_home, JACKDBUS_DIR))) goto fail; - if (!(g_jackdbus_log_dir = pathname_cat(xdg_log_home, JACKDBUS_DIR))) goto fail; - - if (!ensure_dir_exist(xdg_config_home, 0700)) - { - goto fail; - } - - if (!ensure_dir_exist(xdg_log_home, 0700)) - { - goto fail; - } - - if (!ensure_dir_exist(g_jackdbus_config_dir, 0700)) - { - free(g_jackdbus_config_dir); - goto fail; - } - g_jackdbus_config_dir_len = strlen(g_jackdbus_config_dir); - - if (!ensure_dir_exist(g_jackdbus_log_dir, 0700)) - { - free(g_jackdbus_log_dir); - goto fail; - } - g_jackdbus_log_dir_len = strlen(g_jackdbus_log_dir); - - return true; - -fail: - return false; -} - -void -paths_uninit() -{ - free(g_jackdbus_config_dir); - free(g_jackdbus_log_dir); -} - -int -log_init() -{ - char *log_filename; - size_t log_len; - - log_len = strlen(JACKDBUS_LOG); - - log_filename = malloc(g_jackdbus_log_dir_len + log_len + 1); - if (log_filename == NULL) - { - fprintf(stderr, "Out of memory\n"); - return FALSE; - } - - memcpy(log_filename, g_jackdbus_log_dir, g_jackdbus_log_dir_len); - memcpy(log_filename + g_jackdbus_log_dir_len, JACKDBUS_LOG, log_len); - log_filename[g_jackdbus_log_dir_len + log_len] = 0; - - g_logfile = fopen(log_filename, "a"); - if (g_logfile == NULL) - { - fprintf(stderr, "Cannot open jackdbus log file \"%s\": %d (%s)\n", log_filename, errno, strerror(errno)); - free(log_filename); - return FALSE; - } - - free(log_filename); - - return TRUE; -} - -void -log_uninit() -{ - fclose(g_logfile); -} - -void -jack_dbus_error( - void *dbus_call_context_ptr, - const char *error_name, - const char *format, - ...) -{ - va_list ap; - char buffer[300]; - - va_start(ap, format); - - vsnprintf(buffer, sizeof(buffer), format, ap); - - jack_error_callback(buffer); - if (dbus_call_context_ptr != NULL) - { - ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = dbus_message_new_error( - ((struct jack_dbus_method_call *)dbus_call_context_ptr)->message, - error_name, - buffer); - } - - va_end(ap); -} - -int -main (int argc, char **argv) -{ - DBusError error; - int ret; - void *controller_ptr; - - if (!jack_controller_settings_init()) - { - ret = 1; - goto fail; - } - - if (argc != 2 || strcmp(argv[1], "auto") != 0) - { - ret = 0; - fprintf( - stderr, - "jackdbus should be auto-executed by D-Bus message bus daemon.\n" - "If you want to run it manually anyway, specify \"auto\" as only parameter\n"); - goto fail_uninit_xml; - } - - if (!paths_init()) - { - ret = 1; - goto fail_uninit_xml; - } - - if (!log_init()) - { - ret = 1; - goto fail_uninit_paths; - } - -#if !defined(DISABLE_SIGNAL_MAGIC) - jackctl_setup_signals(0); -#endif - - jack_set_error_function(jack_dbus_error_callback); - jack_set_info_function(jack_dbus_info_callback); - - jack_info("------------------"); - jack_info("Controller activated. Version %s (%s)", jack_get_version_string(), JACK_SVNREVISION); - - if (!dbus_threads_init_default()) - { - jack_error("dbus_threads_init_default() failed"); - ret = 1; - goto fail_uninit_log; - } - - dbus_error_init (&error); - g_connection = dbus_bus_get (DBUS_BUS_SESSION, &error); - if (dbus_error_is_set (&error)) - { - jack_error("Cannot connect to D-Bus session bus: %s", error.message); - ret = 1; - goto fail_uninit_log; - } - - ret = dbus_bus_request_name( - g_connection, - "org.jackaudio.service", - DBUS_NAME_FLAG_DO_NOT_QUEUE, - &error); - if (ret == -1) - { - jack_error("Cannot request service name: %s", error.message); - dbus_error_free(&error); - ret = 1; - goto fail_unref_connection; - } - else if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS) - { - jack_error("Requested D-Bus service name already exists"); - ret = 1; - goto fail_unref_connection; - } - - controller_ptr = jack_controller_create(g_connection); - - if (controller_ptr == NULL) - { - ret = 1; - goto fail_unref_connection; - } - - jack_info("Listening for D-Bus messages"); - - g_exit_command = FALSE; - while (!g_exit_command && dbus_connection_read_write_dispatch (g_connection, 200)); - - jack_controller_destroy(controller_ptr); - - jack_info("Controller deactivated."); - - ret = 0; - -fail_unref_connection: - dbus_connection_unref(g_connection); - -fail_uninit_log: - log_uninit(); - -fail_uninit_paths: - paths_uninit(); - -fail_uninit_xml: - jack_controller_settings_uninit(); - -fail: - return ret; -} diff --git a/linux/dbus/xml.c b/linux/dbus/xml.c index ed5aa9ae..c40952ce 100644 --- a/linux/dbus/xml.c +++ b/linux/dbus/xml.c @@ -311,942 +311,3 @@ jack_controller_settings_save_driver_options( { return jack_controller_settings_save_options(context, jackctl_driver_get_parameters(driver), dbus_call_context_ptr); } -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include - -#include "controller_internal.h" - -void -jack_controller_settings_set_bool_option( - const char *value_str, - int *value_ptr) -{ - if (strcmp(value_str, "true") == 0) - { - *value_ptr = true; - } - else if (strcmp(value_str, "false") == 0) - { - *value_ptr = false; - } - else - { - jack_error("ignoring unknown bool value \"%s\"", value_str); - } -} - -void -jack_controller_settings_set_sint_option( - const char *value_str, - int *value_ptr) -{ - *value_ptr = atoi(value_str); -} - -void -jack_controller_settings_set_uint_option( - const char *value_str, - unsigned int *value_ptr) -{ - *value_ptr = strtoul(value_str, NULL, 10); -} - -void -jack_controller_settings_set_char_option( - const char *value_str, - char *value_ptr) -{ - if (value_str[0] == 0 || value_str[1] != 0) - { - jack_error("invalid char option value \"%s\"", value_str); - return; - } - - *value_ptr = *value_str; -} - -void -jack_controller_settings_set_string_option( - const char *value_str, - char *value_ptr, - size_t max_size) -{ - size_t size; - - size = strlen(value_str); - - if (size >= max_size) - { - jack_error("string option value \"%s\" is too long, max is %u chars (including terminating zero)", value_str, (unsigned int)max_size); - return; - } - - strcpy(value_ptr, value_str); -} - -void -jack_controller_settings_set_driver_option( - jackctl_driver_t *driver, - const char *option_name, - const char *option_value) -{ - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - int value_int; - unsigned int value_uint; - union jackctl_parameter_value value; - - jack_info("setting driver option \"%s\" to value \"%s\"", option_name, option_value); - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(driver), option_name); - if (parameter == NULL) - { - jack_error( - "Unknown parameter \"%s\" of driver \"%s\"", - option_name, - jackctl_driver_get_name(driver)); - return; - } - - type = jackctl_parameter_get_type(parameter); - - switch (type) - { - case JackParamInt: - jack_controller_settings_set_sint_option(option_value, &value_int); - value.i = value_int; - break; - case JackParamUInt: - jack_controller_settings_set_uint_option(option_value, &value_uint); - value.ui = value_uint; - break; - case JackParamChar: - jack_controller_settings_set_char_option(option_value, &value.c); - break; - case JackParamString: - jack_controller_settings_set_string_option(option_value, value.str, sizeof(value.str)); - break; - case JackParamBool: - jack_controller_settings_set_bool_option(option_value, &value_int); - value.i = value_int; - break; - default: - jack_error("Parameter \"%s\" of driver \"%s\" is of unknown type %d", - jackctl_parameter_get_name(parameter), - jackctl_driver_get_name(driver), - type); - } - - jackctl_parameter_set_value(parameter, &value); -} - -void -jack_controller_settings_set_engine_option( - struct jack_controller *controller_ptr, - const char *option_name, - const char *option_value) -{ - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - int value_int; - unsigned int value_uint; - union jackctl_parameter_value value; - - jack_info("setting engine option \"%s\" to value \"%s\"", option_name, option_value); - - if (strcmp(option_name, "driver") == 0) - { - if (!jack_controller_select_driver(controller_ptr, option_value)) - { - jack_error("unknown driver '%s'", option_value); - } - - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), option_name); - if (parameter == NULL) - { - jack_error( - "Unknown engine parameter \"%s\"", - option_name); - return; - } - - type = jackctl_parameter_get_type(parameter); - - switch (type) - { - case JackParamInt: - jack_controller_settings_set_sint_option(option_value, &value_int); - value.i = value_int; - break; - case JackParamUInt: - jack_controller_settings_set_uint_option(option_value, &value_uint); - value.ui = value_uint; - break; - case JackParamChar: - jack_controller_settings_set_char_option(option_value, &value.c); - break; - case JackParamString: - jack_controller_settings_set_string_option(option_value, value.str, sizeof(value.str)); - break; - case JackParamBool: - jack_controller_settings_set_bool_option(option_value, &value_int); - value.i = value_int; - break; - default: - jack_error("Engine parameter \"%s\" is of unknown type %d", - jackctl_parameter_get_name(parameter), - type); - } - - jackctl_parameter_set_value(parameter, &value); -} - -static -bool -jack_controller_settings_save_options( - void *context, - const JSList * parameters_list, - void *dbus_call_context_ptr) -{ - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - union jackctl_parameter_value value; - const char * name; - char value_str[50]; - - while (parameters_list != NULL) - { - parameter = (jackctl_parameter_t *)parameters_list->data; - - if (jackctl_parameter_is_set(parameter)) - { - type = jackctl_parameter_get_type(parameter); - value = jackctl_parameter_get_value(parameter); - name = jackctl_parameter_get_name(parameter); - - switch (type) - { - case JackParamInt: - sprintf(value_str, "%d", (int)value.i); - if (!jack_controller_settings_write_option(context, name, value_str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamUInt: - sprintf(value_str, "%u", (unsigned int)value.ui); - if (!jack_controller_settings_write_option(context, name, value_str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamChar: - sprintf(value_str, "%c", (char)value.c); - if (!jack_controller_settings_write_option(context, name, value_str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamString: - if (!jack_controller_settings_write_option(context, name, value.str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamBool: - if (!jack_controller_settings_write_option(context, name, value.b ? "true" : "false", dbus_call_context_ptr)) - { - return false; - } - break; - default: - jack_error("parameter of unknown type %d", type); - } - } - - parameters_list = jack_slist_next(parameters_list); - } - - return true; -} - -bool -jack_controller_settings_save_engine_options( - void *context, - struct jack_controller *controller_ptr, - void *dbus_call_context_ptr) -{ - if (controller_ptr->driver != NULL) - { - if (!jack_controller_settings_write_option( - context, - "driver", - jackctl_driver_get_name(controller_ptr->driver), - dbus_call_context_ptr)) - { - return false; - } - } - - return jack_controller_settings_save_options(context, jackctl_server_get_parameters(controller_ptr->server), dbus_call_context_ptr); -} - -bool -jack_controller_settings_save_driver_options( - void *context, - jackctl_driver_t *driver, - void *dbus_call_context_ptr) -{ - return jack_controller_settings_save_options(context, jackctl_driver_get_parameters(driver), dbus_call_context_ptr); -} -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include - -#include "controller_internal.h" - -void -jack_controller_settings_set_bool_option( - const char *value_str, - int *value_ptr) -{ - if (strcmp(value_str, "true") == 0) - { - *value_ptr = true; - } - else if (strcmp(value_str, "false") == 0) - { - *value_ptr = false; - } - else - { - jack_error("ignoring unknown bool value \"%s\"", value_str); - } -} - -void -jack_controller_settings_set_sint_option( - const char *value_str, - int *value_ptr) -{ - *value_ptr = atoi(value_str); -} - -void -jack_controller_settings_set_uint_option( - const char *value_str, - unsigned int *value_ptr) -{ - *value_ptr = strtoul(value_str, NULL, 10); -} - -void -jack_controller_settings_set_char_option( - const char *value_str, - char *value_ptr) -{ - if (value_str[0] == 0 || value_str[1] != 0) - { - jack_error("invalid char option value \"%s\"", value_str); - return; - } - - *value_ptr = *value_str; -} - -void -jack_controller_settings_set_string_option( - const char *value_str, - char *value_ptr, - size_t max_size) -{ - size_t size; - - size = strlen(value_str); - - if (size >= max_size) - { - jack_error("string option value \"%s\" is too long, max is %u chars (including terminating zero)", value_str, (unsigned int)max_size); - return; - } - - strcpy(value_ptr, value_str); -} - -void -jack_controller_settings_set_driver_option( - jackctl_driver_t *driver, - const char *option_name, - const char *option_value) -{ - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - int value_int; - unsigned int value_uint; - union jackctl_parameter_value value; - - jack_info("setting driver option \"%s\" to value \"%s\"", option_name, option_value); - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(driver), option_name); - if (parameter == NULL) - { - jack_error( - "Unknown parameter \"%s\" of driver \"%s\"", - option_name, - jackctl_driver_get_name(driver)); - return; - } - - type = jackctl_parameter_get_type(parameter); - - switch (type) - { - case JackParamInt: - jack_controller_settings_set_sint_option(option_value, &value_int); - value.i = value_int; - break; - case JackParamUInt: - jack_controller_settings_set_uint_option(option_value, &value_uint); - value.ui = value_uint; - break; - case JackParamChar: - jack_controller_settings_set_char_option(option_value, &value.c); - break; - case JackParamString: - jack_controller_settings_set_string_option(option_value, value.str, sizeof(value.str)); - break; - case JackParamBool: - jack_controller_settings_set_bool_option(option_value, &value_int); - value.i = value_int; - break; - default: - jack_error("Parameter \"%s\" of driver \"%s\" is of unknown type %d", - jackctl_parameter_get_name(parameter), - jackctl_driver_get_name(driver), - type); - } - - jackctl_parameter_set_value(parameter, &value); -} - -void -jack_controller_settings_set_engine_option( - struct jack_controller *controller_ptr, - const char *option_name, - const char *option_value) -{ - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - int value_int; - unsigned int value_uint; - union jackctl_parameter_value value; - - jack_info("setting engine option \"%s\" to value \"%s\"", option_name, option_value); - - if (strcmp(option_name, "driver") == 0) - { - if (!jack_controller_select_driver(controller_ptr, option_value)) - { - jack_error("unknown driver '%s'", option_value); - } - - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), option_name); - if (parameter == NULL) - { - jack_error( - "Unknown engine parameter \"%s\"", - option_name); - return; - } - - type = jackctl_parameter_get_type(parameter); - - switch (type) - { - case JackParamInt: - jack_controller_settings_set_sint_option(option_value, &value_int); - value.i = value_int; - break; - case JackParamUInt: - jack_controller_settings_set_uint_option(option_value, &value_uint); - value.ui = value_uint; - break; - case JackParamChar: - jack_controller_settings_set_char_option(option_value, &value.c); - break; - case JackParamString: - jack_controller_settings_set_string_option(option_value, value.str, sizeof(value.str)); - break; - case JackParamBool: - jack_controller_settings_set_bool_option(option_value, &value_int); - value.i = value_int; - break; - default: - jack_error("Engine parameter \"%s\" is of unknown type %d", - jackctl_parameter_get_name(parameter), - type); - } - - jackctl_parameter_set_value(parameter, &value); -} - -static -bool -jack_controller_settings_save_options( - void *context, - const JSList * parameters_list, - void *dbus_call_context_ptr) -{ - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - union jackctl_parameter_value value; - const char * name; - char value_str[50]; - - while (parameters_list != NULL) - { - parameter = (jackctl_parameter_t *)parameters_list->data; - - if (jackctl_parameter_is_set(parameter)) - { - type = jackctl_parameter_get_type(parameter); - value = jackctl_parameter_get_value(parameter); - name = jackctl_parameter_get_name(parameter); - - switch (type) - { - case JackParamInt: - sprintf(value_str, "%d", (int)value.i); - if (!jack_controller_settings_write_option(context, name, value_str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamUInt: - sprintf(value_str, "%u", (unsigned int)value.ui); - if (!jack_controller_settings_write_option(context, name, value_str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamChar: - sprintf(value_str, "%c", (char)value.c); - if (!jack_controller_settings_write_option(context, name, value_str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamString: - if (!jack_controller_settings_write_option(context, name, value.str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamBool: - if (!jack_controller_settings_write_option(context, name, value.b ? "true" : "false", dbus_call_context_ptr)) - { - return false; - } - break; - default: - jack_error("parameter of unknown type %d", type); - } - } - - parameters_list = jack_slist_next(parameters_list); - } - - return true; -} - -bool -jack_controller_settings_save_engine_options( - void *context, - struct jack_controller *controller_ptr, - void *dbus_call_context_ptr) -{ - if (controller_ptr->driver != NULL) - { - if (!jack_controller_settings_write_option( - context, - "driver", - jackctl_driver_get_name(controller_ptr->driver), - dbus_call_context_ptr)) - { - return false; - } - } - - return jack_controller_settings_save_options(context, jackctl_server_get_parameters(controller_ptr->server), dbus_call_context_ptr); -} - -bool -jack_controller_settings_save_driver_options( - void *context, - jackctl_driver_t *driver, - void *dbus_call_context_ptr) -{ - return jack_controller_settings_save_options(context, jackctl_driver_get_parameters(driver), dbus_call_context_ptr); -} -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include - -#include "controller_internal.h" - -void -jack_controller_settings_set_bool_option( - const char *value_str, - int *value_ptr) -{ - if (strcmp(value_str, "true") == 0) - { - *value_ptr = true; - } - else if (strcmp(value_str, "false") == 0) - { - *value_ptr = false; - } - else - { - jack_error("ignoring unknown bool value \"%s\"", value_str); - } -} - -void -jack_controller_settings_set_sint_option( - const char *value_str, - int *value_ptr) -{ - *value_ptr = atoi(value_str); -} - -void -jack_controller_settings_set_uint_option( - const char *value_str, - unsigned int *value_ptr) -{ - *value_ptr = strtoul(value_str, NULL, 10); -} - -void -jack_controller_settings_set_char_option( - const char *value_str, - char *value_ptr) -{ - if (value_str[0] == 0 || value_str[1] != 0) - { - jack_error("invalid char option value \"%s\"", value_str); - return; - } - - *value_ptr = *value_str; -} - -void -jack_controller_settings_set_string_option( - const char *value_str, - char *value_ptr, - size_t max_size) -{ - size_t size; - - size = strlen(value_str); - - if (size >= max_size) - { - jack_error("string option value \"%s\" is too long, max is %u chars (including terminating zero)", value_str, (unsigned int)max_size); - return; - } - - strcpy(value_ptr, value_str); -} - -void -jack_controller_settings_set_driver_option( - jackctl_driver_t *driver, - const char *option_name, - const char *option_value) -{ - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - int value_int; - unsigned int value_uint; - union jackctl_parameter_value value; - - jack_info("setting driver option \"%s\" to value \"%s\"", option_name, option_value); - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(driver), option_name); - if (parameter == NULL) - { - jack_error( - "Unknown parameter \"%s\" of driver \"%s\"", - option_name, - jackctl_driver_get_name(driver)); - return; - } - - type = jackctl_parameter_get_type(parameter); - - switch (type) - { - case JackParamInt: - jack_controller_settings_set_sint_option(option_value, &value_int); - value.i = value_int; - break; - case JackParamUInt: - jack_controller_settings_set_uint_option(option_value, &value_uint); - value.ui = value_uint; - break; - case JackParamChar: - jack_controller_settings_set_char_option(option_value, &value.c); - break; - case JackParamString: - jack_controller_settings_set_string_option(option_value, value.str, sizeof(value.str)); - break; - case JackParamBool: - jack_controller_settings_set_bool_option(option_value, &value_int); - value.i = value_int; - break; - default: - jack_error("Parameter \"%s\" of driver \"%s\" is of unknown type %d", - jackctl_parameter_get_name(parameter), - jackctl_driver_get_name(driver), - type); - } - - jackctl_parameter_set_value(parameter, &value); -} - -void -jack_controller_settings_set_engine_option( - struct jack_controller *controller_ptr, - const char *option_name, - const char *option_value) -{ - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - int value_int; - unsigned int value_uint; - union jackctl_parameter_value value; - - jack_info("setting engine option \"%s\" to value \"%s\"", option_name, option_value); - - if (strcmp(option_name, "driver") == 0) - { - if (!jack_controller_select_driver(controller_ptr, option_value)) - { - jack_error("unknown driver '%s'", option_value); - } - - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), option_name); - if (parameter == NULL) - { - jack_error( - "Unknown engine parameter \"%s\"", - option_name); - return; - } - - type = jackctl_parameter_get_type(parameter); - - switch (type) - { - case JackParamInt: - jack_controller_settings_set_sint_option(option_value, &value_int); - value.i = value_int; - break; - case JackParamUInt: - jack_controller_settings_set_uint_option(option_value, &value_uint); - value.ui = value_uint; - break; - case JackParamChar: - jack_controller_settings_set_char_option(option_value, &value.c); - break; - case JackParamString: - jack_controller_settings_set_string_option(option_value, value.str, sizeof(value.str)); - break; - case JackParamBool: - jack_controller_settings_set_bool_option(option_value, &value_int); - value.i = value_int; - break; - default: - jack_error("Engine parameter \"%s\" is of unknown type %d", - jackctl_parameter_get_name(parameter), - type); - } - - jackctl_parameter_set_value(parameter, &value); -} - -static -bool -jack_controller_settings_save_options( - void *context, - const JSList * parameters_list, - void *dbus_call_context_ptr) -{ - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - union jackctl_parameter_value value; - const char * name; - char value_str[50]; - - while (parameters_list != NULL) - { - parameter = (jackctl_parameter_t *)parameters_list->data; - - if (jackctl_parameter_is_set(parameter)) - { - type = jackctl_parameter_get_type(parameter); - value = jackctl_parameter_get_value(parameter); - name = jackctl_parameter_get_name(parameter); - - switch (type) - { - case JackParamInt: - sprintf(value_str, "%d", (int)value.i); - if (!jack_controller_settings_write_option(context, name, value_str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamUInt: - sprintf(value_str, "%u", (unsigned int)value.ui); - if (!jack_controller_settings_write_option(context, name, value_str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamChar: - sprintf(value_str, "%c", (char)value.c); - if (!jack_controller_settings_write_option(context, name, value_str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamString: - if (!jack_controller_settings_write_option(context, name, value.str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamBool: - if (!jack_controller_settings_write_option(context, name, value.b ? "true" : "false", dbus_call_context_ptr)) - { - return false; - } - break; - default: - jack_error("parameter of unknown type %d", type); - } - } - - parameters_list = jack_slist_next(parameters_list); - } - - return true; -} - -bool -jack_controller_settings_save_engine_options( - void *context, - struct jack_controller *controller_ptr, - void *dbus_call_context_ptr) -{ - if (controller_ptr->driver != NULL) - { - if (!jack_controller_settings_write_option( - context, - "driver", - jackctl_driver_get_name(controller_ptr->driver), - dbus_call_context_ptr)) - { - return false; - } - } - - return jack_controller_settings_save_options(context, jackctl_server_get_parameters(controller_ptr->server), dbus_call_context_ptr); -} - -bool -jack_controller_settings_save_driver_options( - void *context, - jackctl_driver_t *driver, - void *dbus_call_context_ptr) -{ - return jack_controller_settings_save_options(context, jackctl_driver_get_parameters(driver), dbus_call_context_ptr); -} diff --git a/linux/dbus/xml_expat.c b/linux/dbus/xml_expat.c index c9f3fefb..5e58a491 100644 --- a/linux/dbus/xml_expat.c +++ b/linux/dbus/xml_expat.c @@ -315,954 +315,3 @@ exit_free_filename: exit: return; } -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - Copyright (C) 2007,2008 Nedko Arnaudov - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "controller_internal.h" -#include "jackdbus.h" - -bool -jack_controller_settings_init() -{ - return true; -} - -void -jack_controller_settings_uninit() -{ -} - -#define PARSE_CONTEXT_ROOT 0 -#define PARSE_CONTEXT_JACK 1 -#define PARSE_CONTEXT_ENGINE 1 -#define PARSE_CONTEXT_DRIVERS 2 -#define PARSE_CONTEXT_DRIVER 3 -#define PARSE_CONTEXT_OPTION 4 - -#define MAX_STACK_DEPTH 10 - -struct parse_context -{ - struct jack_controller *controller_ptr; - XML_Bool error; - unsigned int element[MAX_STACK_DEPTH]; - signed int depth; - jackctl_driver_t *driver; - char option[JACK_PARAM_STRING_MAX+1]; - int option_used; - char *name; -}; - -#define context_ptr ((struct parse_context *)data) - -void -jack_controller_settings_callback_chrdata(void *data, const XML_Char *s, int len) -{ - if (context_ptr->error) - { - return; - } - - if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_OPTION) - { - if (context_ptr->option_used + len >= JACK_PARAM_STRING_MAX) - { - jack_error("xml parse max char data length reached"); - context_ptr->error = XML_TRUE; - return; - } - - memcpy(context_ptr->option + context_ptr->option_used, s, len); - context_ptr->option_used += len; - } -} - -void -jack_controller_settings_callback_elstart(void *data, const char *el, const char **attr) -{ - jackctl_driver_t *driver; - - if (context_ptr->error) - { - return; - } - - if (context_ptr->depth + 1 >= MAX_STACK_DEPTH) - { - jack_error("xml parse max stack depth reached"); - context_ptr->error = XML_TRUE; - return; - } - - if (strcmp(el, "jack") == 0) - { - //jack_info(""); - context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_JACK; - return; - } - - if (strcmp(el, "engine") == 0) - { - //jack_info(""); - context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_ENGINE; - return; - } - - if (strcmp(el, "drivers") == 0) - { - //jack_info(""); - context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_DRIVERS; - return; - } - - if (strcmp(el, "driver") == 0) - { - if ((attr[0] == NULL || attr[2] != NULL) || strcmp(attr[0], "name") != 0) - { - jack_error(" XML element must contain exactly one attribute, named \"name\""); - context_ptr->error = XML_TRUE; - return; - } - - //jack_info(""); - context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_DRIVER; - - driver = jack_controller_find_driver(context_ptr->controller_ptr->server, attr[1]); - if (driver == NULL) - { - jack_error("ignoring settings for unknown driver \"%s\"", attr[1]); - } - else - { - jack_info("setting for driver \"%s\" found", attr[1]); - } - - context_ptr->driver = driver; - - return; - } - - if (strcmp(el, "option") == 0) - { - //jack_info("