Jack2 1.9.6
|
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, 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, &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::kReleaseTimebase: { 00256 jack_log("JackRequest::ReleaseTimebase"); 00257 JackReleaseTimebaseRequest req; 00258 JackResult res; 00259 if (req.Read(fPipe) == 0) 00260 res.fResult = fServer->ReleaseTimebase(req.fRefNum); 00261 res.Write(fPipe); 00262 break; 00263 } 00264 00265 case JackRequest::kSetTimebaseCallback: { 00266 jack_log("JackRequest::SetTimebaseCallback"); 00267 JackSetTimebaseCallbackRequest req; 00268 JackResult res; 00269 if (req.Read(fPipe) == 0) 00270 res.fResult = fServer->SetTimebaseCallback(req.fRefNum, req.fConditionnal); 00271 res.Write(fPipe); 00272 break; 00273 } 00274 00275 case JackRequest::kGetInternalClientName: { 00276 jack_log("JackRequest::GetInternalClientName"); 00277 JackGetInternalClientNameRequest req; 00278 JackGetInternalClientNameResult res; 00279 if (req.Read(fPipe) == 0) 00280 res.fResult = fServer->GetEngine()->GetInternalClientName(req.fIntRefNum, res.fName); 00281 res.Write(fPipe); 00282 break; 00283 } 00284 00285 case JackRequest::kInternalClientHandle: { 00286 jack_log("JackRequest::InternalClientHandle"); 00287 JackInternalClientHandleRequest req; 00288 JackInternalClientHandleResult res; 00289 if (req.Read(fPipe) == 0) 00290 res.fResult = fServer->GetEngine()->InternalClientHandle(req.fName, &res.fStatus, &res.fIntRefNum); 00291 res.Write(fPipe); 00292 break; 00293 } 00294 00295 case JackRequest::kInternalClientLoad: { 00296 jack_log("JackRequest::InternalClientLoad"); 00297 JackInternalClientLoadRequest req; 00298 JackInternalClientLoadResult res; 00299 if (req.Read(fPipe) == 0) 00300 res.fResult = fServer->InternalClientLoad(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, &res.fStatus); 00301 res.Write(fPipe); 00302 break; 00303 } 00304 00305 case JackRequest::kInternalClientUnload: { 00306 jack_log("JackRequest::InternalClientUnload"); 00307 JackInternalClientUnloadRequest req; 00308 JackInternalClientUnloadResult res; 00309 if (req.Read(fPipe) == 0) 00310 res.fResult = fServer->GetEngine()->InternalClientUnload(req.fIntRefNum, &res.fStatus); 00311 res.Write(fPipe); 00312 break; 00313 } 00314 00315 case JackRequest::kNotification: { 00316 jack_log("JackRequest::Notification"); 00317 JackClientNotificationRequest req; 00318 if (req.Read(fPipe) == 0) { 00319 if (req.fNotify == kQUIT) { 00320 jack_log("JackRequest::Notification kQUIT"); 00321 throw JackQuitException(); 00322 } else { 00323 fServer->Notify(req.fRefNum, req.fNotify, req.fValue); 00324 } 00325 } 00326 break; 00327 } 00328 00329 default: 00330 jack_log("Unknown request %ld", header.fType); 00331 break; 00332 } 00333 } 00334 00335 // Unlock the global mutex 00336 ReleaseMutex(fMutex); 00337 return ret; 00338 } 00339 00340 void JackClientPipeThread::ClientAdd(char* name, int pid, int* shared_engine, int* shared_client, int* shared_graph, int* result) 00341 { 00342 jack_log("JackClientPipeThread::ClientAdd %s", name); 00343 fRefNum = -1; 00344 *result = fServer->GetEngine()->ClientExternalOpen(name, pid, &fRefNum, shared_engine, shared_client, shared_graph); 00345 } 00346 00347 void JackClientPipeThread::ClientRemove() 00348 { 00349 jack_log("JackClientPipeThread::ClientRemove ref = %d", fRefNum); 00350 /* TODO : solve WIN32 thread Kill issue 00351 Close(); 00352 */ 00353 fRefNum = -1; 00354 fPipe->Close(); 00355 } 00356 00357 void JackClientPipeThread::ClientKill() 00358 { 00359 jack_log("JackClientPipeThread::ClientKill ref = %d", fRefNum); 00360 00361 if (fRefNum == -1) { // Correspond to an already removed client. 00362 jack_log("Kill a closed client"); 00363 } else if (fRefNum == 0) { // Correspond to a still not opened client. 00364 jack_log("Kill a not opened client"); 00365 } else { 00366 fServer->ClientKill(fRefNum); 00367 } 00368 00369 Close(); 00370 } 00371 00372 JackWinNamedPipeServerChannel::JackWinNamedPipeServerChannel():fThread(this) 00373 {} 00374 00375 JackWinNamedPipeServerChannel::~JackWinNamedPipeServerChannel() 00376 { 00377 std::list<JackClientPipeThread*>::iterator it; 00378 00379 for (it = fClientList.begin(); it != fClientList.end(); it++) { 00380 JackClientPipeThread* client = *it; 00381 client->Close(); 00382 delete client; 00383 } 00384 } 00385 00386 int JackWinNamedPipeServerChannel::Open(const char* server_name, JackServer* server) 00387 { 00388 jack_log("JackWinNamedPipeServerChannel::Open "); 00389 snprintf(fServerName, sizeof(fServerName), server_name); 00390 00391 // Needed for internal connection from JackWinNamedPipeServerNotifyChannel object 00392 if (fRequestListenPipe.Bind(jack_server_dir, server_name, 0) < 0) { 00393 jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe"); 00394 return -1; 00395 } 00396 00397 fServer = server; 00398 return 0; 00399 } 00400 00401 void JackWinNamedPipeServerChannel::Close() 00402 { 00403 /* TODO : solve WIN32 thread Kill issue 00404 This would hang the server... since we are quitting it, its not really problematic, 00405 all ressources will be desallocated at the end. 00406 00407 fRequestListenPipe.Close(); 00408 fThread.Stop(); 00409 */ 00410 00411 fThread.Kill(); 00412 fRequestListenPipe.Close(); 00413 } 00414 00415 int JackWinNamedPipeServerChannel::Start() 00416 { 00417 if (fThread.Start() != 0) { 00418 jack_error("Cannot start Jack server listener"); 00419 return -1; 00420 } 00421 00422 return 0; 00423 } 00424 00425 bool JackWinNamedPipeServerChannel::Init() 00426 { 00427 jack_log("JackWinNamedPipeServerChannel::Init "); 00428 JackWinNamedPipeClient* pipe; 00429 00430 // Accept first client, that is the JackWinNamedPipeServerNotifyChannel object 00431 if ((pipe = fRequestListenPipe.AcceptClient()) == NULL) { 00432 jack_error("JackWinNamedPipeServerChannel::Init : cannot connect pipe"); 00433 return false; 00434 } else { 00435 ClientAdd(pipe); 00436 return true; 00437 } 00438 } 00439 00440 bool JackWinNamedPipeServerChannel::Execute() 00441 { 00442 JackWinNamedPipeClient* pipe; 00443 00444 if (fRequestListenPipe.Bind(jack_server_dir, fServerName, 0) < 0) { 00445 jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe"); 00446 return false; 00447 } 00448 00449 if ((pipe = fRequestListenPipe.AcceptClient()) == NULL) { 00450 jack_error("JackWinNamedPipeServerChannel::Open : cannot connect pipe"); 00451 return false; 00452 } 00453 00454 ClientAdd(pipe); 00455 return true; 00456 } 00457 00458 void JackWinNamedPipeServerChannel::ClientAdd(JackWinNamedPipeClient* pipe) 00459 { 00460 // Remove dead (= not running anymore) clients. 00461 std::list<JackClientPipeThread*>::iterator it = fClientList.begin(); 00462 JackClientPipeThread* client; 00463 00464 jack_log("ClientAdd size %ld", fClientList.size()); 00465 00466 while (it != fClientList.end()) { 00467 client = *it; 00468 jack_log("Remove dead client = %x running = %ld", client, client->IsRunning()); 00469 if (client->IsRunning()) { 00470 it++; 00471 } else { 00472 it = fClientList.erase(it); 00473 delete client; 00474 } 00475 } 00476 00477 client = new JackClientPipeThread(pipe); 00478 client->Open(fServer); 00479 // Here we are sure that the client is running (because it's thread is in "running" state). 00480 fClientList.push_back(client); 00481 } 00482 00483 } // end of namespace 00484 00485