Jack2 1.9.6
|
00001 /* 00002 Copyright (C) 2001 Paul Davis 00003 Copyright (C) 2004-2008 Grame 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU Lesser General Public License as published by 00007 the Free Software Foundation; either version 2.1 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU Lesser General Public License for more details. 00014 00015 You should have received a copy of the GNU Lesser General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00018 00019 */ 00020 00021 #include "JackGraphManager.h" 00022 #include "JackConstants.h" 00023 #include "JackError.h" 00024 #include <assert.h> 00025 #include <stdlib.h> 00026 #include <algorithm> 00027 #include <regex.h> 00028 00029 namespace Jack 00030 { 00031 00032 00033 static void AssertBufferSize(jack_nframes_t buffer_size) 00034 { 00035 if (buffer_size > BUFFER_SIZE_MAX) { 00036 jack_log("JackGraphManager::AssertBufferSize frames = %ld", buffer_size); 00037 assert(buffer_size <= BUFFER_SIZE_MAX); 00038 } 00039 } 00040 00041 void JackGraphManager::AssertPort(jack_port_id_t port_index) 00042 { 00043 if (port_index >= fPortMax) { 00044 jack_log("JackGraphManager::AssertPort port_index = %ld", port_index); 00045 assert(port_index < fPortMax); 00046 } 00047 } 00048 00049 JackGraphManager* JackGraphManager::Allocate(int port_max) 00050 { 00051 // Using "Placement" new 00052 void* shared_ptr = JackShmMem::operator new(sizeof(JackGraphManager) + port_max * sizeof(JackPort)); 00053 return new(shared_ptr) JackGraphManager(port_max); 00054 } 00055 00056 void JackGraphManager::Destroy(JackGraphManager* manager) 00057 { 00058 // "Placement" new was used 00059 manager->~JackGraphManager(); 00060 JackShmMem::operator delete(manager); 00061 } 00062 00063 JackGraphManager::JackGraphManager(int port_max) 00064 { 00065 assert(port_max <= PORT_NUM_MAX); 00066 00067 for (int i = 0; i < port_max; i++) { 00068 fPortArray[i].Release(); 00069 } 00070 00071 fPortMax = port_max; 00072 } 00073 00074 JackPort* JackGraphManager::GetPort(jack_port_id_t port_index) 00075 { 00076 AssertPort(port_index); 00077 return &fPortArray[port_index]; 00078 } 00079 00080 float* JackGraphManager::GetBuffer(jack_port_id_t port_index) 00081 { 00082 return fPortArray[port_index].GetBuffer(); 00083 } 00084 00085 // Server 00086 void JackGraphManager::InitRefNum(int refnum) 00087 { 00088 JackConnectionManager* manager = WriteNextStateStart(); 00089 manager->InitRefNum(refnum); 00090 WriteNextStateStop(); 00091 } 00092 00093 // RT 00094 void JackGraphManager::RunCurrentGraph() 00095 { 00096 JackConnectionManager* manager = ReadCurrentState(); 00097 manager->ResetGraph(fClientTiming); 00098 } 00099 00100 // RT 00101 bool JackGraphManager::RunNextGraph() 00102 { 00103 bool res; 00104 JackConnectionManager* manager = TrySwitchState(&res); 00105 manager->ResetGraph(fClientTiming); 00106 return res; 00107 } 00108 00109 // RT 00110 bool JackGraphManager::IsFinishedGraph() 00111 { 00112 JackConnectionManager* manager = ReadCurrentState(); 00113 return (manager->GetActivation(FREEWHEEL_DRIVER_REFNUM) == 0); 00114 } 00115 00116 // RT 00117 int JackGraphManager::ResumeRefNum(JackClientControl* control, JackSynchro* table) 00118 { 00119 JackConnectionManager* manager = ReadCurrentState(); 00120 return manager->ResumeRefNum(control, table, fClientTiming); 00121 } 00122 00123 // RT 00124 int JackGraphManager::SuspendRefNum(JackClientControl* control, JackSynchro* table, long usec) 00125 { 00126 JackConnectionManager* manager = ReadCurrentState(); 00127 return manager->SuspendRefNum(control, table, fClientTiming, usec); 00128 } 00129 00130 // Server 00131 void JackGraphManager::DirectConnect(int ref1, int ref2) 00132 { 00133 JackConnectionManager* manager = WriteNextStateStart(); 00134 manager->DirectConnect(ref1, ref2); 00135 jack_log("JackGraphManager::ConnectRefNum cur_index = %ld ref1 = %ld ref2 = %ld", CurIndex(fCounter), ref1, ref2); 00136 WriteNextStateStop(); 00137 } 00138 00139 // Server 00140 void JackGraphManager::DirectDisconnect(int ref1, int ref2) 00141 { 00142 JackConnectionManager* manager = WriteNextStateStart(); 00143 manager->DirectDisconnect(ref1, ref2); 00144 jack_log("JackGraphManager::DisconnectRefNum cur_index = %ld ref1 = %ld ref2 = %ld", CurIndex(fCounter), ref1, ref2); 00145 WriteNextStateStop(); 00146 } 00147 00148 // Server 00149 bool JackGraphManager::IsDirectConnection(int ref1, int ref2) 00150 { 00151 JackConnectionManager* manager = ReadCurrentState(); 00152 return manager->IsDirectConnection(ref1, ref2); 00153 } 00154 00155 // RT 00156 void* JackGraphManager::GetBuffer(jack_port_id_t port_index, jack_nframes_t buffer_size) 00157 { 00158 AssertPort(port_index); 00159 AssertBufferSize(buffer_size); 00160 00161 JackConnectionManager* manager = ReadCurrentState(); 00162 JackPort* port = GetPort(port_index); 00163 00164 // This happens when a port has just been unregistered and is still used by the RT code 00165 if (!port->IsUsed()) { 00166 jack_log("JackGraphManager::GetBuffer : port = %ld is released state", port_index); 00167 return GetBuffer(0); // port_index 0 is not used 00168 } 00169 00170 // Output port 00171 if (port->fFlags & JackPortIsOutput) { 00172 return (port->fTied != NO_PORT) ? GetBuffer(port->fTied, buffer_size) : GetBuffer(port_index); 00173 } 00174 00175 // Input port 00176 jack_int_t len = manager->Connections(port_index); 00177 00178 // No connections : return a zero-filled buffer 00179 if (len == 0) { 00180 port->ClearBuffer(buffer_size); 00181 return port->GetBuffer(); 00182 00183 // One connection 00184 } else if (len == 1) { 00185 jack_port_id_t src_index = manager->GetPort(port_index, 0); 00186 00187 // Ports in same client : copy the buffer 00188 if (GetPort(src_index)->GetRefNum() == port->GetRefNum()) { 00189 void* buffers[1]; 00190 buffers[0] = GetBuffer(src_index, buffer_size); 00191 port->MixBuffers(buffers, 1, buffer_size); 00192 return port->GetBuffer(); 00193 // Otherwise, use zero-copy mode, just pass the buffer of the connected (output) port. 00194 } else { 00195 return GetBuffer(src_index, buffer_size); 00196 } 00197 00198 // Multiple connections : mix all buffers 00199 } else { 00200 00201 const jack_int_t* connections = manager->GetConnections(port_index); 00202 void* buffers[CONNECTION_NUM_FOR_PORT]; 00203 jack_port_id_t src_index; 00204 int i; 00205 00206 for (i = 0; (i < CONNECTION_NUM_FOR_PORT) && ((src_index = connections[i]) != EMPTY); i++) { 00207 AssertPort(src_index); 00208 buffers[i] = GetBuffer(src_index, buffer_size); 00209 } 00210 00211 port->MixBuffers(buffers, i, buffer_size); 00212 return port->GetBuffer(); 00213 } 00214 } 00215 00216 // Server 00217 int JackGraphManager::RequestMonitor(jack_port_id_t port_index, bool onoff) // Client 00218 { 00219 AssertPort(port_index); 00220 JackPort* port = GetPort(port_index); 00221 00231 port->RequestMonitor(onoff); 00232 00233 const jack_int_t* connections = ReadCurrentState()->GetConnections(port_index); 00234 if ((port->fFlags & JackPortIsOutput) == 0) { // ?? Taken from jack, why not (port->fFlags & JackPortIsInput) ? 00235 jack_port_id_t src_index; 00236 for (int i = 0; (i < CONNECTION_NUM_FOR_PORT) && ((src_index = connections[i]) != EMPTY); i++) { 00237 // XXX much worse things will happen if there is a feedback loop !!! 00238 RequestMonitor(src_index, onoff); 00239 } 00240 } 00241 00242 return 0; 00243 } 00244 00245 // Client 00246 jack_nframes_t JackGraphManager::ComputeTotalLatencyAux(jack_port_id_t port_index, jack_port_id_t src_port_index, JackConnectionManager* manager, int hop_count) 00247 { 00248 const jack_int_t* connections = manager->GetConnections(port_index); 00249 jack_nframes_t max_latency = 0; 00250 jack_port_id_t dst_index; 00251 00252 if (hop_count > 8) 00253 return GetPort(port_index)->GetLatency(); 00254 00255 for (int i = 0; (i < CONNECTION_NUM_FOR_PORT) && ((dst_index = connections[i]) != EMPTY); i++) { 00256 if (src_port_index != dst_index) { 00257 AssertPort(dst_index); 00258 JackPort* dst_port = GetPort(dst_index); 00259 jack_nframes_t this_latency = (dst_port->fFlags & JackPortIsTerminal) 00260 ? dst_port->GetLatency() 00261 : ComputeTotalLatencyAux(dst_index, port_index, manager, hop_count + 1); 00262 max_latency = ((max_latency > this_latency) ? max_latency : this_latency); 00263 } 00264 } 00265 00266 return max_latency + GetPort(port_index)->GetLatency(); 00267 } 00268 00269 // Client 00270 int JackGraphManager::ComputeTotalLatency(jack_port_id_t port_index) 00271 { 00272 UInt16 cur_index; 00273 UInt16 next_index; 00274 JackPort* port = GetPort(port_index); 00275 AssertPort(port_index); 00276 00277 do { 00278 cur_index = GetCurrentIndex(); 00279 port->fTotalLatency = ComputeTotalLatencyAux(port_index, port_index, ReadCurrentState(), 0); 00280 next_index = GetCurrentIndex(); 00281 } while (cur_index != next_index); // Until a coherent state has been read 00282 00283 jack_log("JackGraphManager::GetTotalLatency port_index = %ld total latency = %ld", port_index, port->fTotalLatency); 00284 return 0; 00285 } 00286 00287 // Client 00288 int JackGraphManager::ComputeTotalLatencies() 00289 { 00290 jack_port_id_t port_index; 00291 for (port_index = FIRST_AVAILABLE_PORT; port_index < fPortMax; port_index++) { 00292 JackPort* port = GetPort(port_index); 00293 if (port->IsUsed()) 00294 ComputeTotalLatency(port_index); 00295 } 00296 return 0; 00297 } 00298 00299 // Server 00300 void JackGraphManager::SetBufferSize(jack_nframes_t buffer_size) 00301 { 00302 jack_log("JackGraphManager::SetBufferSize size = %ld", buffer_size); 00303 00304 jack_port_id_t port_index; 00305 for (port_index = FIRST_AVAILABLE_PORT; port_index < fPortMax; port_index++) { 00306 JackPort* port = GetPort(port_index); 00307 if (port->IsUsed()) 00308 port->ClearBuffer(buffer_size); 00309 } 00310 } 00311 00312 // Server 00313 jack_port_id_t JackGraphManager::AllocatePortAux(int refnum, const char* port_name, const char* port_type, JackPortFlags flags) 00314 { 00315 jack_port_id_t port_index; 00316 00317 // Available ports start at FIRST_AVAILABLE_PORT (= 1), otherwise a port_index of 0 is "seen" as a NULL port by the external API... 00318 for (port_index = FIRST_AVAILABLE_PORT; port_index < fPortMax; port_index++) { 00319 JackPort* port = GetPort(port_index); 00320 if (!port->IsUsed()) { 00321 jack_log("JackGraphManager::AllocatePortAux port_index = %ld name = %s type = %s", port_index, port_name, port_type); 00322 if (!port->Allocate(refnum, port_name, port_type, flags)) 00323 return NO_PORT; 00324 break; 00325 } 00326 } 00327 00328 return (port_index < fPortMax) ? port_index : NO_PORT; 00329 } 00330 00331 // Server 00332 jack_port_id_t JackGraphManager::AllocatePort(int refnum, const char* port_name, const char* port_type, JackPortFlags flags, jack_nframes_t buffer_size) 00333 { 00334 JackConnectionManager* manager = WriteNextStateStart(); 00335 jack_port_id_t port_index = AllocatePortAux(refnum, port_name, port_type, flags); 00336 00337 if (port_index != NO_PORT) { 00338 JackPort* port = GetPort(port_index); 00339 assert(port); 00340 port->ClearBuffer(buffer_size); 00341 00342 int res; 00343 if (flags & JackPortIsOutput) { 00344 res = manager->AddOutputPort(refnum, port_index); 00345 } else { 00346 res = manager->AddInputPort(refnum, port_index); 00347 } 00348 // Insertion failure 00349 if (res < 0) { 00350 port->Release(); 00351 port_index = NO_PORT; 00352 } 00353 } 00354 00355 WriteNextStateStop(); 00356 return port_index; 00357 } 00358 00359 // Server 00360 int JackGraphManager::ReleasePort(int refnum, jack_port_id_t port_index) 00361 { 00362 JackConnectionManager* manager = WriteNextStateStart(); 00363 JackPort* port = GetPort(port_index); 00364 int res; 00365 00366 if (port->fFlags & JackPortIsOutput) { 00367 DisconnectAllOutput(port_index); 00368 res = manager->RemoveOutputPort(refnum, port_index); 00369 } else { 00370 DisconnectAllInput(port_index); 00371 res = manager->RemoveInputPort(refnum, port_index); 00372 } 00373 00374 port->Release(); 00375 WriteNextStateStop(); 00376 return res; 00377 } 00378 00379 void JackGraphManager::ActivatePort(jack_port_id_t port_index) 00380 { 00381 JackPort* port = GetPort(port_index); 00382 port->fFlags = (JackPortFlags)(port->fFlags | JackPortIsActive); 00383 } 00384 00385 void JackGraphManager::DeactivatePort(jack_port_id_t port_index) 00386 { 00387 JackPort* port = GetPort(port_index); 00388 port->fFlags = (JackPortFlags)(port->fFlags & ~JackPortIsActive); 00389 } 00390 00391 void JackGraphManager::GetInputPorts(int refnum, jack_int_t* res) 00392 { 00393 JackConnectionManager* manager = WriteNextStateStart(); 00394 const jack_int_t* input = manager->GetInputPorts(refnum); 00395 memcpy(res, input, sizeof(jack_int_t) * PORT_NUM_FOR_CLIENT); 00396 WriteNextStateStop(); 00397 } 00398 00399 void JackGraphManager::GetOutputPorts(int refnum, jack_int_t* res) 00400 { 00401 JackConnectionManager* manager = WriteNextStateStart(); 00402 const jack_int_t* output = manager->GetOutputPorts(refnum); 00403 memcpy(res, output, sizeof(jack_int_t) * PORT_NUM_FOR_CLIENT); 00404 WriteNextStateStop(); 00405 } 00406 00407 // Server 00408 void JackGraphManager::RemoveAllPorts(int refnum) 00409 { 00410 jack_log("JackGraphManager::RemoveAllPorts ref = %ld", refnum); 00411 JackConnectionManager* manager = WriteNextStateStart(); 00412 jack_port_id_t port_index; 00413 00414 // Warning : ReleasePort shift port to left, thus we always remove the first port until the "input" table is empty 00415 const jack_int_t* input = manager->GetInputPorts(refnum); 00416 while ((port_index = input[0]) != EMPTY) { 00417 int res = ReleasePort(refnum, port_index); 00418 if (res < 0) { 00419 jack_error("JackGraphManager::RemoveAllPorts failure ref = %ld port_index = %ld", refnum, port_index); 00420 assert(true); 00421 break; 00422 } 00423 } 00424 00425 // Warning : ReleasePort shift port to left, thus we always remove the first port until the "output" table is empty 00426 const jack_int_t* output = manager->GetOutputPorts(refnum); 00427 while ((port_index = output[0]) != EMPTY) { 00428 int res = ReleasePort(refnum, port_index); 00429 if (res < 0) { 00430 jack_error("JackGraphManager::RemoveAllPorts failure ref = %ld port_index = %ld", refnum, port_index); 00431 assert(true); 00432 break; 00433 } 00434 } 00435 00436 WriteNextStateStop(); 00437 } 00438 00439 // Server 00440 void JackGraphManager::DisconnectAllPorts(int refnum) 00441 { 00442 int i; 00443 jack_log("JackGraphManager::DisconnectAllPorts ref = %ld", refnum); 00444 JackConnectionManager* manager = WriteNextStateStart(); 00445 00446 const jack_int_t* input = manager->GetInputPorts(refnum); 00447 for (i = 0; i < PORT_NUM_FOR_CLIENT && input[i] != EMPTY ; i++) { 00448 DisconnectAllInput(input[i]); 00449 } 00450 00451 const jack_int_t* output = manager->GetOutputPorts(refnum); 00452 for (i = 0; i < PORT_NUM_FOR_CLIENT && output[i] != EMPTY; i++) { 00453 DisconnectAllOutput(output[i]); 00454 } 00455 00456 WriteNextStateStop(); 00457 } 00458 00459 // Server 00460 void JackGraphManager::DisconnectAllInput(jack_port_id_t port_index) 00461 { 00462 jack_log("JackGraphManager::DisconnectAllInput port_index = %ld", port_index); 00463 JackConnectionManager* manager = WriteNextStateStart(); 00464 00465 for (unsigned int i = 0; i < fPortMax; i++) { 00466 if (manager->IsConnected(i, port_index)) { 00467 jack_log("JackGraphManager::Disconnect i = %ld port_index = %ld", i, port_index); 00468 Disconnect(i, port_index); 00469 } 00470 } 00471 WriteNextStateStop(); 00472 } 00473 00474 // Server 00475 void JackGraphManager::DisconnectAllOutput(jack_port_id_t port_index) 00476 { 00477 jack_log("JackGraphManager::DisconnectAllOutput port_index = %ld ", port_index); 00478 JackConnectionManager* manager = WriteNextStateStart(); 00479 00480 const jack_int_t* connections = manager->GetConnections(port_index); 00481 while (connections[0] != EMPTY) { 00482 Disconnect(port_index, connections[0]); // Warning : Disconnect shift port to left 00483 } 00484 WriteNextStateStop(); 00485 } 00486 00487 // Server 00488 int JackGraphManager::DisconnectAll(jack_port_id_t port_index) 00489 { 00490 AssertPort(port_index); 00491 00492 JackPort* port = GetPort(port_index); 00493 if (port->fFlags & JackPortIsOutput) { 00494 DisconnectAllOutput(port_index); 00495 } else { 00496 DisconnectAllInput(port_index); 00497 } 00498 return 0; 00499 } 00500 00501 // Server 00502 void JackGraphManager::GetConnections(jack_port_id_t port_index, jack_int_t* res) 00503 { 00504 JackConnectionManager* manager = WriteNextStateStart(); 00505 const jack_int_t* connections = manager->GetConnections(port_index); 00506 memcpy(res, connections, sizeof(jack_int_t) * CONNECTION_NUM_FOR_PORT); 00507 WriteNextStateStop(); 00508 } 00509 00510 // Server 00511 void JackGraphManager::Activate(int refnum) 00512 { 00513 DirectConnect(FREEWHEEL_DRIVER_REFNUM, refnum); 00514 DirectConnect(refnum, FREEWHEEL_DRIVER_REFNUM); 00515 } 00516 00517 /* 00518 Disconnection from the FW must be done in last otherwise an intermediate "unconnected" 00519 (thus unactivated) state may happen where the client is still checked for its end. 00520 */ 00521 00522 // Server 00523 void JackGraphManager::Deactivate(int refnum) 00524 { 00525 // Disconnect only when needed 00526 if (IsDirectConnection(refnum, FREEWHEEL_DRIVER_REFNUM)) { 00527 DirectDisconnect(refnum, FREEWHEEL_DRIVER_REFNUM); 00528 } else { 00529 jack_log("JackServer::Deactivate client = %ld was not activated", refnum); 00530 } 00531 00532 // Disconnect only when needed 00533 if (IsDirectConnection(FREEWHEEL_DRIVER_REFNUM, refnum)) { 00534 DirectDisconnect(FREEWHEEL_DRIVER_REFNUM, refnum); 00535 } else { 00536 jack_log("JackServer::Deactivate client = %ld was not activated", refnum); 00537 } 00538 } 00539 00540 // Server 00541 int JackGraphManager::GetInputRefNum(jack_port_id_t port_index) 00542 { 00543 AssertPort(port_index); 00544 JackConnectionManager* manager = WriteNextStateStart(); 00545 int res = manager->GetInputRefNum(port_index); 00546 WriteNextStateStop(); 00547 return res; 00548 } 00549 00550 // Server 00551 int JackGraphManager::GetOutputRefNum(jack_port_id_t port_index) 00552 { 00553 AssertPort(port_index); 00554 JackConnectionManager* manager = WriteNextStateStart(); 00555 int res = manager->GetOutputRefNum(port_index); 00556 WriteNextStateStop(); 00557 return res; 00558 } 00559 00560 int JackGraphManager::Connect(jack_port_id_t port_src, jack_port_id_t port_dst) 00561 { 00562 JackConnectionManager* manager = WriteNextStateStart(); 00563 jack_log("JackGraphManager::Connect port_src = %ld port_dst = %ld", port_src, port_dst); 00564 JackPort* src = GetPort(port_src); 00565 JackPort* dst = GetPort(port_dst); 00566 int res = 0; 00567 00568 if (!src->fInUse || !dst->fInUse) { 00569 if (!src->fInUse) 00570 jack_error("JackGraphManager::Connect port_src = %ld not used name = %s", port_src, GetPort(port_src)->fName); 00571 if (!dst->fInUse) 00572 jack_error("JackGraphManager::Connect port_dst = %ld not used name = %s", port_dst, GetPort(port_dst)->fName); 00573 res = -1; 00574 goto end; 00575 } 00576 if (src->fTypeId != dst->fTypeId) { 00577 jack_error("JackGraphManager::Connect different port types port_src = %ld port_dst = %ld", port_src, port_dst); 00578 res = -1; 00579 goto end; 00580 } 00581 if (manager->IsConnected(port_src, port_dst)) { 00582 jack_error("JackGraphManager::Connect already connected port_src = %ld port_dst = %ld", port_src, port_dst); 00583 res = EEXIST; 00584 goto end; 00585 } 00586 00587 res = manager->Connect(port_src, port_dst); 00588 if (res < 0) { 00589 jack_error("JackGraphManager::Connect failed port_src = %ld port_dst = %ld", port_src, port_dst); 00590 goto end; 00591 } 00592 res = manager->Connect(port_dst, port_src); 00593 if (res < 0) { 00594 jack_error("JackGraphManager::Connect failed port_dst = %ld port_src = %ld", port_dst, port_src); 00595 goto end; 00596 } 00597 00598 if (manager->IsLoopPath(port_src, port_dst)) { 00599 jack_log("JackGraphManager::Connect: LOOP detected"); 00600 manager->IncFeedbackConnection(port_src, port_dst); 00601 } else { 00602 manager->IncDirectConnection(port_src, port_dst); 00603 } 00604 00605 end: 00606 WriteNextStateStop(); 00607 return res; 00608 } 00609 00610 // Server 00611 int JackGraphManager::Disconnect(jack_port_id_t port_src, jack_port_id_t port_dst) 00612 { 00613 JackConnectionManager* manager = WriteNextStateStart(); 00614 jack_log("JackGraphManager::Disconnect port_src = %ld port_dst = %ld", port_src, port_dst); 00615 bool in_use_src = GetPort(port_src)->fInUse; 00616 bool in_use_dst = GetPort(port_dst)->fInUse; 00617 int res = 0; 00618 00619 if (!in_use_src || !in_use_dst) { 00620 if (!in_use_src) 00621 jack_error("JackGraphManager::Disconnect: port_src = %ld not used name = %s", port_src, GetPort(port_src)->fName); 00622 if (!in_use_dst) 00623 jack_error("JackGraphManager::Disconnect: port_src = %ld not used name = %s", port_dst, GetPort(port_dst)->fName); 00624 res = -1; 00625 goto end; 00626 } 00627 if (!manager->IsConnected(port_src, port_dst)) { 00628 jack_error("JackGraphManager::Disconnect not connected port_src = %ld port_dst = %ld", port_src, port_dst); 00629 res = -1; 00630 goto end; 00631 } 00632 00633 res = manager->Disconnect(port_src, port_dst); 00634 if (res < 0) { 00635 jack_error("JackGraphManager::Disconnect failed port_src = %ld port_dst = %ld", port_src, port_dst); 00636 goto end; 00637 } 00638 res = manager->Disconnect(port_dst, port_src); 00639 if (res < 0) { 00640 jack_error("JackGraphManager::Disconnect failed port_dst = %ld port_src = %ld", port_dst, port_src); 00641 goto end; 00642 } 00643 00644 if (manager->IsFeedbackConnection(port_src, port_dst)) { 00645 jack_log("JackGraphManager::Disconnect: FEEDBACK removed"); 00646 manager->DecFeedbackConnection(port_src, port_dst); 00647 } else { 00648 manager->DecDirectConnection(port_src, port_dst); 00649 } 00650 00651 end: 00652 WriteNextStateStop(); 00653 return res; 00654 } 00655 00656 // Client 00657 int JackGraphManager::IsConnected(jack_port_id_t port_src, jack_port_id_t port_dst) 00658 { 00659 JackConnectionManager* manager = ReadCurrentState(); 00660 return manager->IsConnected(port_src, port_dst); 00661 } 00662 00663 // Server 00664 int JackGraphManager::CheckPorts(jack_port_id_t port_src, jack_port_id_t port_dst) 00665 { 00666 JackPort* src = GetPort(port_src); 00667 JackPort* dst = GetPort(port_dst); 00668 00669 if ((dst->fFlags & JackPortIsInput) == 0) { 00670 jack_error("Destination port in attempted (dis)connection of %s and %s is not an input port", src->fName, dst->fName); 00671 return -1; 00672 } 00673 00674 if ((src->fFlags & JackPortIsOutput) == 0) { 00675 jack_error("Source port in attempted (dis)connection of %s and %s is not an output port", src->fName, dst->fName); 00676 return -1; 00677 } 00678 00679 return 0; 00680 } 00681 00682 int JackGraphManager::GetTwoPorts(const char* src_name, const char* dst_name, jack_port_id_t* port_src, jack_port_id_t* port_dst) 00683 { 00684 jack_log("JackGraphManager::CheckConnect src_name = %s dst_name = %s", src_name, dst_name); 00685 00686 if ((*port_src = GetPort(src_name)) == NO_PORT) { 00687 jack_error("Unknown source port in attempted (dis)connection src_name [%s] dst_name [%s]", src_name, dst_name); 00688 return -1; 00689 } 00690 00691 if ((*port_dst = GetPort(dst_name)) == NO_PORT) { 00692 jack_error("Unknown destination port in attempted (dis)connection src_name [%s] dst_name [%s]", src_name, dst_name); 00693 return -1; 00694 } 00695 00696 return 0; 00697 } 00698 00699 // Client : port array 00700 jack_port_id_t JackGraphManager::GetPort(const char* name) 00701 { 00702 for (unsigned int i = 0; i < fPortMax; i++) { 00703 JackPort* port = GetPort(i); 00704 if (port->IsUsed() && port->NameEquals(name)) 00705 return i; 00706 } 00707 return NO_PORT; 00708 } 00709 00714 // Client 00715 void JackGraphManager::GetConnectionsAux(JackConnectionManager* manager, const char** res, jack_port_id_t port_index) 00716 { 00717 const jack_int_t* connections = manager->GetConnections(port_index); 00718 jack_int_t index; 00719 int i; 00720 00721 // Cleanup connection array 00722 memset(res, 0, sizeof(char*) * CONNECTION_NUM_FOR_PORT); 00723 00724 for (i = 0; (i < CONNECTION_NUM_FOR_PORT) && ((index = connections[i]) != EMPTY); i++) { 00725 JackPort* port = GetPort(index); 00726 res[i] = port->fName; 00727 } 00728 00729 res[i] = NULL; 00730 } 00731 00732 /* 00733 Use the state returned by ReadCurrentState and check that the state was not changed during the read operation. 00734 The operation is lock-free since there is no intermediate state in the write operation that could cause the 00735 read to loop forever. 00736 */ 00737 00738 // Client 00739 const char** JackGraphManager::GetConnections(jack_port_id_t port_index) 00740 { 00741 const char** res = (const char**)malloc(sizeof(char*) * CONNECTION_NUM_FOR_PORT); 00742 UInt16 cur_index, next_index; 00743 00744 if (!res) 00745 return NULL; 00746 00747 do { 00748 cur_index = GetCurrentIndex(); 00749 GetConnectionsAux(ReadCurrentState(), res, port_index); 00750 next_index = GetCurrentIndex(); 00751 } while (cur_index != next_index); // Until a coherent state has been read 00752 00753 if (res[0]) { // at least one connection 00754 return res; 00755 } else { // empty array, should return NULL 00756 free(res); 00757 return NULL; 00758 } 00759 } 00760 00761 // Client 00762 void JackGraphManager::GetPortsAux(const char** matching_ports, const char* port_name_pattern, const char* type_name_pattern, unsigned long flags) 00763 { 00764 int match_cnt = 0; 00765 regex_t port_regex, type_regex; 00766 00767 if (port_name_pattern && port_name_pattern[0]) { 00768 regcomp(&port_regex, port_name_pattern, REG_EXTENDED | REG_NOSUB); 00769 } 00770 if (type_name_pattern && type_name_pattern[0]) { 00771 regcomp(&type_regex, type_name_pattern, REG_EXTENDED | REG_NOSUB); 00772 } 00773 00774 // Cleanup port array 00775 memset(matching_ports, 0, sizeof(char*) * fPortMax); 00776 00777 for (unsigned int i = 0; i < fPortMax; i++) { 00778 bool matching = true; 00779 JackPort* port = GetPort(i); 00780 00781 if (port->IsUsed()) { 00782 00783 if (flags) { 00784 if ((port->fFlags & flags) != flags) { 00785 matching = false; 00786 } 00787 } 00788 00789 if (matching && port_name_pattern && port_name_pattern[0]) { 00790 if (regexec(&port_regex, port->GetName(), 0, NULL, 0)) { 00791 matching = false; 00792 } 00793 } 00794 if (matching && type_name_pattern && type_name_pattern[0]) { 00795 if (regexec(&type_regex, port->GetType(), 0, NULL, 0)) { 00796 matching = false; 00797 } 00798 } 00799 00800 if (matching) { 00801 matching_ports[match_cnt++] = port->fName; 00802 } 00803 } 00804 } 00805 00806 matching_ports[match_cnt] = 0; 00807 00808 if (port_name_pattern && port_name_pattern[0]) { 00809 regfree(&port_regex); 00810 } 00811 if (type_name_pattern && type_name_pattern[0]) { 00812 regfree(&type_regex); 00813 } 00814 } 00815 00816 // Client 00817 /* 00818 Check that the state was not changed during the read operation. 00819 The operation is lock-free since there is no intermediate state in the write operation that could cause the 00820 read to loop forever. 00821 */ 00822 const char** JackGraphManager::GetPorts(const char* port_name_pattern, const char* type_name_pattern, unsigned long flags) 00823 { 00824 const char** res = (const char**)malloc(sizeof(char*) * fPortMax); 00825 UInt16 cur_index, next_index; 00826 00827 if (!res) 00828 return NULL; 00829 00830 do { 00831 cur_index = GetCurrentIndex(); 00832 GetPortsAux(res, port_name_pattern, type_name_pattern, flags); 00833 next_index = GetCurrentIndex(); 00834 } while (cur_index != next_index); // Until a coherent state has been read 00835 00836 if (res[0]) { // at least one port 00837 return res; 00838 } else { 00839 free(res); // empty array, should return NULL 00840 return NULL; 00841 } 00842 } 00843 00844 // Server 00845 void JackGraphManager::Save(JackConnectionManager* dst) 00846 { 00847 JackConnectionManager* manager = WriteNextStateStart(); 00848 memcpy(dst, manager, sizeof(JackConnectionManager)); 00849 WriteNextStateStop(); 00850 } 00851 00852 // Server 00853 void JackGraphManager::Restore(JackConnectionManager* src) 00854 { 00855 JackConnectionManager* manager = WriteNextStateStart(); 00856 memcpy(manager, src, sizeof(JackConnectionManager)); 00857 WriteNextStateStop(); 00858 } 00859 00860 } // end of namespace 00861 00862