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