| @@ -1859,3 +1859,36 @@ EXPORT void jack_free(void* 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__ | |||
| #include "types.h" | |||
| #include "session.h" | |||
| namespace Jack | |||
| { | |||
| @@ -126,6 +127,8 @@ class JackClientChannelInterface | |||
| 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 | |||
| //------------------ | |||
| @@ -1038,6 +1051,15 @@ void JackClient::InternalClientUnload(int ref, jack_status_t* status) | |||
| 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 | |||
| @@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| #include "JackPlatformPlug.h" | |||
| #include "JackChannel.h" | |||
| #include "types.h" | |||
| #include "session.h" | |||
| #include "varargs.h" | |||
| #include <list> | |||
| @@ -66,6 +67,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||
| JackTimebaseCallback fTimebase; | |||
| JackSyncCallback fSync; | |||
| JackThreadCallback fThreadFun; | |||
| JackSessionCallback fSession; | |||
| void* fProcessArg; | |||
| void* fGraphOrderArg; | |||
| @@ -83,6 +85,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||
| void* fTimebaseArg; | |||
| void* fSyncArg; | |||
| void* fThreadFunArg; | |||
| void* fSessionArg; | |||
| char fServerName[64]; | |||
| 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 SetPortConnectCallback(JackPortConnectCallback callback, void *arg); | |||
| virtual int SetPortRenameCallback(JackPortRenameCallback callback, void *arg); | |||
| virtual int SetSessionCallback(JackSessionCallback callback, void *arg); | |||
| // Internal clients | |||
| virtual char* GetInternalClientName(int ref); | |||
| @@ -184,6 +188,9 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||
| void CycleSignal(int status); | |||
| 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 | |||
| bool Init(); | |||
| bool Execute(); | |||
| @@ -863,5 +863,12 @@ int JackEngine::PortRename(int refnum, jack_port_id_t port, const char* name) | |||
| 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 | |||
| @@ -131,6 +131,8 @@ class SERVER_EXPORT JackEngine : public JackLockAble | |||
| void NotifySampleRate(jack_nframes_t sample_rate); | |||
| void NotifyFreewheel(bool onoff); | |||
| 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); | |||
| } | |||
| 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) | |||
| { | |||
| *result = fServer->ReleaseTimebase(refnum); | |||
| @@ -306,6 +306,14 @@ class SERVER_EXPORT JackLockedEngine | |||
| return fEngine.NotifyQuit(); | |||
| 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, | |||
| kShutDownCallback = 15, | |||
| kQUIT = 16, | |||
| kSessionCallback = 17, | |||
| kMaxNotification | |||
| }; | |||
| @@ -65,7 +65,11 @@ struct JackRequest | |||
| kInternalClientLoad = 29, | |||
| kInternalClientUnload = 30, | |||
| kPortRename = 31, | |||
| kNotification = 32 | |||
| kNotification = 32, | |||
| kSessionNotify = 33, | |||
| kSessionReply = 34, | |||
| kGetClientByUUID = 35, | |||
| kReserveClientName = 36 | |||
| }; | |||
| RequestType fType; | |||
| @@ -1067,6 +1071,110 @@ struct JackClientNotificationRequest : public JackRequest | |||
| } 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. | |||
| */ | |||
| @@ -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) | |||
| { | |||
| 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); | |||
| } | |||
| 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) | |||
| { | |||
| JackReleaseTimebaseRequest req(refnum); | |||
| @@ -94,6 +94,8 @@ class JackSocketClientChannel : public detail::JackClientChannelInterface, publi | |||
| // JackRunnableInterface interface | |||
| bool Init(); | |||
| bool Execute(); | |||
| void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, int* result); | |||
| }; | |||
| } // end of namespace | |||
| @@ -400,6 +400,18 @@ bool JackSocketServerChannel::HandleRequest(int fd) | |||
| 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: | |||
| jack_error("Unknown request %ld", header.fType); | |||
| break; | |||
| @@ -246,6 +246,16 @@ void JackWinNamedPipeClientChannel::SetFreewheel(int onoff, int* 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) | |||
| { | |||
| JackReleaseTimebaseRequest req(refnum); | |||
| @@ -326,6 +326,17 @@ bool JackClientPipeThread::HandleRequest() | |||
| 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: | |||
| jack_log("Unknown request %ld", header.fType); | |||
| break; | |||