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