00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef WIN32
00022 #pragma warning (disable : 4786)
00023 #endif
00024
00025 #include "JackAudioDriver.h"
00026 #include "JackTime.h"
00027 #include "JackError.h"
00028 #include "JackEngineControl.h"
00029 #include "JackClientControl.h"
00030 #include "JackPort.h"
00031 #include "JackGraphManager.h"
00032 #include "JackEngine.h"
00033 #include <assert.h>
00034
00035 namespace Jack
00036 {
00037
00038 JackAudioDriver::JackAudioDriver(const char* name, JackEngine* engine, JackSynchro** table)
00039 : JackDriver(name, engine, table),
00040 fCaptureChannels(0),
00041 fPlaybackChannels(0),
00042 fWithMonitorPorts(false)
00043 {}
00044
00045 JackAudioDriver::~JackAudioDriver()
00046 {}
00047
00048 int JackAudioDriver::Open(jack_nframes_t nframes,
00049 jack_nframes_t samplerate,
00050 int capturing,
00051 int playing,
00052 int inchannels,
00053 int outchannels,
00054 bool monitor,
00055 const char* capture_driver_name,
00056 const char* playback_driver_name,
00057 jack_nframes_t capture_latency,
00058 jack_nframes_t playback_latency)
00059 {
00060 fCaptureChannels = inchannels;
00061 fPlaybackChannels = outchannels;
00062 fWithMonitorPorts = monitor;
00063 return JackDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency);
00064 }
00065
00066 int JackAudioDriver::Attach()
00067 {
00068 JackPort* port;
00069 jack_port_id_t port_index;
00070 char buf[JACK_PORT_NAME_SIZE];
00071 unsigned long port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
00072 int i;
00073
00074 JackLog("JackAudioDriver::Attach fBufferSize = %ld fSampleRate = %ld\n", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
00075
00076 for (i = 0; i < fCaptureChannels; i++) {
00077 snprintf(buf, sizeof(buf) - 1, "%s:%s:out%d", fClientControl->fName, fCaptureDriverName, i + 1);
00078 if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, (JackPortFlags)port_flags)) == NO_PORT) {
00079 jack_error("driver: cannot register port for %s", buf);
00080 return -1;
00081 }
00082 port = fGraphManager->GetPort(port_index);
00083 port->SetLatency(fEngineControl->fBufferSize + fCaptureLatency);
00084 fCapturePortList[i] = port_index;
00085 JackLog("JackAudioDriver::Attach fCapturePortList[i] %ld = \n", port_index);
00086 }
00087
00088 port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
00089
00090 for (i = 0; i < fPlaybackChannels; i++) {
00091 snprintf(buf, sizeof(buf) - 1, "%s:%s:in%d", fClientControl->fName, fPlaybackDriverName, i + 1);
00092 if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, (JackPortFlags)port_flags)) == NO_PORT) {
00093 jack_error("driver: cannot register port for %s", buf);
00094 return -1;
00095 }
00096 port = fGraphManager->GetPort(port_index);
00097 port->SetLatency(fEngineControl->fBufferSize + fPlaybackLatency);
00098 fPlaybackPortList[i] = port_index;
00099 JackLog("JackAudioDriver::Attach fPlaybackPortList[i] %ld = \n", port_index);
00100
00101
00102 if (fWithMonitorPorts) {
00103 JackLog("Create monitor port \n");
00104 snprintf(buf, sizeof(buf) - 1, "%s:%s:monitor_%u", fClientControl->fName, fPlaybackDriverName, i + 1);
00105 if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, JackPortIsOutput)) == NO_PORT) {
00106 jack_error("Cannot register monitor port for %s", buf);
00107 return -1;
00108 } else {
00109 port = fGraphManager->GetPort(port_index);
00110 port->SetLatency(fEngineControl->fBufferSize);
00111 fMonitorPortList[i] = port_index;
00112 }
00113 }
00114 }
00115
00116 return 0;
00117 }
00118
00119 int JackAudioDriver::Detach()
00120 {
00121 int i;
00122 JackLog("JackAudioDriver::Detach\n");
00123
00124 for (i = 0; i < fCaptureChannels; i++) {
00125 fGraphManager->RemovePort(fClientControl->fRefNum, fCapturePortList[i]);
00126 }
00127
00128 for (i = 0; i < fPlaybackChannels; i++) {
00129 fGraphManager->RemovePort(fClientControl->fRefNum, fPlaybackPortList[i]);
00130 if (fWithMonitorPorts)
00131 fGraphManager->RemovePort(fClientControl->fRefNum, fMonitorPortList[i]);
00132 }
00133
00134 return 0;
00135 }
00136
00137 int JackAudioDriver::Write()
00138 {
00139 for (int i = 0; i < fPlaybackChannels; i++) {
00140 if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
00141 float* buffer = GetOutputBuffer(i);
00142 int size = sizeof(float) * fEngineControl->fBufferSize;
00143
00144 if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0)
00145 memcpy(GetMonitorBuffer(i), buffer, size);
00146 }
00147 }
00148 return 0;
00149 }
00150
00151 int JackAudioDriver::Process()
00152 {
00153 return (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync();
00154 }
00155
00156
00157
00158
00159
00160
00161 int JackAudioDriver::ProcessAsync()
00162 {
00163 if (Read() < 0) {
00164 jack_error("ProcessAsync: read error");
00165 return 0;
00166 }
00167
00168 if (Write() < 0) {
00169 jack_error("ProcessAsync: write error");
00170 return 0;
00171 }
00172
00173 if (fIsMaster) {
00174 fEngine->Process(fLastWaitUst);
00175 fGraphManager->ResumeRefNum(fClientControl, fSynchroTable);
00176 ProcessSlaves();
00177 } else {
00178 fGraphManager->ResumeRefNum(fClientControl, fSynchroTable);
00179 }
00180 return 0;
00181 }
00182
00183
00184
00185
00186
00187
00188 int JackAudioDriver::ProcessSync()
00189 {
00190 if (Read() < 0) {
00191 jack_error("ProcessSync: read error");
00192 return 0;
00193 }
00194
00195 if (fIsMaster) {
00196
00197 if (fEngine->Process(fLastWaitUst)) {
00198 fGraphManager->ResumeRefNum(fClientControl, fSynchroTable);
00199 if (ProcessSlaves() < 0)
00200 jack_error("JackAudioDriver::ProcessSync ProcessSlaves error, engine may now behave abnormally!!");
00201 if (fGraphManager->SuspendRefNum(fClientControl, fSynchroTable, fEngineControl->fTimeOutUsecs) < 0)
00202 jack_error("JackAudioDriver::ProcessSync SuspendRefNum error, engine may now behave abnormally!!");
00203 } else {
00204 jack_error("JackAudioDriver::ProcessSync: error");
00205 }
00206
00207 if (Write() < 0)
00208 jack_error("Process: write error");
00209
00210 } else {
00211 fGraphManager->ResumeRefNum(fClientControl, fSynchroTable);
00212 }
00213 return 0;
00214 }
00215
00216 void JackAudioDriver::NotifyXRun(jack_time_t callback_usecs)
00217 {
00218 fEngine->NotifyXRun(callback_usecs);
00219 }
00220
00221 jack_default_audio_sample_t* JackAudioDriver::GetInputBuffer(int port_index)
00222 {
00223 assert(fCapturePortList[port_index]);
00224 return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[port_index], fEngineControl->fBufferSize);
00225 }
00226
00227 jack_default_audio_sample_t* JackAudioDriver::GetOutputBuffer(int port_index)
00228 {
00229 assert(fPlaybackPortList[port_index]);
00230 return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[port_index], fEngineControl->fBufferSize);
00231 }
00232
00233 jack_default_audio_sample_t* JackAudioDriver::GetMonitorBuffer(int port_index)
00234 {
00235 assert(fPlaybackPortList[port_index]);
00236 return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fMonitorPortList[port_index], fEngineControl->fBufferSize);
00237 }
00238
00239 }