00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "JackSystemDeps.h"
00022 #include "JackGraphManager.h"
00023 #include "JackClientControl.h"
00024 #include "JackEngineControl.h"
00025 #include "JackGlobals.h"
00026 #include "JackChannel.h"
00027 #include "JackTransportEngine.h"
00028 #include "driver_interface.h"
00029 #include "JackLibGlobals.h"
00030
00031 #include <math.h>
00032 #include <string>
00033 #include <algorithm>
00034
00035 using namespace std;
00036
00037 namespace Jack
00038 {
00039
00040 #define IsRealTime() ((fProcess != NULL) | (fThreadFun != NULL) | (fSync != NULL) | (fTimebase != NULL))
00041
00042 JackClient::JackClient():fThread(this)
00043 {}
00044
00045 JackClient::JackClient(JackSynchro* table):fThread(this)
00046 {
00047 fSynchroTable = table;
00048 fProcess = NULL;
00049 fGraphOrder = NULL;
00050 fXrun = NULL;
00051 fShutdown = NULL;
00052 fInfoShutdown = NULL;
00053 fInit = NULL;
00054 fBufferSize = NULL;
00055 fClientRegistration = NULL;
00056 fFreewheel = NULL;
00057 fPortRegistration = NULL;
00058 fPortConnect = NULL;
00059 fPortRename = NULL;
00060 fTimebase = NULL;
00061 fSync = NULL;
00062 fThreadFun = NULL;
00063 fSession = NULL;
00064 fLatency = NULL;
00065
00066 fProcessArg = NULL;
00067 fGraphOrderArg = NULL;
00068 fXrunArg = NULL;
00069 fShutdownArg = NULL;
00070 fInfoShutdownArg = NULL;
00071 fInitArg = NULL;
00072 fBufferSizeArg = NULL;
00073 fFreewheelArg = NULL;
00074 fClientRegistrationArg = NULL;
00075 fPortRegistrationArg = NULL;
00076 fPortConnectArg = NULL;
00077 fPortRenameArg = NULL;
00078 fSyncArg = NULL;
00079 fTimebaseArg = NULL;
00080 fThreadFunArg = NULL;
00081 fSessionArg = NULL;
00082 fLatencyArg = NULL;
00083
00084 fSessionReply = kPendingSessionReply;
00085 }
00086
00087 JackClient::~JackClient()
00088 {}
00089
00090 void JackClient::ShutDown(jack_status_t code, const char* message)
00091 {
00092 jack_log("JackClient::ShutDown");
00093
00094
00095 if (fInfoShutdown) {
00096 fInfoShutdown(code, message, fInfoShutdownArg);
00097 fInfoShutdown = NULL;
00098
00099 } else if (fShutdown) {
00100 fShutdown(fShutdownArg);
00101 fShutdown = NULL;
00102 }
00103 }
00104
00105 int JackClient::Close()
00106 {
00107 jack_log("JackClient::Close ref = %ld", GetClientControl()->fRefNum);
00108 int result = 0;
00109
00110 Deactivate();
00111
00112
00113 fChannel->Stop();
00114
00115 fChannel->ClientClose(GetClientControl()->fRefNum, &result);
00116
00117 fChannel->Close();
00118 assert(JackGlobals::fSynchroMutex);
00119 JackGlobals::fSynchroMutex->Lock();
00120 fSynchroTable[GetClientControl()->fRefNum].Disconnect();
00121 JackGlobals::fSynchroMutex->Unlock();
00122 JackGlobals::fClientTable[GetClientControl()->fRefNum] = NULL;
00123 return result;
00124 }
00125
00126 bool JackClient::IsActive()
00127 {
00128 return (GetClientControl()) ? GetClientControl()->fActive : false;
00129 }
00130
00131 jack_native_thread_t JackClient::GetThreadID()
00132 {
00133 return fThread.GetThreadID();
00134 }
00135
00141 void JackClient::SetupDriverSync(bool freewheel)
00142 {
00143 if (!freewheel && !GetEngineControl()->fSyncMode) {
00144 jack_log("JackClient::SetupDriverSync driver sem in flush mode");
00145 for (int i = 0; i < GetEngineControl()->fDriverNum; i++) {
00146 fSynchroTable[i].SetFlush(true);
00147 }
00148 } else {
00149 jack_log("JackClient::SetupDriverSync driver sem in normal mode");
00150 for (int i = 0; i < GetEngineControl()->fDriverNum; i++) {
00151 fSynchroTable[i].SetFlush(false);
00152 }
00153 }
00154 }
00155
00160 int JackClient::ClientNotifyImp(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
00161 {
00162 return 0;
00163 }
00164
00165 int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
00166 {
00167 int res = 0;
00168
00169 jack_log("JackClient::ClientNotify ref = %ld name = %s notify = %ld", refnum, name, notify);
00170
00171
00172 switch (notify) {
00173
00174 case kAddClient:
00175 res = ClientNotifyImp(refnum, name, notify, sync, message, value1, value2);
00176 break;
00177
00178 case kRemoveClient:
00179 res = ClientNotifyImp(refnum, name, notify, sync, message, value1, value2);
00180 break;
00181
00182 case kActivateClient:
00183 jack_log("JackClient::kActivateClient name = %s ref = %ld ", name, refnum);
00184 InitAux();
00185 break;
00186 }
00187
00188
00189
00190
00191
00192 if (IsActive()) {
00193
00194 switch (notify) {
00195
00196 case kAddClient:
00197 jack_log("JackClient::kAddClient fName = %s name = %s", GetClientControl()->fName, name);
00198 if (fClientRegistration && strcmp(GetClientControl()->fName, name) != 0) {
00199 fClientRegistration(name, 1, fClientRegistrationArg);
00200 }
00201 break;
00202
00203 case kRemoveClient:
00204 jack_log("JackClient::kRemoveClient fName = %s name = %s", GetClientControl()->fName, name);
00205 if (fClientRegistration && strcmp(GetClientControl()->fName, name) != 0) {
00206 fClientRegistration(name, 0, fClientRegistrationArg);
00207 }
00208 break;
00209
00210 case kBufferSizeCallback:
00211 jack_log("JackClient::kBufferSizeCallback buffer_size = %ld", value1);
00212 if (fBufferSize) {
00213 res = fBufferSize(value1, fBufferSizeArg);
00214 }
00215 break;
00216
00217 case kSampleRateCallback:
00218 jack_log("JackClient::kSampleRateCallback sample_rate = %ld", value1);
00219 if (fSampleRate) {
00220 res = fSampleRate(value1, fSampleRateArg);
00221 }
00222 break;
00223
00224 case kGraphOrderCallback:
00225 jack_log("JackClient::kGraphOrderCallback");
00226 if (fGraphOrder) {
00227 res = fGraphOrder(fGraphOrderArg);
00228 }
00229 break;
00230
00231 case kStartFreewheelCallback:
00232 jack_log("JackClient::kStartFreewheel");
00233 SetupDriverSync(true);
00234
00235 if (fThread.GetStatus() == JackThread::kRunning) {
00236 fThread.DropRealTime();
00237 }
00238 if (fFreewheel) {
00239 fFreewheel(1, fFreewheelArg);
00240 }
00241 break;
00242
00243 case kStopFreewheelCallback:
00244 jack_log("JackClient::kStopFreewheel");
00245 SetupDriverSync(false);
00246 if (fFreewheel) {
00247 fFreewheel(0, fFreewheelArg);
00248 }
00249
00250 if (GetEngineControl()->fRealTime && fThread.GetStatus() == JackThread::kRunning) {
00251 if (fThread.AcquireRealTime(GetEngineControl()->fClientPriority) < 0) {
00252 jack_error("JackClient::AcquireRealTime error");
00253 }
00254 }
00255 break;
00256
00257 case kPortRegistrationOnCallback:
00258 jack_log("JackClient::kPortRegistrationOn port_index = %ld", value1);
00259 if (fPortRegistration) {
00260 fPortRegistration(value1, 1, fPortRegistrationArg);
00261 }
00262 break;
00263
00264 case kPortRegistrationOffCallback:
00265 jack_log("JackClient::kPortRegistrationOff port_index = %ld ", value1);
00266 if (fPortRegistration) {
00267 fPortRegistration(value1, 0, fPortRegistrationArg);
00268 }
00269 break;
00270
00271 case kPortConnectCallback:
00272 jack_log("JackClient::kPortConnectCallback src = %ld dst = %ld", value1, value2);
00273 if (fPortConnect) {
00274 fPortConnect(value1, value2, 1, fPortConnectArg);
00275 }
00276 break;
00277
00278 case kPortDisconnectCallback:
00279 jack_log("JackClient::kPortDisconnectCallback src = %ld dst = %ld", value1, value2);
00280 if (fPortConnect) {
00281 fPortConnect(value1, value2, 0, fPortConnectArg);
00282 }
00283 break;
00284
00285 case kPortRenameCallback:
00286 jack_log("JackClient::kPortRenameCallback port = %ld", value1);
00287 if (fPortRename) {
00288 fPortRename(value1, message, GetGraphManager()->GetPort(value1)->GetName(), fPortRenameArg);
00289 }
00290 break;
00291
00292 case kXRunCallback:
00293 jack_log("JackClient::kXRunCallback");
00294 if (fXrun) {
00295 res = fXrun(fXrunArg);
00296 }
00297 break;
00298
00299 case kShutDownCallback:
00300 jack_log("JackClient::kShutDownCallback");
00301 ShutDown(jack_status_t(value1), message);
00302 break;
00303
00304 case kSessionCallback:
00305 jack_log("JackClient::kSessionCallback");
00306 if (fSession) {
00307 jack_session_event_t* event = (jack_session_event_t*)malloc( sizeof(jack_session_event_t));
00308 char uuid_buf[JACK_UUID_SIZE];
00309 event->type = (jack_session_event_type_t)value1;
00310 event->session_dir = strdup(message);
00311 event->command_line = NULL;
00312 event->flags = (jack_session_flags_t)0;
00313 snprintf(uuid_buf, sizeof(uuid_buf), "%d", GetClientControl()->fSessionID);
00314 event->client_uuid = strdup(uuid_buf);
00315 fSessionReply = kPendingSessionReply;
00316
00317 fSession(event, fSessionArg);
00318 res = fSessionReply;
00319 }
00320 break;
00321
00322 case kLatencyCallback:
00323 res = HandleLatencyCallback(value1);
00324 break;
00325 }
00326 }
00327
00328 return res;
00329 }
00330
00331 int JackClient::HandleLatencyCallback(int status)
00332 {
00333 jack_latency_callback_mode_t mode = (status == 0) ? JackCaptureLatency : JackPlaybackLatency;
00334 jack_latency_range_t latency = { UINT32_MAX, 0 };
00335
00336
00337
00338
00339 list<jack_port_id_t>::iterator it;
00340
00341 for (it = fPortList.begin(); it != fPortList.end(); it++) {
00342 JackPort* port = GetGraphManager()->GetPort(*it);
00343 if ((port->GetFlags() & JackPortIsOutput) && (mode == JackPlaybackLatency)) {
00344 GetGraphManager()->RecalculateLatency(*it, mode);
00345 }
00346 if ((port->GetFlags() & JackPortIsInput) && (mode == JackCaptureLatency)) {
00347 GetGraphManager()->RecalculateLatency(*it, mode);
00348 }
00349 }
00350
00351 if (!fLatency) {
00352
00353
00354
00355
00356
00357 if (mode == JackPlaybackLatency) {
00358
00359
00360 for (it = fPortList.begin(); it != fPortList.end(); it++) {
00361 JackPort* port = GetGraphManager()->GetPort(*it);
00362 if (port->GetFlags() & JackPortIsOutput) {
00363 jack_latency_range_t other_latency;
00364 port->GetLatencyRange(mode, &other_latency);
00365 if (other_latency.max > latency.max) {
00366 latency.max = other_latency.max;
00367 }
00368 if (other_latency.min < latency.min) {
00369 latency.min = other_latency.min;
00370 }
00371 }
00372 }
00373
00374 if (latency.min == UINT32_MAX) {
00375 latency.min = 0;
00376 }
00377
00378
00379
00380 for (it = fPortList.begin(); it != fPortList.end(); it++) {
00381 JackPort* port = GetGraphManager()->GetPort(*it);
00382 if (port->GetFlags() & JackPortIsInput) {
00383 port->SetLatencyRange(mode, &latency);
00384 }
00385 }
00386 }
00387 if (mode == JackCaptureLatency) {
00388
00389
00390 for (it = fPortList.begin(); it != fPortList.end(); it++) {
00391 JackPort* port = GetGraphManager()->GetPort(*it);
00392 if (port->GetFlags() & JackPortIsInput) {
00393 jack_latency_range_t other_latency;
00394 port->GetLatencyRange(mode, &other_latency);
00395 if (other_latency.max > latency.max) {
00396 latency.max = other_latency.max;
00397 }
00398 if (other_latency.min < latency.min) {
00399 latency.min = other_latency.min;
00400 }
00401 }
00402 }
00403
00404 if (latency.min == UINT32_MAX) {
00405 latency.min = 0;
00406 }
00407
00408
00409
00410 for (it = fPortList.begin(); it != fPortList.end(); it++) {
00411 JackPort* port = GetGraphManager()->GetPort(*it);
00412 if (port->GetFlags() & JackPortIsOutput) {
00413 port->SetLatencyRange(mode, &latency);
00414 }
00415 }
00416 }
00417 return 0;
00418 }
00419
00420
00421
00422
00423 fLatency(mode, fLatencyArg);
00424 return 0;
00425 }
00426
00431 int JackClient::Activate()
00432 {
00433 jack_log("JackClient::Activate");
00434 if (IsActive()) {
00435 return 0;
00436 }
00437
00438
00439 if (IsRealTime()) {
00440 if (StartThread() < 0) {
00441 return -1;
00442 }
00443 }
00444
00445
00446
00447
00448
00449 GetClientControl()->fActive = true;
00450
00451
00452 GetClientControl()->fTransportSync = true;
00453 GetClientControl()->fTransportTimebase = true;
00454
00455 int result = -1;
00456 GetClientControl()->fCallback[kRealTimeCallback] = IsRealTime();
00457 fChannel->ClientActivate(GetClientControl()->fRefNum, IsRealTime(), &result);
00458 return result;
00459 }
00460
00464 int JackClient::Deactivate()
00465 {
00466 jack_log("JackClient::Deactivate");
00467 if (!IsActive()) {
00468 return 0;
00469 }
00470
00471 GetClientControl()->fActive = false;
00472
00473
00474 GetClientControl()->fTransportSync = false;
00475 GetClientControl()->fTransportTimebase = false;
00476
00477
00478 int result = -1;
00479 fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result);
00480 jack_log("JackClient::Deactivate res = %ld", result);
00481
00482
00483 if (IsRealTime()) {
00484 fThread.Kill();
00485 }
00486 return result;
00487 }
00488
00489
00490
00491
00492
00493 void JackClient::InitAux()
00494 {
00495 if (fInit) {
00496 jack_log("JackClient::Init calling client thread init callback");
00497 fInit(fInitArg);
00498 }
00499 }
00500
00504 bool JackClient::Init()
00505 {
00506
00507
00508
00509
00510
00511
00512
00513 jack_log("JackClient::kBufferSizeCallback buffer_size = %ld", GetEngineControl()->fBufferSize);
00514 if (fBufferSize) {
00515 fBufferSize(GetEngineControl()->fBufferSize, fBufferSizeArg);
00516 }
00517
00518
00519 InitAux();
00520
00521
00522 if (!jack_tls_set(JackGlobals::fRealTimeThread, this)) {
00523 jack_error("Failed to set thread realtime key");
00524 }
00525
00526
00527 if (GetEngineControl()->fRealTime) {
00528 set_threaded_log_function();
00529 SetupRealTime();
00530 }
00531
00532 return true;
00533 }
00534
00535 void JackClient::SetupRealTime()
00536 {
00537 jack_log("JackClient::Init : period = %ld computation = %ld constraint = %ld",
00538 long(int64_t(GetEngineControl()->fPeriod) / 1000.0f),
00539 long(int64_t(GetEngineControl()->fComputation) / 1000.0f),
00540 long(int64_t(GetEngineControl()->fConstraint) / 1000.0f));
00541
00542
00543 fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
00544
00545 if (fThread.AcquireSelfRealTime(GetEngineControl()->fClientPriority) < 0) {
00546 jack_error("JackClient::AcquireSelfRealTime error");
00547 }
00548 }
00549
00550 int JackClient::StartThread()
00551 {
00552 if (fThread.StartSync() < 0) {
00553 jack_error("Start thread error");
00554 return -1;
00555 }
00556
00557 return 0;
00558 }
00559
00564 bool JackClient::Execute()
00565 {
00566
00567 DummyCycle();
00568
00569 if (fThreadFun) {
00570 fThreadFun(fThreadFunArg);
00571 } else {
00572 ExecuteThread();
00573 }
00574 return false;
00575 }
00576
00577 void JackClient::DummyCycle()
00578 {
00579 WaitSync();
00580 SignalSync();
00581 }
00582
00583 inline void JackClient::ExecuteThread()
00584 {
00585 while (true) {
00586 CycleWaitAux();
00587 CycleSignalAux(CallProcessCallback());
00588 }
00589 }
00590
00591 inline jack_nframes_t JackClient::CycleWaitAux()
00592 {
00593 if (!WaitSync()) {
00594 Error();
00595 }
00596 CallSyncCallbackAux();
00597 return GetEngineControl()->fBufferSize;
00598 }
00599
00600 inline void JackClient::CycleSignalAux(int status)
00601 {
00602 if (status == 0) {
00603 CallTimebaseCallbackAux();
00604 }
00605 SignalSync();
00606 if (status != 0) {
00607 End();
00608 }
00609 }
00610
00611 jack_nframes_t JackClient::CycleWait()
00612 {
00613 return CycleWaitAux();
00614 }
00615
00616 void JackClient::CycleSignal(int status)
00617 {
00618 CycleSignalAux(status);
00619 }
00620
00621 inline int JackClient::CallProcessCallback()
00622 {
00623 return (fProcess != NULL) ? fProcess(GetEngineControl()->fBufferSize, fProcessArg) : 0;
00624 }
00625
00626 inline bool JackClient::WaitSync()
00627 {
00628
00629 if (GetGraphManager()->SuspendRefNum(GetClientControl(), fSynchroTable, 0x7FFFFFFF) < 0) {
00630 jack_error("SuspendRefNum error");
00631 return false;
00632 } else {
00633 return true;
00634 }
00635 }
00636
00637 inline void JackClient::SignalSync()
00638 {
00639
00640 if (GetGraphManager()->ResumeRefNum(GetClientControl(), fSynchroTable) < 0) {
00641 jack_error("ResumeRefNum error");
00642 }
00643 }
00644
00645 inline void JackClient::End()
00646 {
00647 jack_log("JackClient::Execute end name = %s", GetClientControl()->fName);
00648
00649 int result;
00650 fThread.DropSelfRealTime();
00651 GetClientControl()->fActive = false;
00652 fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result);
00653 fThread.Terminate();
00654 }
00655
00656 inline void JackClient::Error()
00657 {
00658 jack_error("JackClient::Execute error name = %s", GetClientControl()->fName);
00659
00660 int result;
00661 fThread.DropSelfRealTime();
00662 GetClientControl()->fActive = false;
00663 fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result);
00664 ShutDown(jack_status_t(JackFailure | JackServerError), JACK_SERVER_FAILURE);
00665 fThread.Terminate();
00666 }
00667
00668
00669
00670
00671
00672 int JackClient::PortRegister(const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size)
00673 {
00674
00675 string port_short_name_str = string(port_name);
00676 if (port_short_name_str.size() == 0) {
00677 jack_error("port_name is empty");
00678 return 0;
00679 }
00680
00681
00682 string port_full_name_str = string(GetClientControl()->fName) + string(":") + port_short_name_str;
00683 if (port_full_name_str.size() >= REAL_JACK_PORT_NAME_SIZE) {
00684 jack_error("\"%s:%s\" is too long to be used as a JACK port name.\n"
00685 "Please use %lu characters or less",
00686 GetClientControl()->fName,
00687 port_name,
00688 JACK_PORT_NAME_SIZE - 1);
00689 return 0;
00690 }
00691
00692 int result = -1;
00693 jack_port_id_t port_index = NO_PORT;
00694 fChannel->PortRegister(GetClientControl()->fRefNum, port_full_name_str.c_str(), port_type, flags, buffer_size, &port_index, &result);
00695
00696 if (result == 0) {
00697 jack_log("JackClient::PortRegister ref = %ld name = %s type = %s port_index = %ld", GetClientControl()->fRefNum, port_full_name_str.c_str(), port_type, port_index);
00698 fPortList.push_back(port_index);
00699 return port_index;
00700 } else {
00701 return 0;
00702 }
00703 }
00704
00705 int JackClient::PortUnRegister(jack_port_id_t port_index)
00706 {
00707 jack_log("JackClient::PortUnRegister port_index = %ld", port_index);
00708 list<jack_port_id_t>::iterator it = find(fPortList.begin(), fPortList.end(), port_index);
00709
00710 if (it != fPortList.end()) {
00711 fPortList.erase(it);
00712 int result = -1;
00713 fChannel->PortUnRegister(GetClientControl()->fRefNum, port_index, &result);
00714 return result;
00715 } else {
00716 jack_error("unregistering a port %ld that is not own by the client", port_index);
00717 return -1;
00718 }
00719 }
00720
00721 int JackClient::PortConnect(const char* src, const char* dst)
00722 {
00723 jack_log("JackClient::Connect src = %s dst = %s", src, dst);
00724 if (strlen(src) >= REAL_JACK_PORT_NAME_SIZE) {
00725 jack_error("\"%s\" is too long to be used as a JACK port name.\n", src);
00726 return -1;
00727 }
00728 if (strlen(dst) >= REAL_JACK_PORT_NAME_SIZE) {
00729 jack_error("\"%s\" is too long to be used as a JACK port name.\n", src);
00730 return -1;
00731 }
00732 int result = -1;
00733 fChannel->PortConnect(GetClientControl()->fRefNum, src, dst, &result);
00734 return result;
00735 }
00736
00737 int JackClient::PortDisconnect(const char* src, const char* dst)
00738 {
00739 jack_log("JackClient::Disconnect src = %s dst = %s", src, dst);
00740 if (strlen(src) >= REAL_JACK_PORT_NAME_SIZE) {
00741 jack_error("\"%s\" is too long to be used as a JACK port name.\n", src);
00742 return -1;
00743 }
00744 if (strlen(dst) >= REAL_JACK_PORT_NAME_SIZE) {
00745 jack_error("\"%s\" is too long to be used as a JACK port name.\n", src);
00746 return -1;
00747 }
00748 int result = -1;
00749 fChannel->PortDisconnect(GetClientControl()->fRefNum, src, dst, &result);
00750 return result;
00751 }
00752
00753 int JackClient::PortDisconnect(jack_port_id_t src)
00754 {
00755 jack_log("JackClient::PortDisconnect src = %ld", src);
00756 int result = -1;
00757 fChannel->PortDisconnect(GetClientControl()->fRefNum, src, ALL_PORTS, &result);
00758 return result;
00759 }
00760
00761 int JackClient::PortIsMine(jack_port_id_t port_index)
00762 {
00763 JackPort* port = GetGraphManager()->GetPort(port_index);
00764 return GetClientControl()->fRefNum == port->GetRefNum();
00765 }
00766
00767 int JackClient::PortRename(jack_port_id_t port_index, const char* name)
00768 {
00769 int result = -1;
00770 fChannel->PortRename(GetClientControl()->fRefNum, port_index, name, &result);
00771 return result;
00772 }
00773
00774
00775
00776
00777
00778 int JackClient::SetBufferSize(jack_nframes_t buffer_size)
00779 {
00780 int result = -1;
00781 fChannel->SetBufferSize(buffer_size, &result);
00782 return result;
00783 }
00784
00785 int JackClient::SetFreeWheel(int onoff)
00786 {
00787 int result = -1;
00788 fChannel->SetFreewheel(onoff, &result);
00789 return result;
00790 }
00791
00792 int JackClient::ComputeTotalLatencies()
00793 {
00794 int result = -1;
00795 fChannel->ComputeTotalLatencies(&result);
00796 return result;
00797 }
00798
00799
00800
00801
00802
00803 inline int JackClient::ActivateAux()
00804 {
00805
00806 if (IsActive() && fThread.GetStatus() != JackThread::kRunning) {
00807
00808 jack_log("JackClient::ActivateAux");
00809
00810
00811 if (StartThread() < 0) {
00812 return -1;
00813 }
00814
00815 int result = -1;
00816 GetClientControl()->fCallback[kRealTimeCallback] = IsRealTime();
00817 fChannel->ClientActivate(GetClientControl()->fRefNum, IsRealTime(), &result);
00818 return result;
00819
00820 } else {
00821 return 0;
00822 }
00823 }
00824
00825 int JackClient::ReleaseTimebase()
00826 {
00827 int result = -1;
00828 fChannel->ReleaseTimebase(GetClientControl()->fRefNum, &result);
00829 if (result == 0) {
00830 GetClientControl()->fTransportTimebase = false;
00831 fTimebase = NULL;
00832 fTimebaseArg = NULL;
00833 }
00834 return result;
00835 }
00836
00837
00838 int JackClient::SetSyncCallback(JackSyncCallback sync_callback, void* arg)
00839 {
00840 GetClientControl()->fTransportSync = (fSync != NULL);
00841 fSyncArg = arg;
00842 fSync = sync_callback;
00843 return ActivateAux();
00844 }
00845
00846 int JackClient::SetTimebaseCallback(int conditional, JackTimebaseCallback timebase_callback, void* arg)
00847 {
00848 int result = -1;
00849 fChannel->SetTimebaseCallback(GetClientControl()->fRefNum, conditional, &result);
00850
00851 if (result == 0) {
00852 GetClientControl()->fTransportTimebase = true;
00853 fTimebase = timebase_callback;
00854 fTimebaseArg = arg;
00855 return ActivateAux();
00856 } else {
00857 fTimebase = NULL;
00858 fTimebaseArg = NULL;
00859 return -1;
00860 }
00861 }
00862
00863 int JackClient::SetSyncTimeout(jack_time_t timeout)
00864 {
00865 GetEngineControl()->fTransport.SetSyncTimeout(timeout);
00866 return 0;
00867 }
00868
00869
00870
00871 void JackClient::TransportLocate(jack_nframes_t frame)
00872 {
00873 jack_position_t pos;
00874 pos.frame = frame;
00875 pos.valid = (jack_position_bits_t)0;
00876 jack_log("JackClient::TransportLocate pos = %ld", pos.frame);
00877 GetEngineControl()->fTransport.RequestNewPos(&pos);
00878 }
00879
00880 int JackClient::TransportReposition(const jack_position_t* pos)
00881 {
00882 jack_position_t tmp = *pos;
00883 jack_log("JackClient::TransportReposition pos = %ld", pos->frame);
00884 if (tmp.valid & ~JACK_POSITION_MASK) {
00885 return EINVAL;
00886 } else {
00887 GetEngineControl()->fTransport.RequestNewPos(&tmp);
00888 return 0;
00889 }
00890 }
00891
00892 jack_transport_state_t JackClient::TransportQuery(jack_position_t* pos)
00893 {
00894 return GetEngineControl()->fTransport.Query(pos);
00895 }
00896
00897 jack_nframes_t JackClient::GetCurrentTransportFrame()
00898 {
00899 return GetEngineControl()->fTransport.GetCurrentFrame();
00900 }
00901
00902
00903 void JackClient::TransportStart()
00904 {
00905 GetEngineControl()->fTransport.SetCommand(TransportCommandStart);
00906 }
00907
00908
00909 void JackClient::TransportStop()
00910 {
00911 GetEngineControl()->fTransport.SetCommand(TransportCommandStop);
00912 }
00913
00914
00915
00916
00917 void JackClient::CallSyncCallback()
00918 {
00919 CallSyncCallbackAux();
00920 }
00921
00922 inline void JackClient::CallSyncCallbackAux()
00923 {
00924 if (GetClientControl()->fTransportSync) {
00925
00926 JackTransportEngine& transport = GetEngineControl()->fTransport;
00927 jack_position_t* cur_pos = transport.ReadCurrentState();
00928 jack_transport_state_t transport_state = transport.GetState();
00929
00930 if (fSync != NULL) {
00931 if (fSync(transport_state, cur_pos, fSyncArg)) {
00932 GetClientControl()->fTransportState = JackTransportRolling;
00933 GetClientControl()->fTransportSync = false;
00934 }
00935 } else {
00936 GetClientControl()->fTransportState = JackTransportRolling;
00937 GetClientControl()->fTransportSync = false;
00938 }
00939 }
00940 }
00941
00942 void JackClient::CallTimebaseCallback()
00943 {
00944 CallTimebaseCallbackAux();
00945 }
00946
00947 inline void JackClient::CallTimebaseCallbackAux()
00948 {
00949 JackTransportEngine& transport = GetEngineControl()->fTransport;
00950 int master;
00951 bool unused;
00952
00953 transport.GetTimebaseMaster(master, unused);
00954
00955 if (GetClientControl()->fRefNum == master && fTimebase) {
00956
00957 jack_transport_state_t transport_state = transport.GetState();
00958 jack_position_t* cur_pos = transport.WriteNextStateStart(1);
00959
00960 if (GetClientControl()->fTransportTimebase) {
00961 fTimebase(transport_state, GetEngineControl()->fBufferSize, cur_pos, true, fTimebaseArg);
00962 GetClientControl()->fTransportTimebase = false;
00963 } else if (transport_state == JackTransportRolling) {
00964 fTimebase(transport_state, GetEngineControl()->fBufferSize, cur_pos, false, fTimebaseArg);
00965 }
00966
00967 transport.WriteNextStateStop(1);
00968 }
00969 }
00970
00971
00972
00973
00974
00975 void JackClient::OnShutdown(JackShutdownCallback callback, void *arg)
00976 {
00977 if (IsActive()) {
00978 jack_error("You cannot set callbacks on an active client");
00979 } else {
00980
00981 GetClientControl()->fCallback[kShutDownCallback] = (callback != NULL);
00982 fShutdownArg = arg;
00983 fShutdown = callback;
00984 }
00985 }
00986
00987 void JackClient::OnInfoShutdown(JackInfoShutdownCallback callback, void *arg)
00988 {
00989 if (IsActive()) {
00990 jack_error("You cannot set callbacks on an active client");
00991 } else {
00992
00993 GetClientControl()->fCallback[kShutDownCallback] = (callback != NULL);
00994 fInfoShutdownArg = arg;
00995 fInfoShutdown = callback;
00996 }
00997 }
00998
00999 int JackClient::SetProcessCallback(JackProcessCallback callback, void *arg)
01000 {
01001 if (IsActive()) {
01002 jack_error("You cannot set callbacks on an active client");
01003 return -1;
01004 } else if (fThreadFun) {
01005 jack_error ("A thread callback has already been setup, both models cannot be used at the same time!");
01006 return -1;
01007 } else {
01008 fProcessArg = arg;
01009 fProcess = callback;
01010 return 0;
01011 }
01012 }
01013
01014 int JackClient::SetXRunCallback(JackXRunCallback callback, void *arg)
01015 {
01016 if (IsActive()) {
01017 jack_error("You cannot set callbacks on an active client");
01018 return -1;
01019 } else {
01020 GetClientControl()->fCallback[kXRunCallback] = (callback != NULL);
01021 fXrunArg = arg;
01022 fXrun = callback;
01023 return 0;
01024 }
01025 }
01026
01027 int JackClient::SetInitCallback(JackThreadInitCallback callback, void *arg)
01028 {
01029 if (IsActive()) {
01030 jack_error("You cannot set callbacks on an active client");
01031 return -1;
01032 } else {
01033 fInitArg = arg;
01034 fInit = callback;
01035
01036 return JackMessageBuffer::fInstance->SetInitCallback(callback, arg);
01037 }
01038 }
01039
01040 int JackClient::SetGraphOrderCallback(JackGraphOrderCallback callback, void *arg)
01041 {
01042 if (IsActive()) {
01043 jack_error("You cannot set callbacks on an active client");
01044 return -1;
01045 } else {
01046 GetClientControl()->fCallback[kGraphOrderCallback] = (callback != NULL);
01047 fGraphOrder = callback;
01048 fGraphOrderArg = arg;
01049 return 0;
01050 }
01051 }
01052
01053 int JackClient::SetBufferSizeCallback(JackBufferSizeCallback callback, void *arg)
01054 {
01055 if (IsActive()) {
01056 jack_error("You cannot set callbacks on an active client");
01057 return -1;
01058 } else {
01059 GetClientControl()->fCallback[kBufferSizeCallback] = (callback != NULL);
01060 fBufferSizeArg = arg;
01061 fBufferSize = callback;
01062 return 0;
01063 }
01064 }
01065
01066 int JackClient::SetSampleRateCallback(JackSampleRateCallback callback, void *arg)
01067 {
01068 if (IsActive()) {
01069 jack_error("You cannot set callbacks on an active client");
01070 return -1;
01071 } else {
01072 GetClientControl()->fCallback[kSampleRateCallback] = (callback != NULL);
01073 fSampleRateArg = arg;
01074 fSampleRate = callback;
01075
01076 if (callback) {
01077 callback(GetEngineControl()->fSampleRate, arg);
01078 }
01079 return 0;
01080 }
01081 }
01082
01083 int JackClient::SetClientRegistrationCallback(JackClientRegistrationCallback callback, void* arg)
01084 {
01085 if (IsActive()) {
01086 jack_error("You cannot set callbacks on an active client");
01087 return -1;
01088 } else {
01089
01090 fClientRegistrationArg = arg;
01091 fClientRegistration = callback;
01092 return 0;
01093 }
01094 }
01095
01096 int JackClient::SetFreewheelCallback(JackFreewheelCallback callback, void *arg)
01097 {
01098 if (IsActive()) {
01099 jack_error("You cannot set callbacks on an active client");
01100 return -1;
01101 } else {
01102 GetClientControl()->fCallback[kStartFreewheelCallback] = (callback != NULL);
01103 GetClientControl()->fCallback[kStopFreewheelCallback] = (callback != NULL);
01104 fFreewheelArg = arg;
01105 fFreewheel = callback;
01106 return 0;
01107 }
01108 }
01109
01110 int JackClient::SetPortRegistrationCallback(JackPortRegistrationCallback callback, void *arg)
01111 {
01112 if (IsActive()) {
01113 jack_error("You cannot set callbacks on an active client");
01114 return -1;
01115 } else {
01116 GetClientControl()->fCallback[kPortRegistrationOnCallback] = (callback != NULL);
01117 GetClientControl()->fCallback[kPortRegistrationOffCallback] = (callback != NULL);
01118 fPortRegistrationArg = arg;
01119 fPortRegistration = callback;
01120 return 0;
01121 }
01122 }
01123
01124 int JackClient::SetPortConnectCallback(JackPortConnectCallback callback, void *arg)
01125 {
01126 if (IsActive()) {
01127 jack_error("You cannot set callbacks on an active client");
01128 return -1;
01129 } else {
01130 GetClientControl()->fCallback[kPortConnectCallback] = (callback != NULL);
01131 GetClientControl()->fCallback[kPortDisconnectCallback] = (callback != NULL);
01132 fPortConnectArg = arg;
01133 fPortConnect = callback;
01134 return 0;
01135 }
01136 }
01137
01138 int JackClient::SetPortRenameCallback(JackPortRenameCallback callback, void *arg)
01139 {
01140 if (IsActive()) {
01141 jack_error("You cannot set callbacks on an active client");
01142 return -1;
01143 } else {
01144 GetClientControl()->fCallback[kPortRenameCallback] = (callback != NULL);
01145 fPortRenameArg = arg;
01146 fPortRename = callback;
01147 return 0;
01148 }
01149 }
01150
01151 int JackClient::SetProcessThread(JackThreadCallback fun, void *arg)
01152 {
01153 if (IsActive()) {
01154 jack_error("You cannot set callbacks on an active client");
01155 return -1;
01156 } else if (fProcess) {
01157 jack_error("A process callback has already been setup, both models cannot be used at the same time!");
01158 return -1;
01159 } else {
01160 fThreadFun = fun;
01161 fThreadFunArg = arg;
01162 return 0;
01163 }
01164 }
01165
01166 int JackClient::SetSessionCallback(JackSessionCallback callback, void *arg)
01167 {
01168 if (IsActive()) {
01169 jack_error("You cannot set callbacks on an active client");
01170 return -1;
01171 } else {
01172 GetClientControl()->fCallback[kSessionCallback] = (callback != NULL);
01173 fSessionArg = arg;
01174 fSession = callback;
01175 return 0;
01176 }
01177 }
01178
01179 int JackClient::SetLatencyCallback(JackLatencyCallback callback, void *arg)
01180 {
01181 if (IsActive()) {
01182 jack_error("You cannot set callbacks on an active client");
01183 return -1;
01184 } else {
01185
01186 fLatencyArg = arg;
01187 fLatency = callback;
01188 return 0;
01189 }
01190 }
01191
01192
01193
01194
01195
01196 char* JackClient::GetInternalClientName(int ref)
01197 {
01198 char name_res[JACK_CLIENT_NAME_SIZE + 1];
01199 int result = -1;
01200 fChannel->GetInternalClientName(GetClientControl()->fRefNum, ref, name_res, &result);
01201 return (result < 0) ? NULL : strdup(name_res);
01202 }
01203
01204 int JackClient::InternalClientHandle(const char* client_name, jack_status_t* status)
01205 {
01206 int int_ref, result = -1;
01207 fChannel->InternalClientHandle(GetClientControl()->fRefNum, client_name, (int*)status, &int_ref, &result);
01208 return int_ref;
01209 }
01210
01211 int JackClient::InternalClientLoad(const char* client_name, jack_options_t options, jack_status_t* status, jack_varargs_t* va)
01212 {
01213 if (strlen(client_name) >= JACK_CLIENT_NAME_SIZE) {
01214 jack_error ("\"%s\" is too long for a JACK client name.\n"
01215 "Please use %lu characters or less.",
01216 client_name, JACK_CLIENT_NAME_SIZE);
01217 return 0;
01218 }
01219
01220 if (va->load_name && (strlen(va->load_name) >= JACK_PATH_MAX)) {
01221 jack_error("\"%s\" is too long for a shared object name.\n"
01222 "Please use %lu characters or less.",
01223 va->load_name, JACK_PATH_MAX);
01224 int my_status1 = *status | (JackFailure | JackInvalidOption);
01225 *status = (jack_status_t)my_status1;
01226 return 0;
01227 }
01228
01229 if (va->load_init && (strlen(va->load_init) >= JACK_LOAD_INIT_LIMIT)) {
01230 jack_error ("\"%s\" is too long for internal client init "
01231 "string.\nPlease use %lu characters or less.",
01232 va->load_init, JACK_LOAD_INIT_LIMIT);
01233 int my_status1 = *status | (JackFailure | JackInvalidOption);
01234 *status = (jack_status_t)my_status1;
01235 return 0;
01236 }
01237
01238 int int_ref, result = -1;
01239 fChannel->InternalClientLoad(GetClientControl()->fRefNum, client_name, va->load_name, va->load_init, options, (int*)status, &int_ref, -1, &result);
01240 return int_ref;
01241 }
01242
01243 void JackClient::InternalClientUnload(int ref, jack_status_t* status)
01244 {
01245 int result = -1;
01246 fChannel->InternalClientUnload(GetClientControl()->fRefNum, ref, (int*)status, &result);
01247 }
01248
01249
01250
01251
01252
01253 jack_session_command_t* JackClient::SessionNotify(const char* target, jack_session_event_type_t type, const char* path)
01254 {
01255 jack_session_command_t* res;
01256 fChannel->SessionNotify(GetClientControl()->fRefNum, target, type, path, &res);
01257 return res;
01258 }
01259
01260 int JackClient::SessionReply(jack_session_event_t* ev)
01261 {
01262 if (ev->command_line) {
01263 strncpy(GetClientControl()->fSessionCommand, ev->command_line, sizeof(GetClientControl()->fSessionCommand));
01264 } else {
01265 GetClientControl()->fSessionCommand[0] = '\0';
01266 }
01267
01268 GetClientControl()->fSessionFlags = ev->flags;
01269
01270 jack_log("JackClient::SessionReply... we are here");
01271 if (fChannel->IsChannelThread()) {
01272 jack_log("JackClient::SessionReply... in callback reply");
01273
01274 fSessionReply = kImmediateSessionReply;
01275 return 0;
01276 }
01277
01278 jack_log("JackClient::SessionReply... out of cb");
01279
01280 int result = -1;
01281 fChannel->SessionReply(GetClientControl()->fRefNum, &result);
01282 return result;
01283 }
01284
01285 char* JackClient::GetUUIDForClientName(const char* client_name)
01286 {
01287 char uuid_res[JACK_UUID_SIZE];
01288 int result = -1;
01289 fChannel->GetUUIDForClientName(GetClientControl()->fRefNum, client_name, uuid_res, &result);
01290 return (result) ? NULL : strdup(uuid_res);
01291 }
01292
01293 char* JackClient::GetClientNameByUUID(const char* uuid)
01294 {
01295 char name_res[JACK_CLIENT_NAME_SIZE + 1];
01296 int result = -1;
01297 fChannel->GetClientNameForUUID(GetClientControl()->fRefNum, uuid, name_res, &result);
01298 return (result) ? NULL : strdup(name_res);
01299 }
01300
01301 int JackClient::ReserveClientName(const char* client_name, const char* uuid)
01302 {
01303 int result = -1;
01304 fChannel->ReserveClientName( GetClientControl()->fRefNum, client_name, uuid, &result);
01305 return result;
01306 }
01307
01308 int JackClient::ClientHasSessionCallback(const char* client_name)
01309 {
01310 int result = -1;
01311 fChannel->ClientHasSessionCallback(client_name, &result);
01312 return result;
01313 }
01314
01315 }
01316