git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4762 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.9.5
@@ -40,6 +40,7 @@ John Emmas | |||||
* Check server API callback from notification thread. | * Check server API callback from notification thread. | ||||
* Use a time-out in notification channel write function. | * Use a time-out in notification channel write function. | ||||
* Fix lock management in JackEngine. | |||||
2012-01-29 Stephane Letz <letz@grame.fr> | 2012-01-29 Stephane Letz <letz@grame.fr> | ||||
@@ -254,28 +254,42 @@ int JackEngine::ComputeTotalLatencies() | |||||
// Notifications | // Notifications | ||||
//--------------- | //--------------- | ||||
int JackEngine::ClientNotify(JackClientInterface* client, int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2) | |||||
{ | |||||
if (!client) { | |||||
return 0; | |||||
} | |||||
if (!client->GetClientControl()->fCallback[notify]) { | |||||
jack_log("JackEngine::ClientNotify: no callback for notification = %ld", notify); | |||||
return 0; | |||||
} | |||||
int ret; | |||||
// External client | |||||
if (dynamic_cast<JackExternalClient*>(client)) { | |||||
ret = client->ClientNotify(refnum, name, notify, sync, message, value1, value2); | |||||
// Important for internal client : unlock before calling the notification callbacks | |||||
} else { | |||||
bool res = Unlock(); | |||||
ret = client->ClientNotify(refnum, name, notify, sync, message, value1, value2); | |||||
if (res) { | |||||
Lock(); | |||||
} | |||||
} | |||||
if (ret < 0) { | |||||
jack_error("NotifyClient fails name = %s notification = %ld val1 = %ld val2 = %ld", name, notify, value1, value2); | |||||
} | |||||
return ret; | |||||
} | |||||
void JackEngine::NotifyClient(int refnum, int event, int sync, const char* message, int value1, int value2) | void JackEngine::NotifyClient(int refnum, int event, int sync, const char* message, int value1, int value2) | ||||
{ | { | ||||
JackClientInterface* client = fClientTable[refnum]; | JackClientInterface* client = fClientTable[refnum]; | ||||
// The client may be notified by the RT thread while closing | |||||
if (client) { | if (client) { | ||||
if (client->GetClientControl()->fCallback[event]) { | |||||
/* | |||||
Important for internal clients : unlock before calling the notification callbacks. | |||||
*/ | |||||
bool res = 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) { | |||||
Lock(); | |||||
} | |||||
} else { | |||||
jack_log("JackEngine::NotifyClient: no callback for event = %ld", event); | |||||
} | |||||
ClientNotify(client, refnum, client->GetClientControl()->fName, event, sync, message, value1, value2); | |||||
} | } | ||||
} | } | ||||
@@ -286,19 +300,21 @@ void JackEngine::NotifyClients(int event, int sync, const char* message, int val | |||||
} | } | ||||
} | } | ||||
int JackEngine::NotifyAddClient(JackClientInterface* new_client, const char* name, int refnum) | |||||
int JackEngine::NotifyAddClient(JackClientInterface* new_client, const char* new_name, int refnum) | |||||
{ | { | ||||
jack_log("JackEngine::NotifyAddClient: name = %s", name); | |||||
jack_log("JackEngine::NotifyAddClient: name = %s", new_name); | |||||
// Notify existing clients of the new client and new client of existing clients. | // Notify existing clients of the new client and new client of existing clients. | ||||
for (int i = 0; i < CLIENT_NUM; i++) { | for (int i = 0; i < CLIENT_NUM; i++) { | ||||
JackClientInterface* old_client = fClientTable[i]; | JackClientInterface* old_client = fClientTable[i]; | ||||
if (old_client && old_client != new_client) { | if (old_client && old_client != new_client) { | ||||
if (old_client->ClientNotify(refnum, name, kAddClient, false, "", 0, 0) < 0) { | |||||
jack_error("NotifyAddClient old_client fails name = %s", old_client->GetClientControl()->fName); | |||||
char* old_name = old_client->GetClientControl()->fName; | |||||
if (ClientNotify(old_client, refnum, new_name, kAddClient, false, "", 0, 0) < 0) { | |||||
jack_error("NotifyAddClient old_client fails name = %s", old_name); | |||||
// Not considered as a failure... | // Not considered as a failure... | ||||
} | } | ||||
if (new_client->ClientNotify(i, old_client->GetClientControl()->fName, kAddClient, true, "", 0, 0) < 0) { | |||||
jack_error("NotifyAddClient new_client fails name = %s", name); | |||||
if (ClientNotify(new_client, i, old_name, kAddClient, true, "", 0, 0) < 0) { | |||||
jack_error("NotifyAddClient new_client fails name = %s", new_name); | |||||
return -1; | return -1; | ||||
} | } | ||||
} | } | ||||
@@ -311,10 +327,7 @@ void JackEngine::NotifyRemoveClient(const char* name, int refnum) | |||||
{ | { | ||||
// Notify existing clients (including the one beeing suppressed) of the removed client | // Notify existing clients (including the one beeing suppressed) of the removed client | ||||
for (int i = 0; i < CLIENT_NUM; i++) { | for (int i = 0; i < CLIENT_NUM; i++) { | ||||
JackClientInterface* client = fClientTable[i]; | |||||
if (client) { | |||||
client->ClientNotify(refnum, name, kRemoveClient, false, "", 0, 0); | |||||
} | |||||
ClientNotify(fClientTable[i], refnum, name, kRemoveClient, false, "", 0, 0); | |||||
} | } | ||||
} | } | ||||
@@ -64,7 +64,7 @@ class SERVER_EXPORT JackEngine : public JackLockAble | |||||
int ClientCloseAux(int refnum, JackClientInterface* client, bool wait); | int ClientCloseAux(int refnum, JackClientInterface* client, bool wait); | ||||
void CheckXRun(jack_time_t callback_usecs); | void CheckXRun(jack_time_t callback_usecs); | ||||
int NotifyAddClient(JackClientInterface* new_client, const char* name, int refnum); | |||||
int NotifyAddClient(JackClientInterface* new_client, const char* new_name, int refnum); | |||||
void NotifyRemoveClient(const char* name, int refnum); | void NotifyRemoveClient(const char* name, int refnum); | ||||
void ProcessNext(jack_time_t callback_usecs); | void ProcessNext(jack_time_t callback_usecs); | ||||
@@ -76,6 +76,8 @@ class SERVER_EXPORT JackEngine : public JackLockAble | |||||
int AllocateRefnum(); | int AllocateRefnum(); | ||||
void ReleaseRefnum(int ref); | void ReleaseRefnum(int ref); | ||||
int ClientNotify(JackClientInterface* client, int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2); | |||||
void NotifyClient(int refnum, int event, int sync, const char* message, int value1, int value2); | void NotifyClient(int refnum, int event, int sync, const char* message, int value1, int value2); | ||||
void NotifyClients(int event, int sync, const char* message, int value1, int value2); | void NotifyClients(int event, int sync, const char* message, int value1, int value2); | ||||
@@ -37,7 +37,6 @@ int JackSocketNotifyChannel::Open(const char* name) | |||||
} | } | ||||
// Use a time out for notifications | // Use a time out for notifications | ||||
fNotifySocket.SetWriteTimeOut(SOCKET_TIME_OUT); | |||||
fNotifySocket.SetReadTimeOut(SOCKET_TIME_OUT); | fNotifySocket.SetReadTimeOut(SOCKET_TIME_OUT); | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -56,7 +55,6 @@ void JackSocketNotifyChannel::ClientNotify(int refnum, const char* name, int not | |||||
// Send notification | // Send notification | ||||
if (event.Write(&fNotifySocket) < 0) { | if (event.Write(&fNotifySocket) < 0) { | ||||
jack_error("Could not write notification"); | jack_error("Could not write notification"); | ||||
//fNotifySocket.Close(); | |||||
*result = -1; | *result = -1; | ||||
return; | return; | ||||
} | } | ||||
@@ -66,7 +64,6 @@ void JackSocketNotifyChannel::ClientNotify(int refnum, const char* name, int not | |||||
// Get result : use a time out | // Get result : use a time out | ||||
if (res.Read(&fNotifySocket) < 0) { | if (res.Read(&fNotifySocket) < 0) { | ||||
jack_error("Could not read notification result"); | jack_error("Could not read notification result"); | ||||
//fNotifySocket.Close(); | |||||
*result = -1; | *result = -1; | ||||
} else { | } else { | ||||
*result = res.fResult; | *result = res.fResult; | ||||
@@ -37,7 +37,6 @@ int JackWinNamedPipeNotifyChannel::Open(const char* name) | |||||
return -1; | return -1; | ||||
} | } | ||||
// TODO : use a time out for notifications | // TODO : use a time out for notifications | ||||
fNotifyPipe.SetWriteTimeOut(SOCKET_TIME_OUT); | |||||
fNotifyPipe.SetReadTimeOut(SOCKET_TIME_OUT); | fNotifyPipe.SetReadTimeOut(SOCKET_TIME_OUT); | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -56,7 +55,6 @@ void JackWinNamedPipeNotifyChannel::ClientNotify(int refnum, const char* name, i | |||||
// Send notification | // Send notification | ||||
if (event.Write(&fNotifyPipe) < 0) { | if (event.Write(&fNotifyPipe) < 0) { | ||||
jack_error("Could not write notification"); | jack_error("Could not write notification"); | ||||
//fNotifyPipe.Close(); | |||||
*result = -1; | *result = -1; | ||||
return; | return; | ||||
} | } | ||||
@@ -66,7 +64,6 @@ void JackWinNamedPipeNotifyChannel::ClientNotify(int refnum, const char* name, i | |||||
// Get result : use a time out | // Get result : use a time out | ||||
if (res.Read(&fNotifyPipe) < 0) { | if (res.Read(&fNotifyPipe) < 0) { | ||||
jack_error("Could not read result"); | jack_error("Could not read result"); | ||||
//fNotifyPipe.Close(); | |||||
*result = -1; | *result = -1; | ||||
} else { | } else { | ||||
*result = res.fResult; | *result = res.fResult; | ||||