Jack2  1.9.10
JackDriver.cpp
00001 /*
00002 Copyright (C) 2001 Paul Davis
00003 Copyright (C) 2004-2008 Grame
00004 
00005 This program is free software; you can redistribute it and/or modify
00006 it under the terms of the GNU General Public License as published by
00007 the Free Software Foundation; either version 2 of the License, or
00008 (at your option) any later version.
00009 
00010 This program is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 
00019 */
00020 
00021 #include "JackSystemDeps.h"
00022 #include "JackDriver.h"
00023 #include "JackTime.h"
00024 #include "JackError.h"
00025 #include "JackPort.h"
00026 #include "JackGraphManager.h"
00027 #include "JackGlobals.h"
00028 #include "JackEngineControl.h"
00029 #include "JackClientControl.h"
00030 #include "JackLockedEngine.h"
00031 #include "JackTime.h"
00032 #include <math.h>
00033 #include <assert.h>
00034 
00035 using namespace std;
00036 
00037 namespace Jack
00038 {
00039 
00040 JackDriver::JackDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
00041     :fCaptureChannels(0),
00042     fPlaybackChannels(0),
00043     fClientControl(name),
00044     fWithMonitorPorts(false){
00045     assert(strlen(name) < JACK_CLIENT_NAME_SIZE);
00046     fSynchroTable = table;
00047     strcpy(fAliasName, alias);
00048     fEngine = engine;
00049     fGraphManager = NULL;
00050     fBeginDateUst = 0;
00051     fDelayedUsecs = 0.f;
00052     fIsMaster = true;
00053     fIsRunning = false;
00054 }
00055 
00056 JackDriver::~JackDriver()
00057 {
00058     jack_log("~JackDriver");
00059 }
00060 
00061 int JackDriver::Open()
00062 {
00063     int refnum = -1;
00064 
00065     if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) {
00066         jack_error("Cannot allocate internal client for driver");
00067         return -1;
00068     }
00069 
00070     fClientControl.fRefNum = refnum;
00071     fClientControl.fActive = true;
00072     fEngineControl->fDriverNum++;
00073     fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode
00074     SetupDriverSync(fClientControl.fRefNum, false);
00075     return 0;
00076 }
00077 
00078 int JackDriver::Open(jack_nframes_t buffer_size,
00079                      jack_nframes_t samplerate,
00080                      bool capturing,
00081                      bool playing,
00082                      int inchannels,
00083                      int outchannels,
00084                      bool monitor,
00085                      const char* capture_driver_name,
00086                      const char* playback_driver_name,
00087                      jack_nframes_t capture_latency,
00088                      jack_nframes_t playback_latency)
00089 {
00090     jack_log("JackDriver::Open capture_driver_name = %s", capture_driver_name);
00091     jack_log("JackDriver::Open playback_driver_name = %s", playback_driver_name);
00092     int refnum = -1;
00093     char name_res[JACK_CLIENT_NAME_SIZE + 1];
00094     int status;
00095 
00096     // Check name and possibly rename
00097     if (fEngine->ClientCheck(fClientControl.fName, -1, name_res, JACK_PROTOCOL_VERSION, (int)JackNullOption, (int*)&status) < 0) {
00098         jack_error("Client name = %s conflits with another running client", fClientControl.fName);
00099         return -1;
00100     }
00101     strcpy(fClientControl.fName, name_res);
00102 
00103     if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) {
00104         jack_error("Cannot allocate internal client for driver");
00105         return -1;
00106     }
00107 
00108     fClientControl.fRefNum = refnum;
00109     fClientControl.fActive = true;
00110     fEngineControl->fDriverNum++;
00111     if (buffer_size > 0) {
00112         fEngineControl->fBufferSize = buffer_size;
00113     }
00114     if (samplerate > 0) {
00115         fEngineControl->fSampleRate = samplerate;
00116     }
00117     fCaptureLatency = capture_latency;
00118     fPlaybackLatency = playback_latency;
00119 
00120     assert(strlen(capture_driver_name) < JACK_CLIENT_NAME_SIZE);
00121     assert(strlen(playback_driver_name) < JACK_CLIENT_NAME_SIZE);
00122 
00123     strcpy(fCaptureDriverName, capture_driver_name);
00124     strcpy(fPlaybackDriverName, playback_driver_name);
00125 
00126     fEngineControl->UpdateTimeOut();
00127 
00128     fGraphManager->SetBufferSize(buffer_size);
00129     fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode
00130     SetupDriverSync(fClientControl.fRefNum, false);
00131     return 0;
00132 }
00133 
00134 int JackDriver::Close()
00135 {
00136     if (fClientControl.fRefNum >= 0) {
00137         jack_log("JackDriver::Close");
00138         fGraphManager->DirectDisconnect(fClientControl.fRefNum, fClientControl.fRefNum); // Disconnect driver from itself for sync
00139         fClientControl.fActive = false;
00140         fEngineControl->fDriverNum--;
00141         return fEngine->ClientInternalClose(fClientControl.fRefNum, false);
00142     } else {
00143         return -1;
00144     }
00145 }
00146 
00152 void JackDriver::SetupDriverSync(int ref, bool freewheel)
00153 {
00154     if (!freewheel && !fEngineControl->fSyncMode) {
00155         jack_log("JackDriver::SetupDriverSync driver sem in flush mode");
00156         fSynchroTable[ref].SetFlush(true);
00157     } else {
00158         jack_log("JackDriver::SetupDriverSync driver sem in normal mode");
00159         fSynchroTable[ref].SetFlush(false);
00160     }
00161 }
00162 
00163 int JackDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
00164 {
00165     jack_log("JackDriver::ClientNotify ref = %ld driver = %s name = %s notify = %ld", refnum, fClientControl.fName, name, notify);
00166 
00167     switch (notify) {
00168 
00169         case kStartFreewheelCallback:
00170             jack_log("JackDriver::kStartFreewheel");
00171             SetupDriverSync(fClientControl.fRefNum, true);
00172             break;
00173 
00174         case kStopFreewheelCallback:
00175             jack_log("JackDriver::kStopFreewheel");
00176             SetupDriverSync(fClientControl.fRefNum, false);
00177             break;
00178     }
00179 
00180     return 0;
00181 }
00182 
00183 bool JackDriver::IsRealTime() const
00184 {
00185     return fEngineControl->fRealTime;
00186 }
00187 
00188 void JackDriver::CycleIncTime()
00189 {
00190     fEngineControl->CycleIncTime(fBeginDateUst);
00191 }
00192 
00193 void JackDriver::CycleTakeBeginTime()
00194 {
00195     fBeginDateUst = GetMicroSeconds();  // Take callback date here
00196     fEngineControl->CycleIncTime(fBeginDateUst);
00197 }
00198 
00199 void JackDriver::CycleTakeEndTime()
00200 {
00201     fEndDateUst = GetMicroSeconds();    // Take end date here
00202 }
00203 
00204 JackClientControl* JackDriver::GetClientControl() const
00205 {
00206     return (JackClientControl*)&fClientControl;
00207 }
00208 
00209 void JackDriver::NotifyXRun(jack_time_t cur_cycle_begin, float delayed_usecs)
00210 {
00211     fEngineControl->NotifyXRun(cur_cycle_begin, delayed_usecs);
00212     fEngine->NotifyDriverXRun();
00213 }
00214 
00215 void JackDriver::NotifyBufferSize(jack_nframes_t buffer_size)
00216 {
00217     fEngine->NotifyBufferSize(buffer_size);
00218     fEngineControl->InitFrameTime();
00219 }
00220 
00221 void JackDriver::NotifySampleRate(jack_nframes_t sample_rate)
00222 {
00223     fEngine->NotifySampleRate(sample_rate);
00224     fEngineControl->InitFrameTime();
00225 }
00226 
00227 void JackDriver::NotifyFailure(int code, const char* reason)
00228 {
00229     fEngine->NotifyFailure(code, reason);
00230 }
00231 
00232 void JackDriver::SetMaster(bool onoff)
00233 {
00234     fIsMaster = onoff;
00235 }
00236 
00237 bool JackDriver::GetMaster()
00238 {
00239     return fIsMaster;
00240 }
00241 
00242 void JackDriver::AddSlave(JackDriverInterface* slave)
00243 {
00244     fSlaveList.push_back(slave);
00245 }
00246 
00247 void JackDriver::RemoveSlave(JackDriverInterface* slave)
00248 {
00249     fSlaveList.remove(slave);
00250 }
00251 
00252 int JackDriver::ProcessReadSlaves()
00253 {
00254     int res = 0;
00255     list<JackDriverInterface*>::const_iterator it;
00256     for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
00257         JackDriverInterface* slave = *it;
00258         if (slave->IsRunning()) {
00259             if (slave->ProcessRead() < 0) {
00260                 res = -1;
00261             }
00262         }
00263     }
00264     return res;
00265 }
00266 
00267 int JackDriver::ProcessWriteSlaves()
00268 {
00269     int res = 0;
00270     list<JackDriverInterface*>::const_iterator it;
00271     for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
00272         JackDriverInterface* slave = *it;
00273         if (slave->IsRunning()) {
00274             if (slave->ProcessWrite() < 0) {
00275                 res = -1;
00276             }
00277         }
00278     }
00279     return res;
00280 }
00281 
00282 int JackDriver::ProcessRead()
00283 {
00284     return (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync();
00285 }
00286 
00287 int JackDriver::ProcessWrite()
00288 {
00289     return (fEngineControl->fSyncMode) ? ProcessWriteSync() : ProcessWriteAsync();
00290 }
00291 
00292 int JackDriver::ProcessReadSync()
00293 {
00294     return 0;
00295 }
00296 
00297 int JackDriver::ProcessWriteSync()
00298 {
00299     return 0;
00300 }
00301 
00302 int JackDriver::ProcessReadAsync()
00303 {
00304     return 0;
00305 }
00306 
00307 int JackDriver::ProcessWriteAsync()
00308 {
00309     return 0;
00310 }
00311 
00312 int JackDriver::Process()
00313 {
00314     return 0;
00315 }
00316 
00317 int JackDriver::Attach()
00318 {
00319     return 0;
00320 }
00321 
00322 int JackDriver::Detach()
00323 {
00324     return 0;
00325 }
00326 
00327 int JackDriver::Read()
00328 {
00329     return 0;
00330 }
00331 
00332 int JackDriver::Write()
00333 {
00334     return 0;
00335 }
00336 
00337 int JackDriver::Start()
00338 {
00339     if (fIsMaster) {
00340         fEngineControl->InitFrameTime();
00341     }
00342     fIsRunning = true;
00343     return StartSlaves();
00344 }
00345 
00346 int JackDriver::Stop()
00347 {
00348     fIsRunning = false;
00349     return StopSlaves();
00350 }
00351 
00352 int JackDriver::StartSlaves()
00353 {
00354     int res = 0;
00355     list<JackDriverInterface*>::const_iterator it;
00356     for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
00357         JackDriverInterface* slave = *it;
00358         if (slave->Start() < 0) {
00359             res = -1;
00360             // XXX: We should attempt to stop all of the slaves that we've
00361             // started here.
00362             break;
00363         }
00364     }
00365     return res;
00366 }
00367 
00368 int JackDriver::StopSlaves()
00369 {
00370     int res = 0;
00371     list<JackDriverInterface*>::const_iterator it;
00372     for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
00373         JackDriverInterface* slave = *it;
00374         if (slave->Stop() < 0) {
00375             res = -1;
00376         }
00377     }
00378     return res;
00379 }
00380 
00381 bool JackDriver::IsFixedBufferSize()
00382 {
00383     return true;
00384 }
00385 
00386 int JackDriver::SetBufferSize(jack_nframes_t buffer_size)
00387 {
00388     int res = 0;
00389     list<JackDriverInterface*>::const_iterator it;
00390     for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
00391         JackDriverInterface* slave = *it;
00392         if (slave->SetBufferSize(buffer_size) < 0) {
00393             res = -1;
00394         }
00395     }
00396     return res;
00397 }
00398 
00399 int JackDriver::SetSampleRate(jack_nframes_t sample_rate)
00400 {
00401     int res = 0;
00402     list<JackDriverInterface*>::const_iterator it;
00403     for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
00404         JackDriverInterface* slave = *it;
00405         if (slave->SetSampleRate(sample_rate) < 0) {
00406             res = -1;
00407         }
00408     }
00409     return res;
00410 }
00411 
00412 bool JackDriver::Initialize()
00413 {
00414     return true;
00415 }
00416 
00417 static string RemoveLast(const string& name)
00418 {
00419     return name.substr(0, name.find_last_of(':')); // Remove end of name after last ":"
00420 }
00421 
00422 void JackDriver::SaveConnections(int alias)
00423 {
00424     const char** connections;
00425     char alias1[REAL_JACK_PORT_NAME_SIZE];
00426     char alias2[REAL_JACK_PORT_NAME_SIZE];
00427     char system_alias1[REAL_JACK_PORT_NAME_SIZE];
00428     char system_alias2[REAL_JACK_PORT_NAME_SIZE];
00429     char* aliases[2];
00430     char* system_aliases[2];
00431 
00432     aliases[0] = alias1;
00433     aliases[1] = alias2;
00434     
00435     system_aliases[0] = system_alias1;
00436     system_aliases[1] = system_alias2;
00437     
00438     fConnections.clear();
00439    
00440     for (int i = 0; i < fCaptureChannels; ++i) {
00441         if (fCapturePortList[i] && (connections = fGraphManager->GetConnections(fCapturePortList[i])) != 0) {
00442             if (alias == 0) {
00443                 for (int j = 0; connections[j]; j++) {
00444                     JackPort* port_id = fGraphManager->GetPort(fCapturePortList[i]);
00445                     fConnections.push_back(make_pair(port_id->GetType(), make_pair(port_id->GetName(), connections[j])));
00446                     jack_info("Save connection: %s %s", fGraphManager->GetPort(fCapturePortList[i])->GetName(), connections[j]);
00447                 }
00448             } else {
00449                 int res1 = fGraphManager->GetPort(fCapturePortList[i])->GetAliases(aliases);
00450                 string sub_system_name;
00451                 if (res1 >= alias) {
00452                     sub_system_name = aliases[alias-1];
00453                 } else {
00454                     sub_system_name = fGraphManager->GetPort(fCapturePortList[i])->GetName();
00455                 }
00456                 for (int j = 0; connections[j]; j++) {
00457                     JackPort* port_id = fGraphManager->GetPort(fGraphManager->GetPort(connections[j]));
00458                     int res2 = port_id->GetAliases(system_aliases);
00459                     string sub_system;
00460                     if (res2 >= alias) {
00461                         sub_system = system_aliases[alias-1];
00462                     } else {
00463                         sub_system = connections[j];
00464                     }
00465                     fConnections.push_back(make_pair(port_id->GetType(), make_pair(sub_system_name, sub_system)));
00466                     jack_info("Save connection: %s %s", sub_system_name.c_str(), sub_system.c_str());
00467                }        
00468             }
00469             free(connections);
00470         }
00471     }
00472 
00473     for (int i = 0; i < fPlaybackChannels; ++i) {
00474         if (fPlaybackPortList[i] && (connections = fGraphManager->GetConnections(fPlaybackPortList[i])) != 0) {
00475             if (alias == 0) {
00476                 for (int j = 0; connections[j]; j++) {
00477                     JackPort* port_id = fGraphManager->GetPort(fPlaybackPortList[i]);
00478                     fConnections.push_back(make_pair(port_id->GetType(), make_pair(connections[j], port_id->GetName())));
00479                     jack_info("Save connection: %s %s", connections[j], fGraphManager->GetPort(fPlaybackPortList[i])->GetName());
00480                 }
00481             } else {
00482                 int res1 = fGraphManager->GetPort(fPlaybackPortList[i])->GetAliases(aliases);
00483                 string sub_system_name;
00484                 if (res1 >= alias) {
00485                     sub_system_name = aliases[alias-1];
00486                 } else {
00487                     sub_system_name = fGraphManager->GetPort(fPlaybackPortList[i])->GetName();
00488                 }
00489                 for (int j = 0; connections[j]; j++) {
00490                     JackPort* port_id = fGraphManager->GetPort(fGraphManager->GetPort(connections[j]));
00491                     int res2 = port_id->GetAliases(system_aliases);
00492                     string sub_name;
00493                     if (res2 >= alias) {
00494                         sub_name = system_aliases[alias-1];
00495                     } else {
00496                         sub_name = connections[j];
00497                     }
00498                     fConnections.push_back(make_pair(port_id->GetType(), make_pair(sub_name, sub_system_name)));
00499                     jack_info("Save connection: %s %s", sub_name.c_str(), sub_system_name.c_str());
00500                }        
00501             }
00502             free(connections);
00503         }
00504     }
00505 }
00506 
00507 string JackDriver::MatchPortName(const char* name, const char** ports, int alias, const std::string& type)
00508 {
00509     char alias1[REAL_JACK_PORT_NAME_SIZE];
00510     char alias2[REAL_JACK_PORT_NAME_SIZE];
00511     char* aliases[2];
00512   
00513     aliases[0] = alias1;
00514     aliases[1] = alias2;
00515   
00516     for (int i = 0; ports && ports[i]; ++i) {
00517         
00518         jack_port_id_t port_id2 = fGraphManager->GetPort(ports[i]);
00519         JackPort* port2 = (port_id2 != NO_PORT) ? fGraphManager->GetPort(port_id2) : NULL;
00520         
00521         if (port2) {
00522             int res = port2->GetAliases(aliases);
00523             string name_str;
00524             if (res >= alias) {
00525                 name_str = string(aliases[alias-1]);
00526             } else {
00527                 name_str = string(ports[i]);
00528             }
00529             string sub_name = RemoveLast(name);
00530             if ((name_str.find(sub_name) != string::npos) && (type == string(port2->GetType()))) {
00531                 return name_str;
00532             }
00533         }
00534     }
00535     
00536     return "";
00537 }
00538 
00539 void JackDriver::LoadConnections(int alias, bool full_name)
00540 {
00541     list<pair<string, pair<string, string> > >::const_iterator it;
00542     
00543     if (full_name) {
00544         for (it = fConnections.begin(); it != fConnections.end(); it++) {
00545             pair<string, string> connection = (*it).second;
00546             jack_info("Load connection: %s %s", connection.first.c_str(), connection.second.c_str());
00547             fEngine->PortConnect(fClientControl.fRefNum, connection.first.c_str(), connection.second.c_str());
00548         }
00549     } else {
00550         const char** inputs = fGraphManager->GetPorts(NULL, NULL, JackPortIsInput);
00551         const char** outputs = fGraphManager->GetPorts(NULL, NULL, JackPortIsOutput);
00552         
00553         for (it = fConnections.begin(); it != fConnections.end(); it++) {
00554             pair<string, string> connection = (*it).second;
00555             string real_input = MatchPortName(connection.first.c_str(), outputs, alias, (*it).first);
00556             string real_output = MatchPortName(connection.second.c_str(), inputs, alias, (*it).first);
00557             if ((real_input != "") && (real_output != "")) {
00558                 jack_info("Load connection: %s %s", real_input.c_str(), real_output.c_str());
00559                 fEngine->PortConnect(fClientControl.fRefNum, real_input.c_str(), real_output.c_str());
00560             }
00561         }
00562         
00563         // Wait for connection change
00564         if (fGraphManager->IsPendingChange()) {
00565             JackSleep(int(fEngineControl->fPeriodUsecs * 1.1f));
00566         }
00567         
00568         if (inputs) {
00569             free(inputs);
00570         }
00571         if (outputs) {
00572             free(outputs);
00573         }
00574     }
00575 }
00576 
00577 int JackDriver::ResumeRefNum()
00578 {
00579     return fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
00580 }
00581 
00582 int JackDriver::SuspendRefNum()
00583 {
00584     return fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs);
00585 }
00586 
00587 } // end of namespace