diff --git a/dbus/controller.c b/dbus/controller.c index ce0f1ec9..42981c1c 100644 --- a/dbus/controller.c +++ b/dbus/controller.c @@ -38,6 +38,7 @@ struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[] = &g_jack_controller_iface_control, &g_jack_controller_iface_configure, &g_jack_controller_iface_patchbay, + &g_jack_controller_iface_session_manager, &g_jack_controller_iface_transport, NULL }; diff --git a/dbus/controller_iface_session_manager.c b/dbus/controller_iface_session_manager.c new file mode 100644 index 00000000..7292cd6c --- /dev/null +++ b/dbus/controller_iface_session_manager.c @@ -0,0 +1,312 @@ +/* -*- Mode: C ; c-basic-offset: 4 -*- */ +/* + Copyright (C) 2011 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. + +*/ + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +#include "jackdbus.h" +#include "controller_internal.h" +#include "jack/session.h" + +#define controller_ptr ((struct jack_controller *)call->context) + +static +void +jack_controller_dbus_session_notify( + struct jack_dbus_method_call * call) +{ + const char * target; + dbus_uint32_t u32; + const char * path; + jack_session_event_type_t type; + jack_session_command_t * commands; + const jack_session_command_t * cmd_ptr; + DBusMessageIter top_iter, array_iter, struct_iter; + + if (!jack_dbus_get_method_args( + call, + DBUS_TYPE_STRING, + &target, + DBUS_TYPE_UINT32, + &u32, + DBUS_TYPE_STRING, + &path, + DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that jack_dbus_get_method_args() has constructed an error for us. */ + goto exit; + } + + if (*target == 0) + { + target = NULL; + } + + type = (jack_session_event_type_t)u32; + + if (type != JackSessionSave && + type != JackSessionSaveAndQuit && + type != JackSessionSaveTemplate) + { + jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "Invalid session event type %" PRIu32, u32); + goto exit; + } + + commands = jack_session_notify(controller_ptr->client, target, type, path); + if (commands == NULL) + { + jack_dbus_error(call, JACK_DBUS_ERROR_GENERIC, "jack_session_notify() failed"); + goto exit; + } + + call->reply = dbus_message_new_method_return(call->message); + if (call->reply == NULL) + { + goto oom; + } + + dbus_message_iter_init_append(call->reply, &top_iter); + + if (!dbus_message_iter_open_container(&top_iter, DBUS_TYPE_ARRAY, "(sssu)", &array_iter)) + { + goto unref; + } + + for (cmd_ptr = commands; cmd_ptr->uuid != NULL; cmd_ptr++) + { + if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)) + { + goto close_array; + } + + if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &cmd_ptr->uuid)) + { + goto close_struct; + } + + if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &cmd_ptr->client_name)) + { + goto close_struct; + } + + if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &cmd_ptr->command)) + { + goto close_struct; + } + + u32 = cmd_ptr->flags; + if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &u32)) + { + goto close_struct; + } + + if (!dbus_message_iter_close_container(&array_iter, &struct_iter)) + { + goto close_array; + } + } + + if (!dbus_message_iter_close_container(&top_iter, &array_iter)) + { + goto unref; + } + + goto free; + +close_struct: + dbus_message_iter_close_container(&array_iter, &struct_iter); +close_array: + dbus_message_iter_close_container(&top_iter, &array_iter); +unref: + dbus_message_unref(call->reply); + call->reply = NULL; +oom: + jack_error("Ran out of memory trying to construct method return"); +free: + jack_session_commands_free(commands); +exit: + return; +} + +static +void +jack_controller_dbus_get_uuid_for_client_name( + struct jack_dbus_method_call * call) +{ + const char * client_name; + char * client_uuid; + + if (!jack_dbus_get_method_args( + call, + DBUS_TYPE_STRING, + &client_name, + DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that jack_dbus_get_method_args() has constructed an error for us. */ + return; + } + + client_uuid = jack_get_uuid_for_client_name(controller_ptr->client, client_name); + if (client_uuid == NULL) + { + jack_dbus_error(call, JACK_DBUS_ERROR_GENERIC, "jack_get_uuid_for_client_name(\"%s\") failed", client_name); + return; + } + + jack_dbus_construct_method_return_single(call, DBUS_TYPE_STRING, (message_arg_t)(const char *)client_uuid); + free(client_uuid); +} + +static +void +jack_controller_dbus_get_client_name_by_uuid( + struct jack_dbus_method_call * call) +{ + const char * client_uuid; + char * client_name; + + if (!jack_dbus_get_method_args( + call, + DBUS_TYPE_STRING, + &client_uuid, + DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that jack_dbus_get_method_args() has constructed an error for us. */ + return; + } + + client_name = jack_get_client_name_by_uuid(controller_ptr->client, client_uuid); + if (client_name == NULL) + { + jack_dbus_error(call, JACK_DBUS_ERROR_GENERIC, "jack_get_client_name_by_uuid(\"%s\") failed", client_uuid); + return; + } + + jack_dbus_construct_method_return_single(call, DBUS_TYPE_STRING, (message_arg_t)(const char *)client_name); + free(client_name); +} + +static +void +jack_controller_dbus_reserve_client_name( + struct jack_dbus_method_call * call) +{ + int ret; + const char * client_name; + const char * client_uuid; + + if (!jack_dbus_get_method_args( + call, + DBUS_TYPE_STRING, + &client_name, + DBUS_TYPE_STRING, + &client_uuid, + DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that jack_dbus_get_method_args() has constructed an error for us. */ + return; + } + + ret = jack_reserve_client_name(controller_ptr->client, client_name, client_uuid); + if (ret < 0) + { + jack_dbus_error(call, JACK_DBUS_ERROR_GENERIC, "jack_reserve_client_name(name=\"%s\", uuid=\"%s\") failed (%d)", client_name, client_uuid, ret); + return; + } + + jack_dbus_construct_method_return_empty(call); +} + +static +void +jack_controller_dbus_has_session_callback( + struct jack_dbus_method_call * call) +{ + int ret; + const char * client_name; + message_arg_t retval; + + if (!jack_dbus_get_method_args( + call, + DBUS_TYPE_STRING, + &client_name, + DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that jack_dbus_get_method_args() has constructed an error for us. */ + return; + } + + ret = jack_client_has_session_callback(controller_ptr->client, client_name); + if (ret < 0) + { + jack_dbus_error(call, JACK_DBUS_ERROR_GENERIC, "jack_client_has_session_callback(\"%s\") failed (%d)", client_name, ret); + return; + } + + retval.boolean = ret; + jack_dbus_construct_method_return_single(call, DBUS_TYPE_BOOLEAN, retval); +} + +#undef controller_ptr + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(Notify) + JACK_DBUS_METHOD_ARGUMENT("target", DBUS_TYPE_STRING_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("type", DBUS_TYPE_UINT32_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("path", DBUS_TYPE_STRING_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("result", "a(sssu)", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetUuidForClientName) + JACK_DBUS_METHOD_ARGUMENT("name", DBUS_TYPE_STRING_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("uuid", DBUS_TYPE_STRING_AS_STRING, true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetClientNameByUuid) + JACK_DBUS_METHOD_ARGUMENT("uuid", DBUS_TYPE_STRING_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("name", DBUS_TYPE_STRING_AS_STRING, true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ReserveClientName) + JACK_DBUS_METHOD_ARGUMENT("name", DBUS_TYPE_STRING_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("uuid", DBUS_TYPE_STRING_AS_STRING, false) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(HasSessionCallback) + JACK_DBUS_METHOD_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("has_session_callback", DBUS_TYPE_BOOLEAN_AS_STRING, true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHODS_BEGIN + JACK_DBUS_METHOD_DESCRIBE(Notify, jack_controller_dbus_session_notify) + JACK_DBUS_METHOD_DESCRIBE(GetUuidForClientName, jack_controller_dbus_get_uuid_for_client_name) + JACK_DBUS_METHOD_DESCRIBE(GetClientNameByUuid, jack_controller_dbus_get_client_name_by_uuid) + JACK_DBUS_METHOD_DESCRIBE(ReserveClientName, jack_controller_dbus_reserve_client_name) + JACK_DBUS_METHOD_DESCRIBE(HasSessionCallback, jack_controller_dbus_has_session_callback) +JACK_DBUS_METHODS_END + +JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_session_manager, "org.jackaudio.SessionManager") + JACK_DBUS_IFACE_EXPOSE_METHODS +JACK_DBUS_IFACE_END diff --git a/dbus/controller_internal.h b/dbus/controller_internal.h index 1b9c7129..1d4d40d3 100644 --- a/dbus/controller_internal.h +++ b/dbus/controller_internal.h @@ -183,6 +183,7 @@ extern struct jack_dbus_interface_descriptor g_jack_controller_iface_introspecta extern struct jack_dbus_interface_descriptor g_jack_controller_iface_control; extern struct jack_dbus_interface_descriptor g_jack_controller_iface_configure; extern struct jack_dbus_interface_descriptor g_jack_controller_iface_patchbay; +extern struct jack_dbus_interface_descriptor g_jack_controller_iface_session_manager; extern struct jack_dbus_interface_descriptor g_jack_controller_iface_transport; #endif /* #ifndef CONTROLLER_INTERNAL_H__04D54D51_3D79_49A2_A1DA_F8587E9E7F42__INCLUDED */ diff --git a/dbus/wscript b/dbus/wscript index fced985f..703c52c7 100644 --- a/dbus/wscript +++ b/dbus/wscript @@ -58,6 +58,7 @@ def build(bld): 'controller_iface_control.c', 'controller_iface_introspectable.c', 'controller_iface_patchbay.c', + 'controller_iface_session_manager.c', 'controller_iface_transport.c', 'xml.c', 'xml_expat.c',