| @@ -1859,3 +1859,36 @@ EXPORT void jack_free(void* ptr) | |||||
| free(ptr); | free(ptr); | ||||
| } | } | ||||
| } | } | ||||
| // session.h | |||||
| EXPORT int jack_set_session_callback(jack_client_t* ext_client, JackSessionCallback session_callback, void* arg) | |||||
| { | |||||
| #ifdef __CLIENTDEBUG__ | |||||
| JackGlobals::CheckContext("jack_set_session_callback"); | |||||
| #endif | |||||
| JackClient* client = (JackClient*)ext_client; | |||||
| jack_log("jack_set_session_callback ext_client %x client %x ", ext_client, client); | |||||
| if (client == NULL) { | |||||
| jack_error("jack_set_session_callback called with a NULL client"); | |||||
| return -1; | |||||
| } else { | |||||
| return client->SetSessionCallback(session_callback, arg); | |||||
| } | |||||
| } | |||||
| EXPORT jack_session_command_t *jack_session_notify(jack_client_t* ext_client, const char* target, jack_session_event_type_t ev_type, const char *path) | |||||
| { | |||||
| #ifdef __CLIENTDEBUG__ | |||||
| JackGlobals::CheckContext("jack_session_notify"); | |||||
| #endif | |||||
| JackClient* client = (JackClient*)ext_client; | |||||
| jack_log("jack_session_notify ext_client %x client %x ", ext_client, client); | |||||
| if (client == NULL) { | |||||
| jack_error("jack_session_notify called with a NULL client"); | |||||
| return NULL; | |||||
| } else { | |||||
| return client->SessionNotify(target, ev_type, path); | |||||
| } | |||||
| } | |||||
| @@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| #define __JackChannel__ | #define __JackChannel__ | ||||
| #include "types.h" | #include "types.h" | ||||
| #include "session.h" | |||||
| namespace Jack | namespace Jack | ||||
| { | { | ||||
| @@ -126,6 +127,8 @@ class JackClientChannelInterface | |||||
| virtual void InternalClientUnload(int refnum, int int_ref, int* status, int* result) | virtual void InternalClientUnload(int refnum, int int_ref, int* status, int* result) | ||||
| {} | {} | ||||
| virtual void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char *path, int *result) | |||||
| {} | |||||
| }; | }; | ||||
| } | } | ||||
| @@ -981,6 +981,19 @@ int JackClient::SetProcessThread(JackThreadCallback fun, void *arg) | |||||
| } | } | ||||
| } | } | ||||
| int JackClient::SetSessionCallback(JackSessionCallback callback, void *arg) | |||||
| { | |||||
| if (IsActive()) { | |||||
| jack_error("You cannot set callbacks on an active client"); | |||||
| return -1; | |||||
| } else { | |||||
| GetClientControl()->fCallback[kSessionCallback] = (callback != NULL); | |||||
| fSessionArg = arg; | |||||
| fSession = callback; | |||||
| return 0; | |||||
| } | |||||
| } | |||||
| //------------------ | //------------------ | ||||
| // Internal clients | // Internal clients | ||||
| //------------------ | //------------------ | ||||
| @@ -1038,6 +1051,15 @@ void JackClient::InternalClientUnload(int ref, jack_status_t* status) | |||||
| fChannel->InternalClientUnload(GetClientControl()->fRefNum, ref, (int*)status, &result); | fChannel->InternalClientUnload(GetClientControl()->fRefNum, ref, (int*)status, &result); | ||||
| } | } | ||||
| //------------------ | |||||
| // Session API | |||||
| //------------------ | |||||
| jack_session_command_t *JackClient::SessionNotify( const char* target, jack_session_event_type_t type, const char* path ) | |||||
| { | |||||
| return NULL; | |||||
| } | |||||
| } // end of namespace | } // end of namespace | ||||
| @@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| #include "JackPlatformPlug.h" | #include "JackPlatformPlug.h" | ||||
| #include "JackChannel.h" | #include "JackChannel.h" | ||||
| #include "types.h" | #include "types.h" | ||||
| #include "session.h" | |||||
| #include "varargs.h" | #include "varargs.h" | ||||
| #include <list> | #include <list> | ||||
| @@ -66,6 +67,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||||
| JackTimebaseCallback fTimebase; | JackTimebaseCallback fTimebase; | ||||
| JackSyncCallback fSync; | JackSyncCallback fSync; | ||||
| JackThreadCallback fThreadFun; | JackThreadCallback fThreadFun; | ||||
| JackSessionCallback fSession; | |||||
| void* fProcessArg; | void* fProcessArg; | ||||
| void* fGraphOrderArg; | void* fGraphOrderArg; | ||||
| @@ -83,6 +85,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||||
| void* fTimebaseArg; | void* fTimebaseArg; | ||||
| void* fSyncArg; | void* fSyncArg; | ||||
| void* fThreadFunArg; | void* fThreadFunArg; | ||||
| void* fSessionArg; | |||||
| char fServerName[64]; | char fServerName[64]; | ||||
| JackThread fThread; /*! Thread to execute the Process function */ | JackThread fThread; /*! Thread to execute the Process function */ | ||||
| @@ -173,6 +176,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||||
| virtual int SetPortRegistrationCallback(JackPortRegistrationCallback callback, void* arg); | virtual int SetPortRegistrationCallback(JackPortRegistrationCallback callback, void* arg); | ||||
| virtual int SetPortConnectCallback(JackPortConnectCallback callback, void *arg); | virtual int SetPortConnectCallback(JackPortConnectCallback callback, void *arg); | ||||
| virtual int SetPortRenameCallback(JackPortRenameCallback callback, void *arg); | virtual int SetPortRenameCallback(JackPortRenameCallback callback, void *arg); | ||||
| virtual int SetSessionCallback(JackSessionCallback callback, void *arg); | |||||
| // Internal clients | // Internal clients | ||||
| virtual char* GetInternalClientName(int ref); | virtual char* GetInternalClientName(int ref); | ||||
| @@ -184,6 +188,9 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||||
| void CycleSignal(int status); | void CycleSignal(int status); | ||||
| int SetProcessThread(JackThreadCallback fun, void *arg); | int SetProcessThread(JackThreadCallback fun, void *arg); | ||||
| // Session api | |||||
| virtual jack_session_command_t *SessionNotify(const char *target, jack_session_event_type_t type, const char *path); | |||||
| // JackRunnableInterface interface | // JackRunnableInterface interface | ||||
| bool Init(); | bool Init(); | ||||
| bool Execute(); | bool Execute(); | ||||
| @@ -863,5 +863,12 @@ int JackEngine::PortRename(int refnum, jack_port_id_t port, const char* name) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| void JackEngine::SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, int *result ) | |||||
| { | |||||
| // yay... :( | |||||
| *result = 0; | |||||
| } | |||||
| } // end of namespace | } // end of namespace | ||||
| @@ -131,6 +131,8 @@ class SERVER_EXPORT JackEngine : public JackLockAble | |||||
| void NotifySampleRate(jack_nframes_t sample_rate); | void NotifySampleRate(jack_nframes_t sample_rate); | ||||
| void NotifyFreewheel(bool onoff); | void NotifyFreewheel(bool onoff); | ||||
| void NotifyQuit(); | void NotifyQuit(); | ||||
| void SessionNotify( int refnum, const char *target, jack_session_event_type_t type, const char *path, int *result ); | |||||
| }; | }; | ||||
| @@ -112,6 +112,11 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface | |||||
| *result = fServer->SetFreewheel(onoff); | *result = fServer->SetFreewheel(onoff); | ||||
| } | } | ||||
| void SessionNotify( int refnum, const char *target, jack_session_event_type_t type, const char *path, jack_session_command_t **result ) | |||||
| { | |||||
| *result = NULL; | |||||
| } | |||||
| void ReleaseTimebase(int refnum, int* result) | void ReleaseTimebase(int refnum, int* result) | ||||
| { | { | ||||
| *result = fServer->ReleaseTimebase(refnum); | *result = fServer->ReleaseTimebase(refnum); | ||||
| @@ -306,6 +306,14 @@ class SERVER_EXPORT JackLockedEngine | |||||
| return fEngine.NotifyQuit(); | return fEngine.NotifyQuit(); | ||||
| CATCH_EXCEPTION | CATCH_EXCEPTION | ||||
| } | } | ||||
| void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char *path, int *result) | |||||
| { | |||||
| TRY_CALL | |||||
| JackLock lock(&fEngine); | |||||
| return fEngine.SessionNotify( refnum, target, type, path, result ); | |||||
| CATCH_EXCEPTION | |||||
| } | |||||
| }; | }; | ||||
| @@ -45,6 +45,7 @@ enum NotificationType { | |||||
| kRealTimeCallback = 14, | kRealTimeCallback = 14, | ||||
| kShutDownCallback = 15, | kShutDownCallback = 15, | ||||
| kQUIT = 16, | kQUIT = 16, | ||||
| kSessionCallback = 17, | |||||
| kMaxNotification | kMaxNotification | ||||
| }; | }; | ||||
| @@ -65,7 +65,11 @@ struct JackRequest | |||||
| kInternalClientLoad = 29, | kInternalClientLoad = 29, | ||||
| kInternalClientUnload = 30, | kInternalClientUnload = 30, | ||||
| kPortRename = 31, | kPortRename = 31, | ||||
| kNotification = 32 | |||||
| kNotification = 32, | |||||
| kSessionNotify = 33, | |||||
| kSessionReply = 34, | |||||
| kGetClientByUUID = 35, | |||||
| kReserveClientName = 36 | |||||
| }; | }; | ||||
| RequestType fType; | RequestType fType; | ||||
| @@ -1067,6 +1071,110 @@ struct JackClientNotificationRequest : public JackRequest | |||||
| } POST_PACKED_STRUCTURE; | } POST_PACKED_STRUCTURE; | ||||
| struct JackSessionNotifyResult : public JackResult | |||||
| { | |||||
| int fStatus; | |||||
| JackSessionNotifyResult(): JackResult() | |||||
| {} | |||||
| JackSessionNotifyResult(int32_t result, int status) | |||||
| : JackResult(result), fStatus(status) | |||||
| {} | |||||
| int Read(JackChannelTransaction* trans) | |||||
| { | |||||
| CheckRes(JackResult::Read(trans)); | |||||
| CheckRes(trans->Read(&fStatus, sizeof(int))); | |||||
| return 0; | |||||
| } | |||||
| int Write(JackChannelTransaction* trans) | |||||
| { | |||||
| CheckRes(JackResult::Write(trans)); | |||||
| CheckRes(trans->Write(&fStatus, sizeof(int))); | |||||
| return 0; | |||||
| } | |||||
| } POST_PACKED_STRUCTURE; | |||||
| /*! | |||||
| \brief SessionNotify request. | |||||
| */ | |||||
| 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; | |||||
| JackSessionNotifyRequest() | |||||
| {} | |||||
| 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) | |||||
| snprintf(fDst, sizeof(fDst), "%s", dst); | |||||
| else | |||||
| fDst[0] = '\0'; | |||||
| } | |||||
| int Read(JackChannelTransaction* trans) | |||||
| { | |||||
| CheckRes(trans->Read(&fRefNum, sizeof(fRefNum))); | |||||
| CheckRes(trans->Read(&fPath, sizeof(fPath))); | |||||
| CheckRes(trans->Read(&fDst, sizeof(fDst))); | |||||
| CheckRes(trans->Read(&fEventType, sizeof(fEventType))); | |||||
| return 0; | |||||
| } | |||||
| int Write(JackChannelTransaction* trans) | |||||
| { | |||||
| CheckRes(JackRequest::Write(trans)); | |||||
| CheckRes(trans->Write(&fRefNum, sizeof(fRefNum))); | |||||
| CheckRes(trans->Write(&fPath, sizeof(fPath))); | |||||
| CheckRes(trans->Write(&fDst, sizeof(fDst))); | |||||
| CheckRes(trans->Write(&fEventType, sizeof(fEventType))); | |||||
| return 0; | |||||
| } | |||||
| } POST_PACKED_STRUCTURE; | |||||
| struct JackSessionReplyRequest : public JackRequest | |||||
| { | |||||
| char fCommand[JACK_MESSAGE_SIZE + 1]; | |||||
| int fFlags; | |||||
| JackSessionReplyRequest() | |||||
| {} | |||||
| JackSessionReplyRequest(const char *command, int flags) | |||||
| : JackRequest(JackRequest::kSessionNotify), fFlags(flags) | |||||
| { | |||||
| if (command) | |||||
| snprintf(fCommand, sizeof(fCommand), "%s", command); | |||||
| else | |||||
| fCommand[0] = '\0'; | |||||
| } | |||||
| int Read(JackChannelTransaction* trans) | |||||
| { | |||||
| CheckRes(trans->Read(&fCommand, sizeof(fCommand))); | |||||
| CheckRes(trans->Read(&fFlags, sizeof(fFlags))); | |||||
| return 0; | |||||
| } | |||||
| int Write(JackChannelTransaction* trans) | |||||
| { | |||||
| CheckRes(JackRequest::Write(trans)); | |||||
| CheckRes(trans->Write(&fCommand, sizeof(fCommand))); | |||||
| CheckRes(trans->Write(&fFlags, sizeof(fFlags))); | |||||
| return 0; | |||||
| } | |||||
| } POST_PACKED_STRUCTURE; | |||||
| /*! | /*! | ||||
| \brief ClientNotification. | \brief ClientNotification. | ||||
| */ | */ | ||||
| @@ -251,6 +251,20 @@ void JackMachClientChannel::SetFreewheel(int onoff, int* result) | |||||
| } | } | ||||
| } | } | ||||
| void JackMachClientChannel::SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char *path, jack_session_command_t **result) | |||||
| { | |||||
| // dunno, how to generate this rpc stuff. | |||||
| #if 0 | |||||
| kern_return_t res = rpc_jack_session_notify(fPrivatePort, target, type, path, result); | |||||
| if (res != KERN_SUCCESS) { | |||||
| *result = -1; | |||||
| jack_error("JackMachClientChannel::SetFreewheel err = %s", mach_error_string(res)); | |||||
| } | |||||
| #else | |||||
| *result = NULL; | |||||
| #endif | |||||
| } | |||||
| void JackMachClientChannel::ReleaseTimebase(int refnum, int* result) | void JackMachClientChannel::ReleaseTimebase(int refnum, int* result) | ||||
| { | { | ||||
| kern_return_t res = rpc_jack_release_timebase(fPrivatePort, refnum, result); | kern_return_t res = rpc_jack_release_timebase(fPrivatePort, refnum, result); | ||||
| @@ -246,6 +246,16 @@ void JackSocketClientChannel::SetFreewheel(int onoff, int* result) | |||||
| ServerSyncCall(&req, &res, result); | ServerSyncCall(&req, &res, result); | ||||
| } | } | ||||
| void JackSocketClientChannel::SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, int* result) | |||||
| { | |||||
| JackSessionNotifyRequest req(refnum, target, type, path); | |||||
| JackResult res; | |||||
| int intresult; | |||||
| ServerSyncCall(&req, &res, &intresult); | |||||
| *result = 0; | |||||
| } | |||||
| void JackSocketClientChannel::ReleaseTimebase(int refnum, int* result) | void JackSocketClientChannel::ReleaseTimebase(int refnum, int* result) | ||||
| { | { | ||||
| JackReleaseTimebaseRequest req(refnum); | JackReleaseTimebaseRequest req(refnum); | ||||
| @@ -94,6 +94,8 @@ class JackSocketClientChannel : public detail::JackClientChannelInterface, publi | |||||
| // JackRunnableInterface interface | // JackRunnableInterface interface | ||||
| bool Init(); | bool Init(); | ||||
| bool Execute(); | bool Execute(); | ||||
| void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, int* result); | |||||
| }; | }; | ||||
| } // end of namespace | } // end of namespace | ||||
| @@ -400,6 +400,18 @@ bool JackSocketServerChannel::HandleRequest(int fd) | |||||
| break; | break; | ||||
| } | } | ||||
| 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, &res.fStatus); | |||||
| } | |||||
| if (res.Write(socket) < 0) | |||||
| jack_error("JackRequest::SessionNotify write error ref = %d", req.fRefNum); | |||||
| break; | |||||
| } | |||||
| default: | default: | ||||
| jack_error("Unknown request %ld", header.fType); | jack_error("Unknown request %ld", header.fType); | ||||
| break; | break; | ||||
| @@ -246,6 +246,16 @@ void JackWinNamedPipeClientChannel::SetFreewheel(int onoff, int* result) | |||||
| ServerSyncCall(&req, &res, result); | ServerSyncCall(&req, &res, result); | ||||
| } | } | ||||
| void JackWinNamedPipeClientChannel::SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, jack_session_command_t** result) | |||||
| { | |||||
| JackSessionNotifyRequest req(refnum, target, type, path); | |||||
| JackResult res; | |||||
| int intresult; | |||||
| ServerSyncCall(&req, &res, &intresult); | |||||
| *result = NULL; | |||||
| } | |||||
| void JackWinNamedPipeClientChannel::ReleaseTimebase(int refnum, int* result) | void JackWinNamedPipeClientChannel::ReleaseTimebase(int refnum, int* result) | ||||
| { | { | ||||
| JackReleaseTimebaseRequest req(refnum); | JackReleaseTimebaseRequest req(refnum); | ||||
| @@ -326,6 +326,17 @@ bool JackClientPipeThread::HandleRequest() | |||||
| break; | break; | ||||
| } | } | ||||
| 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); | |||||
| } | |||||
| res.Write(fPipe); | |||||
| break; | |||||
| } | |||||
| default: | default: | ||||
| jack_log("Unknown request %ld", header.fType); | jack_log("Unknown request %ld", header.fType); | ||||
| break; | break; | ||||