git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@1243 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.59
@@ -2,6 +2,10 @@ | |||
Jackdmp changes log | |||
--------------------------- | |||
2006-09-20 Stephane Letz <letz@grame.fr> | |||
* On Windows, avoid to use the unsafe Kill thread method. Use thread Stop instead and have blocked IO be unlocked. | |||
2006-09-16 Stephane Letz <letz@grame.fr> | |||
* Restore behaviour of LoopBack driver, which has to be opened in any case... | |||
@@ -22,6 +26,7 @@ | |||
2006-09-06 Stephane Letz <letz@grame.fr> | |||
* Correct coreaudio driver (input was not working since 0.55 version). | |||
* Version for 0.58 release. | |||
2006-09-04 Stephane Letz <letz@grame.fr> | |||
@@ -29,4 +34,4 @@ | |||
2006-09-03 Stephane Letz <letz@grame.fr> | |||
* First import of version 0.58 code | |||
* First import of version 0.58 base code |
@@ -188,8 +188,8 @@ int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, | |||
res = fXrun(fXrunArg); | |||
break; | |||
case JackNotifyChannelInterface::kZombifyClient: | |||
res = fThread->Kill(); | |||
case JackNotifyChannelInterface::kZombifyClient: | |||
//res = fThread->Kill(); Really neede ?? Unsafe in WIN32... | |||
JackLog("JackClient::kZombifyClient name = %s ref = %ld \n", name, refnum); | |||
ShutDown(); | |||
break; | |||
@@ -207,10 +207,16 @@ int JackClient::Activate() | |||
{ | |||
JackLog("JackClient::Activate \n"); | |||
if (IsActive()) | |||
return 0; | |||
if (StartThread() < 0) | |||
return -1; | |||
return 0; | |||
// Done first so that the RT thread then access an allocated synchro | |||
if (!fSynchroTable[GetClientControl()->fRefNum]->Connect(GetClientControl()->fName)) { | |||
jack_error("Cannot ConnectSemaphore %s client", GetClientControl()->fName); | |||
return -1; | |||
} | |||
if (StartThread() < 0) | |||
return -1; | |||
int result = -1; | |||
fChannel->ClientActivate(GetClientControl()->fRefNum, &result); | |||
@@ -242,7 +248,13 @@ int JackClient::Deactivate() | |||
JackLog("JackClient::Deactivate res = %ld \n", result); | |||
// We need to wait for the new engine cycle before stopping the RT thread, but this is done by ClientDeactivate | |||
fThread->Kill(); | |||
// steph | |||
fSynchroTable[GetClientControl()->fRefNum]->Disconnect(); | |||
fThread->Stop(); | |||
//fThread->Kill(); | |||
return result; | |||
} | |||
@@ -747,8 +747,10 @@ const char** JackGraphManager::GetPorts(const char* port_name_pattern, const cha | |||
do { | |||
cur_index = GetCurrentIndex(); | |||
if (matching_ports) | |||
free(matching_ports); | |||
if (matching_ports) { | |||
free(matching_ports); | |||
JackLog("JackGraphManager::GetPorts retry... \n"); | |||
} | |||
matching_ports = GetPortsAux(port_name_pattern, type_name_pattern, flags); | |||
next_index = GetCurrentIndex(); | |||
} while (cur_index != next_index); // Until a coherent state has been read | |||
@@ -99,10 +99,12 @@ int JackLibClient::Open(const char* name) | |||
SetupDriverSync(false); | |||
// Connect shared synchro : the synchro must be usable in I/O mode when several clients live in the same process | |||
if (!fSynchroTable[fClientControl->fRefNum]->Connect(name)) { | |||
/* | |||
if (!fSynchroTable[fClientControl->fRefNum]->Connect(name)) { | |||
jack_error("Cannot ConnectSemaphore %s client", name); | |||
goto error; | |||
} | |||
} | |||
*/ | |||
JackLog("JackLibClient::Open name = %s refnum = %ld\n", name, fClientControl->fRefNum); | |||
return 0; | |||
@@ -114,7 +114,8 @@ bool JackWinEvent::ConnectOutput(const char* name) | |||
bool JackWinEvent::Disconnect() | |||
{ | |||
if (fEvent) { | |||
JackLog("JackWinEvent::Disconnect %s\n", fName); | |||
JackLog("JackWinEvent::Disconnect %s\n", fName); | |||
SetEvent(fEvent); // to "unlock" threads pending on the event | |||
CloseHandle(fEvent); | |||
fEvent = NULL; | |||
return true; | |||
@@ -284,8 +284,10 @@ bool JackWinNamedPipeServer::Accept() | |||
JackWinNamedPipeClient* JackWinNamedPipeServer::AcceptClient() | |||
{ | |||
if (ConnectNamedPipe(fNamedPipe, NULL)) { | |||
return new JackWinNamedPipeClient(fNamedPipe); | |||
if (ConnectNamedPipe(fNamedPipe, NULL)) { | |||
JackWinNamedPipeClient* client = new JackWinNamedPipeClient(fNamedPipe); | |||
// Init the pipe to the default value | |||
fNamedPipe = INVALID_HANDLE_VALUE; | |||
} else { | |||
switch (GetLastError()) { | |||
@@ -302,8 +304,10 @@ JackWinNamedPipeClient* JackWinNamedPipeServer::AcceptClient() | |||
int JackWinNamedPipeServer::Close() | |||
{ | |||
if (fNamedPipe != INVALID_HANDLE_VALUE) { | |||
DisconnectNamedPipe(fNamedPipe); | |||
JackLog("JackWinNamedPipeServer::Close\n"); | |||
if (fNamedPipe != INVALID_HANDLE_VALUE) { | |||
DisconnectNamedPipe(fNamedPipe); | |||
CloseHandle(fNamedPipe); | |||
fNamedPipe = INVALID_HANDLE_VALUE; | |||
return 0; | |||
@@ -62,7 +62,9 @@ error: | |||
void JackWinNamedPipeClientChannel::Close() | |||
{ | |||
fRequestPipe.Close(); | |||
fNotificationListenPipe.Close(); | |||
fNotificationListenPipe.Close(); | |||
// Here the thread will correctly stop when the pipe are closed | |||
fThread->Stop(); | |||
} | |||
int JackWinNamedPipeClientChannel::Start() | |||
@@ -80,7 +82,7 @@ int JackWinNamedPipeClientChannel::Start() | |||
void JackWinNamedPipeClientChannel::Stop() | |||
{ | |||
JackLog("JackWinNamedPipeClientChannel::Stop\n"); | |||
fThread->Kill(); | |||
//fThread->Kill(); Unsafe on WIN32... | |||
} | |||
void JackWinNamedPipeClientChannel::ServerSyncCall(JackRequest* req, JackResult* res, int* result) | |||
@@ -248,8 +250,9 @@ bool JackWinNamedPipeClientChannel::Execute() | |||
} | |||
return true; | |||
error: | |||
fClient->ShutDown(); | |||
error: | |||
//fClient->ShutDown(); needed ?? | |||
return false; | |||
} | |||
@@ -43,7 +43,8 @@ JackClientPipeThread::JackClientPipeThread(JackWinNamedPipeClient* pipe) | |||
} | |||
JackClientPipeThread::~JackClientPipeThread() | |||
{ | |||
{ | |||
JackLog("JackClientPipeThread::~JackClientPipeThread\n"); | |||
delete fPipe; | |||
delete fThread; | |||
} | |||
@@ -62,10 +63,18 @@ int JackClientPipeThread::Open(JackServer* server) // Open the Server/Client con | |||
} | |||
void JackClientPipeThread::Close() // Close the Server/Client connection | |||
{ | |||
{ | |||
JackLog("JackClientPipeThread::Close %x %ld\n", this, fRefNum); | |||
/* | |||
This would hang.. since Close will be followed by a delete, | |||
all ressources will be desallocated at the end. | |||
*/ | |||
/* | |||
fThread->Kill(); | |||
fPipe->Close(); | |||
fRefNum = -1; | |||
fPipe->Close(); | |||
*/ | |||
fRefNum = -1; | |||
} | |||
bool JackClientPipeThread::Execute() | |||
@@ -111,7 +120,8 @@ int JackClientPipeThread::HandleRequest() | |||
if (req.Read(fPipe) == 0) | |||
res.fResult = fServer->GetEngine()->ClientClose(req.fRefNum); | |||
res.Write(fPipe); | |||
RemoveClient(); | |||
RemoveClient(); | |||
ret = -1; | |||
break; | |||
} | |||
@@ -257,21 +267,20 @@ int JackClientPipeThread::HandleRequest() | |||
void JackClientPipeThread::AddClient(char* name, int* shared_engine, int* shared_client, int* shared_ports, int* result) | |||
{ | |||
JackLog("JackWinNamedPipeServerChannel::AddClient %s\n", name); | |||
JackLog("JackClientPipeThread::AddClient %s\n", name); | |||
fRefNum = -1; | |||
*result = fServer->GetEngine()->ClientNew(name, &fRefNum, shared_engine, shared_client, shared_ports); | |||
} | |||
void JackClientPipeThread::RemoveClient() | |||
{ | |||
JackLog("JackWinNamedPipeServerChannel::RemoveClient ref = %d\n", fRefNum); | |||
JackLog("JackClientPipeThread::RemoveClient ref = %d\n", fRefNum); | |||
Close(); | |||
} | |||
void JackClientPipeThread::KillClient() | |||
{ | |||
JackLog("JackClientPipeThread::KillClient \n"); | |||
JackLog("JackWinNamedPipeServerChannel::KillClient ref = %d\n", fRefNum); | |||
JackLog("JackClientPipeThread::KillClient ref = %d\n", fRefNum); | |||
if (fRefNum == -1) { // Correspond to an already removed client. | |||
JackLog("Kill a closed client\n"); | |||
@@ -290,7 +299,15 @@ JackWinNamedPipeServerChannel::JackWinNamedPipeServerChannel() | |||
} | |||
JackWinNamedPipeServerChannel::~JackWinNamedPipeServerChannel() | |||
{ | |||
{ | |||
std::list<JackClientPipeThread*>::iterator it; | |||
for (it = fClientList.begin(); it != fClientList.end(); it++) { | |||
JackClientPipeThread* client = *it; | |||
client->Close(); | |||
delete client; | |||
} | |||
delete fThread; | |||
} | |||
@@ -318,12 +335,19 @@ error: | |||
fRequestListenPipe.Close(); | |||
return -1; | |||
} | |||
void JackWinNamedPipeServerChannel::Close() | |||
{ | |||
fThread->Kill(); | |||
fRequestListenPipe.Close(); | |||
} | |||
void JackWinNamedPipeServerChannel::Close() | |||
{ | |||
/* | |||
This would hang the server... since we are quitting it, its not really problematic, | |||
all ressources will be desallocated at the end. | |||
*/ | |||
/* | |||
fRequestListenPipe.Close(); | |||
fThread->Stop(); | |||
*/ | |||
} | |||
bool JackWinNamedPipeServerChannel::Init() | |||
{ | |||
@@ -355,31 +379,34 @@ bool JackWinNamedPipeServerChannel::Execute() | |||
} | |||
AddClient(pipe); | |||
return true; | |||
} | |||
void JackWinNamedPipeServerChannel::AddClient(JackWinNamedPipeClient* pipe) | |||
{ | |||
// Remove dead (= not running anymore) clients. | |||
std::list<JackClientPipeThread*>::iterator it = fClientList.begin(); | |||
JackClientPipeThread* client; | |||
while (it != fClientList.end()) { | |||
client = *it; | |||
if (client->IsRunning()) { | |||
it++; | |||
} else { | |||
JackLog("Remove client from list\n"); | |||
it = fClientList.erase(it); | |||
delete(client); | |||
} | |||
} | |||
client = new JackClientPipeThread(pipe); | |||
client->Open(fServer); | |||
// Here we are sure that the client is running (because it's thread is in "running" state). | |||
fClientList.push_back(client); | |||
} | |||
} // end of namespace | |||
return true; | |||
} | |||
void JackWinNamedPipeServerChannel::AddClient(JackWinNamedPipeClient* pipe) | |||
{ | |||
// Remove dead (= not running anymore) clients. | |||
std::list<JackClientPipeThread*>::iterator it = fClientList.begin(); | |||
JackClientPipeThread* client; | |||
JackLog("AddClient size %ld\n", fClientList.size()); | |||
while (it != fClientList.end()) { | |||
client = *it; | |||
JackLog("Remove dead client = %x running = %ld\n", client, client->IsRunning()); | |||
if (client->IsRunning()) { | |||
it++; | |||
} else { | |||
it = fClientList.erase(it); | |||
delete client; | |||
} | |||
} | |||
client = new JackClientPipeThread(pipe); | |||
client->Open(fServer); | |||
// Here we are sure that the client is running (because it's thread is in "running" state). | |||
fClientList.push_back(client); | |||
} | |||
} // end of namespace | |||
@@ -167,9 +167,10 @@ int JackWinThread::StartSync() | |||
int JackWinThread::Kill() | |||
{ | |||
if (fThread) { // If thread has been started | |||
JackLog("JackWinThread::Kill\n"); | |||
TerminateThread(fThread, 0); /// TO CHECK : dangerous | |||
CloseHandle(fThread); | |||
TerminateThread(fThread, 0); | |||
WaitForSingleObject(fThread, INFINITE); | |||
CloseHandle(fThread); | |||
JackLog("JackWinThread::Kill 2\n"); | |||
fThread = NULL; | |||
fRunning = false; | |||
return 0; | |||
@@ -204,6 +204,48 @@ static void jack_cleanup_files (const char *server_name) | |||
} | |||
} | |||
} | |||
*/ | |||
/* | |||
BOOL CtrlHandler( DWORD fdwCtrlType ) | |||
{ | |||
switch( fdwCtrlType ) | |||
{ | |||
// Handle the CTRL-C signal. | |||
case CTRL_C_EVENT: | |||
printf( "Ctrl-C event\n\n" ); | |||
Beep( 750, 300 ); | |||
SetEvent(waitEvent); | |||
return( TRUE ); | |||
// CTRL-CLOSE: confirm that the user wants to exit. | |||
case CTRL_CLOSE_EVENT: | |||
Beep( 600, 200 ); | |||
printf( "Ctrl-Close event\n\n" ); | |||
SetEvent(waitEvent); | |||
return( TRUE ); | |||
// Pass other signals to the next handler. | |||
case CTRL_BREAK_EVENT: | |||
Beep( 900, 200 ); | |||
printf( "Ctrl-Break event\n\n" ); | |||
return FALSE; | |||
case CTRL_LOGOFF_EVENT: | |||
Beep( 1000, 200 ); | |||
printf( "Ctrl-Logoff event\n\n" ); | |||
return FALSE; | |||
case CTRL_SHUTDOWN_EVENT: | |||
Beep( 750, 500 ); | |||
printf( "Ctrl-Shutdown event\n\n" ); | |||
return FALSE; | |||
default: | |||
return FALSE; | |||
} | |||
} | |||
*/ | |||
int main(int argc, char* argv[]) | |||
@@ -324,19 +366,22 @@ int main(int argc, char* argv[]) | |||
if (!seen_driver) { | |||
usage (stderr); | |||
exit (1); | |||
//exit (1); | |||
return 0; | |||
} | |||
drivers = jack_drivers_load (drivers); | |||
if (!drivers) { | |||
fprintf (stderr, "jackdmp: no drivers found; exiting\n"); | |||
exit (1); | |||
//exit (1); | |||
return 0; | |||
} | |||
driver_desc = jack_find_driver_descriptor (drivers, driver_name); | |||
if (!driver_desc) { | |||
fprintf (stderr, "jackdmp: unknown driver '%s'\n", driver_name); | |||
exit (1); | |||
//exit (1); | |||
return 0; | |||
} | |||
if (optind < argc) { | |||
@@ -360,7 +405,8 @@ int main(int argc, char* argv[]) | |||
if (jack_parse_driver_params (driver_desc, driver_nargs, | |||
driver_args, &driver_params)) { | |||
exit (0); | |||
// exit (0); | |||
return 0; | |||
} | |||
//if (server_name == NULL) | |||
@@ -372,13 +418,16 @@ int main(int argc, char* argv[]) | |||
switch (rc) { | |||
case EEXIST: | |||
fprintf (stderr, "`%s' server already active\n", server_name); | |||
exit (1); | |||
//exit (1); | |||
return 0; | |||
case ENOSPC: | |||
fprintf (stderr, "too many servers already active\n"); | |||
exit (2); | |||
//exit (2); | |||
return 0; | |||
case ENOMEM: | |||
fprintf (stderr, "no access to shm registry\n"); | |||
exit (3); | |||
//exit (3); | |||
return 0; | |||
default: | |||
if (xverbose) | |||
fprintf (stderr, "server `%s' registered\n", | |||
@@ -401,8 +450,19 @@ int main(int argc, char* argv[]) | |||
return 0; | |||
} | |||
/* | |||
if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ) ) | |||
{ | |||
printf( "\nThe Control Handler is installed.\n" ); | |||
} else { | |||
printf( "\nERROR: Could not set control handler"); | |||
} | |||
*/ | |||
(void) signal(SIGINT, intrpt); | |||
(void) signal(SIGABRT, intrpt); | |||
(void) signal(SIGTERM, intrpt); | |||
if ((res = WaitForSingleObject(waitEvent, INFINITE)) != WAIT_OBJECT_0) { | |||
printf("WaitForSingleObject fails err = %ld\n", GetLastError()); | |||
@@ -411,7 +471,8 @@ int main(int argc, char* argv[]) | |||
/* | |||
printf("Type 'q' to quit\n"); | |||
while ((c = getchar()) != 'q') {} | |||
*/ | |||
*/ | |||
JackStop(); | |||
@@ -108,6 +108,28 @@ SOURCE="..\example-clients\metro.c" | |||
# Begin Source File | |||
SOURCE=.\Release\libjackmp.lib | |||
!IF "$(CFG)" == "jack_metro - Win32 Release" | |||
!ELSEIF "$(CFG)" == "jack_metro - Win32 Debug" | |||
# PROP Exclude_From_Build 1 | |||
!ENDIF | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=.\Debug\libjackmp_debug.lib | |||
!IF "$(CFG)" == "jack_metro - Win32 Release" | |||
# PROP Exclude_From_Build 1 | |||
!ELSEIF "$(CFG)" == "jack_metro - Win32 Debug" | |||
!ENDIF | |||
# End Source File | |||
# End Target | |||
# End Project |
@@ -122,6 +122,15 @@ SOURCE=.\Release\libjackdmp.lib | |||
# Begin Source File | |||
SOURCE=.\Debug\libjackdmp_debug.lib | |||
!IF "$(CFG)" == "jackdmp - Win32 Release" | |||
# PROP Exclude_From_Build 1 | |||
!ELSEIF "$(CFG)" == "jackdmp - Win32 Debug" | |||
!ENDIF | |||
# End Source File | |||
# End Target | |||
# End Project |
@@ -42,7 +42,7 @@ RSC=rc.exe | |||
# PROP Intermediate_Dir "Release" | |||
# PROP Target_Dir "" | |||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBJACKDMP_EXPORTS" /YX /FD /c | |||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../common" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBJACKDMP_EXPORTS" /D "__STDC__" /D "REGEX_MALLOC" /D "STDC_HEADERS" /D "__SMP__" /YX /FD /c | |||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../common" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBJACKDMP_EXPORTS" /D "__STDC__" /D "REGEX_MALLOC" /D "STDC_HEADERS" /D "__SMP__" /FR /YX /FD /c | |||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 | |||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 | |||
# ADD BASE RSC /l 0x40c /d "NDEBUG" | |||
@@ -241,6 +241,10 @@ SOURCE=.\resource.rc | |||
SOURCE=..\common\shm.c | |||
# End Source File | |||
# Begin Source File | |||
SOURCE="..\..\..\..\pthreads-win32\pthreadVC2.lib" | |||
# End Source File | |||
# End Group | |||
# Begin Group "Header Files" | |||
@@ -42,7 +42,7 @@ RSC=rc.exe | |||
# PROP Intermediate_Dir "Release" | |||
# PROP Target_Dir "" | |||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBJACKMP_EXPORTS" /YX /FD /c | |||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../common" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBJACKMP_EXPORTS" /D "__STDC__" /D "REGEX_MALLOC" /D "STDC_HEADERS" /D "__SMP__" /YX /FD /c | |||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../common" /I "../../../../pthreads-win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBJACKMP_EXPORTS" /D "__STDC__" /D "REGEX_MALLOC" /D "STDC_HEADERS" /D "__SMP__" /YX /FD /c | |||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 | |||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 | |||
# ADD BASE RSC /l 0x40c /d "NDEBUG" | |||
@@ -186,5 +186,9 @@ SOURCE=..\common\shm.c | |||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" | |||
# End Group | |||
# Begin Source File | |||
SOURCE="..\..\..\..\pthreads-win32\pthreadVC2.lib" | |||
# End Source File | |||
# End Target | |||
# End Project |