Jack2 1.9.7
|
00001 /* 00002 Copyright (C) 2004-2008 Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU Lesser General Public License as published by 00006 the Free Software Foundation; either version 2.1 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU Lesser General Public License for more details. 00013 00014 You should have received a copy of the GNU Lesser General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 00018 */ 00019 00020 00021 #include "JackWinNamedPipeServerChannel.h" 00022 #include "JackNotification.h" 00023 #include "JackRequest.h" 00024 #include "JackServer.h" 00025 #include "JackLockedEngine.h" 00026 #include "JackGlobals.h" 00027 #include "JackClient.h" 00028 #include "JackNotification.h" 00029 #include "JackException.h" 00030 #include <assert.h> 00031 00032 using namespace std; 00033 00034 namespace Jack 00035 { 00036 00037 HANDLE JackClientPipeThread::fMutex = NULL; // Never released.... 00038 00039 // fRefNum = -1 correspond to already removed client 00040 00041 JackClientPipeThread::JackClientPipeThread(JackWinNamedPipeClient* pipe) 00042 :fPipe(pipe), fServer(NULL), fThread(this), fRefNum(0) 00043 { 00044 // First one allocated the static fMutex 00045 if (fMutex == NULL) { 00046 fMutex = CreateMutex(NULL, FALSE, NULL); 00047 } 00048 } 00049 00050 JackClientPipeThread::~JackClientPipeThread() 00051 { 00052 jack_log("JackClientPipeThread::~JackClientPipeThread"); 00053 delete fPipe; 00054 } 00055 00056 int JackClientPipeThread::Open(JackServer* server) // Open the Server/Client connection 00057 { 00058 // Start listening 00059 if (fThread.Start() != 0) { 00060 jack_error("Cannot start Jack server listener\n"); 00061 return -1; 00062 } 00063 00064 fServer = server; 00065 return 0; 00066 } 00067 00068 void JackClientPipeThread::Close() // Close the Server/Client connection 00069 { 00070 jack_log("JackClientPipeThread::Close %x %ld", this, fRefNum); 00071 /* 00072 TODO : solve WIN32 thread Kill issue 00073 This would hang.. since Close will be followed by a delete, 00074 all ressources will be desallocated at the end. 00075 */ 00076 00077 fThread.Kill(); 00078 fPipe->Close(); 00079 fRefNum = -1; 00080 } 00081 00082 bool JackClientPipeThread::Execute() 00083 { 00084 try{ 00085 jack_log("JackClientPipeThread::Execute"); 00086 return (HandleRequest()); 00087 } catch (JackQuitException& e) { 00088 jack_log("JackMachServerChannel::Execute JackQuitException"); 00089 return false; 00090 } 00091 } 00092 00093 bool JackClientPipeThread::HandleRequest() 00094 { 00095 // Read header 00096 JackRequest header; 00097 int res = header.Read(fPipe); 00098 bool ret = true; 00099 00100 // Lock the global mutex 00101 if (WaitForSingleObject(fMutex, INFINITE) == WAIT_FAILED) 00102 jack_error("JackClientPipeThread::HandleRequest: mutex wait error"); 00103 00104 if (res < 0) { 00105 jack_error("HandleRequest: cannot read header"); 00106 ClientKill(); 00107 ret = false; 00108 } else { 00109 00110 // Read data 00111 switch (header.fType) { 00112 00113 case JackRequest::kClientCheck: { 00114 jack_log("JackRequest::ClientCheck"); 00115 JackClientCheckRequest req; 00116 JackClientCheckResult res; 00117 if (req.Read(fPipe) == 0) 00118 res.fResult = fServer->GetEngine()->ClientCheck(req.fName, req.fUUID, res.fName, req.fProtocol, req.fOptions, &res.fStatus); 00119 res.Write(fPipe); 00120 break; 00121 } 00122 00123 case JackRequest::kClientOpen: { 00124 jack_log("JackRequest::ClientOpen"); 00125 JackClientOpenRequest req; 00126 JackClientOpenResult res; 00127 if (req.Read(fPipe) == 0) 00128 ClientAdd(req.fName, req.fPID, req.fUUID, &res.fSharedEngine, &res.fSharedClient, &res.fSharedGraph, &res.fResult); 00129 res.Write(fPipe); 00130 break; 00131 } 00132 00133 case JackRequest::kClientClose: { 00134 jack_log("JackRequest::ClientClose"); 00135 JackClientCloseRequest req; 00136 JackResult res; 00137 if (req.Read(fPipe) == 0) 00138 res.fResult = fServer->GetEngine()->ClientExternalClose(req.fRefNum); 00139 res.Write(fPipe); 00140 ClientRemove(); 00141 ret = false; 00142 break; 00143 } 00144 00145 case JackRequest::kActivateClient: { 00146 JackActivateRequest req; 00147 JackResult res; 00148 jack_log("JackRequest::ActivateClient"); 00149 if (req.Read(fPipe) == 0) 00150 res.fResult = fServer->GetEngine()->ClientActivate(req.fRefNum, req.fIsRealTime); 00151 res.Write(fPipe); 00152 break; 00153 } 00154 00155 case JackRequest::kDeactivateClient: { 00156 jack_log("JackRequest::DeactivateClient"); 00157 JackDeactivateRequest req; 00158 JackResult res; 00159 if (req.Read(fPipe) == 0) 00160 res.fResult = fServer->GetEngine()->ClientDeactivate(req.fRefNum); 00161 res.Write(fPipe); 00162 break; 00163 } 00164 00165 case JackRequest::kRegisterPort: { 00166 jack_log("JackRequest::RegisterPort"); 00167 JackPortRegisterRequest req; 00168 JackPortRegisterResult res; 00169 if (req.Read(fPipe) == 0) 00170 res.fResult = fServer->GetEngine()->PortRegister(req.fRefNum, req.fName, req.fPortType, req.fFlags, req.fBufferSize, &res.fPortIndex); 00171 res.Write(fPipe); 00172 break; 00173 } 00174 00175 case JackRequest::kUnRegisterPort: { 00176 jack_log("JackRequest::UnRegisterPort"); 00177 JackPortUnRegisterRequest req; 00178 JackResult res; 00179 if (req.Read(fPipe) == 0) 00180 res.fResult = fServer->GetEngine()->PortUnRegister(req.fRefNum, req.fPortIndex); 00181 res.Write(fPipe); 00182 break; 00183 } 00184 00185 case JackRequest::kConnectNamePorts: { 00186 jack_log("JackRequest::ConnectNamePorts"); 00187 JackPortConnectNameRequest req; 00188 JackResult res; 00189 if (req.Read(fPipe) == 0) 00190 res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst); 00191 res.Write(fPipe); 00192 break; 00193 } 00194 00195 case JackRequest::kDisconnectNamePorts: { 00196 jack_log("JackRequest::DisconnectNamePorts"); 00197 JackPortDisconnectNameRequest req; 00198 JackResult res; 00199 if (req.Read(fPipe) == 0) 00200 res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst); 00201 res.Write(fPipe); 00202 break; 00203 } 00204 00205 case JackRequest::kConnectPorts: { 00206 jack_log("JackRequest::ConnectPorts"); 00207 JackPortConnectRequest req; 00208 JackResult res; 00209 if (req.Read(fPipe) == 0) 00210 res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst); 00211 res.Write(fPipe); 00212 break; 00213 } 00214 00215 case JackRequest::kDisconnectPorts: { 00216 jack_log("JackRequest::DisconnectPorts"); 00217 JackPortDisconnectRequest req; 00218 JackResult res; 00219 if (req.Read(fPipe) == 0) 00220 res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst); 00221 res.Write(fPipe); 00222 break; 00223 } 00224 00225 case JackRequest::kPortRename: { 00226 jack_log("JackRequest::PortRename"); 00227 JackPortRenameRequest req; 00228 JackResult res; 00229 if (req.Read(fPipe) == 0) 00230 res.fResult = fServer->GetEngine()->PortRename(req.fRefNum, req.fPort, req.fName); 00231 res.Write(fPipe); 00232 break; 00233 } 00234 00235 case JackRequest::kSetBufferSize: { 00236 jack_log("JackRequest::SetBufferSize"); 00237 JackSetBufferSizeRequest req; 00238 JackResult res; 00239 if (req.Read(fPipe) == 0) 00240 res.fResult = fServer->SetBufferSize(req.fBufferSize); 00241 res.Write(fPipe); 00242 break; 00243 } 00244 00245 case JackRequest::kSetFreeWheel: { 00246 jack_log("JackRequest::SetFreeWheel"); 00247 JackSetFreeWheelRequest req; 00248 JackResult res; 00249 if (req.Read(fPipe) == 0) 00250 res.fResult = fServer->SetFreewheel(req.fOnOff); 00251 res.Write(fPipe); 00252 break; 00253 } 00254 00255 case JackRequest::kComputeTotalLatencies: { 00256 jack_log("JackRequest::ComputeTotalLatencies"); 00257 JackComputeTotalLatenciesRequest req; 00258 JackResult res; 00259 if (req.Read(fPipe) == 0) 00260 res.fResult = fServer->GetEngine()->ComputeTotalLatencies(); 00261 res.Write(fPipe); 00262 break; 00263 } 00264 00265 case JackRequest::kReleaseTimebase: { 00266 jack_log("JackRequest::ReleaseTimebase"); 00267 JackReleaseTimebaseRequest req; 00268 JackResult res; 00269 if (req.Read(fPipe) == 0) 00270 res.fResult = fServer->ReleaseTimebase(req.fRefNum); 00271 res.Write(fPipe); 00272 break; 00273 } 00274 00275 case JackRequest::kSetTimebaseCallback: { 00276 jack_log("JackRequest::SetTimebaseCallback"); 00277 JackSetTimebaseCallbackRequest req; 00278 JackResult res; 00279 if (req.Read(fPipe) == 0) 00280 res.fResult = fServer->SetTimebaseCallback(req.fRefNum, req.fConditionnal); 00281 res.Write(fPipe); 00282 break; 00283 } 00284 00285 case JackRequest::kGetInternalClientName: { 00286 jack_log("JackRequest::GetInternalClientName"); 00287 JackGetInternalClientNameRequest req; 00288 JackGetInternalClientNameResult res; 00289 if (req.Read(fPipe) == 0) 00290 res.fResult = fServer->GetEngine()->GetInternalClientName(req.fIntRefNum, res.fName); 00291 res.Write(fPipe); 00292 break; 00293 } 00294 00295 case JackRequest::kInternalClientHandle: { 00296 jack_log("JackRequest::InternalClientHandle"); 00297 JackInternalClientHandleRequest req; 00298 JackInternalClientHandleResult res; 00299 if (req.Read(fPipe) == 0) 00300 res.fResult = fServer->GetEngine()->InternalClientHandle(req.fName, &res.fStatus, &res.fIntRefNum); 00301 res.Write(fPipe); 00302 break; 00303 } 00304 00305 case JackRequest::kInternalClientLoad: { 00306 jack_log("JackRequest::InternalClientLoad"); 00307 JackInternalClientLoadRequest req; 00308 JackInternalClientLoadResult res; 00309 if (req.Read(fPipe) == 0) 00310 res.fResult = fServer->InternalClientLoad1(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, req.fUUID, &res.fStatus); 00311 res.Write(fPipe); 00312 break; 00313 } 00314 00315 case JackRequest::kInternalClientUnload: { 00316 jack_log("JackRequest::InternalClientUnload"); 00317 JackInternalClientUnloadRequest req; 00318 JackInternalClientUnloadResult res; 00319 if (req.Read(fPipe) == 0) 00320 res.fResult = fServer->GetEngine()->InternalClientUnload(req.fIntRefNum, &res.fStatus); 00321 res.Write(fPipe); 00322 break; 00323 } 00324 00325 case JackRequest::kNotification: { 00326 jack_log("JackRequest::Notification"); 00327 JackClientNotificationRequest req; 00328 if (req.Read(fPipe) == 0) { 00329 if (req.fNotify == kQUIT) { 00330 jack_log("JackRequest::Notification kQUIT"); 00331 throw JackQuitException(); 00332 } else { 00333 fServer->Notify(req.fRefNum, req.fNotify, req.fValue); 00334 } 00335 } 00336 break; 00337 } 00338 00339 case JackRequest::kSessionNotify: { 00340 jack_log("JackRequest::SessionNotify"); 00341 JackSessionNotifyRequest req; 00342 JackSessionNotifyResult res; 00343 if (req.Read(fPipe) == 0) { 00344 fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, fPipe); 00345 } 00346 res.Write(fPipe); 00347 break; 00348 } 00349 00350 case JackRequest::kSessionReply: { 00351 jack_log("JackRequest::SessionReply"); 00352 JackSessionReplyRequest req; 00353 JackResult res; 00354 if (req.Read(fPipe) == 0) { 00355 fServer->GetEngine()->SessionReply(req.fRefNum); 00356 res.fResult = 0; 00357 } 00358 res.Write(fPipe); 00359 break; 00360 } 00361 00362 case JackRequest::kGetClientByUUID: { 00363 jack_log("JackRequest::GetClientByUUID"); 00364 JackGetClientNameRequest req; 00365 JackClientNameResult res; 00366 if (req.Read(fPipe) == 0) { 00367 fServer->GetEngine()->GetClientNameForUUID(req.fUUID, res.fName, &res.fResult); 00368 } 00369 res.Write(fPipe); 00370 break; 00371 } 00372 00373 case JackRequest::kGetUUIDByClient: { 00374 jack_log("JackRequest::GetUUIDByClient"); 00375 JackGetUUIDRequest req; 00376 JackUUIDResult res; 00377 if (req.Read(fPipe) == 0) { 00378 fServer->GetEngine()->GetUUIDForClientName(req.fName, res.fUUID, &res.fResult); 00379 } 00380 res.Write(fPipe); 00381 break; 00382 } 00383 00384 case JackRequest::kReserveClientName: { 00385 jack_log("JackRequest::ReserveClientName"); 00386 JackReserveNameRequest req; 00387 JackResult res; 00388 if (req.Read(fPipe) == 0) { 00389 fServer->GetEngine()->ReserveClientName(req.fName, req.fUUID, &res.fResult); 00390 } 00391 res.Write(fPipe); 00392 break; 00393 } 00394 00395 case JackRequest::kClientHasSessionCallback: { 00396 jack_log("JackRequest::ClientHasSessionCallback"); 00397 JackClientHasSessionCallbackRequest req; 00398 JackResult res; 00399 if (req.Read(fPipe) == 0) { 00400 fServer->GetEngine()->ClientHasSessionCallbackRequest(req.fName, &res.fResult); 00401 } 00402 res.Write(fPipe); 00403 break; 00404 } 00405 00406 default: 00407 jack_log("Unknown request %ld", header.fType); 00408 break; 00409 } 00410 } 00411 00412 // Unlock the global mutex 00413 ReleaseMutex(fMutex); 00414 return ret; 00415 } 00416 00417 void JackClientPipeThread::ClientAdd(char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result) 00418 { 00419 jack_log("JackClientPipeThread::ClientAdd %s", name); 00420 fRefNum = -1; 00421 *result = fServer->GetEngine()->ClientExternalOpen(name, pid, uuid, &fRefNum, shared_engine, shared_client, shared_graph); 00422 } 00423 00424 void JackClientPipeThread::ClientRemove() 00425 { 00426 jack_log("JackClientPipeThread::ClientRemove ref = %d", fRefNum); 00427 /* TODO : solve WIN32 thread Kill issue 00428 Close(); 00429 */ 00430 fRefNum = -1; 00431 fPipe->Close(); 00432 } 00433 00434 void JackClientPipeThread::ClientKill() 00435 { 00436 jack_log("JackClientPipeThread::ClientKill ref = %d", fRefNum); 00437 00438 if (fRefNum == -1) { // Correspond to an already removed client. 00439 jack_log("Kill a closed client"); 00440 } else if (fRefNum == 0) { // Correspond to a still not opened client. 00441 jack_log("Kill a not opened client"); 00442 } else { 00443 fServer->ClientKill(fRefNum); 00444 } 00445 00446 Close(); 00447 } 00448 00449 JackWinNamedPipeServerChannel::JackWinNamedPipeServerChannel():fThread(this) 00450 {} 00451 00452 JackWinNamedPipeServerChannel::~JackWinNamedPipeServerChannel() 00453 { 00454 std::list<JackClientPipeThread*>::iterator it; 00455 00456 for (it = fClientList.begin(); it != fClientList.end(); it++) { 00457 JackClientPipeThread* client = *it; 00458 client->Close(); 00459 delete client; 00460 } 00461 } 00462 00463 int JackWinNamedPipeServerChannel::Open(const char* server_name, JackServer* server) 00464 { 00465 jack_log("JackWinNamedPipeServerChannel::Open "); 00466 snprintf(fServerName, sizeof(fServerName), server_name); 00467 00468 // Needed for internal connection from JackWinNamedPipeServerNotifyChannel object 00469 if (fRequestListenPipe.Bind(jack_server_dir, server_name, 0) < 0) { 00470 jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe"); 00471 return -1; 00472 } 00473 00474 fServer = server; 00475 return 0; 00476 } 00477 00478 void JackWinNamedPipeServerChannel::Close() 00479 { 00480 /* TODO : solve WIN32 thread Kill issue 00481 This would hang the server... since we are quitting it, its not really problematic, 00482 all ressources will be desallocated at the end. 00483 00484 fRequestListenPipe.Close(); 00485 fThread.Stop(); 00486 */ 00487 00488 fThread.Kill(); 00489 fRequestListenPipe.Close(); 00490 } 00491 00492 int JackWinNamedPipeServerChannel::Start() 00493 { 00494 if (fThread.Start() != 0) { 00495 jack_error("Cannot start Jack server listener"); 00496 return -1; 00497 } 00498 00499 return 0; 00500 } 00501 00502 bool JackWinNamedPipeServerChannel::Init() 00503 { 00504 jack_log("JackWinNamedPipeServerChannel::Init "); 00505 JackWinNamedPipeClient* pipe; 00506 00507 // Accept first client, that is the JackWinNamedPipeServerNotifyChannel object 00508 if ((pipe = fRequestListenPipe.AcceptClient()) == NULL) { 00509 jack_error("JackWinNamedPipeServerChannel::Init : cannot connect pipe"); 00510 return false; 00511 } else { 00512 ClientAdd(pipe); 00513 return true; 00514 } 00515 } 00516 00517 bool JackWinNamedPipeServerChannel::Execute() 00518 { 00519 JackWinNamedPipeClient* pipe; 00520 00521 if (fRequestListenPipe.Bind(jack_server_dir, fServerName, 0) < 0) { 00522 jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe"); 00523 return false; 00524 } 00525 00526 if ((pipe = fRequestListenPipe.AcceptClient()) == NULL) { 00527 jack_error("JackWinNamedPipeServerChannel::Open : cannot connect pipe"); 00528 return false; 00529 } 00530 00531 ClientAdd(pipe); 00532 return true; 00533 } 00534 00535 void JackWinNamedPipeServerChannel::ClientAdd(JackWinNamedPipeClient* pipe) 00536 { 00537 // Remove dead (= not running anymore) clients. 00538 std::list<JackClientPipeThread*>::iterator it = fClientList.begin(); 00539 JackClientPipeThread* client; 00540 00541 jack_log("ClientAdd size %ld", fClientList.size()); 00542 00543 while (it != fClientList.end()) { 00544 client = *it; 00545 jack_log("Remove dead client = %x running = %ld", client, client->IsRunning()); 00546 if (client->IsRunning()) { 00547 it++; 00548 } else { 00549 it = fClientList.erase(it); 00550 delete client; 00551 } 00552 } 00553 00554 client = new JackClientPipeThread(pipe); 00555 client->Open(fServer); 00556 // Here we are sure that the client is running (because it's thread is in "running" state). 00557 fClientList.push_back(client); 00558 } 00559 00560 } // end of namespace 00561 00562