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