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 <math.h>
00030 #include <string>
00031 #include <algorithm>
00032
00033 using namespace std;
00034
00035 namespace Jack
00036 {
00037
00038 JackClient::JackClient()
00039 {}
00040
00041 JackClient::JackClient(JackSynchro** table)
00042 {
00043 fThread = JackGlobals::MakeThread(this);
00044 fSynchroTable = table;
00045 fProcess = NULL;
00046 fGraphOrder = NULL;
00047 fXrun = NULL;
00048 fShutdown = NULL;
00049 fInit = NULL;
00050 fBufferSize = NULL;
00051 fFreewheel = NULL;
00052 fPortRegistration = NULL;
00053 fSync = NULL;
00054 fProcessArg = NULL;
00055 fGraphOrderArg = NULL;
00056 fXrunArg = NULL;
00057 fShutdownArg = NULL;
00058 fInitArg = NULL;
00059 fBufferSizeArg = NULL;
00060 fFreewheelArg = NULL;
00061 fPortRegistrationArg = NULL;
00062 fSyncArg = NULL;
00063 fConditionnal = 0;
00064 }
00065
00066 JackClient::~JackClient()
00067 {
00068 delete fThread;
00069 }
00070
00071 int JackClient::Close()
00072 {
00073 JackLog("JackClient::Close ref = %ld\n", GetClientControl()->fRefNum);
00074 Deactivate();
00075 int result = -1;
00076 fChannel->ClientClose(GetClientControl()->fRefNum, &result);
00077 fChannel->Stop();
00078 fChannel->Close();
00079 fSynchroTable[GetClientControl()->fRefNum]->Disconnect();
00080 return result;
00081 }
00082
00083 bool JackClient::IsActive()
00084 {
00085 return (GetClientControl()) ? GetClientControl()->fActive : false;
00086 }
00087
00088 pthread_t JackClient::GetThreadID()
00089 {
00090 return fThread->GetThreadID();
00091 }
00092
00099 void JackClient::SetupDriverSync(bool freewheel)
00100 {
00101 if (!freewheel && !GetEngineControl()->fSyncMode) {
00102 JackLog("JackClient::SetupDriverSync driver sem in flush mode\n");
00103 fSynchroTable[AUDIO_DRIVER_REFNUM]->SetFlush(true);
00104 fSynchroTable[FREEWHEEL_DRIVER_REFNUM]->SetFlush(true);
00105 fSynchroTable[LOOPBACK_DRIVER_REFNUM]->SetFlush(true);
00106 } else {
00107 JackLog("JackClient::SetupDriverSync driver sem in normal mode\n");
00108 fSynchroTable[AUDIO_DRIVER_REFNUM]->SetFlush(false);
00109 fSynchroTable[FREEWHEEL_DRIVER_REFNUM]->SetFlush(false);
00110 fSynchroTable[LOOPBACK_DRIVER_REFNUM]->SetFlush(false);
00111 }
00112 }
00113
00118 int JackClient::ClientNotifyImp(int refnum, const char* name, int notify, int sync, int value)
00119 {
00120 return 0;
00121 }
00122
00123 int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, int value)
00124 {
00125 int res = 0;
00126
00127
00128 switch (notify) {
00129
00130 case JackNotifyChannelInterface::kAddClient:
00131 case JackNotifyChannelInterface::kRemoveClient:
00132 res = ClientNotifyImp(refnum, name, notify, sync, value);
00133 break;
00134
00135 case JackNotifyChannelInterface::kActivateClient:
00136 JackLog("JackClient::kActivateClient name = %s ref = %ld \n", name, refnum);
00137 Init();
00138 break;
00139 }
00140
00141
00142
00143
00144
00145 if (IsActive()) {
00146
00147 switch (notify) {
00148
00149 case JackNotifyChannelInterface::kBufferSizeCallback:
00150 JackLog("JackClient::kBufferSizeCallback buffer_size = %ld\n", value);
00151 if (fBufferSize)
00152 res = fBufferSize(value, fBufferSizeArg);
00153 break;
00154
00155 case JackNotifyChannelInterface::kGraphOrderCallback:
00156 JackLog("JackClient::kGraphOrderCallback\n");
00157 if (fGraphOrder)
00158 res = fGraphOrder(fGraphOrderArg);
00159 break;
00160
00161 case JackNotifyChannelInterface::kStartFreewheel:
00162 JackLog("JackClient::kStartFreewheel\n");
00163 SetupDriverSync(true);
00164 fThread->DropRealTime();
00165 if (fFreewheel)
00166 fFreewheel(1, fFreewheelArg);
00167 break;
00168
00169 case JackNotifyChannelInterface::kStopFreewheel:
00170 JackLog("JackClient::kStopFreewheel\n");
00171 SetupDriverSync(false);
00172 if (fFreewheel)
00173 fFreewheel(0, fFreewheelArg);
00174 fThread->AcquireRealTime();
00175 break;
00176
00177 case JackNotifyChannelInterface::kPortRegistrationOn:
00178 JackLog("JackClient::kPortRegistrationOn port_index = %ld\n", value);
00179 if (fPortRegistration)
00180 fPortRegistration(value, 1, fPortRegistrationArg);
00181 break;
00182
00183 case JackNotifyChannelInterface::kPortRegistrationOff:
00184 JackLog("JackClient::kPortRegistrationOff port_index = %ld \n", value);
00185 if (fPortRegistration)
00186 fPortRegistration(value, 0, fPortRegistrationArg);
00187 break;
00188
00189 case JackNotifyChannelInterface::kXRunCallback:
00190 JackLog("JackClient::kXRunCallback\n");
00191 if (fXrun)
00192 res = fXrun(fXrunArg);
00193 break;
00194
00195 case JackNotifyChannelInterface::kZombifyClient:
00196 JackLog("JackClient::kZombifyClient name = %s ref = %ld \n", name, refnum);
00197 ShutDown();
00198 break;
00199 }
00200 }
00201
00202 return res;
00203 }
00204
00209 int JackClient::Activate()
00210 {
00211 JackLog("JackClient::Activate \n");
00212 if (IsActive())
00213 return 0;
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 if (StartThread() < 0)
00226 return -1;
00227
00228 int result = -1;
00229 fChannel->ClientActivate(GetClientControl()->fRefNum, &result);
00230 if (result < 0)
00231 return result;
00232
00233 if (fSync != NULL)
00234 SetSyncCallback(fSync, fSyncArg);
00235
00236 if (fTimebase != NULL)
00237 SetTimebaseCallback(fConditionnal, fTimebase, fTimebaseArg);
00238
00239 GetClientControl()->fActive = true;
00240 return 0;
00241 }
00242
00246 int JackClient::Deactivate()
00247 {
00248 JackLog("JackClient::Deactivate \n");
00249 if (!IsActive())
00250 return 0;
00251
00252 GetClientControl()->fActive = false;
00253 int result = -1;
00254 fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result);
00255
00256 JackLog("JackClient::Deactivate res = %ld \n", result);
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 fThread->Kill();
00268 return result;
00269 }
00270
00271
00272
00273
00274
00275 bool JackClient::CallProcessCallback()
00276 {
00277 return (fProcess == NULL) ? true : (fProcess(GetEngineControl()->fBufferSize, fProcessArg) == 0);
00278 }
00279
00283 bool JackClient::Init()
00284 {
00285 if (fInit) {
00286 JackLog("JackClient::Init calling client thread init callback\n");
00287 fInit(fInitArg);
00288 }
00289 return true;
00290 }
00291
00292 int JackClient::StartThread()
00293 {
00294 JackLog("JackClient::StartThread : period = %ld computation = %ld constraint = %ld\n",
00295 long(int64_t(GetEngineControl()->fPeriod) / 1000.0f),
00296 long(int64_t(GetEngineControl()->fComputation) / 1000.0f),
00297 long(int64_t(GetEngineControl()->fConstraint) / 1000.0f));
00298
00299
00300 fThread->SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
00301
00302 if (fThread->Start() < 0) {
00303 jack_error("Start thread error");
00304 return -1;
00305 }
00306
00307 if (GetEngineControl()->fRealTime) {
00308 if (fThread->AcquireRealTime(GetEngineControl()->fPriority - 1) < 0) {
00309 jack_error("AcquireRealTime error");
00310 }
00311 }
00312
00313 return 0;
00314 }
00315
00319 bool JackClient::Execute()
00320 {
00321
00322 if (GetGraphManager()->SuspendRefNum(GetClientControl(), fSynchroTable, 0x7FFFFFFF) < 0) {
00323 jack_error("SuspendRefNum error");
00324 goto error;
00325 }
00326
00327
00328 if (IsActive()) {
00329 CallSyncCallback();
00330 bool res = CallProcessCallback();
00331 CallTimebaseCallback();
00332 if (!res)
00333 goto end;
00334 } else {
00335 JackLog("Process called for an inactive client\n");
00336
00337
00338 }
00339
00340
00341 if (GetGraphManager()->ResumeRefNum(GetClientControl(), fSynchroTable) < 0) {
00342 jack_error("ResumeRefNum error");
00343 }
00344
00345 return true;
00346
00347 end:
00348 JackLog("JackClient::Execute end name = %s\n", GetClientControl()->fName);
00349
00350
00351 if (GetGraphManager()->ResumeRefNum(GetClientControl(), fSynchroTable) < 0) {
00352 jack_error("ResumeRefNum error");
00353 }
00354
00355
00356 int result;
00357 fThread->DropRealTime();
00358 fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result);
00359 Close();
00360 return false;
00361
00362 error:
00363 jack_error("JackClient::Execute error name = %s", GetClientControl()->fName);
00364
00365 fThread->DropRealTime();
00366 ShutDown();
00367 return false;
00368 }
00369
00370
00371
00372
00373
00374 int JackClient::PortRegister(const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size)
00375 {
00376
00377 string port_name_str = string(port_name);
00378 if (port_name_str.size() == 0) {
00379 jack_error("port_name is empty.");
00380 return 0;
00381 }
00382
00383 string name = string(GetClientControl()->fName) + string(":") + port_name_str;
00384 if (name.size() >= JACK_PORT_NAME_SIZE) {
00385 jack_error("\"%s:%s\" is too long to be used as a JACK port name.\n"
00386 "Please use %lu characters or less.",
00387 GetClientControl()->fName,
00388 port_name,
00389 JACK_PORT_NAME_SIZE - 1);
00390 return 0;
00391 }
00392
00393
00394 if (GetGraphManager()->GetPort(name.c_str()) != NO_PORT) {
00395 jack_error("port_name \"%s\" already exists.", port_name);
00396 return 0;
00397 }
00398
00399 JackLog("JackClient::PortRegister ref = %ld name = %s \n", GetClientControl()->fRefNum, name.c_str());
00400
00401 int result = -1;
00402 jack_port_id_t port_index = NO_PORT;
00403 fChannel->PortRegister(GetClientControl()->fRefNum, name.c_str(), flags, buffer_size, &port_index, &result);
00404 JackLog("JackClient::PortRegister port_index = %ld \n", port_index);
00405
00406 if (result == 0) {
00407 fPortList.push_back(port_index);
00408 return port_index;
00409 } else {
00410 return 0;
00411 }
00412 }
00413
00414 int JackClient::PortUnRegister(jack_port_id_t port_index)
00415 {
00416 JackLog("JackClient::PortUnRegister port_index = %ld\n", port_index);
00417 list<jack_port_id_t>::iterator it = find(fPortList.begin(), fPortList.end(), port_index);
00418
00419 if (it != fPortList.end()) {
00420 fPortList.erase(it);
00421 int result = -1;
00422 fChannel->PortUnRegister(GetClientControl()->fRefNum, port_index, &result);
00423 return result;
00424 } else {
00425 jack_error("unregistering a port %ld that is not own by the client", port_index);
00426 return -1;
00427 }
00428 }
00429
00430 int JackClient::PortConnect(const char* src, const char* dst)
00431 {
00432 JackLog("JackClient::Connect src = %s dst = %s\n", src, dst);
00433 int result = -1;
00434 fChannel->PortConnect(GetClientControl()->fRefNum, src, dst, &result);
00435 return result;
00436 }
00437
00438 int JackClient::PortDisconnect(const char* src, const char* dst)
00439 {
00440 JackLog("JackClient::Disconnect src = %s dst = %s\n", src, dst);
00441 int result = -1;
00442 fChannel->PortDisconnect(GetClientControl()->fRefNum, src, dst, &result);
00443 return result;
00444 }
00445
00446 int JackClient::PortConnect(jack_port_id_t src, jack_port_id_t dst)
00447 {
00448 JackLog("JackClient::PortConnect src = %ld dst = %ld\n", src, dst);
00449 int result = -1;
00450 fChannel->PortConnect(GetClientControl()->fRefNum, src, dst, &result);
00451 return result;
00452 }
00453
00454 int JackClient::PortDisconnect(jack_port_id_t src)
00455 {
00456 JackLog("JackClient::PortDisconnect src = %ld\n", src);
00457 int result = -1;
00458 fChannel->PortDisconnect(GetClientControl()->fRefNum, src, ALL_PORTS, &result);
00459 return result;
00460 }
00461
00462 int JackClient::PortIsMine(jack_port_id_t port_index)
00463 {
00464 JackPort* port = GetGraphManager()->GetPort(port_index);
00465 return GetClientControl()->fRefNum == port->GetRefNum();
00466 }
00467
00468
00469
00470
00471
00472 int JackClient::SetBufferSize(jack_nframes_t buffer_size)
00473 {
00474 int result = -1;
00475 fChannel->SetBufferSize(buffer_size, &result);
00476 return result;
00477 }
00478
00479 int JackClient::SetFreeWheel(int onoff)
00480 {
00481 int result = -1;
00482 fChannel->SetFreewheel(onoff, &result);
00483 return result;
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493 void JackClient::ShutDown()
00494 {
00495 JackLog("ShutDown\n");
00496 if (fShutdown) {
00497 GetClientControl()->fActive = false;
00498 fShutdown(fShutdownArg);
00499 fShutdown = NULL;
00500 }
00501 }
00502
00503
00504
00505
00506
00507 int JackClient::ReleaseTimebase()
00508 {
00509 int result = -1;
00510 fChannel->ReleaseTimebase(GetClientControl()->fRefNum, &result);
00511 if (result == 0) {
00512 fTimebase = NULL;
00513 fTimebaseArg = NULL;
00514 }
00515 return result;
00516 }
00517
00518
00519 int JackClient::SetSyncCallback(JackSyncCallback sync_callback, void* arg)
00520 {
00521 if (IsActive())
00522 GetClientControl()->fTransportState = (sync_callback == NULL) ? JackTransportStopped : JackTransportSynching;
00523 fSync = sync_callback;
00524 fSyncArg = arg;
00525 return 0;
00526 }
00527
00528 int JackClient::SetSyncTimeout(jack_time_t timeout)
00529 {
00530 GetEngineControl()->fTransport.SetSyncTimeout(timeout);
00531 return 0;
00532 }
00533
00534
00535 int JackClient::SetTimebaseCallback(int conditional, JackTimebaseCallback timebase_callback, void* arg)
00536 {
00537 if (IsActive()) {
00538 int result = -1;
00539 fChannel->SetTimebaseCallback(GetClientControl()->fRefNum, conditional, &result);
00540 JackLog("SetTimebaseCallback result = %ld\n", result);
00541 if (result == 0) {
00542 fTimebase = timebase_callback;
00543 fTimebaseArg = arg;
00544 } else {
00545 fTimebase = NULL;
00546 fTimebaseArg = NULL;
00547 }
00548 JackLog("SetTimebaseCallback OK result = %ld\n", result);
00549 return result;
00550 } else {
00551 fTimebase = timebase_callback;
00552 fTimebaseArg = arg;
00553 fConditionnal = conditional;
00554 return 0;
00555 }
00556 }
00557
00558
00559 int JackClient::RequestNewPos(jack_position_t* pos)
00560 {
00561 JackTransportEngine& transport = GetEngineControl()->fTransport;
00562 jack_position_t* request = transport.WriteNextStateStart(2);
00563 pos->unique_1 = pos->unique_2 = transport.GenerateUniqueID();
00564 JackTransportEngine::TransportCopyPosition(pos, request);
00565 JackLog("RequestNewPos pos = %ld\n", pos->frame);
00566 transport.WriteNextStateStop(2);
00567 return 0;
00568 }
00569
00570 int JackClient::TransportLocate(jack_nframes_t frame)
00571 {
00572 jack_position_t pos;
00573 pos.frame = frame;
00574 pos.valid = (jack_position_bits_t)0;
00575 JackLog("TransportLocate pos = %ld\n", pos.frame);
00576 return RequestNewPos(&pos);
00577 }
00578
00579 int JackClient::TransportReposition(jack_position_t* pos)
00580 {
00581 jack_position_t tmp = *pos;
00582 JackLog("TransportReposition pos = %ld\n", pos->frame);
00583 return (tmp.valid & ~JACK_POSITION_MASK) ? EINVAL : RequestNewPos(&tmp);
00584 }
00585
00586 jack_transport_state_t JackClient::TransportQuery(jack_position_t* pos)
00587 {
00588 if (pos)
00589 GetEngineControl()->fTransport.ReadCurrentPos(pos);
00590 return GetEngineControl()->fTransport.GetState();
00591 }
00592
00593 jack_nframes_t JackClient::GetCurrentTransportFrame()
00594 {
00595 jack_position_t pos;
00596 jack_transport_state_t state = TransportQuery(&pos);
00597
00598 if (state == JackTransportRolling) {
00599 float usecs = GetMicroSeconds() - pos.usecs;
00600 jack_nframes_t elapsed = (jack_nframes_t)floor((((float) pos.frame_rate) / 1000000.0f) * usecs);
00601 return pos.frame + elapsed;
00602 } else {
00603 return pos.frame;
00604 }
00605 }
00606
00607
00608 void JackClient::TransportStart()
00609 {
00610 GetEngineControl()->fTransport.SetCommand(TransportCommandStart);
00611 }
00612
00613
00614 void JackClient::TransportStop()
00615 {
00616 GetEngineControl()->fTransport.SetCommand(TransportCommandStop);
00617 }
00618
00619
00620
00621
00622 void JackClient::CallSyncCallback()
00623 {
00624 JackTransportEngine& transport = GetEngineControl()->fTransport;
00625 jack_position_t* cur_pos = transport.ReadCurrentState();
00626 jack_transport_state_t transport_state = transport.GetState();
00627
00628 switch (transport_state) {
00629
00630 case JackTransportStarting:
00631 if (fSync == NULL) {
00632 GetClientControl()->fTransportState = JackTransportRolling;
00633 } else if (GetClientControl()->fTransportState == JackTransportStarting) {
00634 if (fSync(transport_state, cur_pos, fSyncArg))
00635 GetClientControl()->fTransportState = JackTransportRolling;
00636 }
00637 break;
00638
00639 case JackTransportRolling:
00640 if (fSync != NULL && GetClientControl()->fTransportState == JackTransportStarting) {
00641 if (fSync(transport_state, cur_pos, fSyncArg))
00642 GetClientControl()->fTransportState = JackTransportRolling;
00643 }
00644 break;
00645
00646 case JackTransportSynching:
00647
00648 if (fSync != NULL) {
00649 fSync(JackTransportStopped, cur_pos, fSyncArg);
00650 GetClientControl()->fTransportState = JackTransportStopped;
00651 }
00652 break;
00653
00654 default:
00655 break;
00656 }
00657 }
00658
00659 void JackClient::CallTimebaseCallback()
00660 {
00661 JackTransportEngine& transport = GetEngineControl()->fTransport;
00662
00663 if (fTimebase != NULL && fTimebaseArg != NULL && GetClientControl()->fRefNum == transport.GetTimebaseMaster()) {
00664
00665 jack_transport_state_t transport_state = transport.GetState();
00666 jack_position_t* cur_pos = transport.WriteNextStateStart(1);
00667
00668 switch (transport_state) {
00669
00670 case JackTransportRolling:
00671 fTimebase(transport_state, GetEngineControl()->fBufferSize, cur_pos, false, fTimebaseArg);
00672 break;
00673
00674 case JackTransportSynching:
00675 fTimebase(JackTransportStopped, GetEngineControl()->fBufferSize, cur_pos, true, fTimebaseArg);
00676 break;
00677
00678 default:
00679 break;
00680 }
00681
00682 transport.WriteNextStateStop(1);
00683 }
00684 }
00685
00686
00687
00688
00689
00690 void JackClient::OnShutdown(JackShutdownCallback callback, void *arg)
00691 {
00692 if (IsActive()) {
00693 jack_error("You cannot set callbacks on an active client");
00694 } else {
00695 fShutdownArg = arg;
00696 fShutdown = callback;
00697 }
00698 }
00699
00700 int JackClient::SetProcessCallback(JackProcessCallback callback, void *arg)
00701 {
00702 if (IsActive()) {
00703 jack_error("You cannot set callbacks on an active client");
00704 return -1;
00705 } else {
00706 fProcessArg = arg;
00707 fProcess = callback;
00708 return 0;
00709 }
00710 }
00711
00712 int JackClient::SetXRunCallback(JackXRunCallback callback, void *arg)
00713 {
00714 if (IsActive()) {
00715 jack_error("You cannot set callbacks on an active client");
00716 return -1;
00717 } else {
00718 fXrunArg = arg;
00719 fXrun = callback;
00720 return 0;
00721 }
00722 }
00723
00724 int JackClient::SetInitCallback(JackThreadInitCallback callback, void *arg)
00725 {
00726 if (IsActive()) {
00727 jack_error("You cannot set callbacks on an active client");
00728 return -1;
00729 } else {
00730 fInitArg = arg;
00731 fInit = callback;
00732 return 0;
00733 }
00734 }
00735
00736 int JackClient::SetGraphOrderCallback(JackGraphOrderCallback callback, void *arg)
00737 {
00738 JackLog("SetGraphOrderCallback \n");
00739
00740 if (IsActive()) {
00741 jack_error("You cannot set callbacks on an active client");
00742 return -1;
00743 } else {
00744 fGraphOrder = callback;
00745 fGraphOrderArg = arg;
00746 return 0;
00747 }
00748 }
00749
00750 int JackClient::SetBufferSizeCallback(JackBufferSizeCallback callback, void *arg)
00751 {
00752 if (IsActive()) {
00753 jack_error("You cannot set callbacks on an active client");
00754 return -1;
00755 } else {
00756 fBufferSizeArg = arg;
00757 fBufferSize = callback;
00758 return 0;
00759 }
00760 }
00761
00762 int JackClient::SetFreewheelCallback(JackFreewheelCallback callback, void *arg)
00763 {
00764 if (IsActive()) {
00765 jack_error("You cannot set callbacks on an active client");
00766 return -1;
00767 } else {
00768 fFreewheelArg = arg;
00769 fFreewheel = callback;
00770 return 0;
00771 }
00772 }
00773
00774 int JackClient::SetPortRegistrationCallback(JackPortRegistrationCallback callback, void *arg)
00775 {
00776 if (IsActive()) {
00777 jack_error("You cannot set callbacks on an active client");
00778 return -1;
00779 } else {
00780 fPortRegistrationArg = arg;
00781 fPortRegistration = callback;
00782 return 0;
00783 }
00784 }
00785
00786 }
00787