git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4525 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.8
| @@ -81,6 +81,8 @@ JackClient::JackClient(JackSynchro* table):fThread(this) | |||
| fThreadFunArg = NULL; | |||
| fSessionArg = NULL; | |||
| fLatencyArg = NULL; | |||
| fSessionReply = kPendingSessionReply; | |||
| } | |||
| JackClient::~JackClient() | |||
| @@ -286,17 +288,18 @@ int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, | |||
| case kSessionCallback: | |||
| jack_log("JackClient::kSessionCallback"); | |||
| if (fSession) { | |||
| jack_session_event_t *event = (jack_session_event_t *) malloc( sizeof(jack_session_event_t) ); | |||
| jack_session_event_t* event = (jack_session_event_t*)malloc( sizeof(jack_session_event_t)); | |||
| char uuid_buf[JACK_UUID_SIZE]; | |||
| event->type = (jack_session_event_type_t) value1; | |||
| event->session_dir = strdup( message ); | |||
| event->type = (jack_session_event_type_t)value1; | |||
| event->session_dir = strdup(message); | |||
| event->command_line = NULL; | |||
| event->flags = (jack_session_flags_t) 0; | |||
| snprintf( uuid_buf, sizeof(uuid_buf), "%d", GetClientControl()->fSessionID ); | |||
| event->client_uuid = strdup( uuid_buf ); | |||
| fImmediateSessionReply = false; | |||
| event->flags = (jack_session_flags_t)0; | |||
| snprintf(uuid_buf, sizeof(uuid_buf), "%d", GetClientControl()->fSessionID); | |||
| event->client_uuid = strdup(uuid_buf); | |||
| fSessionReply = kPendingSessionReply; | |||
| // Session callback may change fSessionReply by directly using jack_session_reply | |||
| fSession(event, fSessionArg); | |||
| res = (fImmediateSessionReply) ? 1 : 2; | |||
| res = fSessionReply; | |||
| } | |||
| break; | |||
| @@ -1234,8 +1237,9 @@ int JackClient::SessionReply(jack_session_event_t* ev) | |||
| jack_log("JackClient::SessionReply... we are here"); | |||
| if (fChannel->IsChannelThread()) { | |||
| jack_log( "JackClient::SessionReply... in callback reply"); | |||
| fImmediateSessionReply = true; | |||
| jack_log("JackClient::SessionReply... in callback reply"); | |||
| // OK, immediate reply... | |||
| fSessionReply = kImmediateSessionReply; | |||
| return 0; | |||
| } | |||
| @@ -93,7 +93,7 @@ class SERVER_EXPORT JackClient : public JackClientInterface, public JackRunnable | |||
| JackSynchro* fSynchroTable; | |||
| std::list<jack_port_id_t> fPortList; | |||
| bool fImmediateSessionReply; | |||
| JackSessionReply fSessionReply; | |||
| int StartThread(); | |||
| void SetupDriverSync(bool freewheel); | |||
| @@ -932,12 +932,15 @@ int JackEngine::PortRename(int refnum, jack_port_id_t port, const char* name) | |||
| // Session management | |||
| //-------------------- | |||
| void JackEngine::SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket) | |||
| void JackEngine::SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket, JackSessionNotifyResult** result) | |||
| { | |||
| if (fSessionPendingReplies != 0) { | |||
| JackSessionNotifyResult res(-1); | |||
| res.Write(socket); | |||
| jack_log("JackEngine::SessionNotify ... busy"); | |||
| if (result != NULL) { | |||
| *result = NULL; | |||
| } | |||
| return; | |||
| } | |||
| @@ -961,30 +964,36 @@ void JackEngine::SessionNotify(int refnum, const char *target, jack_session_even | |||
| } | |||
| char path_buf[JACK_PORT_NAME_SIZE]; | |||
| snprintf( path_buf, sizeof(path_buf), "%s%s%c", path, client->GetClientControl()->fName, DIR_SEPARATOR ); | |||
| snprintf(path_buf, sizeof(path_buf), "%s%s%c", path, client->GetClientControl()->fName, DIR_SEPARATOR); | |||
| int res = JackTools::MkDir(path_buf); | |||
| if (res) | |||
| jack_error( "JackEngine::SessionNotify: can not create session directory '%s'", path_buf ); | |||
| jack_error("JackEngine::SessionNotify: can not create session directory '%s'", path_buf); | |||
| int result = client->ClientNotify(i, client->GetClientControl()->fName, kSessionCallback, true, path_buf, (int) type, 0); | |||
| int result = client->ClientNotify(i, client->GetClientControl()->fName, kSessionCallback, true, path_buf, (int)type, 0); | |||
| if (result == 2) { | |||
| if (result == kPendingSessionReply) { | |||
| fSessionPendingReplies += 1; | |||
| } else if (result == 1) { | |||
| } else if (result == kImmediateSessionReply) { | |||
| char uuid_buf[JACK_UUID_SIZE]; | |||
| snprintf( uuid_buf, sizeof(uuid_buf), "%d", client->GetClientControl()->fSessionID ); | |||
| fSessionResult->fCommandList.push_back( JackSessionCommand( uuid_buf, | |||
| client->GetClientControl()->fName, | |||
| client->GetClientControl()->fSessionCommand, | |||
| client->GetClientControl()->fSessionFlags )); | |||
| snprintf(uuid_buf, sizeof(uuid_buf), "%d", client->GetClientControl()->fSessionID); | |||
| fSessionResult->fCommandList.push_back(JackSessionCommand(uuid_buf, | |||
| client->GetClientControl()->fName, | |||
| client->GetClientControl()->fSessionCommand, | |||
| client->GetClientControl()->fSessionFlags)); | |||
| } | |||
| } | |||
| } | |||
| if (result != NULL) { | |||
| *result = fSessionResult; | |||
| } | |||
| if (fSessionPendingReplies == 0) { | |||
| fSessionResult->Write(socket); | |||
| delete fSessionResult; | |||
| if (result == NULL) { | |||
| delete fSessionResult; | |||
| } | |||
| fSessionResult = NULL; | |||
| } else { | |||
| fSessionTransaction = socket; | |||
| @@ -995,7 +1004,7 @@ void JackEngine::SessionReply(int refnum) | |||
| { | |||
| JackClientInterface* client = fClientTable[refnum]; | |||
| char uuid_buf[JACK_UUID_SIZE]; | |||
| snprintf( uuid_buf, sizeof(uuid_buf), "%d", client->GetClientControl()->fSessionID); | |||
| snprintf(uuid_buf, sizeof(uuid_buf), "%d", client->GetClientControl()->fSessionID); | |||
| fSessionResult->fCommandList.push_back(JackSessionCommand(uuid_buf, | |||
| client->GetClientControl()->fName, | |||
| client->GetClientControl()->fSessionCommand, | |||
| @@ -1004,7 +1013,10 @@ void JackEngine::SessionReply(int refnum) | |||
| if (fSessionPendingReplies == 0) { | |||
| fSessionResult->Write(fSessionTransaction); | |||
| delete fSessionResult; | |||
| if (fSessionTransaction != NULL) | |||
| { | |||
| delete fSessionResult; | |||
| } | |||
| fSessionResult = NULL; | |||
| } | |||
| } | |||
| @@ -1060,11 +1072,11 @@ void JackEngine::ReserveClientName(const char *name, const char *uuid, int *resu | |||
| *result = 0; | |||
| } | |||
| void JackEngine::ClientHasSessionCallbackRequest(const char *name, int *result) | |||
| void JackEngine::ClientHasSessionCallback(const char *name, int *result) | |||
| { | |||
| JackClientInterface* client = NULL; | |||
| for (int i = 0; i < CLIENT_NUM; i++) { | |||
| JackClientInterface* client = fClientTable[i]; | |||
| client = fClientTable[i]; | |||
| if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) | |||
| break; | |||
| } | |||
| @@ -54,8 +54,8 @@ class SERVER_EXPORT JackEngine : public JackLockAble | |||
| jack_time_t fLastSwitchUsecs; | |||
| int fSessionPendingReplies; | |||
| JackChannelTransaction *fSessionTransaction; | |||
| JackSessionNotifyResult *fSessionResult; | |||
| JackChannelTransaction* fSessionTransaction; | |||
| JackSessionNotifyResult* fSessionResult; | |||
| std::map<int,std::string> fReservationMap; | |||
| int fMaxUUID; | |||
| @@ -145,13 +145,13 @@ class SERVER_EXPORT JackEngine : public JackLockAble | |||
| void NotifyQuit(); | |||
| // Session management | |||
| void SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket); | |||
| void SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket, JackSessionNotifyResult** result); | |||
| void SessionReply(int refnum); | |||
| void GetUUIDForClientName(const char *client_name, char *uuid_res, int *result); | |||
| void GetClientNameForUUID(const char *uuid, char *name_res, int *result); | |||
| void ReserveClientName(const char *name, const char *uuid, int *result); | |||
| void ClientHasSessionCallbackRequest(const char *name, int *result); | |||
| void ClientHasSessionCallback(const char *name, int *result); | |||
| }; | |||
| @@ -146,7 +146,42 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface | |||
| void SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, jack_session_command_t** result) | |||
| { | |||
| *result = NULL; | |||
| JackSessionNotifyResult* res; | |||
| fEngine->SessionNotify(refnum, target, type, path, NULL, &res); | |||
| if (res == NULL) | |||
| { | |||
| *result = NULL; | |||
| return; | |||
| } | |||
| *result = res->GetCommands(); | |||
| delete(res); | |||
| } | |||
| void SessionReply(int refnum, int* result) | |||
| { | |||
| fEngine->SessionReply(refnum); | |||
| *result = 0; | |||
| } | |||
| void GetUUIDForClientName(int refnum, const char* client_name, char* uuid_res, int* result) | |||
| { | |||
| fEngine->GetUUIDForClientName(client_name, uuid_res, result); | |||
| } | |||
| void GetClientNameForUUID(int refnum, const char* uuid, char* name_res, int* result) | |||
| { | |||
| fEngine->GetClientNameForUUID(uuid, name_res, result); | |||
| } | |||
| void ReserveClientName(int refnum, const char* client_name, const char *uuid, int* result) | |||
| { | |||
| fEngine->ReserveClientName(client_name, uuid, result); | |||
| } | |||
| void ClientHasSessionCallback(const char* client_name, int* result) | |||
| { | |||
| fEngine->ClientHasSessionCallback(client_name, result); | |||
| } | |||
| @@ -325,11 +325,11 @@ class SERVER_EXPORT JackLockedEngine | |||
| CATCH_EXCEPTION | |||
| } | |||
| void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket) | |||
| void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket, JackSessionNotifyResult** result) | |||
| { | |||
| TRY_CALL | |||
| JackLock lock(&fEngine); | |||
| fEngine.SessionNotify(refnum, target, type, path, socket); | |||
| fEngine.SessionNotify(refnum, target, type, path, socket, result); | |||
| CATCH_EXCEPTION | |||
| } | |||
| @@ -363,11 +363,11 @@ class SERVER_EXPORT JackLockedEngine | |||
| CATCH_EXCEPTION | |||
| } | |||
| void ClientHasSessionCallbackRequest(const char *name, int *result) | |||
| void ClientHasSessionCallback(const char *name, int *result) | |||
| { | |||
| TRY_CALL | |||
| JackLock lock(&fEngine); | |||
| fEngine.ClientHasSessionCallbackRequest(name, result); | |||
| fEngine.ClientHasSessionCallback(name, result); | |||
| CATCH_EXCEPTION | |||
| } | |||
| }; | |||
| @@ -23,15 +23,28 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| #include "JackConstants.h" | |||
| #include "JackPlatformPlug.h" | |||
| #include "JackTime.h" | |||
| #include "types.h" | |||
| #include <string.h> | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <list> | |||
| namespace Jack | |||
| { | |||
| #define CheckRes(exp) { if ((exp) < 0) return -1;} | |||
| #define CheckRes(exp) { if ((exp) < 0) return -1; } | |||
| /*! | |||
| \brief Session API constants. | |||
| */ | |||
| enum JackSessionReply { | |||
| kImmediateSessionReply = 1, | |||
| kPendingSessionReply = 2 | |||
| }; | |||
| /*! | |||
| \brief Request from client to server. | |||
| @@ -1122,11 +1135,11 @@ struct JackSessionCommand | |||
| JackSessionCommand() | |||
| {} | |||
| JackSessionCommand( const char *uuid, const char *clientname, const char *command, jack_session_flags_t flags ) | |||
| JackSessionCommand(const char *uuid, const char *clientname, const char *command, jack_session_flags_t flags) | |||
| { | |||
| strncpy( fUUID, uuid, sizeof(fUUID)); | |||
| strncpy( fClientName, clientname, sizeof(fClientName)); | |||
| strncpy( fCommand, command, sizeof(fCommand)); | |||
| strncpy(fUUID, uuid, sizeof(fUUID)); | |||
| strncpy(fClientName, clientname, sizeof(fClientName)); | |||
| strncpy(fCommand, command, sizeof(fCommand)); | |||
| fFlags = flags; | |||
| } | |||
| }; | |||
| @@ -1135,17 +1148,23 @@ struct JackSessionNotifyResult : public JackResult | |||
| { | |||
| std::list<JackSessionCommand> fCommandList; | |||
| bool fDone; | |||
| JackSessionNotifyResult(): JackResult() | |||
| JackSessionNotifyResult(): JackResult(), fDone(false) | |||
| {} | |||
| JackSessionNotifyResult(int32_t result) | |||
| : JackResult(result) | |||
| : JackResult(result), fDone(false) | |||
| {} | |||
| int Read(JackChannelTransaction* trans) | |||
| { | |||
| if (trans == NULL) | |||
| { | |||
| return 0; | |||
| } | |||
| CheckRes(JackResult::Read(trans)); | |||
| while(1) { | |||
| while (true) { | |||
| JackSessionCommand buffer; | |||
| CheckRes(trans->Read(buffer.fUUID, sizeof(buffer.fUUID))); | |||
| @@ -1158,16 +1177,25 @@ struct JackSessionNotifyResult : public JackResult | |||
| fCommandList.push_back(buffer); | |||
| } | |||
| fDone = true; | |||
| return 0; | |||
| } | |||
| int Write(JackChannelTransaction* trans) | |||
| { | |||
| if (trans == NULL) | |||
| { | |||
| fDone = true; | |||
| return 0; | |||
| } | |||
| char terminator[JACK_UUID_SIZE]; | |||
| terminator[0] = '\0'; | |||
| CheckRes(JackResult::Write(trans)); | |||
| for (std::list<JackSessionCommand>::iterator i=fCommandList.begin(); i!=fCommandList.end(); i++) { | |||
| for (std::list<JackSessionCommand>::iterator i = fCommandList.begin(); i != fCommandList.end(); i++) { | |||
| CheckRes(trans->Write(i->fUUID, sizeof(i->fUUID))); | |||
| CheckRes(trans->Write(i->fClientName, sizeof(i->fClientName))); | |||
| CheckRes(trans->Write(i->fCommand, sizeof(i->fCommand))); | |||
| @@ -1177,6 +1205,32 @@ struct JackSessionNotifyResult : public JackResult | |||
| return 0; | |||
| } | |||
| jack_session_command_t* GetCommands() | |||
| { | |||
| /* TODO: some kind of signal should be used instead */ | |||
| while (!fDone) | |||
| { | |||
| JackSleep(50000); /* 50 ms */ | |||
| } | |||
| jack_session_command_t* session_command = (jack_session_command_t *)malloc(sizeof(jack_session_command_t) * (fCommandList.size() + 1)); | |||
| int i = 0; | |||
| for (std::list<JackSessionCommand>::iterator ci = fCommandList.begin(); ci != fCommandList.end(); ci++) { | |||
| session_command[i].uuid = strdup(ci->fUUID); | |||
| session_command[i].client_name = strdup(ci->fClientName); | |||
| session_command[i].command = strdup(ci->fCommand); | |||
| session_command[i].flags = ci->fFlags; | |||
| i += 1; | |||
| } | |||
| session_command[i].uuid = NULL; | |||
| session_command[i].client_name = NULL; | |||
| session_command[i].command = NULL; | |||
| session_command[i].flags = (jack_session_flags_t)0; | |||
| return session_command; | |||
| } | |||
| }; | |||
| /*! | |||
| @@ -1187,19 +1241,20 @@ struct JackSessionNotifyRequest : public JackRequest | |||
| { | |||
| char fPath[JACK_MESSAGE_SIZE + 1]; | |||
| char fDst[JACK_CLIENT_NAME_SIZE + 1]; | |||
| jack_session_event_type_t fEventType; | |||
| int fRefNum; | |||
| jack_session_event_type_t fEventType; | |||
| int fRefNum; | |||
| JackSessionNotifyRequest() | |||
| {} | |||
| JackSessionNotifyRequest(int refnum, const char *path, jack_session_event_type_t type, const char *dst) | |||
| JackSessionNotifyRequest(int refnum, const char* path, jack_session_event_type_t type, const char* dst) | |||
| : JackRequest(JackRequest::kSessionNotify), fEventType(type), fRefNum(refnum) | |||
| { | |||
| snprintf(fPath, sizeof(fPath), "%s", path); | |||
| if (dst) | |||
| if (dst) { | |||
| snprintf(fDst, sizeof(fDst), "%s", dst); | |||
| else | |||
| } else { | |||
| fDst[0] = '\0'; | |||
| } | |||
| } | |||
| int Read(JackChannelTransaction* trans) | |||
| @@ -1279,7 +1334,6 @@ struct JackClientNameResult : public JackResult | |||
| struct JackUUIDResult : public JackResult | |||
| { | |||
| char fUUID[JACK_UUID_SIZE]; | |||
| JackUUIDResult(): JackResult() | |||
| @@ -26,6 +26,7 @@ | |||
| #include <string.h> | |||
| #include <dbus/dbus.h> | |||
| #include <assert.h> | |||
| #include <unistd.h> | |||
| #include "controller.h" | |||
| #include "controller_internal.h" | |||
| @@ -38,6 +39,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 | |||
| }; | |||
| @@ -286,6 +288,15 @@ jack_controller_stop_server( | |||
| { | |||
| int ret; | |||
| pthread_mutex_lock(&controller_ptr->lock); | |||
| if (!list_empty(&controller_ptr->session_pending_commands)) | |||
| { | |||
| pthread_mutex_unlock(&controller_ptr->lock); | |||
| jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Refusing to stop JACK server because of pending session commands"); | |||
| return false; | |||
| } | |||
| pthread_mutex_unlock(&controller_ptr->lock); | |||
| jack_info("Stopping jack server..."); | |||
| assert(controller_ptr->started); /* should be ensured by caller */ | |||
| @@ -506,6 +517,7 @@ void * | |||
| jack_controller_create( | |||
| DBusConnection *connection) | |||
| { | |||
| int error; | |||
| struct jack_controller *controller_ptr; | |||
| const char * address[PARAM_ADDRESS_SIZE]; | |||
| DBusObjectPathVTable vtable = | |||
| @@ -522,11 +534,20 @@ jack_controller_create( | |||
| goto fail; | |||
| } | |||
| error = pthread_mutex_init(&controller_ptr->lock, NULL); | |||
| if (error != 0) | |||
| { | |||
| jack_error("Failed to initialize mutex. error %d", error); | |||
| goto fail_free; | |||
| } | |||
| INIT_LIST_HEAD(&controller_ptr->session_pending_commands); | |||
| controller_ptr->server = jackctl_server_create(on_device_acquire, on_device_release); | |||
| if (controller_ptr->server == NULL) | |||
| { | |||
| jack_error("Failed to create server object"); | |||
| goto fail_free; | |||
| goto fail_uninit_mutex; | |||
| } | |||
| controller_ptr->params = jack_params_create(controller_ptr->server); | |||
| @@ -584,6 +605,9 @@ fail_destroy_params: | |||
| fail_destroy_server: | |||
| jackctl_server_destroy(controller_ptr->server); | |||
| fail_uninit_mutex: | |||
| pthread_mutex_destroy(&controller_ptr->lock); | |||
| fail_free: | |||
| free(controller_ptr); | |||
| @@ -738,13 +762,17 @@ jack_controller_destroy( | |||
| { | |||
| if (controller_ptr->started) | |||
| { | |||
| jack_controller_stop_server(controller_ptr, NULL); | |||
| while (!jack_controller_stop_server(controller_ptr, NULL)) | |||
| { | |||
| jack_info("jack server failed to stop, retrying in 3 seconds..."); | |||
| usleep(3000000); | |||
| } | |||
| } | |||
| jack_controller_remove_slave_drivers(controller_ptr); | |||
| jack_params_destroy(controller_ptr->params); | |||
| jackctl_server_destroy(controller_ptr->server); | |||
| pthread_mutex_destroy(&controller_ptr->lock); | |||
| free(controller_ptr); | |||
| } | |||
| @@ -0,0 +1,573 @@ | |||
| /* -*- 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 <stdint.h> | |||
| #include <string.h> | |||
| #include <stdio.h> | |||
| #include <assert.h> | |||
| #include <dbus/dbus.h> | |||
| #include "jackdbus.h" | |||
| #include "controller_internal.h" | |||
| #include "jack/session.h" | |||
| #include "common/JackError.h" | |||
| #define JACK_DBUS_IFACE_NAME "org.jackaudio.SessionManager" | |||
| static | |||
| void | |||
| jack_controller_control_send_signal_session_state_changed( | |||
| jack_session_event_type_t type, | |||
| const char * target) | |||
| { | |||
| dbus_uint32_t u32; | |||
| u32 = type; | |||
| if (target == NULL) | |||
| { | |||
| target = ""; | |||
| } | |||
| jack_dbus_send_signal( | |||
| JACK_CONTROLLER_OBJECT_PATH, | |||
| JACK_DBUS_IFACE_NAME, | |||
| "StateChanged", | |||
| DBUS_TYPE_UINT32, | |||
| &u32, | |||
| DBUS_TYPE_STRING, | |||
| &target, | |||
| DBUS_TYPE_INVALID); | |||
| } | |||
| static bool start_detached_thread(void * (* start_routine)(void *), void * arg) | |||
| { | |||
| int ret; | |||
| static pthread_attr_t attr; | |||
| pthread_t tid; | |||
| ret = pthread_attr_init(&attr); | |||
| if (ret != 0) | |||
| { | |||
| jack_error("pthread_attr_init() failed with %d", ret); | |||
| goto exit; | |||
| } | |||
| ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); | |||
| if (ret != 0) | |||
| { | |||
| jack_error("pthread_attr_setdetachstate() failed with %d", ret); | |||
| goto destroy_attr; | |||
| } | |||
| ret = pthread_create(&tid, &attr, start_routine, arg); | |||
| if (ret != 0) | |||
| { | |||
| jack_error("pthread_create() failed with %d", ret); | |||
| goto destroy_attr; | |||
| } | |||
| jack_log("Detached thread %d created", (int)tid); | |||
| destroy_attr: | |||
| pthread_attr_destroy(&attr); | |||
| exit: | |||
| return ret == 0; | |||
| } | |||
| static void send_session_notify_reply(struct jack_session_pending_command * pending_cmd_ptr, jack_session_command_t * commands) | |||
| { | |||
| struct jack_dbus_method_call call; | |||
| const jack_session_command_t * cmd_ptr; | |||
| DBusMessageIter top_iter, array_iter, struct_iter; | |||
| dbus_uint32_t u32; | |||
| /* jack_dbus_error() wants call struct */ | |||
| call.message = pending_cmd_ptr->message; | |||
| call.connection = pending_cmd_ptr->connection; | |||
| if (commands == NULL) | |||
| { | |||
| jack_dbus_error(&call, JACK_DBUS_ERROR_GENERIC, "jack_session_notify() failed"); | |||
| goto send_reply; | |||
| } | |||
| jack_info("Session notify complete, commands follow:"); | |||
| call.reply = dbus_message_new_method_return(pending_cmd_ptr->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; | |||
| } | |||
| jack_info("uuid='%s', client='%s', command='%s', flags=0x%"PRIX32, cmd_ptr->uuid, cmd_ptr->client_name, cmd_ptr->command, u32); | |||
| if (!dbus_message_iter_close_container(&array_iter, &struct_iter)) | |||
| { | |||
| goto close_array; | |||
| } | |||
| } | |||
| jack_info("End of session commands."); | |||
| if (!dbus_message_iter_close_container(&top_iter, &array_iter)) | |||
| { | |||
| goto unref; | |||
| } | |||
| goto send_reply; | |||
| 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); | |||
| goto oom; | |||
| send_reply: | |||
| if (call.reply != NULL) | |||
| { | |||
| if (!dbus_connection_send(pending_cmd_ptr->connection, call.reply, NULL)) | |||
| { | |||
| jack_error("Ran out of memory trying to queue method return"); | |||
| } | |||
| dbus_connection_flush(pending_cmd_ptr->connection); | |||
| dbus_message_unref(call.reply); | |||
| } | |||
| else | |||
| { | |||
| oom: | |||
| jack_error("Ran out of memory trying to construct method return"); | |||
| } | |||
| } | |||
| #define controller_ptr ((struct jack_controller *)context) | |||
| void * jack_controller_process_session_command_thread(void * context) | |||
| { | |||
| struct jack_session_pending_command * pending_cmd_ptr; | |||
| jack_session_command_t * commands; | |||
| jack_log("jack_controller_process_session_command_thread enter"); | |||
| pthread_mutex_lock(&controller_ptr->lock); | |||
| loop: | |||
| /* get next command */ | |||
| assert(!list_empty(&controller_ptr->session_pending_commands)); | |||
| pending_cmd_ptr = list_entry(controller_ptr->session_pending_commands.next, struct jack_session_pending_command, siblings); | |||
| pthread_mutex_unlock(&controller_ptr->lock); | |||
| jack_info("Session notify initiated. target='%s', type=%d, path='%s'", pending_cmd_ptr->target, (int)pending_cmd_ptr->type, pending_cmd_ptr->path); | |||
| jack_controller_control_send_signal_session_state_changed(pending_cmd_ptr->type, pending_cmd_ptr->target); | |||
| commands = jack_session_notify(controller_ptr->client, pending_cmd_ptr->target, pending_cmd_ptr->type, pending_cmd_ptr->path); | |||
| usleep(5000000); | |||
| send_session_notify_reply(pending_cmd_ptr, commands); | |||
| if (commands != NULL) | |||
| { | |||
| jack_session_commands_free(commands); | |||
| } | |||
| pthread_mutex_lock(&controller_ptr->lock); | |||
| /* keep state consistent by sending signal after to lock */ | |||
| /* otherwise the main thread may receive not-to-be-queued request and fail */ | |||
| jack_controller_control_send_signal_session_state_changed(0, NULL); | |||
| /* remove the head of the list (queue) */ | |||
| assert(!list_empty(&controller_ptr->session_pending_commands)); | |||
| assert(pending_cmd_ptr == list_entry(controller_ptr->session_pending_commands.next, struct jack_session_pending_command, siblings)); | |||
| list_del(&pending_cmd_ptr->siblings); | |||
| /* command cleanup */ | |||
| dbus_message_unref(pending_cmd_ptr->message); | |||
| dbus_connection_ref(pending_cmd_ptr->connection); | |||
| free(pending_cmd_ptr); | |||
| /* If there are more commands, process them. Otherwise - exit the thread */ | |||
| if (!list_empty(&controller_ptr->session_pending_commands)) | |||
| { | |||
| goto loop; | |||
| } | |||
| pthread_mutex_unlock(&controller_ptr->lock); | |||
| jack_log("jack_controller_process_session_command_thread exit"); | |||
| return NULL; | |||
| } | |||
| #undef controller_ptr | |||
| #define controller_ptr ((struct jack_controller *)call->context) | |||
| static | |||
| void | |||
| jack_controller_dbus_session_notify( | |||
| struct jack_dbus_method_call * call) | |||
| { | |||
| dbus_bool_t queue; | |||
| const char * target; | |||
| dbus_uint32_t u32; | |||
| const char * path; | |||
| jack_session_event_type_t type; | |||
| struct jack_session_pending_command * cmd_ptr; | |||
| if (!controller_ptr->started) | |||
| { | |||
| jack_dbus_only_error(call, JACK_DBUS_ERROR_SERVER_NOT_RUNNING, "Can't execute method '%s' with stopped JACK server", call->method_name); | |||
| return; | |||
| } | |||
| if (!jack_dbus_get_method_args( | |||
| call, | |||
| DBUS_TYPE_BOOLEAN, | |||
| &queue, | |||
| 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. */ | |||
| return; | |||
| } | |||
| 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); | |||
| return; | |||
| } | |||
| pthread_mutex_lock(&controller_ptr->lock); | |||
| if (list_empty(&controller_ptr->session_pending_commands)) | |||
| { | |||
| if (!start_detached_thread(jack_controller_process_session_command_thread, controller_ptr)) | |||
| { | |||
| jack_dbus_error(call, JACK_DBUS_ERROR_GENERIC, "Cannot start thread to process the command"); | |||
| goto unlock; | |||
| } | |||
| jack_log("Session notify thread started"); | |||
| } | |||
| else if (!queue) | |||
| { | |||
| jack_dbus_error(call, JACK_DBUS_ERROR_GENERIC, "Busy"); | |||
| goto unlock; | |||
| } | |||
| cmd_ptr = malloc(sizeof(struct jack_session_pending_command)); | |||
| if (cmd_ptr == NULL) | |||
| { | |||
| jack_dbus_error(call, JACK_DBUS_ERROR_GENERIC, "malloc() failed for jack_session_pending_command struct"); | |||
| goto unlock; | |||
| } | |||
| cmd_ptr->message = dbus_message_ref(call->message); | |||
| call->message = NULL; /* mark that reply will be sent asynchronously */ | |||
| cmd_ptr->connection = dbus_connection_ref(call->connection); | |||
| /* it is safe to use the retrived pointers because we already made an additional message reference */ | |||
| cmd_ptr->type = type; | |||
| cmd_ptr->target = target; | |||
| cmd_ptr->path = path; | |||
| list_add_tail(&cmd_ptr->siblings, &controller_ptr->session_pending_commands); | |||
| jack_log("Session notify scheduled. target='%s', type=%"PRIu32", path='%s'", target, u32, path); | |||
| unlock: | |||
| pthread_mutex_unlock(&controller_ptr->lock); | |||
| } | |||
| 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); | |||
| } | |||
| static | |||
| void | |||
| jack_controller_dbus_get_session_state( | |||
| struct jack_dbus_method_call * call) | |||
| { | |||
| DBusMessageIter iter; | |||
| struct jack_session_pending_command * cmd_ptr; | |||
| const char * target; | |||
| dbus_uint32_t type; | |||
| bool append_failed; | |||
| call->reply = dbus_message_new_method_return(call->message); | |||
| if (call->reply == NULL) | |||
| { | |||
| goto oom; | |||
| } | |||
| dbus_message_iter_init_append(call->reply, &iter); | |||
| pthread_mutex_lock(&controller_ptr->lock); | |||
| if (list_empty(&controller_ptr->session_pending_commands)) | |||
| { | |||
| type = 0; | |||
| target = ""; | |||
| } | |||
| else | |||
| { | |||
| cmd_ptr = list_entry(controller_ptr->session_pending_commands.next, struct jack_session_pending_command, siblings); | |||
| type = (dbus_uint32_t)cmd_ptr->type; | |||
| target = cmd_ptr->target; | |||
| } | |||
| append_failed = | |||
| !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &type) || | |||
| !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &target); | |||
| pthread_mutex_unlock(&controller_ptr->lock); | |||
| if (!append_failed) | |||
| { | |||
| return; | |||
| } | |||
| dbus_message_unref(call->reply); | |||
| call->reply = NULL; | |||
| oom: | |||
| jack_error("Ran out of memory trying to construct method return"); | |||
| } | |||
| #undef controller_ptr | |||
| JACK_DBUS_METHOD_ARGUMENTS_BEGIN(Notify) | |||
| JACK_DBUS_METHOD_ARGUMENT("queue", DBUS_TYPE_BOOLEAN_AS_STRING, false) | |||
| 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_METHOD_ARGUMENTS_BEGIN(GetState) | |||
| JACK_DBUS_METHOD_ARGUMENT("type", DBUS_TYPE_UINT32_AS_STRING, true) | |||
| JACK_DBUS_METHOD_ARGUMENT("target", DBUS_TYPE_STRING_AS_STRING, true) | |||
| JACK_DBUS_METHOD_ARGUMENTS_END | |||
| JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(StateChanged) | |||
| JACK_DBUS_SIGNAL_ARGUMENT("type", DBUS_TYPE_UINT32_AS_STRING) | |||
| JACK_DBUS_SIGNAL_ARGUMENT("target", DBUS_TYPE_STRING_AS_STRING) | |||
| JACK_DBUS_SIGNAL_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_METHOD_DESCRIBE(GetState, jack_controller_dbus_get_session_state) | |||
| JACK_DBUS_METHODS_END | |||
| JACK_DBUS_SIGNALS_BEGIN | |||
| JACK_DBUS_SIGNAL_DESCRIBE(StateChanged) | |||
| JACK_DBUS_SIGNALS_END | |||
| JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_session_manager, JACK_DBUS_IFACE_NAME) | |||
| JACK_DBUS_IFACE_EXPOSE_METHODS | |||
| JACK_DBUS_IFACE_EXPOSE_SIGNALS | |||
| JACK_DBUS_IFACE_END | |||
| @@ -25,6 +25,7 @@ | |||
| #include "jslist.h" | |||
| #include "jack/control.h" | |||
| #include "jack/jack.h" | |||
| #include "jack/session.h" | |||
| #include "jackdbus.h" | |||
| #include "list.h" | |||
| #include "params.h" | |||
| @@ -37,6 +38,16 @@ struct jack_controller_slave_driver | |||
| bool loaded; | |||
| }; | |||
| struct jack_session_pending_command | |||
| { | |||
| struct list_head siblings; | |||
| DBusConnection * connection; | |||
| DBusMessage * message; | |||
| jack_session_event_type_t type; | |||
| const char * target; | |||
| const char * path; | |||
| }; | |||
| struct jack_controller | |||
| { | |||
| jackctl_server_t *server; | |||
| @@ -54,6 +65,9 @@ struct jack_controller | |||
| union jackctl_parameter_value slave_drivers_vparam_value; | |||
| struct jack_dbus_object_descriptor dbus_descriptor; | |||
| pthread_mutex_t lock; | |||
| struct list_head session_pending_commands; | |||
| }; | |||
| #define DEFAULT_DRIVER "dummy" | |||
| @@ -183,6 +197,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 */ | |||
| @@ -105,6 +105,12 @@ void | |||
| jack_dbus_send_method_return( | |||
| struct jack_dbus_method_call * call) | |||
| { | |||
| if (call->message == NULL) | |||
| { | |||
| /* async call */ | |||
| return; | |||
| } | |||
| if (call->reply) | |||
| { | |||
| retry_send: | |||
| @@ -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', | |||
| @@ -2,7 +2,7 @@ | |||
| * session_notify.c -- ultra minimal session manager | |||
| * | |||
| * Copyright (C) 2010 Torben Hohn. | |||
| * | |||
| * | |||
| * 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, or | |||
| @@ -141,15 +141,15 @@ int main(int argc, char *argv[]) | |||
| retval = jack_session_notify( client, NULL, notify_type, save_path ); | |||
| for(i=0; retval[i].uuid; i++ ) { | |||
| for (i = 0; retval[i].uuid; i++) { | |||
| printf( "export SESSION_DIR=\"%s%s/\"\n", save_path, retval[i].client_name ); | |||
| printf( "%s &\n", retval[i].command ); | |||
| add_uuid_mapping(retval[i].uuid); | |||
| add_uuid_mapping(retval[i].uuid); | |||
| } | |||
| printf( "sleep 10\n" ); | |||
| for(k=0; retval[k].uuid; k++ ) { | |||
| for (k = 0; retval[k].uuid; k++) { | |||
| char* port_regexp = alloca( jack_client_name_size()+3 ); | |||
| char* client_name = jack_get_client_name_by_uuid( client, retval[k].uuid ); | |||
| @@ -163,12 +163,12 @@ int main(int argc, char *argv[]) | |||
| const char **connections; | |||
| if ((connections = jack_port_get_all_connections (client, jack_port_by_name(client, ports[i]))) != 0) { | |||
| for (j = 0; connections[j]; j++) { | |||
| char *src = map_port_name_to_uuid_port( ports[i] ); | |||
| char *dst = map_port_name_to_uuid_port( connections[j] ); | |||
| char *src = map_port_name_to_uuid_port( ports[i] ); | |||
| char *dst = map_port_name_to_uuid_port( connections[j] ); | |||
| printf( "jack_connect -u \"%s\" \"%s\"\n", src, dst ); | |||
| } | |||
| jack_free (connections); | |||
| } | |||
| } | |||
| } | |||
| jack_free(ports); | |||
| @@ -259,24 +259,7 @@ void JackSocketClientChannel::SessionNotify(int refnum, const char* target, jack | |||
| JackSessionNotifyResult res; | |||
| int intresult; | |||
| ServerSyncCall(&req, &res, &intresult); | |||
| jack_session_command_t* session_command = (jack_session_command_t *)malloc(sizeof(jack_session_command_t) * (res.fCommandList.size() + 1)); | |||
| int i = 0; | |||
| for (std::list<JackSessionCommand>::iterator ci=res.fCommandList.begin(); ci!=res.fCommandList.end(); ci++) { | |||
| session_command[i].uuid = strdup( ci->fUUID ); | |||
| session_command[i].client_name = strdup( ci->fClientName ); | |||
| session_command[i].command = strdup( ci->fCommand ); | |||
| session_command[i].flags = ci->fFlags; | |||
| i += 1; | |||
| } | |||
| session_command[i].uuid = NULL; | |||
| session_command[i].client_name = NULL; | |||
| session_command[i].command = NULL; | |||
| session_command[i].flags = (jack_session_flags_t)0; | |||
| *result = session_command; | |||
| *result = res.GetCommands(); | |||
| } | |||
| void JackSocketClientChannel::SessionReply(int refnum, int* result) | |||
| @@ -429,9 +429,8 @@ bool JackSocketServerChannel::HandleRequest(int fd) | |||
| case JackRequest::kSessionNotify: { | |||
| jack_log("JackRequest::SessionNotify"); | |||
| JackSessionNotifyRequest req; | |||
| JackSessionNotifyResult res; | |||
| if (req.Read(socket) == 0) { | |||
| fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, socket); | |||
| fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, socket, NULL); | |||
| } | |||
| break; | |||
| } | |||
| @@ -490,7 +489,7 @@ bool JackSocketServerChannel::HandleRequest(int fd) | |||
| JackClientHasSessionCallbackRequest req; | |||
| JackResult res; | |||
| if (req.Read(socket) == 0) { | |||
| fServer->GetEngine()->ClientHasSessionCallbackRequest(req.fName, &res.fResult); | |||
| fServer->GetEngine()->ClientHasSessionCallback(req.fName, &res.fResult); | |||
| } | |||
| if (res.Write(socket) < 0) | |||
| jack_error("JackRequest::ClientHasSessionCallback write error"); | |||
| @@ -263,24 +263,7 @@ void JackWinNamedPipeClientChannel::SessionNotify(int refnum, const char* target | |||
| JackSessionNotifyResult res; | |||
| int intresult; | |||
| ServerSyncCall(&req, &res, &intresult); | |||
| jack_session_command_t* session_command = (jack_session_command_t *)malloc(sizeof(jack_session_command_t) * (res.fCommandList.size() + 1)); | |||
| int i = 0; | |||
| for (std::list<JackSessionCommand>::iterator ci=res.fCommandList.begin(); ci!=res.fCommandList.end(); ci++) { | |||
| session_command[i].uuid = strdup( ci->fUUID ); | |||
| session_command[i].client_name = strdup( ci->fClientName ); | |||
| session_command[i].command = strdup( ci->fCommand ); | |||
| session_command[i].flags = ci->fFlags; | |||
| i += 1; | |||
| } | |||
| session_command[i].uuid = NULL; | |||
| session_command[i].client_name = NULL; | |||
| session_command[i].command = NULL; | |||
| session_command[i].flags = (jack_session_flags_t)0; | |||
| *result = session_command; | |||
| *result = res.GetCommands(); | |||
| } | |||
| void JackWinNamedPipeClientChannel::SessionReply(int refnum, int* result) | |||
| @@ -342,9 +342,8 @@ bool JackClientPipeThread::HandleRequest() | |||
| case JackRequest::kSessionNotify: { | |||
| jack_log("JackRequest::SessionNotify"); | |||
| JackSessionNotifyRequest req; | |||
| JackSessionNotifyResult res; | |||
| if (req.Read(fPipe) == 0) { | |||
| fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, fPipe); | |||
| fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, fPipe, NULL); | |||
| } | |||
| res.Write(fPipe); | |||
| break; | |||