JackDriver.cpp

00001 /*
00002 Copyright (C) 2001 Paul Davis 
00003 Copyright (C) 2004-2006 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 #ifdef WIN32 
00022 #pragma warning (disable : 4786)
00023 #endif
00024 
00025 #include "JackDriver.h"
00026 #include "JackTime.h"
00027 #include "JackError.h"
00028 #include "JackPort.h"
00029 #include "JackGraphManager.h"
00030 #include "JackGlobals.h"
00031 #include "JackEngineControl.h"
00032 #include "JackClientControl.h"
00033 #include "JackEngine.h"
00034 #include <math.h>
00035 #include <assert.h>
00036 
00037 using namespace std;
00038 
00039 namespace Jack
00040 {
00041 
00042 JackDriver::JackDriver(const char* name, JackEngine* engine, JackSynchro** table)
00043 {
00044     assert(strlen(name) < JACK_CLIENT_NAME_SIZE);
00045     fSynchroTable = table;
00046     fClientControl = new JackClientControl(name);
00047     fEngine = engine;
00048     fGraphManager = NULL;
00049     fLastWaitUst = 0;
00050     fIsMaster = true;
00051 }
00052 
00053 JackDriver::JackDriver()
00054 {
00055     fSynchroTable = NULL;
00056     fClientControl = NULL;
00057     fEngine = NULL;
00058     fGraphManager = NULL;
00059     fLastWaitUst = 0;
00060     fIsMaster = true;
00061 }
00062 
00063 JackDriver::~JackDriver()
00064 {
00065     JackLog("~JackDriver\n");
00066     delete fClientControl;
00067 }
00068 
00069 int JackDriver::Open()
00070 {
00071     int refnum = -1;
00072 
00073     if (fEngine->ClientCheckName(fClientControl->fName)) {
00074         jack_error("client %s already registered", fClientControl->fName);
00075         return -1;
00076     }
00077 
00078     if (fEngine->ClientInternalNew(fClientControl->fName, &refnum, &fEngineControl, &fGraphManager, this) != 0) {
00079         jack_error("Cannot allocate internal client for audio driver");
00080         return -1;
00081     }
00082 
00083     fClientControl->fRefNum = refnum;
00084     fClientControl->fActive = true;
00085     fGraphManager->DirectConnect(fClientControl->fRefNum, fClientControl->fRefNum); // Connect driver to itself for sync
00086 
00087     /*
00088         In ASYNC mode, the server does not synchronize itself on the output drivers, thus it would never "consume" the activations.
00089         The synchronization primitives for drivers are setup in "flush" mode that to not keep unneeded activations.
00090     */
00091     if (!fEngineControl->fSyncMode) {
00092         fSynchroTable[AUDIO_DRIVER_REFNUM]->SetFlush(true);
00093         fSynchroTable[FREEWHEEL_DRIVER_REFNUM]->SetFlush(true);
00094         fSynchroTable[LOOPBACK_DRIVER_REFNUM]->SetFlush(true);
00095     }
00096     return 0;
00097 }
00098 
00099 int JackDriver::Open(jack_nframes_t nframes,
00100                      jack_nframes_t samplerate,
00101                      int capturing,
00102                      int playing,
00103                      int inchannels,
00104                      int outchannels,
00105                      bool monitor,
00106                      const char* capture_driver_name,
00107                      const char* playback_driver_name,
00108                      jack_nframes_t capture_latency,
00109                      jack_nframes_t playback_latency)
00110 {
00111     JackLog("JackDriver::Open capture_driver_name = %s\n", capture_driver_name);
00112     JackLog("JackDriver::Open playback_driver_name = %s\n", playback_driver_name);
00113     int refnum = -1;
00114 
00115     if (fEngine->ClientCheckName(fClientControl->fName)) {
00116         jack_error("client %s already registered", fClientControl->fName);
00117         return -1;
00118     }
00119 
00120     if (fEngine->ClientInternalNew(fClientControl->fName, &refnum, &fEngineControl, &fGraphManager, this) != 0) {
00121         jack_error("Cannot allocate internal client for audio driver");
00122         return -1;
00123     }
00124 
00125     fClientControl->fRefNum = refnum;
00126     fClientControl->fActive = true;
00127     fEngineControl->fBufferSize = nframes;
00128     fEngineControl->fSampleRate = samplerate;
00129     fCaptureLatency = capture_latency;
00130     fPlaybackLatency = playback_latency;
00131 
00132     assert(strlen(capture_driver_name) < JACK_CLIENT_NAME_SIZE);
00133     assert(strlen(playback_driver_name) < JACK_CLIENT_NAME_SIZE);
00134 
00135     strcpy(fCaptureDriverName, capture_driver_name);
00136     strcpy(fPlaybackDriverName, playback_driver_name);
00137 
00138     fEngineControl->fPeriodUsecs = (jack_time_t)floor((((float)nframes) / (float)samplerate) * 1000000.0f);
00139     if (fEngineControl->fTimeOutUsecs == 0)  /* usecs; if zero, use 10 period size. */
00140         fEngineControl->fTimeOutUsecs = (jack_time_t)(2.f * fEngineControl->fPeriodUsecs);
00141 
00142     fGraphManager->DirectConnect(fClientControl->fRefNum, fClientControl->fRefNum); // Connect driver to itself for sync
00143 
00144     /*
00145         In ASYNC mode, the server does not synchronize itself on the output drivers, thus it would never "consume" the activations.
00146         The synchronization primitives for drivers are setup in "flush" mode that to not keep unneeded activations.
00147     */
00148     if (!fEngineControl->fSyncMode) {
00149         fSynchroTable[AUDIO_DRIVER_REFNUM]->SetFlush(true);
00150         fSynchroTable[FREEWHEEL_DRIVER_REFNUM]->SetFlush(true);
00151         fSynchroTable[LOOPBACK_DRIVER_REFNUM]->SetFlush(true);
00152     }
00153     return 0;
00154 }
00155 
00156 int JackDriver::Close()
00157 {
00158     JackLog("JackDriver::Close\n");
00159     fGraphManager->DirectDisconnect(fClientControl->fRefNum, fClientControl->fRefNum); // Disconnect driver from itself for sync
00160     fClientControl->fActive = false;
00161     return fEngine->ClientInternalCloseIm(fClientControl->fRefNum);
00162 }
00163 
00164 bool JackDriver::IsRealTime()
00165 {
00166     return fEngineControl->fRealTime;
00167 }
00168 
00169 JackClientControl* JackDriver::GetClientControl() const
00170 {
00171     return fClientControl;
00172 }
00173 
00174 void JackDriver::NotifyXRun(jack_time_t callback_usecs)
00175 {
00176     fEngine->NotifyXRun(callback_usecs);
00177 }
00178 
00179 void JackDriverClient::SetMaster(bool onoff)
00180 {
00181     fIsMaster = onoff;
00182 }
00183 
00184 bool JackDriverClient::GetMaster()
00185 {
00186     return fIsMaster;
00187 }
00188 
00189 void JackDriverClient::AddSlave(JackDriverInterface* slave)
00190 {
00191     fSlaveList.push_back(slave);
00192 }
00193 
00194 void JackDriverClient::RemoveSlave(JackDriverInterface* slave)
00195 {
00196     fSlaveList.remove(slave);
00197 }
00198 
00199 int JackDriverClient::ProcessSlaves()
00200 {
00201         int res = 0;
00202     list<JackDriverInterface*>::const_iterator it;
00203     for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
00204         JackDriverInterface* slave = *it;
00205         if (slave->Process() < 0)
00206                         res = -1;
00207     }
00208         return res;
00209 }
00210 
00211 } // end of namespace

Generated on Wed Jan 10 11:42:44 2007 for Jackdmp by  doxygen 1.4.5