Jack2 1.9.7
JackAudioDriver.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 This program is distributed in the hope that it will be useful,
00009 but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 (at your option) any later version.
00012 
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 "JackAudioDriver.h"
00023 #include "JackTime.h"
00024 #include "JackError.h"
00025 #include "JackEngineControl.h"
00026 #include "JackPort.h"
00027 #include "JackGraphManager.h"
00028 #include "JackLockedEngine.h"
00029 #include "JackException.h"
00030 #include <assert.h>
00031 
00032 namespace Jack
00033 {
00034 
00035 JackAudioDriver::JackAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
00036         : JackDriver(name, alias, engine, table),
00037         fCaptureChannels(0),
00038         fPlaybackChannels(0),
00039         fWithMonitorPorts(false)
00040 {}
00041 
00042 JackAudioDriver::~JackAudioDriver()
00043 {}
00044 
00045 int JackAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
00046 {
00047     fEngineControl->fBufferSize = buffer_size;
00048     fGraphManager->SetBufferSize(buffer_size);
00049     fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize);  // in microsec
00050     if (!fEngineControl->fTimeOut)
00051         fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs);
00052     return 0;
00053 }
00054 
00055 int JackAudioDriver::SetSampleRate(jack_nframes_t sample_rate)
00056 {
00057     fEngineControl->fSampleRate = sample_rate;
00058     fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize);  // in microsec
00059     if (!fEngineControl->fTimeOut)
00060         fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs);
00061     return 0;
00062 }
00063 
00064 int JackAudioDriver::Open(jack_nframes_t buffer_size,
00065                           jack_nframes_t samplerate,
00066                           bool capturing,
00067                           bool playing,
00068                           int inchannels,
00069                           int outchannels,
00070                           bool monitor,
00071                           const char* capture_driver_name,
00072                           const char* playback_driver_name,
00073                           jack_nframes_t capture_latency,
00074                           jack_nframes_t playback_latency)
00075 {
00076     fCaptureChannels = inchannels;
00077     fPlaybackChannels = outchannels;
00078     fWithMonitorPorts = monitor;
00079     return JackDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency);
00080 }
00081 
00082 int JackAudioDriver::Open(bool capturing,
00083                           bool playing,
00084                           int inchannels,
00085                           int outchannels,
00086                           bool monitor,
00087                           const char* capture_driver_name,
00088                           const char* playback_driver_name,
00089                           jack_nframes_t capture_latency,
00090                           jack_nframes_t playback_latency)
00091 {
00092     fCaptureChannels = inchannels;
00093     fPlaybackChannels = outchannels;
00094     fWithMonitorPorts = monitor;
00095     return JackDriver::Open(capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency);
00096 }
00097 
00098 int JackAudioDriver::Attach()
00099 {
00100     JackPort* port;
00101     jack_port_id_t port_index;
00102     char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
00103     char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
00104     jack_latency_range_t range;
00105     int i;
00106 
00107     jack_log("JackAudioDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
00108 
00109     for (i = 0; i < fCaptureChannels; i++) {
00110         snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1);
00111         snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1);
00112         if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
00113             jack_error("driver: cannot register port for %s", name);
00114             return -1;
00115         }
00116         port = fGraphManager->GetPort(port_index);
00117         port->SetAlias(alias);
00118         range.min = range.max = fEngineControl->fBufferSize + fCaptureLatency;
00119         port->SetLatencyRange(JackCaptureLatency, &range);
00120         fCapturePortList[i] = port_index;
00121         jack_log("JackAudioDriver::Attach fCapturePortList[i] port_index = %ld", port_index);
00122     }
00123 
00124     for (i = 0; i < fPlaybackChannels; i++) {
00125         snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, i + 1);
00126         snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1);
00127         if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
00128             jack_error("driver: cannot register port for %s", name);
00129             return -1;
00130         }
00131         port = fGraphManager->GetPort(port_index);
00132         port->SetAlias(alias);
00133         // Add more latency if "async" mode is used...
00134         range.min = range.max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + fPlaybackLatency;
00135         port->SetLatencyRange(JackPlaybackLatency, &range);
00136         fPlaybackPortList[i] = port_index;
00137         jack_log("JackAudioDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index);
00138 
00139         // Monitor ports
00140         if (fWithMonitorPorts) {
00141             jack_log("Create monitor port");
00142             snprintf(name, sizeof(name) - 1, "%s:monitor_%u", fClientControl.fName, i + 1);
00143             if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, fEngineControl->fBufferSize)) == NO_PORT) {
00144                 jack_error("Cannot register monitor port for %s", name);
00145                 return -1;
00146             } else {
00147                 port = fGraphManager->GetPort(port_index);
00148                 range.min = range.max = fEngineControl->fBufferSize;
00149                 port->SetLatencyRange(JackCaptureLatency, &range);
00150                 fMonitorPortList[i] = port_index;
00151             }
00152         }
00153     }
00154 
00155     return 0;
00156 }
00157 
00158 int JackAudioDriver::Detach()
00159 {
00160     int i;
00161     jack_log("JackAudioDriver::Detach");
00162 
00163     for (i = 0; i < fCaptureChannels; i++) {
00164         fGraphManager->ReleasePort(fClientControl.fRefNum, fCapturePortList[i]);
00165     }
00166 
00167     for (i = 0; i < fPlaybackChannels; i++) {
00168         fGraphManager->ReleasePort(fClientControl.fRefNum, fPlaybackPortList[i]);
00169         if (fWithMonitorPorts)
00170             fGraphManager->ReleasePort(fClientControl.fRefNum, fMonitorPortList[i]);
00171     }
00172 
00173     return 0;
00174 }
00175 
00176 int JackAudioDriver::Write()
00177 {
00178     for (int i = 0; i < fPlaybackChannels; i++) {
00179         if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
00180             jack_default_audio_sample_t* buffer = GetOutputBuffer(i);
00181             int size = sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize;
00182             // Monitor ports
00183             if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0)
00184                 memcpy(GetMonitorBuffer(i), buffer, size);
00185         }
00186     }
00187     return 0;
00188 }
00189 
00190 int JackAudioDriver::ProcessNull()
00191 {
00192     // Keep begin cycle time
00193     JackDriver::CycleTakeBeginTime();
00194 
00195     if (fEngineControl->fSyncMode) {
00196         ProcessGraphSync();
00197     } else {
00198         ProcessGraphAsync();
00199     }
00200 
00201     // Keep end cycle time
00202     JackDriver::CycleTakeEndTime();
00203     WaitUntilNextCycle();
00204     return 0;
00205 }
00206 
00207 int JackAudioDriver::Process()
00208 {
00209     return (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync();
00210 }
00211 
00212 /*
00213 The driver ASYNC mode: output buffers computed at the *previous cycle* are used, the server does not
00214 synchronize to the end of client graph execution.
00215 */
00216 
00217 int JackAudioDriver::ProcessAsync()
00218 {
00219     // Read input buffers for the current cycle
00220     if (Read() < 0) {
00221         jack_error("JackAudioDriver::ProcessAsync: read error, stopping...");
00222         return -1;
00223     }
00224 
00225     // Write output buffers from the previous cycle
00226     if (Write() < 0) {
00227         jack_error("JackAudioDriver::ProcessAsync: write error, stopping...");
00228         return -1;
00229     }
00230 
00231     // Process graph
00232     if (fIsMaster) {
00233         ProcessGraphAsync();
00234     } else {
00235         fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
00236     }
00237 
00238     // Keep end cycle time
00239     JackDriver::CycleTakeEndTime();
00240     return 0;
00241 }
00242 
00243 /*
00244 The driver SYNC mode: the server does synchronize to the end of client graph execution,
00245 if graph process succeed, output buffers computed at the *current cycle* are used.
00246 */
00247 
00248 int JackAudioDriver::ProcessSync()
00249 {
00250     // Read input buffers for the current cycle
00251     if (Read() < 0) {
00252         jack_error("JackAudioDriver::ProcessSync: read error, stopping...");
00253         return -1;
00254     }
00255 
00256     // Process graph
00257     if (fIsMaster) {
00258         if (ProcessGraphSync() < 0) {
00259             jack_error("JackAudioDriver::ProcessSync: process error, skip cycle...");
00260             goto end;
00261         }
00262     } else {
00263         if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable) < 0) {
00264             jack_error("JackAudioDriver::ProcessSync: process error, skip cycle...");
00265             goto end;
00266         }
00267     }
00268 
00269     // Write output buffers from the current cycle
00270     if (Write() < 0) {
00271         jack_error("JackAudioDriver::ProcessSync: write error, stopping...");
00272         return -1;
00273     }
00274 
00275 end:
00276 
00277     // Keep end cycle time
00278     JackDriver::CycleTakeEndTime();
00279     return 0;
00280 }
00281 
00282 void JackAudioDriver::ProcessGraphAsync()
00283 {
00284     // fBeginDateUst is set in the "low level" layer, fEndDateUst is from previous cycle
00285     if (!fEngine->Process(fBeginDateUst, fEndDateUst))
00286         jack_error("JackAudioDriver::ProcessGraphAsync: Process error");
00287     fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
00288     if (ProcessSlaves() < 0)
00289         jack_error("JackAudioDriver::ProcessGraphAsync: ProcessSlaves error");
00290 }
00291 
00292 int JackAudioDriver::ProcessGraphSync()
00293 {
00294     int res = 0;
00295 
00296     // fBeginDateUst is set in the "low level" layer, fEndDateUst is from previous cycle
00297     if (fEngine->Process(fBeginDateUst, fEndDateUst)) {
00298         fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
00299         if (ProcessSlaves() < 0) {
00300             jack_error("JackAudioDriver::ProcessGraphSync: ProcessSlaves error, engine may now behave abnormally!!");
00301             res = -1;
00302         }
00303         if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs) < 0) {
00304             jack_error("JackAudioDriver::ProcessGraphSync: SuspendRefNum error, engine may now behave abnormally!!");
00305             res = -1;
00306         }
00307     } else { // Graph not finished: do not activate it
00308         jack_error("JackAudioDriver::ProcessGraphSync: Process error");
00309         res = -1;
00310     }
00311 
00312     return res;
00313 }
00314 
00315 int JackAudioDriver::Start()
00316 {
00317     int res = JackDriver::Start();
00318     if ((res >= 0) && fIsMaster) {
00319         res = StartSlaves();
00320     }
00321     return res;
00322 }
00323 
00324 int JackAudioDriver::Stop()
00325 {
00326     int res = JackDriver::Stop();
00327     if (fIsMaster) {
00328         if (StopSlaves() < 0) {
00329             res = -1;
00330         }
00331     }
00332     return res;
00333 }
00334 
00335 void JackAudioDriver::WaitUntilNextCycle()
00336 {
00337     int wait_time_usec = (int((float(fEngineControl->fBufferSize) / (float(fEngineControl->fSampleRate))) * 1000000.0f));
00338     wait_time_usec = int(wait_time_usec - (GetMicroSeconds() - fBeginDateUst));
00339         if (wait_time_usec > 0)
00340                 JackSleep(wait_time_usec);
00341 }
00342 
00343 jack_default_audio_sample_t* JackAudioDriver::GetInputBuffer(int port_index)
00344 {
00345     assert(fCapturePortList[port_index]);
00346     return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[port_index], fEngineControl->fBufferSize);
00347 }
00348 
00349 jack_default_audio_sample_t* JackAudioDriver::GetOutputBuffer(int port_index)
00350 {
00351     assert(fPlaybackPortList[port_index]);
00352     return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[port_index], fEngineControl->fBufferSize);
00353 }
00354 
00355 jack_default_audio_sample_t* JackAudioDriver::GetMonitorBuffer(int port_index)
00356 {
00357     assert(fPlaybackPortList[port_index]);
00358     return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fMonitorPortList[port_index], fEngineControl->fBufferSize);
00359 }
00360 
00361 int JackAudioDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
00362 {
00363     switch (notify) {
00364 
00365         case kLatencyCallback:
00366             HandleLatencyCallback(value1);
00367             break;
00368 
00369         default:
00370             JackDriver::ClientNotify(refnum, name, notify, sync, message, value1, value2);
00371             break;
00372     }
00373 
00374     return 0;
00375 }
00376 
00377 void JackAudioDriver::HandleLatencyCallback(int status)
00378 {
00379     jack_latency_callback_mode_t mode = (status == 0) ? JackCaptureLatency : JackPlaybackLatency;
00380 
00381     for (int i = 0; i < fCaptureChannels; i++) {
00382         if (mode == JackPlaybackLatency) {
00383            fGraphManager->RecalculateLatency(fCapturePortList[i], mode);
00384                 }
00385         }
00386 
00387     for (int i = 0; i < fPlaybackChannels; i++) {
00388         if (mode == JackCaptureLatency) {
00389             fGraphManager->RecalculateLatency(fPlaybackPortList[i], mode);
00390                 }
00391         }
00392 }
00393 
00394 } // end of namespace