00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "JackClient.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 JackClient* JackClient::fClientTable[CLIENT_NUM] = {};
00041
00042 #define IsRealTime() ((fProcess != NULL) | (fThreadFun != NULL) | (fSync != NULL) | (fTimebase != NULL))
00043
00044 JackClient::JackClient():fThread(this)
00045 {}
00046
00047 JackClient::JackClient(JackSynchro* table):fThread(this)
00048 {
00049 fSynchroTable = table;
00050 fProcess = NULL;
00051 fGraphOrder = NULL;
00052 fXrun = NULL;
00053 fShutdown = 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 fProcessArg = NULL;
00065 fGraphOrderArg = NULL;
00066 fXrunArg = NULL;
00067 fShutdownArg = NULL;
00068 fInitArg = NULL;
00069 fBufferSizeArg = NULL;
00070 fFreewheelArg = NULL;
00071 fClientRegistrationArg = NULL;
00072 fPortRegistrationArg = NULL;
00073 fPortConnectArg = NULL;
00074 fPortRenameArg = NULL;
00075 fSyncArg = NULL;
00076 fTimebaseArg = NULL;
00077 fThreadFunArg = NULL;
00078 }
00079
00080 JackClient::~JackClient()
00081 {}
00082
00083 int JackClient::Close()
00084 {
00085 jack_log("JackClient::Close ref = %ld", GetClientControl()->fRefNum);
00086 int result = 0;
00087
00088 Deactivate();
00089 fChannel->Stop();
00090
00091
00092 if (GetClientControl()->fServer) {
00093 fChannel->ClientClose(GetClientControl()->fRefNum, &result);
00094 } else {
00095 jack_log("JackClient::Close server is shutdown");
00096 }
00097
00098 fChannel->Close();
00099 fSynchroTable[GetClientControl()->fRefNum].Disconnect();
00100 fClientTable[GetClientControl()->fRefNum] = NULL;
00101 return result;
00102 }
00103
00104 bool JackClient::IsActive()
00105 {
00106 return (GetClientControl()) ? GetClientControl()->fActive : false;
00107 }
00108
00109 pthread_t JackClient::GetThreadID()
00110 {
00111 return fThread.GetThreadID();
00112 }
00113
00119 void JackClient::SetupDriverSync(bool freewheel)
00120 {
00121 if (!freewheel && !GetEngineControl()->fSyncMode) {
00122 jack_log("JackClient::SetupDriverSync driver sem in flush mode");
00123 fSynchroTable[AUDIO_DRIVER_REFNUM].SetFlush(true);
00124 fSynchroTable[FREEWHEEL_DRIVER_REFNUM].SetFlush(true);
00125 fSynchroTable[LOOPBACK_DRIVER_REFNUM].SetFlush(true);
00126 } else {
00127 jack_log("JackClient::SetupDriverSync driver sem in normal mode");
00128 fSynchroTable[AUDIO_DRIVER_REFNUM].SetFlush(false);
00129 fSynchroTable[FREEWHEEL_DRIVER_REFNUM].SetFlush(false);
00130 fSynchroTable[LOOPBACK_DRIVER_REFNUM].SetFlush(false);
00131 }
00132 }
00133
00138 int JackClient::ClientNotifyImp(int refnum, const char* name, int notify, int sync, int value1, int value2)
00139 {
00140 return 0;
00141 }
00142
00143 int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2)
00144 {
00145 int res = 0;
00146
00147
00148 switch (notify) {
00149
00150 case kAddClient:
00151 res = ClientNotifyImp(refnum, name, notify, sync, value1, value2);
00152 break;
00153
00154 case kRemoveClient:
00155 res = ClientNotifyImp(refnum, name, notify, sync, value1, value2);
00156 break;
00157
00158 case kActivateClient:
00159 jack_log("JackClient::kActivateClient name = %s ref = %ld ", name, refnum);
00160 Init();
00161 break;
00162 }
00163
00164
00165
00166
00167
00168 if (IsActive()) {
00169
00170 switch (notify) {
00171
00172 case kAddClient:
00173 jack_log("JackClient::kAddClient fName = %s name = %s", GetClientControl()->fName, name);
00174 if (fClientRegistration && strcmp(GetClientControl()->fName, name) != 0)
00175 fClientRegistration(name, 1, fClientRegistrationArg);
00176 break;
00177
00178 case kRemoveClient:
00179 jack_log("JackClient::kRemoveClient fName = %s name = %s", GetClientControl()->fName, name);
00180 if (fClientRegistration && strcmp(GetClientControl()->fName, name) != 0)
00181 fClientRegistration(name, 0, fClientRegistrationArg);
00182 break;
00183
00184 case kBufferSizeCallback:
00185 jack_log("JackClient::kBufferSizeCallback buffer_size = %ld", value1);
00186 if (fBufferSize)
00187 res = fBufferSize(value1, fBufferSizeArg);
00188 break;
00189
00190 case kSampleRateCallback:
00191 jack_log("JackClient::kSampleRateCallback sample_rate = %ld", value1);
00192 if (fSampleRate)
00193 res = fSampleRate(value1, fSampleRateArg);
00194 break;
00195
00196 case kGraphOrderCallback:
00197 jack_log("JackClient::kGraphOrderCallback");
00198 if (fGraphOrder)
00199 res = fGraphOrder(fGraphOrderArg);
00200 break;
00201
00202 case kStartFreewheelCallback:
00203 jack_log("JackClient::kStartFreewheel");
00204 SetupDriverSync(true);
00205 fThread.DropRealTime();
00206 if (fFreewheel)
00207 fFreewheel(1, fFreewheelArg);
00208 break;
00209
00210 case kStopFreewheelCallback:
00211 jack_log("JackClient::kStopFreewheel");
00212 SetupDriverSync(false);
00213 if (fFreewheel)
00214 fFreewheel(0, fFreewheelArg);
00215 fThread.AcquireRealTime();
00216 break;
00217
00218 case kPortRegistrationOnCallback:
00219 jack_log("JackClient::kPortRegistrationOn port_index = %ld", value1);
00220 if (fPortRegistration)
00221 fPortRegistration(value1, 1, fPortRegistrationArg);
00222 break;
00223
00224 case kPortRegistrationOffCallback:
00225 jack_log("JackClient::kPortRegistrationOff port_index = %ld ", value1);
00226 if (fPortRegistration)
00227 fPortRegistration(value1, 0, fPortRegistrationArg);
00228 break;
00229
00230 case kPortConnectCallback:
00231 jack_log("JackClient::kPortConnectCallback src = %ld dst = %ld", value1, value2);
00232 if (fPortConnect)
00233 fPortConnect(value1, value2, 1, fPortConnectArg);
00234 break;
00235
00236 case kPortDisconnectCallback:
00237 jack_log("JackClient::kPortDisconnectCallback src = %ld dst = %ld", value1, value2);
00238 if (fPortConnect)
00239 fPortConnect(value1, value2, 0, fPortConnectArg);
00240 break;
00241
00242 case kPortRenameCallback:
00243 jack_log("JackClient::kPortRenameCallback port = %ld");
00244 if (fPortRename)
00245 fPortRename(value1, GetGraphManager()->GetPort(value1)->GetName(), fPortRenameArg);
00246 break;
00247
00248 case kXRunCallback:
00249 jack_log("JackClient::kXRunCallback");
00250 if (fXrun)
00251 res = fXrun(fXrunArg);
00252 break;
00253 }
00254 }
00255
00256 return res;
00257 }
00258
00263 int JackClient::Activate()
00264 {
00265 jack_log("JackClient::Activate");
00266 if (IsActive())
00267 return 0;
00268
00269
00270 if (IsRealTime()) {
00271 if (StartThread() < 0)
00272 return -1;
00273 }
00274
00275
00276
00277
00278
00279 GetClientControl()->fActive = true;
00280
00281
00282 GetClientControl()->fTransportSync = true;
00283 GetClientControl()->fTransportTimebase = true;
00284
00285 int result = -1;
00286 GetClientControl()->fCallback[kRealTimeCallback] = IsRealTime();
00287 fChannel->ClientActivate(GetClientControl()->fRefNum, IsRealTime(), &result);
00288 return result;
00289 }
00290
00294 int JackClient::Deactivate()
00295 {
00296 jack_log("JackClient::Deactivate");
00297 if (!IsActive())
00298 return 0;
00299
00300 GetClientControl()->fActive = false;
00301
00302
00303 GetClientControl()->fTransportSync = false;
00304 GetClientControl()->fTransportTimebase = false;
00305
00306
00307 int result = -1;
00308 fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result);
00309 jack_log("JackClient::Deactivate res = %ld", result);
00310
00311
00312 if (IsRealTime())
00313 fThread.Kill();
00314 return result;
00315 }
00316
00317
00318
00319
00320
00324 bool JackClient::Init()
00325 {
00326 if (fInit) {
00327 jack_log("JackClient::Init calling client thread init callback");
00328 fInit(fInitArg);
00329 }
00330 return true;
00331 }
00332
00333 int JackClient::StartThread()
00334 {
00335 jack_log("JackClient::StartThread : period = %ld computation = %ld constraint = %ld",
00336 long(int64_t(GetEngineControl()->fPeriod) / 1000.0f),
00337 long(int64_t(GetEngineControl()->fComputation) / 1000.0f),
00338 long(int64_t(GetEngineControl()->fConstraint) / 1000.0f));
00339
00340
00341 fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
00342
00343 if (fThread.Start() < 0) {
00344 jack_error("Start thread error");
00345 return -1;
00346 }
00347
00348 if (GetEngineControl()->fRealTime) {
00349 if (fThread.AcquireRealTime(GetEngineControl()->fPriority - 1) < 0) {
00350 jack_error("AcquireRealTime error");
00351 }
00352 }
00353
00354 return 0;
00355 }
00356
00360 bool JackClient::Execute()
00361 {
00362 if (!jack_tls_set(gRealTime, this))
00363 jack_error("failed to set thread realtime key");
00364
00365 if (GetEngineControl()->fRealTime)
00366 set_threaded_log_function();
00367
00368 if (fThreadFun) {
00369
00370 WaitSync();
00371 SignalSync();
00372 fThreadFun(fThreadFunArg);
00373 } else {
00374 if (WaitFirstSync())
00375 ExecuteThread();
00376 }
00377 return false;
00378 }
00379
00380 inline bool JackClient::WaitFirstSync()
00381 {
00382 while (true) {
00383
00384 WaitSync();
00385 if (IsActive()) {
00386 CallSyncCallback();
00387
00388 if (Wait(CallProcessCallback()) != GetEngineControl()->fBufferSize)
00389 return false;
00390 return true;
00391 } else {
00392 jack_log("Process called for an inactive client");
00393 }
00394 SignalSync();
00395 }
00396 return false;
00397 }
00398
00399 inline void JackClient::ExecuteThread()
00400 {
00401 while (Wait(CallProcessCallback()) == GetEngineControl()->fBufferSize);
00402 }
00403
00404 jack_nframes_t JackClient::Wait(int status)
00405 {
00406 if (status == 0)
00407 CallTimebaseCallback();
00408 SignalSync();
00409 if (status != 0)
00410 End();
00411 if (!WaitSync())
00412 Error();
00413 CallSyncCallback();
00414 return GetEngineControl()->fBufferSize;
00415 }
00416
00417 jack_nframes_t JackClient::CycleWait()
00418 {
00419 if (!WaitSync())
00420 Error();
00421 CallSyncCallback();
00422 return GetEngineControl()->fBufferSize;
00423 }
00424
00425 void JackClient::CycleSignal(int status)
00426 {
00427 if (status == 0)
00428 CallTimebaseCallback();
00429 SignalSync();
00430 if (status != 0)
00431 End();
00432 }
00433
00434 inline int JackClient::CallProcessCallback()
00435 {
00436 return (fProcess != NULL) ? fProcess(GetEngineControl()->fBufferSize, fProcessArg) : 0;
00437 }
00438
00439 inline bool JackClient::WaitSync()
00440 {
00441
00442 if (GetGraphManager()->SuspendRefNum(GetClientControl(), fSynchroTable, 0x7FFFFFFF) < 0) {
00443 jack_error("SuspendRefNum error");
00444 return false;
00445 } else {
00446 return true;
00447 }
00448 }
00449
00450 inline void JackClient::SignalSync()
00451 {
00452
00453 if (GetGraphManager()->ResumeRefNum(GetClientControl(), fSynchroTable) < 0) {
00454 jack_error("ResumeRefNum error");
00455 }
00456 }
00457
00458 inline void JackClient::End()
00459 {
00460 jack_log("JackClient::Execute end name = %s", GetClientControl()->fName);
00461
00462 int result;
00463 fThread.DropRealTime();
00464 GetClientControl()->fActive = false;
00465 fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result);
00466 fThread.Terminate();
00467 }
00468
00469 inline void JackClient::Error()
00470 {
00471 jack_error("JackClient::Execute error name = %s", GetClientControl()->fName);
00472
00473 int result;
00474 fThread.DropRealTime();
00475 GetClientControl()->fActive = false;
00476 fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result);
00477 ShutDown();
00478 fThread.Terminate();
00479 }
00480
00481
00482
00483
00484
00485 int JackClient::PortRegister(const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size)
00486 {
00487
00488 string port_name_str = string(port_name);
00489 if (port_name_str.size() == 0) {
00490 jack_error("port_name is empty");
00491 return 0;
00492 }
00493
00494
00495 string name = string(GetClientControl()->fName) + string(":") + port_name_str;
00496 if (name.size() >= JACK_PORT_NAME_SIZE) {
00497 jack_error("\"%s:%s\" is too long to be used as a JACK port name.\n"
00498 "Please use %lu characters or less",
00499 GetClientControl()->fName,
00500 port_name,
00501 JACK_PORT_NAME_SIZE - 1);
00502 return 0;
00503 }
00504
00505 int result = -1;
00506 jack_port_id_t port_index = NO_PORT;
00507 fChannel->PortRegister(GetClientControl()->fRefNum, name.c_str(), port_type, flags, buffer_size, &port_index, &result);
00508
00509 if (result == 0) {
00510 jack_log("JackClient::PortRegister ref = %ld name = %s type = %s port_index = %ld", GetClientControl()->fRefNum, name.c_str(), port_type, port_index);
00511 fPortList.push_back(port_index);
00512 return port_index;
00513 } else {
00514 return 0;
00515 }
00516 }
00517
00518 int JackClient::PortUnRegister(jack_port_id_t port_index)
00519 {
00520 jack_log("JackClient::PortUnRegister port_index = %ld", port_index);
00521 list<jack_port_id_t>::iterator it = find(fPortList.begin(), fPortList.end(), port_index);
00522
00523 if (it != fPortList.end()) {
00524 fPortList.erase(it);
00525 int result = -1;
00526 fChannel->PortUnRegister(GetClientControl()->fRefNum, port_index, &result);
00527 return result;
00528 } else {
00529 jack_error("unregistering a port %ld that is not own by the client", port_index);
00530 return -1;
00531 }
00532 }
00533
00534 int JackClient::PortConnect(const char* src, const char* dst)
00535 {
00536 jack_log("JackClient::Connect src = %s dst = %s", src, dst);
00537 int result = -1;
00538 fChannel->PortConnect(GetClientControl()->fRefNum, src, dst, &result);
00539 return result;
00540 }
00541
00542 int JackClient::PortDisconnect(const char* src, const char* dst)
00543 {
00544 jack_log("JackClient::Disconnect src = %s dst = %s", src, dst);
00545 int result = -1;
00546 fChannel->PortDisconnect(GetClientControl()->fRefNum, src, dst, &result);
00547 return result;
00548 }
00549
00550 int JackClient::PortDisconnect(jack_port_id_t src)
00551 {
00552 jack_log("JackClient::PortDisconnect src = %ld", src);
00553 int result = -1;
00554 fChannel->PortDisconnect(GetClientControl()->fRefNum, src, ALL_PORTS, &result);
00555 return result;
00556 }
00557
00558 int JackClient::PortIsMine(jack_port_id_t port_index)
00559 {
00560 JackPort* port = GetGraphManager()->GetPort(port_index);
00561 return GetClientControl()->fRefNum == port->GetRefNum();
00562 }
00563
00564 int JackClient::PortRename(jack_port_id_t port_index, const char* name)
00565 {
00566 int result = -1;
00567 fChannel->PortRename(GetClientControl()->fRefNum, port_index, name, &result);
00568 return result;
00569 }
00570
00571
00572
00573
00574
00575 int JackClient::SetBufferSize(jack_nframes_t buffer_size)
00576 {
00577 int result = -1;
00578 fChannel->SetBufferSize(buffer_size, &result);
00579 return result;
00580 }
00581
00582 int JackClient::SetFreeWheel(int onoff)
00583 {
00584 int result = -1;
00585 fChannel->SetFreewheel(onoff, &result);
00586 return result;
00587 }
00588
00589
00590
00591
00592
00593
00594
00595
00596 void JackClient::ShutDown()
00597 {
00598 jack_log("ShutDown");
00599
00600
00601 if (GetClientControl()) {
00602 GetClientControl()->fServer = false;
00603 }
00604
00605 if (fShutdown) {
00606 fShutdown(fShutdownArg);
00607 fShutdown = NULL;
00608 }
00609 }
00610
00611
00612
00613
00614
00615 int JackClient::ReleaseTimebase()
00616 {
00617 int result = -1;
00618 fChannel->ReleaseTimebase(GetClientControl()->fRefNum, &result);
00619 if (result == 0) {
00620 GetClientControl()->fTransportTimebase = false;
00621 fTimebase = NULL;
00622 fTimebaseArg = NULL;
00623 }
00624 return result;
00625 }
00626
00627
00628 int JackClient::SetSyncCallback(JackSyncCallback sync_callback, void* arg)
00629 {
00630 GetClientControl()->fTransportSync = (fSync != NULL);
00631 fSyncArg = arg;
00632 fSync = sync_callback;
00633 return 0;
00634 }
00635
00636 int JackClient::SetSyncTimeout(jack_time_t timeout)
00637 {
00638 GetEngineControl()->fTransport.SetSyncTimeout(timeout);
00639 return 0;
00640 }
00641
00642 int JackClient::SetTimebaseCallback(int conditional, JackTimebaseCallback timebase_callback, void* arg)
00643 {
00644 int result = -1;
00645 fChannel->SetTimebaseCallback(GetClientControl()->fRefNum, conditional, &result);
00646 jack_log("SetTimebaseCallback result = %ld", result);
00647 if (result == 0) {
00648 GetClientControl()->fTransportTimebase = true;
00649 fTimebase = timebase_callback;
00650 fTimebaseArg = arg;
00651 } else {
00652 fTimebase = NULL;
00653 fTimebaseArg = NULL;
00654 }
00655 return result;
00656 }
00657
00658
00659
00660 void JackClient::TransportLocate(jack_nframes_t frame)
00661 {
00662 jack_position_t pos;
00663 pos.frame = frame;
00664 pos.valid = (jack_position_bits_t)0;
00665 jack_log("TransportLocate pos = %ld", pos.frame);
00666 GetEngineControl()->fTransport.RequestNewPos(&pos);
00667 }
00668
00669 int JackClient::TransportReposition(jack_position_t* pos)
00670 {
00671 jack_position_t tmp = *pos;
00672 jack_log("TransportReposition pos = %ld", pos->frame);
00673 if (tmp.valid & ~JACK_POSITION_MASK) {
00674 return EINVAL;
00675 } else {
00676 GetEngineControl()->fTransport.RequestNewPos(pos);
00677 return 0;
00678 }
00679 }
00680
00681 jack_transport_state_t JackClient::TransportQuery(jack_position_t* pos)
00682 {
00683 return GetEngineControl()->fTransport.Query(pos);
00684 }
00685
00686 jack_nframes_t JackClient::GetCurrentTransportFrame()
00687 {
00688 return GetEngineControl()->fTransport.GetCurrentFrame();
00689 }
00690
00691
00692 void JackClient::TransportStart()
00693 {
00694 GetEngineControl()->fTransport.SetCommand(TransportCommandStart);
00695 }
00696
00697
00698 void JackClient::TransportStop()
00699 {
00700 GetEngineControl()->fTransport.SetCommand(TransportCommandStop);
00701 }
00702
00703
00704
00705 void JackClient::CallSyncCallback()
00706 {
00707 if (GetClientControl()->fTransportSync) {
00708
00709 JackTransportEngine& transport = GetEngineControl()->fTransport;
00710 jack_position_t* cur_pos = transport.ReadCurrentState();
00711 jack_transport_state_t transport_state = transport.GetState();
00712
00713 if (fSync != NULL) {
00714 if (fSync(transport_state, cur_pos, fSyncArg)) {
00715 GetClientControl()->fTransportState = JackTransportRolling;
00716 GetClientControl()->fTransportSync = false;
00717 }
00718 } else {
00719 GetClientControl()->fTransportState = JackTransportRolling;
00720 GetClientControl()->fTransportSync = false;
00721 }
00722 }
00723 }
00724
00725 void JackClient::CallTimebaseCallback()
00726 {
00727 JackTransportEngine& transport = GetEngineControl()->fTransport;
00728 int master;
00729 bool unused;
00730
00731 transport.GetTimebaseMaster(master, unused);
00732
00733 if (GetClientControl()->fRefNum == master && fTimebase) {
00734
00735 jack_transport_state_t transport_state = transport.GetState();
00736 jack_position_t* cur_pos = transport.WriteNextStateStart(1);
00737
00738 if (GetClientControl()->fTransportTimebase) {
00739 fTimebase(transport_state, GetEngineControl()->fBufferSize, cur_pos, true, fTimebaseArg);
00740 GetClientControl()->fTransportTimebase = false;
00741 } else if (transport_state == JackTransportRolling) {
00742 fTimebase(transport_state, GetEngineControl()->fBufferSize, cur_pos, false, fTimebaseArg);
00743 }
00744
00745 transport.WriteNextStateStop(1);
00746 }
00747 }
00748
00749
00750
00751
00752
00753 void JackClient::OnShutdown(JackShutdownCallback callback, void *arg)
00754 {
00755 if (IsActive()) {
00756 jack_error("You cannot set callbacks on an active client");
00757 } else {
00758 fShutdownArg = arg;
00759 fShutdown = callback;
00760 }
00761 }
00762
00763 int JackClient::SetProcessCallback(JackProcessCallback callback, void *arg)
00764 {
00765 if (IsActive()) {
00766 jack_error("You cannot set callbacks on an active client");
00767 return -1;
00768 } else if (fThreadFun) {
00769 jack_error ("A thread callback has already been setup, both models cannot be used at the same time!");
00770 return -1;
00771 } else {
00772 fProcessArg = arg;
00773 fProcess = callback;
00774 return 0;
00775 }
00776 }
00777
00778 int JackClient::SetXRunCallback(JackXRunCallback callback, void *arg)
00779 {
00780 if (IsActive()) {
00781 jack_error("You cannot set callbacks on an active client");
00782 return -1;
00783 } else {
00784 GetClientControl()->fCallback[kXRunCallback] = (callback != NULL);
00785 fXrunArg = arg;
00786 fXrun = callback;
00787 return 0;
00788 }
00789 }
00790
00791 int JackClient::SetInitCallback(JackThreadInitCallback callback, void *arg)
00792 {
00793 if (IsActive()) {
00794 jack_error("You cannot set callbacks on an active client");
00795 return -1;
00796 } else {
00797 fInitArg = arg;
00798 fInit = callback;
00799 return 0;
00800 }
00801 }
00802
00803 int JackClient::SetGraphOrderCallback(JackGraphOrderCallback callback, void *arg)
00804 {
00805 jack_log("SetGraphOrderCallback ");
00806
00807 if (IsActive()) {
00808 jack_error("You cannot set callbacks on an active client");
00809 return -1;
00810 } else {
00811 GetClientControl()->fCallback[kGraphOrderCallback] = (callback != NULL);
00812 fGraphOrder = callback;
00813 fGraphOrderArg = arg;
00814 return 0;
00815 }
00816 }
00817
00818 int JackClient::SetBufferSizeCallback(JackBufferSizeCallback callback, void *arg)
00819 {
00820 if (IsActive()) {
00821 jack_error("You cannot set callbacks on an active client");
00822 return -1;
00823 } else {
00824 GetClientControl()->fCallback[kBufferSizeCallback] = (callback != NULL);
00825 fBufferSizeArg = arg;
00826 fBufferSize = callback;
00827 return 0;
00828 }
00829 }
00830
00831 int JackClient::SetSampleRateCallback(JackSampleRateCallback callback, void *arg)
00832 {
00833 if (IsActive()) {
00834 jack_error("You cannot set callbacks on an active client");
00835 return -1;
00836 } else {
00837 GetClientControl()->fCallback[kSampleRateCallback] = (callback != NULL);
00838 fSampleRateArg = arg;
00839 fSampleRate = callback;
00840 return 0;
00841 }
00842 }
00843
00844 int JackClient::SetClientRegistrationCallback(JackClientRegistrationCallback callback, void* arg)
00845 {
00846 if (IsActive()) {
00847 jack_error("You cannot set callbacks on an active client");
00848 return -1;
00849 } else {
00850
00851 fClientRegistrationArg = arg;
00852 fClientRegistration = callback;
00853 return 0;
00854 }
00855 }
00856
00857 int JackClient::SetFreewheelCallback(JackFreewheelCallback callback, void *arg)
00858 {
00859 if (IsActive()) {
00860 jack_error("You cannot set callbacks on an active client");
00861 return -1;
00862 } else {
00863 GetClientControl()->fCallback[kStartFreewheelCallback] = (callback != NULL);
00864 GetClientControl()->fCallback[kStopFreewheelCallback] = (callback != NULL);
00865 fFreewheelArg = arg;
00866 fFreewheel = callback;
00867 return 0;
00868 }
00869 }
00870
00871 int JackClient::SetPortRegistrationCallback(JackPortRegistrationCallback callback, void *arg)
00872 {
00873 if (IsActive()) {
00874 jack_error("You cannot set callbacks on an active client");
00875 return -1;
00876 } else {
00877 GetClientControl()->fCallback[kPortRegistrationOnCallback] = (callback != NULL);
00878 GetClientControl()->fCallback[kPortRegistrationOffCallback] = (callback != NULL);
00879 fPortRegistrationArg = arg;
00880 fPortRegistration = callback;
00881 return 0;
00882 }
00883 }
00884
00885 int JackClient::SetPortConnectCallback(JackPortConnectCallback callback, void *arg)
00886 {
00887 if (IsActive()) {
00888 jack_error("You cannot set callbacks on an active client");
00889 return -1;
00890 } else {
00891 GetClientControl()->fCallback[kPortConnectCallback] = (callback != NULL);
00892 GetClientControl()->fCallback[kPortDisconnectCallback] = (callback != NULL);
00893 fPortConnectArg = arg;
00894 fPortConnect = callback;
00895 return 0;
00896 }
00897 }
00898
00899 int JackClient::SetPortRenameCallback(JackPortRenameCallback callback, void *arg)
00900 {
00901 if (IsActive()) {
00902 jack_error("You cannot set callbacks on an active client");
00903 return -1;
00904 } else {
00905 GetClientControl()->fCallback[kPortRenameCallback] = (callback != NULL);
00906 fPortRenameArg = arg;
00907 fPortRename = callback;
00908 return 0;
00909 }
00910 }
00911
00912 int JackClient::SetProcessThread(JackThreadCallback fun, void *arg)
00913 {
00914 if (IsActive()) {
00915 jack_error("You cannot set callbacks on an active client");
00916 return -1;
00917 } else if (fProcess) {
00918 jack_error ("A process callback has already been setup, both models cannot be used at the same time!");
00919 return -1;
00920 } else {
00921 fThreadFun = fun;
00922 fThreadFunArg = arg;
00923 return 0;
00924 }
00925 }
00926
00927
00928
00929
00930
00931 char* JackClient::GetInternalClientName(int ref)
00932 {
00933 char name_res[JACK_CLIENT_NAME_SIZE];
00934 int result = -1;
00935 fChannel->GetInternalClientName(GetClientControl()->fRefNum, ref, name_res, &result);
00936
00937 if (result < 0) {
00938 return NULL;
00939 } else {
00940 char* name = (char*)malloc(strlen(name_res));
00941 strcpy(name, name_res);
00942 return name;
00943 }
00944 }
00945
00946 int JackClient::InternalClientHandle(const char* client_name, jack_status_t* status)
00947 {
00948 int int_ref, result = -1;
00949 fChannel->InternalClientHandle(GetClientControl()->fRefNum, client_name, (int*)status, &int_ref, &result);
00950 return int_ref;
00951 }
00952
00953 int JackClient::InternalClientLoad(const char* client_name, jack_options_t options, jack_status_t* status, jack_varargs_t* va)
00954 {
00955 if (strlen(client_name) >= JACK_CLIENT_NAME_SIZE) {
00956 jack_error ("\"%s\" is too long for a JACK client name.\n"
00957 "Please use %lu characters or less.",
00958 client_name, JACK_CLIENT_NAME_SIZE);
00959 return 0;
00960 }
00961
00962 if (va->load_name && (strlen(va->load_name) >= JACK_PATH_MAX)) {
00963 jack_error("\"%s\" is too long for a shared object name.\n"
00964 "Please use %lu characters or less.",
00965 va->load_name, PATH_MAX);
00966 int my_status1 = *status | (JackFailure | JackInvalidOption);
00967 *status = (jack_status_t)my_status1;
00968 return 0;
00969 }
00970
00971 if (va->load_init && (strlen(va->load_init) >= JACK_LOAD_INIT_LIMIT)) {
00972 jack_error ("\"%s\" is too long for internal client init "
00973 "string.\nPlease use %lu characters or less.",
00974 va->load_init, JACK_LOAD_INIT_LIMIT);
00975 int my_status1 = *status | (JackFailure | JackInvalidOption);
00976 *status = (jack_status_t)my_status1;
00977 return 0;
00978 }
00979
00980 int int_ref, result = -1;
00981 fChannel->InternalClientLoad(GetClientControl()->fRefNum, client_name, va->load_name, va->load_init, options, (int*)status, &int_ref, &result);
00982 return int_ref;
00983 }
00984
00985 void JackClient::InternalClientUnload(int ref, jack_status_t* status)
00986 {
00987 int result = -1;
00988 fChannel->InternalClientUnload(GetClientControl()->fRefNum, ref, (int*)status, &result);
00989 }
00990
00991
00992 }
00993