Jack2
1.9.8
|
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 deallocated 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("JackClientPipeThread::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 00105 if (res < 0) { 00106 jack_error("HandleRequest: cannot read header"); 00107 ClientKill(); 00108 ret = false; 00109 } else { 00110 00111 // Read data 00112 switch (header.fType) { 00113 00114 case JackRequest::kClientCheck: { 00115 jack_log("JackRequest::ClientCheck"); 00116 JackClientCheckRequest req; 00117 JackClientCheckResult res; 00118 if (req.Read(fPipe) == 0) 00119 res.fResult = fServer->GetEngine()->ClientCheck(req.fName, req.fUUID, res.fName, req.fProtocol, req.fOptions, &res.fStatus); 00120 res.Write(fPipe); 00121 // Atomic ClientCheck followed by ClientOpen on same pipe 00122 if (req.fOpen) 00123 HandleRequest(); 00124 break; 00125 } 00126 00127 case JackRequest::kClientOpen: { 00128 jack_log("JackRequest::ClientOpen"); 00129 JackClientOpenRequest req; 00130 JackClientOpenResult res; 00131 if (req.Read(fPipe) == 0) 00132 ClientAdd(req.fName, req.fPID, req.fUUID, &res.fSharedEngine, &res.fSharedClient, &res.fSharedGraph, &res.fResult); 00133 res.Write(fPipe); 00134 break; 00135 } 00136 00137 case JackRequest::kClientClose: { 00138 jack_log("JackRequest::ClientClose"); 00139 JackClientCloseRequest req; 00140 JackResult res; 00141 if (req.Read(fPipe) == 0) 00142 res.fResult = fServer->GetEngine()->ClientExternalClose(req.fRefNum); 00143 res.Write(fPipe); 00144 ClientRemove(); 00145 ret = false; 00146 break; 00147 } 00148 00149 case JackRequest::kActivateClient: { 00150 JackActivateRequest req; 00151 JackResult res; 00152 jack_log("JackRequest::ActivateClient"); 00153 if (req.Read(fPipe) == 0) 00154 res.fResult = fServer->GetEngine()->ClientActivate(req.fRefNum, req.fIsRealTime); 00155 res.Write(fPipe); 00156 break; 00157 } 00158 00159 case JackRequest::kDeactivateClient: { 00160 jack_log("JackRequest::DeactivateClient"); 00161 JackDeactivateRequest req; 00162 JackResult res; 00163 if (req.Read(fPipe) == 0) 00164 res.fResult = fServer->GetEngine()->ClientDeactivate(req.fRefNum); 00165 res.Write(fPipe); 00166 break; 00167 } 00168 00169 case JackRequest::kRegisterPort: { 00170 jack_log("JackRequest::RegisterPort"); 00171 JackPortRegisterRequest req; 00172 JackPortRegisterResult res; 00173 if (req.Read(fPipe) == 0) 00174 res.fResult = fServer->GetEngine()->PortRegister(req.fRefNum, req.fName, req.fPortType, req.fFlags, req.fBufferSize, &res.fPortIndex); 00175 res.Write(fPipe); 00176 break; 00177 } 00178 00179 case JackRequest::kUnRegisterPort: { 00180 jack_log("JackRequest::UnRegisterPort"); 00181 JackPortUnRegisterRequest req; 00182 JackResult res; 00183 if (req.Read(fPipe) == 0) 00184 res.fResult = fServer->GetEngine()->PortUnRegister(req.fRefNum, req.fPortIndex); 00185 res.Write(fPipe); 00186 break; 00187 } 00188 00189 case JackRequest::kConnectNamePorts: { 00190 jack_log("JackRequest::ConnectNamePorts"); 00191 JackPortConnectNameRequest req; 00192 JackResult res; 00193 if (req.Read(fPipe) == 0) 00194 res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst); 00195 res.Write(fPipe); 00196 break; 00197 } 00198 00199 case JackRequest::kDisconnectNamePorts: { 00200 jack_log("JackRequest::DisconnectNamePorts"); 00201 JackPortDisconnectNameRequest req; 00202 JackResult res; 00203 if (req.Read(fPipe) == 0) 00204 res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst); 00205 res.Write(fPipe); 00206 break; 00207 } 00208 00209 case JackRequest::kConnectPorts: { 00210 jack_log("JackRequest::ConnectPorts"); 00211 JackPortConnectRequest req; 00212 JackResult res; 00213 if (req.Read(fPipe) == 0) 00214 res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst); 00215 res.Write(fPipe); 00216 break; 00217 } 00218 00219 case JackRequest::kDisconnectPorts: { 00220 jack_log("JackRequest::DisconnectPorts"); 00221 JackPortDisconnectRequest req; 00222 JackResult res; 00223 if (req.Read(fPipe) == 0) 00224 res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst); 00225 res.Write(fPipe); 00226 break; 00227 } 00228 00229 case JackRequest::kPortRename: { 00230 jack_log("JackRequest::PortRename"); 00231 JackPortRenameRequest req; 00232 JackResult res; 00233 if (req.Read(fPipe) == 0) 00234 res.fResult = fServer->GetEngine()->PortRename(req.fRefNum, req.fPort, req.fName); 00235 res.Write(fPipe); 00236 break; 00237 } 00238 00239 case JackRequest::kSetBufferSize: { 00240 jack_log("JackRequest::SetBufferSize"); 00241 JackSetBufferSizeRequest req; 00242 JackResult res; 00243 if (req.Read(fPipe) == 0) 00244 res.fResult = fServer->SetBufferSize(req.fBufferSize); 00245 res.Write(fPipe); 00246 break; 00247 } 00248 00249 case JackRequest::kSetFreeWheel: { 00250 jack_log("JackRequest::SetFreeWheel"); 00251 JackSetFreeWheelRequest req; 00252 JackResult res; 00253 if (req.Read(fPipe) == 0) 00254 res.fResult = fServer->SetFreewheel(req.fOnOff); 00255 res.Write(fPipe); 00256 break; 00257 } 00258 00259 case JackRequest::kComputeTotalLatencies: { 00260 jack_log("JackRequest::ComputeTotalLatencies"); 00261 JackComputeTotalLatenciesRequest req; 00262 JackResult res; 00263 if (req.Read(fPipe) == 0) 00264 res.fResult = fServer->GetEngine()->ComputeTotalLatencies(); 00265 res.Write(fPipe); 00266 break; 00267 } 00268 00269 case JackRequest::kReleaseTimebase: { 00270 jack_log("JackRequest::ReleaseTimebase"); 00271 JackReleaseTimebaseRequest req; 00272 JackResult res; 00273 if (req.Read(fPipe) == 0) 00274 res.fResult = fServer->ReleaseTimebase(req.fRefNum); 00275 res.Write(fPipe); 00276 break; 00277 } 00278 00279 case JackRequest::kSetTimebaseCallback: { 00280 jack_log("JackRequest::SetTimebaseCallback"); 00281 JackSetTimebaseCallbackRequest req; 00282 JackResult res; 00283 if (req.Read(fPipe) == 0) 00284 res.fResult = fServer->SetTimebaseCallback(req.fRefNum, req.fConditionnal); 00285 res.Write(fPipe); 00286 break; 00287 } 00288 00289 case JackRequest::kGetInternalClientName: { 00290 jack_log("JackRequest::GetInternalClientName"); 00291 JackGetInternalClientNameRequest req; 00292 JackGetInternalClientNameResult res; 00293 if (req.Read(fPipe) == 0) 00294 res.fResult = fServer->GetEngine()->GetInternalClientName(req.fIntRefNum, res.fName); 00295 res.Write(fPipe); 00296 break; 00297 } 00298 00299 case JackRequest::kInternalClientHandle: { 00300 jack_log("JackRequest::InternalClientHandle"); 00301 JackInternalClientHandleRequest req; 00302 JackInternalClientHandleResult res; 00303 if (req.Read(fPipe) == 0) 00304 res.fResult = fServer->GetEngine()->InternalClientHandle(req.fName, &res.fStatus, &res.fIntRefNum); 00305 res.Write(fPipe); 00306 break; 00307 } 00308 00309 case JackRequest::kInternalClientLoad: { 00310 jack_log("JackRequest::InternalClientLoad"); 00311 JackInternalClientLoadRequest req; 00312 JackInternalClientLoadResult res; 00313 if (req.Read(fPipe) == 0) 00314 res.fResult = fServer->InternalClientLoad1(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, req.fUUID, &res.fStatus); 00315 res.Write(fPipe); 00316 break; 00317 } 00318 00319 case JackRequest::kInternalClientUnload: { 00320 jack_log("JackRequest::InternalClientUnload"); 00321 JackInternalClientUnloadRequest req; 00322 JackInternalClientUnloadResult res; 00323 if (req.Read(fPipe) == 0) 00324 res.fResult = fServer->GetEngine()->InternalClientUnload(req.fIntRefNum, &res.fStatus); 00325 res.Write(fPipe); 00326 break; 00327 } 00328 00329 case JackRequest::kNotification: { 00330 jack_log("JackRequest::Notification"); 00331 JackClientNotificationRequest req; 00332 if (req.Read(fPipe) == 0) { 00333 if (req.fNotify == kQUIT) { 00334 jack_log("JackRequest::Notification kQUIT"); 00335 throw JackQuitException(); 00336 } else { 00337 fServer->Notify(req.fRefNum, req.fNotify, req.fValue); 00338 } 00339 } 00340 break; 00341 } 00342 00343 case JackRequest::kSessionNotify: { 00344 jack_log("JackRequest::SessionNotify"); 00345 JackSessionNotifyRequest req; 00346 if (req.Read(fPipe) == 0) { 00347 fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, fPipe, NULL); 00348 } 00349 break; 00350 } 00351 00352 case JackRequest::kSessionReply: { 00353 jack_log("JackRequest::SessionReply"); 00354 JackSessionReplyRequest req; 00355 JackResult res; 00356 if (req.Read(fPipe) == 0) { 00357 fServer->GetEngine()->SessionReply(req.fRefNum); 00358 res.fResult = 0; 00359 } 00360 res.Write(fPipe); 00361 break; 00362 } 00363 00364 case JackRequest::kGetClientByUUID: { 00365 jack_log("JackRequest::GetClientByUUID"); 00366 JackGetClientNameRequest req; 00367 JackClientNameResult res; 00368 if (req.Read(fPipe) == 0) { 00369 fServer->GetEngine()->GetClientNameForUUID(req.fUUID, res.fName, &res.fResult); 00370 } 00371 res.Write(fPipe); 00372 break; 00373 } 00374 00375 case JackRequest::kGetUUIDByClient: { 00376 jack_log("JackRequest::GetUUIDByClient"); 00377 JackGetUUIDRequest req; 00378 JackUUIDResult res; 00379 if (req.Read(fPipe) == 0) { 00380 fServer->GetEngine()->GetUUIDForClientName(req.fName, res.fUUID, &res.fResult); 00381 } 00382 res.Write(fPipe); 00383 break; 00384 } 00385 00386 case JackRequest::kReserveClientName: { 00387 jack_log("JackRequest::ReserveClientName"); 00388 JackReserveNameRequest req; 00389 JackResult res; 00390 if (req.Read(fPipe) == 0) { 00391 fServer->GetEngine()->ReserveClientName(req.fName, req.fUUID, &res.fResult); 00392 } 00393 res.Write(fPipe); 00394 break; 00395 } 00396 00397 case JackRequest::kClientHasSessionCallback: { 00398 jack_log("JackRequest::ClientHasSessionCallback"); 00399 JackClientHasSessionCallbackRequest req; 00400 JackResult res; 00401 if (req.Read(fPipe) == 0) { 00402 fServer->GetEngine()->ClientHasSessionCallback(req.fName, &res.fResult); 00403 } 00404 res.Write(fPipe); 00405 break; 00406 } 00407 00408 default: 00409 jack_log("Unknown request %ld", header.fType); 00410 break; 00411 } 00412 } 00413 00414 // Unlock the global mutex 00415 ReleaseMutex(fMutex); 00416 return ret; 00417 } 00418 00419 void JackClientPipeThread::ClientAdd(char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result) 00420 { 00421 jack_log("JackClientPipeThread::ClientAdd %s", name); 00422 fRefNum = -1; 00423 *result = fServer->GetEngine()->ClientExternalOpen(name, pid, uuid, &fRefNum, shared_engine, shared_client, shared_graph); 00424 } 00425 00426 void JackClientPipeThread::ClientRemove() 00427 { 00428 jack_log("JackClientPipeThread::ClientRemove ref = %d", fRefNum); 00429 /* TODO : solve WIN32 thread Kill issue 00430 Close(); 00431 */ 00432 fRefNum = -1; 00433 fPipe->Close(); 00434 } 00435 00436 void JackClientPipeThread::ClientKill() 00437 { 00438 jack_log("JackClientPipeThread::ClientKill ref = %d", fRefNum); 00439 00440 if (fRefNum == -1) { // Correspond to an already removed client. 00441 jack_log("Kill a closed client"); 00442 } else if (fRefNum == 0) { // Correspond to a still not opened client. 00443 jack_log("Kill a not opened client"); 00444 } else { 00445 fServer->ClientKill(fRefNum); 00446 } 00447 00448 Close(); 00449 } 00450 00451 JackWinNamedPipeServerChannel::JackWinNamedPipeServerChannel():fThread(this) 00452 {} 00453 00454 JackWinNamedPipeServerChannel::~JackWinNamedPipeServerChannel() 00455 { 00456 std::list<JackClientPipeThread*>::iterator it; 00457 00458 for (it = fClientList.begin(); it != fClientList.end(); it++) { 00459 JackClientPipeThread* client = *it; 00460 client->Close(); 00461 delete client; 00462 } 00463 } 00464 00465 int JackWinNamedPipeServerChannel::Open(const char* server_name, JackServer* server) 00466 { 00467 jack_log("JackWinNamedPipeServerChannel::Open "); 00468 snprintf(fServerName, sizeof(fServerName), server_name); 00469 00470 // Needed for internal connection from JackWinNamedPipeServerNotifyChannel object 00471 if (fRequestListenPipe.Bind(jack_server_dir, server_name, 0) < 0) { 00472 jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe"); 00473 return -1; 00474 } 00475 00476 fServer = server; 00477 return 0; 00478 } 00479 00480 void JackWinNamedPipeServerChannel::Close() 00481 { 00482 /* TODO : solve WIN32 thread Kill issue 00483 This would hang the server... since we are quitting it, its not really problematic, 00484 all ressources will be deallocated at the end. 00485 00486 fRequestListenPipe.Close(); 00487 fThread.Stop(); 00488 */ 00489 00490 fRequestListenPipe.Close(); 00491 } 00492 00493 int JackWinNamedPipeServerChannel::Start() 00494 { 00495 if (fThread.Start() != 0) { 00496 jack_error("Cannot start Jack server listener"); 00497 return -1; 00498 } else { 00499 return 0; 00500 } 00501 } 00502 00503 void JackWinNamedPipeServerChannel::Stop() 00504 { 00505 fThread.Kill(); 00506 } 00507 00508 bool JackWinNamedPipeServerChannel::Init() 00509 { 00510 jack_log("JackWinNamedPipeServerChannel::Init "); 00511 JackWinNamedPipeClient* pipe; 00512 00513 // Accept first client, that is the JackWinNamedPipeServerNotifyChannel object 00514 if ((pipe = fRequestListenPipe.AcceptClient()) == NULL) { 00515 jack_error("JackWinNamedPipeServerChannel::Init : cannot connect pipe"); 00516 return false; 00517 } else { 00518 ClientAdd(pipe); 00519 return true; 00520 } 00521 } 00522 00523 bool JackWinNamedPipeServerChannel::Execute() 00524 { 00525 JackWinNamedPipeClient* pipe; 00526 00527 if (fRequestListenPipe.Bind(jack_server_dir, fServerName, 0) < 0) { 00528 jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe"); 00529 return false; 00530 } 00531 00532 if ((pipe = fRequestListenPipe.AcceptClient()) == NULL) { 00533 jack_error("JackWinNamedPipeServerChannel::Open : cannot connect pipe"); 00534 return false; 00535 } 00536 00537 ClientAdd(pipe); 00538 return true; 00539 } 00540 00541 void JackWinNamedPipeServerChannel::ClientAdd(JackWinNamedPipeClient* pipe) 00542 { 00543 // Remove dead (= not running anymore) clients. 00544 std::list<JackClientPipeThread*>::iterator it = fClientList.begin(); 00545 JackClientPipeThread* client; 00546 00547 jack_log("ClientAdd size %ld", fClientList.size()); 00548 00549 while (it != fClientList.end()) { 00550 client = *it; 00551 jack_log("Remove dead client = %x running = %ld", client, client->IsRunning()); 00552 if (client->IsRunning()) { 00553 it++; 00554 } else { 00555 it = fClientList.erase(it); 00556 delete client; 00557 } 00558 } 00559 00560 client = new JackClientPipeThread(pipe); 00561 client->Open(fServer); 00562 // Here we are sure that the client is running (because it's thread is in "running" state). 00563 fClientList.push_back(client); 00564 } 00565 00566 } // end of namespace 00567 00568