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