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()->fClientPriority) < 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 jack_log("TransportQuery");
00678 return GetEngineControl()->fTransport.Query(pos);
00679 }
00680
00681 jack_nframes_t JackClient::GetCurrentTransportFrame()
00682 {
00683 jack_log("GetCurrentTransportFrame");
00684 return GetEngineControl()->fTransport.GetCurrentFrame();
00685 }
00686
00687
00688 void JackClient::TransportStart()
00689 {
00690 GetEngineControl()->fTransport.SetCommand(TransportCommandStart);
00691 }
00692
00693
00694 void JackClient::TransportStop()
00695 {
00696 GetEngineControl()->fTransport.SetCommand(TransportCommandStop);
00697 }
00698
00699
00700
00701 void JackClient::CallSyncCallback()
00702 {
00703 if (GetClientControl()->fTransportSync) {
00704
00705 JackTransportEngine& transport = GetEngineControl()->fTransport;
00706 jack_position_t* cur_pos = transport.ReadCurrentState();
00707 jack_transport_state_t transport_state = transport.GetState();
00708
00709 if (fSync != NULL) {
00710 if (fSync(transport_state, cur_pos, fSyncArg)) {
00711 GetClientControl()->fTransportState = JackTransportRolling;
00712 GetClientControl()->fTransportSync = false;
00713 }
00714 } else {
00715 GetClientControl()->fTransportState = JackTransportRolling;
00716 GetClientControl()->fTransportSync = false;
00717 }
00718 }
00719 }
00720
00721 void JackClient::CallTimebaseCallback()
00722 {
00723 JackTransportEngine& transport = GetEngineControl()->fTransport;
00724 int master;
00725 bool unused;
00726
00727 transport.GetTimebaseMaster(master, unused);
00728
00729 if (GetClientControl()->fRefNum == master && fTimebase) {
00730
00731 jack_transport_state_t transport_state = transport.GetState();
00732 jack_position_t* cur_pos = transport.WriteNextStateStart(1);
00733
00734 if (GetClientControl()->fTransportTimebase) {
00735 fTimebase(transport_state, GetEngineControl()->fBufferSize, cur_pos, true, fTimebaseArg);
00736 GetClientControl()->fTransportTimebase = false;
00737 } else if (transport_state == JackTransportRolling) {
00738 fTimebase(transport_state, GetEngineControl()->fBufferSize, cur_pos, false, fTimebaseArg);
00739 }
00740
00741 transport.WriteNextStateStop(1);
00742 }
00743 }
00744
00745
00746
00747
00748
00749 void JackClient::OnShutdown(JackShutdownCallback callback, void *arg)
00750 {
00751 if (IsActive()) {
00752 jack_error("You cannot set callbacks on an active client");
00753 } else {
00754 fShutdownArg = arg;
00755 fShutdown = callback;
00756 }
00757 }
00758
00759 int JackClient::SetProcessCallback(JackProcessCallback callback, void *arg)
00760 {
00761 if (IsActive()) {
00762 jack_error("You cannot set callbacks on an active client");
00763 return -1;
00764 } else if (fThreadFun) {
00765 jack_error ("A thread callback has already been setup, both models cannot be used at the same time!");
00766 return -1;
00767 } else {
00768 fProcessArg = arg;
00769 fProcess = callback;
00770 return 0;
00771 }
00772 }
00773
00774 int JackClient::SetXRunCallback(JackXRunCallback callback, void *arg)
00775 {
00776 if (IsActive()) {
00777 jack_error("You cannot set callbacks on an active client");
00778 return -1;
00779 } else {
00780 GetClientControl()->fCallback[kXRunCallback] = (callback != NULL);
00781 fXrunArg = arg;
00782 fXrun = callback;
00783 return 0;
00784 }
00785 }
00786
00787 int JackClient::SetInitCallback(JackThreadInitCallback callback, void *arg)
00788 {
00789 if (IsActive()) {
00790 jack_error("You cannot set callbacks on an active client");
00791 return -1;
00792 } else {
00793 fInitArg = arg;
00794 fInit = callback;
00795 return 0;
00796 }
00797 }
00798
00799 int JackClient::SetGraphOrderCallback(JackGraphOrderCallback callback, void *arg)
00800 {
00801 jack_log("SetGraphOrderCallback ");
00802
00803 if (IsActive()) {
00804 jack_error("You cannot set callbacks on an active client");
00805 return -1;
00806 } else {
00807 GetClientControl()->fCallback[kGraphOrderCallback] = (callback != NULL);
00808 fGraphOrder = callback;
00809 fGraphOrderArg = arg;
00810 return 0;
00811 }
00812 }
00813
00814 int JackClient::SetBufferSizeCallback(JackBufferSizeCallback callback, void *arg)
00815 {
00816 if (IsActive()) {
00817 jack_error("You cannot set callbacks on an active client");
00818 return -1;
00819 } else {
00820 GetClientControl()->fCallback[kBufferSizeCallback] = (callback != NULL);
00821 fBufferSizeArg = arg;
00822 fBufferSize = callback;
00823 return 0;
00824 }
00825 }
00826
00827 int JackClient::SetSampleRateCallback(JackSampleRateCallback callback, void *arg)
00828 {
00829 if (IsActive()) {
00830 jack_error("You cannot set callbacks on an active client");
00831 return -1;
00832 } else {
00833 GetClientControl()->fCallback[kSampleRateCallback] = (callback != NULL);
00834 fSampleRateArg = arg;
00835 fSampleRate = callback;
00836 return 0;
00837 }
00838 }
00839
00840 int JackClient::SetClientRegistrationCallback(JackClientRegistrationCallback callback, void* arg)
00841 {
00842 if (IsActive()) {
00843 jack_error("You cannot set callbacks on an active client");
00844 return -1;
00845 } else {
00846
00847 fClientRegistrationArg = arg;
00848 fClientRegistration = callback;
00849 return 0;
00850 }
00851 }
00852
00853 int JackClient::SetFreewheelCallback(JackFreewheelCallback callback, void *arg)
00854 {
00855 if (IsActive()) {
00856 jack_error("You cannot set callbacks on an active client");
00857 return -1;
00858 } else {
00859 GetClientControl()->fCallback[kStartFreewheelCallback] = (callback != NULL);
00860 GetClientControl()->fCallback[kStopFreewheelCallback] = (callback != NULL);
00861 fFreewheelArg = arg;
00862 fFreewheel = callback;
00863 return 0;
00864 }
00865 }
00866
00867 int JackClient::SetPortRegistrationCallback(JackPortRegistrationCallback callback, void *arg)
00868 {
00869 if (IsActive()) {
00870 jack_error("You cannot set callbacks on an active client");
00871 return -1;
00872 } else {
00873 GetClientControl()->fCallback[kPortRegistrationOnCallback] = (callback != NULL);
00874 GetClientControl()->fCallback[kPortRegistrationOffCallback] = (callback != NULL);
00875 fPortRegistrationArg = arg;
00876 fPortRegistration = callback;
00877 return 0;
00878 }
00879 }
00880
00881 int JackClient::SetPortConnectCallback(JackPortConnectCallback callback, void *arg)
00882 {
00883 if (IsActive()) {
00884 jack_error("You cannot set callbacks on an active client");
00885 return -1;
00886 } else {
00887 GetClientControl()->fCallback[kPortConnectCallback] = (callback != NULL);
00888 GetClientControl()->fCallback[kPortDisconnectCallback] = (callback != NULL);
00889 fPortConnectArg = arg;
00890 fPortConnect = callback;
00891 return 0;
00892 }
00893 }
00894
00895 int JackClient::SetPortRenameCallback(JackPortRenameCallback callback, void *arg)
00896 {
00897 if (IsActive()) {
00898 jack_error("You cannot set callbacks on an active client");
00899 return -1;
00900 } else {
00901 GetClientControl()->fCallback[kPortRenameCallback] = (callback != NULL);
00902 fPortRenameArg = arg;
00903 fPortRename = callback;
00904 return 0;
00905 }
00906 }
00907
00908 int JackClient::SetProcessThread(JackThreadCallback fun, void *arg)
00909 {
00910 if (IsActive()) {
00911 jack_error("You cannot set callbacks on an active client");
00912 return -1;
00913 } else if (fProcess) {
00914 jack_error ("A process callback has already been setup, both models cannot be used at the same time!");
00915 return -1;
00916 } else {
00917 fThreadFun = fun;
00918 fThreadFunArg = arg;
00919 return 0;
00920 }
00921 }
00922
00923
00924
00925
00926
00927 char* JackClient::GetInternalClientName(int ref)
00928 {
00929 char name_res[JACK_CLIENT_NAME_SIZE];
00930 int result = -1;
00931 fChannel->GetInternalClientName(GetClientControl()->fRefNum, ref, name_res, &result);
00932
00933 if (result < 0) {
00934 return NULL;
00935 } else {
00936 char* name = (char*)malloc(strlen(name_res));
00937 strcpy(name, name_res);
00938 return name;
00939 }
00940 }
00941
00942 int JackClient::InternalClientHandle(const char* client_name, jack_status_t* status)
00943 {
00944 int int_ref, result = -1;
00945 fChannel->InternalClientHandle(GetClientControl()->fRefNum, client_name, (int*)status, &int_ref, &result);
00946 return int_ref;
00947 }
00948
00949 int JackClient::InternalClientLoad(const char* client_name, jack_options_t options, jack_status_t* status, jack_varargs_t* va)
00950 {
00951 if (strlen(client_name) >= JACK_CLIENT_NAME_SIZE) {
00952 jack_error ("\"%s\" is too long for a JACK client name.\n"
00953 "Please use %lu characters or less.",
00954 client_name, JACK_CLIENT_NAME_SIZE);
00955 return 0;
00956 }
00957
00958 if (va->load_name && (strlen(va->load_name) >= JACK_PATH_MAX)) {
00959 jack_error("\"%s\" is too long for a shared object name.\n"
00960 "Please use %lu characters or less.",
00961 va->load_name, PATH_MAX);
00962 int my_status1 = *status | (JackFailure | JackInvalidOption);
00963 *status = (jack_status_t)my_status1;
00964 return 0;
00965 }
00966
00967 if (va->load_init && (strlen(va->load_init) >= JACK_LOAD_INIT_LIMIT)) {
00968 jack_error ("\"%s\" is too long for internal client init "
00969 "string.\nPlease use %lu characters or less.",
00970 va->load_init, JACK_LOAD_INIT_LIMIT);
00971 int my_status1 = *status | (JackFailure | JackInvalidOption);
00972 *status = (jack_status_t)my_status1;
00973 return 0;
00974 }
00975
00976 int int_ref, result = -1;
00977 fChannel->InternalClientLoad(GetClientControl()->fRefNum, client_name, va->load_name, va->load_init, options, (int*)status, &int_ref, &result);
00978 return int_ref;
00979 }
00980
00981 void JackClient::InternalClientUnload(int ref, jack_status_t* status)
00982 {
00983 int result = -1;
00984 fChannel->InternalClientUnload(GetClientControl()->fRefNum, ref, (int*)status, &result);
00985 }
00986
00987
00988 }
00989