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