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