diff --git a/common/JackEngine.cpp b/common/JackEngine.cpp index fabebb01..4dc1967f 100644 --- a/common/JackEngine.cpp +++ b/common/JackEngine.cpp @@ -35,8 +35,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. namespace Jack { -#define AssertRefnum(ref) assert(ref >= 0 && ref < CLIENT_NUM); - JackEngine::JackEngine(JackGraphManager* manager, JackSynchro* table, JackEngineControl* control) @@ -213,28 +211,28 @@ void JackEngine::NotifyClient(int refnum, int event, int sync, const char* messa JackClientInterface* client = fClientTable[refnum]; // The client may be notified by the RT thread while closing - if (!client) { - jack_log("JackEngine::NotifyClient: client not available anymore"); - } else if (client->GetClientControl()->fCallback[event]) { - if (client->ClientNotify(refnum, client->GetClientControl()->fName, event, sync, message, value1, value2) < 0) - jack_error("NotifyClient fails name = %s event = %ld val1 = %ld val2 = %ld", client->GetClientControl()->fName, event, value1, value2); - } else { - jack_log("JackEngine::NotifyClient: no callback for event = %ld", event); + if (client) { + + if (client && client->GetClientControl()->fCallback[event]) { + /* + Important for internal clients : unlock before calling the notification callbacks. + */ + bool res = fMutex.Unlock(); + if (client->ClientNotify(refnum, client->GetClientControl()->fName, event, sync, message, value1, value2) < 0) + jack_error("NotifyClient fails name = %s event = %ld val1 = %ld val2 = %ld", client->GetClientControl()->fName, event, value1, value2); + if (res) + fMutex.Lock(); + + } else { + jack_log("JackEngine::NotifyClient: no callback for event = %ld", event); + } } } -void JackEngine::NotifyClients(int event, int sync, const char* message, int value1, int value2) +void JackEngine::NotifyClients(int event, int sync, const char* message, int value1, int value2) { for (int i = 0; i < CLIENT_NUM; i++) { - JackClientInterface* client = fClientTable[i]; - if (client) { - if (client->GetClientControl()->fCallback[event]) { - if (client->ClientNotify(i, client->GetClientControl()->fName, event, sync, message, value1, value2) < 0) - jack_error("NotifyClient fails name = %s event = %ld val1 = %ld val2 = %ld", client->GetClientControl()->fName, event, value1, value2); - } else { - jack_log("JackEngine::NotifyClients: no callback for event = %ld", event); - } - } + NotifyClient(i, event, sync, message, value1, value2); } } @@ -274,8 +272,7 @@ void JackEngine::NotifyRemoveClient(const char* name, int refnum) void JackEngine::NotifyXRun(jack_time_t callback_usecs, float delayed_usecs) { // Use the audio thread => request thread communication channel - fEngineControl->ResetFrameTime(callback_usecs); - fEngineControl->NotifyXRun(delayed_usecs); + fEngineControl->NotifyXRun(callback_usecs, delayed_usecs); fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0); } @@ -348,14 +345,9 @@ void JackEngine::NotifyActivate(int refnum) int JackEngine::GetInternalClientName(int refnum, char* name_res) { - AssertRefnum(refnum); JackClientInterface* client = fClientTable[refnum]; - if (client) { - strncpy(name_res, client->GetClientControl()->fName, JACK_CLIENT_NAME_SIZE); - return 0; - } else { - return -1; - } + strncpy(name_res, client->GetClientControl()->fName, JACK_CLIENT_NAME_SIZE); + return 0; } int JackEngine::InternalClientHandle(const char* client_name, int* status, int* int_ref) @@ -378,7 +370,6 @@ int JackEngine::InternalClientHandle(const char* client_name, int* status, int* int JackEngine::InternalClientUnload(int refnum, int* status) { - AssertRefnum(refnum); JackClientInterface* client = fClientTable[refnum]; if (client) { int res = client->Close(); @@ -592,26 +583,19 @@ error: // Used for external clients int JackEngine::ClientExternalClose(int refnum) { - AssertRefnum(refnum); JackClientInterface* client = fClientTable[refnum]; - - if (client) { - fEngineControl->fTransport.ResetTimebase(refnum); - int res = ClientCloseAux(refnum, client, true); - client->Close(); - delete client; - return res; - } else { - return -1; - } + fEngineControl->fTransport.ResetTimebase(refnum); + int res = ClientCloseAux(refnum, client, true); + client->Close(); + delete client; + return res; } // Used for server internal clients or drivers when the RT thread is stopped int JackEngine::ClientInternalClose(int refnum, bool wait) { - AssertRefnum(refnum); JackClientInterface* client = fClientTable[refnum]; - return (client) ? ClientCloseAux(refnum, client, wait) : -1; + return ClientCloseAux(refnum, client, wait); } int JackEngine::ClientCloseAux(int refnum, JackClientInterface* client, bool wait) @@ -656,11 +640,9 @@ int JackEngine::ClientCloseAux(int refnum, JackClientInterface* client, bool wai int JackEngine::ClientActivate(int refnum, bool is_real_time) { - AssertRefnum(refnum); JackClientInterface* client = fClientTable[refnum]; - assert(fClientTable[refnum]); - jack_log("JackEngine::ClientActivate ref = %ld name = %s", refnum, client->GetClientControl()->fName); + if (is_real_time) fGraphManager->Activate(refnum); @@ -677,11 +659,7 @@ int JackEngine::ClientActivate(int refnum, bool is_real_time) // May be called without client int JackEngine::ClientDeactivate(int refnum) { - AssertRefnum(refnum); JackClientInterface* client = fClientTable[refnum]; - if (client == NULL) - return -1; - jack_log("JackEngine::ClientDeactivate ref = %ld name = %s", refnum, client->GetClientControl()->fName); // Disconnect all ports ==> notifications are sent @@ -717,9 +695,7 @@ int JackEngine::ClientDeactivate(int refnum) int JackEngine::PortRegister(int refnum, const char* name, const char *type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index) { jack_log("JackEngine::PortRegister ref = %ld name = %s type = %s flags = %d buffer_size = %d", refnum, name, type, flags, buffer_size); - AssertRefnum(refnum); - assert(fClientTable[refnum]); - + // Check if port name already exists if (fGraphManager->GetPort(name) != NO_PORT) { jack_error("port_name \"%s\" already exists", name); @@ -738,9 +714,7 @@ int JackEngine::PortRegister(int refnum, const char* name, const char *type, uns int JackEngine::PortUnRegister(int refnum, jack_port_id_t port_index) { jack_log("JackEngine::PortUnRegister ref = %ld port_index = %ld", refnum, port_index); - AssertRefnum(refnum); - assert(fClientTable[refnum]); - + // Disconnect port ==> notification is sent PortDisconnect(refnum, port_index, ALL_PORTS); @@ -755,7 +729,6 @@ int JackEngine::PortUnRegister(int refnum, jack_port_id_t port_index) int JackEngine::PortConnect(int refnum, const char* src, const char* dst) { jack_log("JackEngine::PortConnect src = %s dst = %s", src, dst); - AssertRefnum(refnum); jack_port_id_t port_src, port_dst; return (fGraphManager->GetTwoPorts(src, dst, &port_src, &port_dst) < 0) @@ -766,7 +739,6 @@ int JackEngine::PortConnect(int refnum, const char* src, const char* dst) int JackEngine::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst) { jack_log("JackEngine::PortConnect src = %d dst = %d", src, dst); - AssertRefnum(refnum); JackClientInterface* client; int ref; @@ -802,7 +774,6 @@ int JackEngine::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst) int JackEngine::PortDisconnect(int refnum, const char* src, const char* dst) { jack_log("JackEngine::PortDisconnect src = %s dst = %s", src, dst); - AssertRefnum(refnum); jack_port_id_t port_src, port_dst; return (fGraphManager->GetTwoPorts(src, dst, &port_src, &port_dst) < 0) @@ -813,8 +784,7 @@ int JackEngine::PortDisconnect(int refnum, const char* src, const char* dst) int JackEngine::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst) { jack_log("JackEngine::PortDisconnect src = %d dst = %d", src, dst); - AssertRefnum(refnum); - + if (dst == ALL_PORTS) { jack_int_t connections[CONNECTION_NUM_FOR_PORT]; @@ -850,7 +820,6 @@ int JackEngine::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t ds int JackEngine::PortRename(int refnum, jack_port_id_t port, const char* name) { - AssertRefnum(refnum); char old_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; strcpy(old_name, fGraphManager->GetPort(port)->GetName()); fGraphManager->GetPort(port)->SetName(name); diff --git a/common/JackEngine.h b/common/JackEngine.h index 3a4a24a9..945d7e9c 100644 --- a/common/JackEngine.h +++ b/common/JackEngine.h @@ -23,6 +23,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "JackConstants.h" #include "JackGraphManager.h" #include "JackSynchro.h" +#include "JackMutex.h" #include "JackTransportEngine.h" #include "JackPlatformPlug.h" @@ -37,8 +38,10 @@ class JackExternalClient; \brief Engine description. */ -class SERVER_EXPORT JackEngine +class SERVER_EXPORT JackEngine : public JackLockAble { + friend class JackLockedEngine; + private: JackGraphManager* fGraphManager; @@ -71,6 +74,11 @@ class SERVER_EXPORT JackEngine void NotifyPortConnect(jack_port_id_t src, jack_port_id_t dst, bool onoff); void NotifyPortRename(jack_port_id_t src, const char* old_name); void NotifyActivate(int refnum); + + bool CheckClient(int refnum) + { + return (refnum >= 0 && refnum < CLIENT_NUM && fClientTable[refnum] != NULL); + } public: diff --git a/common/JackEngineControl.cpp b/common/JackEngineControl.cpp index 872dcd32..db13ae78 100644 --- a/common/JackEngineControl.cpp +++ b/common/JackEngineControl.cpp @@ -81,8 +81,9 @@ void JackEngineControl::ResetRollingUsecs() fRollingInterval = int(floor((JACK_ENGINE_ROLLING_INTERVAL * 1000.f) / fPeriodUsecs)); } -void JackEngineControl::NotifyXRun(float delayed_usecs) +void JackEngineControl::NotifyXRun(jack_time_t callback_usecs, float delayed_usecs) { + ResetFrameTime(callback_usecs); fXrunDelayedUsecs = delayed_usecs; if (delayed_usecs > fMaxDelayedUsecs) fMaxDelayedUsecs = delayed_usecs; diff --git a/common/JackEngineControl.h b/common/JackEngineControl.h index 326e3b7f..3ba54b87 100644 --- a/common/JackEngineControl.h +++ b/common/JackEngineControl.h @@ -162,7 +162,7 @@ struct SERVER_EXPORT JackEngineControl : public JackShmMem } // XRun - void NotifyXRun(float delayed_usecs); + void NotifyXRun(jack_time_t callback_usecs, float delayed_usecs); void ResetXRun() { fMaxDelayedUsecs = 0.f; diff --git a/common/JackLockedEngine.h b/common/JackLockedEngine.h index a9f044a8..827ab527 100644 --- a/common/JackLockedEngine.h +++ b/common/JackLockedEngine.h @@ -37,7 +37,6 @@ See : http://groups.google.com/group/comp.programming.threads/browse_thread/thre catch (...) { // Assuming thread cancellation, must rethrow throw; - } */ @@ -62,11 +61,12 @@ catch (...) { throw; \ } \ + /*! \brief Locked Engine, access to methods is serialized using a mutex. */ -class SERVER_EXPORT JackLockedEngine : public JackLockAble +class SERVER_EXPORT JackLockedEngine { private: @@ -99,21 +99,21 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble int ClientCheck(const char* name, char* name_res, int protocol, int options, int* status) { TRY_CALL - JackLock lock(this); + JackLock lock(&fEngine); return fEngine.ClientCheck(name, name_res, protocol, options, status); CATCH_EXCEPTION_RETURN } int ClientExternalOpen(const char* name, int pid, int* ref, int* shared_engine, int* shared_client, int* shared_graph_manager) { TRY_CALL - JackLock lock(this); + JackLock lock(&fEngine); return fEngine.ClientExternalOpen(name, pid, ref, shared_engine, shared_client, shared_graph_manager); CATCH_EXCEPTION_RETURN } int ClientInternalOpen(const char* name, int* ref, JackEngineControl** shared_engine, JackGraphManager** shared_manager, JackClientInterface* client, bool wait) { TRY_CALL - JackLock lock(this); + JackLock lock(&fEngine); return fEngine.ClientInternalOpen(name, ref, shared_engine, shared_manager, client, wait); CATCH_EXCEPTION_RETURN } @@ -121,30 +121,30 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble int ClientExternalClose(int refnum) { TRY_CALL - JackLock lock(this); - return fEngine.ClientExternalClose(refnum); + JackLock lock(&fEngine); + return (fEngine.CheckClient(refnum)) ? fEngine.ClientExternalClose(refnum) : - 1; CATCH_EXCEPTION_RETURN } int ClientInternalClose(int refnum, bool wait) { TRY_CALL - JackLock lock(this); - return fEngine.ClientInternalClose(refnum, wait); + JackLock lock(&fEngine); + return (fEngine.CheckClient(refnum)) ? fEngine.ClientInternalClose(refnum, wait) : -1; CATCH_EXCEPTION_RETURN } int ClientActivate(int refnum, bool is_real_time) { TRY_CALL - JackLock lock(this); - return fEngine.ClientActivate(refnum, is_real_time); + JackLock lock(&fEngine); + return (fEngine.CheckClient(refnum)) ? fEngine.ClientActivate(refnum, is_real_time) : -1; CATCH_EXCEPTION_RETURN } int ClientDeactivate(int refnum) { TRY_CALL - JackLock lock(this); - return fEngine.ClientDeactivate(refnum); + JackLock lock(&fEngine); + return (fEngine.CheckClient(refnum)) ? fEngine.ClientDeactivate(refnum) : -1; CATCH_EXCEPTION_RETURN } @@ -152,21 +152,22 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble int GetInternalClientName(int int_ref, char* name_res) { TRY_CALL - JackLock lock(this); + JackLock lock(&fEngine); return fEngine.GetInternalClientName(int_ref, name_res); CATCH_EXCEPTION_RETURN } int InternalClientHandle(const char* client_name, int* status, int* int_ref) { TRY_CALL - JackLock lock(this); + JackLock lock(&fEngine); return fEngine.InternalClientHandle(client_name, status, int_ref); CATCH_EXCEPTION_RETURN } int InternalClientUnload(int refnum, int* status) { TRY_CALL - JackLock lock(this); + JackLock lock(&fEngine); + // Client is tested in fEngine.InternalClientUnload return fEngine.InternalClientUnload(refnum, status); CATCH_EXCEPTION_RETURN } @@ -175,53 +176,53 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble int PortRegister(int refnum, const char* name, const char *type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port) { TRY_CALL - JackLock lock(this); - return fEngine.PortRegister(refnum, name, type, flags, buffer_size, port); + JackLock lock(&fEngine); + return (fEngine.CheckClient(refnum)) ? fEngine.PortRegister(refnum, name, type, flags, buffer_size, port) : -1; CATCH_EXCEPTION_RETURN } int PortUnRegister(int refnum, jack_port_id_t port) { TRY_CALL - JackLock lock(this); - return fEngine.PortUnRegister(refnum, port); + JackLock lock(&fEngine); + return (fEngine.CheckClient(refnum)) ? fEngine.PortUnRegister(refnum, port) : -1; CATCH_EXCEPTION_RETURN } int PortConnect(int refnum, const char* src, const char* dst) { TRY_CALL - JackLock lock(this); - return fEngine.PortConnect(refnum, src, dst); + JackLock lock(&fEngine); + return (fEngine.CheckClient(refnum)) ? fEngine.PortConnect(refnum, src, dst) : -1; CATCH_EXCEPTION_RETURN } int PortDisconnect(int refnum, const char* src, const char* dst) { TRY_CALL - JackLock lock(this); - return fEngine.PortDisconnect(refnum, src, dst); + JackLock lock(&fEngine); + return (fEngine.CheckClient(refnum)) ? fEngine.PortDisconnect(refnum, src, dst) : -1; CATCH_EXCEPTION_RETURN } int PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst) { TRY_CALL - JackLock lock(this); - return fEngine.PortConnect(refnum, src, dst); + JackLock lock(&fEngine); + return (fEngine.CheckClient(refnum)) ? fEngine.PortConnect(refnum, src, dst) : -1; CATCH_EXCEPTION_RETURN } int PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst) { TRY_CALL - JackLock lock(this); - return fEngine.PortDisconnect(refnum, src, dst); + JackLock lock(&fEngine); + return (fEngine.CheckClient(refnum)) ? fEngine.PortDisconnect(refnum, src, dst) : -1; CATCH_EXCEPTION_RETURN } int PortRename(int refnum, jack_port_id_t port, const char* name) { TRY_CALL - JackLock lock(this); - return fEngine.PortRename(refnum, port, name); + JackLock lock(&fEngine); + return (fEngine.CheckClient(refnum)) ? fEngine.PortRename(refnum, port, name) : -1; CATCH_EXCEPTION_RETURN } @@ -241,36 +242,35 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble void NotifyXRun(int refnum) { - TRY_CALL - JackLock lock(this); + // RT : no lock fEngine.NotifyXRun(refnum); - CATCH_EXCEPTION } + void NotifyGraphReorder() { TRY_CALL - JackLock lock(this); + JackLock lock(&fEngine); fEngine.NotifyGraphReorder(); CATCH_EXCEPTION } void NotifyBufferSize(jack_nframes_t buffer_size) { TRY_CALL - JackLock lock(this); + JackLock lock(&fEngine); fEngine.NotifyBufferSize(buffer_size); CATCH_EXCEPTION } void NotifySampleRate(jack_nframes_t sample_rate) { TRY_CALL - JackLock lock(this); + JackLock lock(&fEngine); fEngine.NotifySampleRate(sample_rate); CATCH_EXCEPTION } void NotifyFreewheel(bool onoff) { TRY_CALL - JackLock lock(this); + JackLock lock(&fEngine); fEngine.NotifyFreewheel(onoff); CATCH_EXCEPTION } @@ -278,7 +278,7 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble void NotifyFailure(int code, const char* reason) { TRY_CALL - JackLock lock(this); + JackLock lock(&fEngine); fEngine.NotifyFailure(code, reason); CATCH_EXCEPTION } @@ -286,7 +286,7 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble int GetClientPID(const char* name) { TRY_CALL - JackLock lock(this); + JackLock lock(&fEngine); return fEngine.GetClientPID(name); CATCH_EXCEPTION_RETURN } @@ -294,7 +294,7 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble int GetClientRefNum(const char* name) { TRY_CALL - JackLock lock(this); + JackLock lock(&fEngine); return fEngine.GetClientRefNum(name); CATCH_EXCEPTION_RETURN } @@ -302,7 +302,7 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble void NotifyQuit() { TRY_CALL - JackLock lock(this); + JackLock lock(&fEngine); return fEngine.NotifyQuit(); CATCH_EXCEPTION } diff --git a/common/JackMutex.h b/common/JackMutex.h index e2472add..0a2600d7 100644 --- a/common/JackMutex.h +++ b/common/JackMutex.h @@ -36,11 +36,9 @@ namespace Jack class JackLockAble { - private: - - JackMutex fMutex; - protected: + + JackMutex fMutex; JackLockAble() {} diff --git a/posix/JackPosixMutex.h b/posix/JackPosixMutex.h index 91d21132..ddf89553 100644 --- a/posix/JackPosixMutex.h +++ b/posix/JackPosixMutex.h @@ -103,11 +103,12 @@ class JackPosixMutex pthread_mutex_destroy(&fMutex); } - void Lock() + bool Lock() { int res = pthread_mutex_lock(&fMutex); if (res != 0) jack_error("JackPosixMutex::Lock res = %d", res); + return (res == 0); } bool Trylock() @@ -115,11 +116,12 @@ class JackPosixMutex return (pthread_mutex_trylock(&fMutex) == 0); } - void Unlock() + bool Unlock() { int res = pthread_mutex_unlock(&fMutex); if (res != 0) jack_error("JackPosixMutex::Unlock res = %d", res); + return (res == 0); } };