Cleanup
[jack2.git] / common / JackAudioDriver.cpp
blobc64b5cbbe3f27c1f58ceaf89a1cadf2aad20aabf
1 /*
2 Copyright (C) 2001 Paul Davis
3 Copyright (C) 2004-2006 Grame
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #ifdef WIN32
22 #pragma warning (disable : 4786)
23 #endif
25 #include "JackAudioDriver.h"
26 #include "JackTime.h"
27 #include "JackError.h"
28 #include "JackEngineControl.h"
29 #include "JackClientControl.h"
30 #include "JackPort.h"
31 #include "JackGraphManager.h"
32 #include "JackEngine.h"
33 #include <assert.h>
35 namespace Jack
38 JackAudioDriver::JackAudioDriver(const char* name, JackEngine* engine, JackSynchro** table)
39 : JackDriver(name, engine, table),
40 fCaptureChannels(0),
41 fPlaybackChannels(0),
42 fWithMonitorPorts(false)
45 JackAudioDriver::~JackAudioDriver()
48 int JackAudioDriver::Open(jack_nframes_t nframes,
49 jack_nframes_t samplerate,
50 int capturing,
51 int playing,
52 int inchannels,
53 int outchannels,
54 bool monitor,
55 const char* capture_driver_name,
56 const char* playback_driver_name,
57 jack_nframes_t capture_latency,
58 jack_nframes_t playback_latency)
60 fCaptureChannels = inchannels;
61 fPlaybackChannels = outchannels;
62 fWithMonitorPorts = monitor;
63 return JackDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency);
66 int JackAudioDriver::Attach()
68 JackPort* port;
69 jack_port_id_t port_index;
70 char buf[JACK_PORT_NAME_SIZE];
71 unsigned long port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
72 int i;
74 JackLog("JackAudioDriver::Attach fBufferSize = %ld fSampleRate = %ld\n", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
76 for (i = 0; i < fCaptureChannels; i++) {
77 snprintf(buf, sizeof(buf) - 1, "%s:%s:out%d", fClientControl->fName, fCaptureDriverName, i + 1);
78 if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, (JackPortFlags)port_flags)) == NO_PORT) {
79 jack_error("driver: cannot register port for %s", buf);
80 return -1;
82 port = fGraphManager->GetPort(port_index);
83 port->SetLatency(fEngineControl->fBufferSize + fCaptureLatency);
84 fCapturePortList[i] = port_index;
85 JackLog("JackAudioDriver::Attach fCapturePortList[i] %ld = \n", port_index);
88 port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
90 for (i = 0; i < fPlaybackChannels; i++) {
91 snprintf(buf, sizeof(buf) - 1, "%s:%s:in%d", fClientControl->fName, fPlaybackDriverName, i + 1);
92 if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, (JackPortFlags)port_flags)) == NO_PORT) {
93 jack_error("driver: cannot register port for %s", buf);
94 return -1;
96 port = fGraphManager->GetPort(port_index);
97 port->SetLatency(fEngineControl->fBufferSize + fPlaybackLatency);
98 fPlaybackPortList[i] = port_index;
99 JackLog("JackAudioDriver::Attach fPlaybackPortList[i] %ld = \n", port_index);
101 // Monitor ports
102 if (fWithMonitorPorts) {
103 JackLog("Create monitor port \n");
104 snprintf(buf, sizeof(buf) - 1, "%s:%s:monitor_%u", fClientControl->fName, fPlaybackDriverName, i + 1);
105 if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, JackPortIsOutput)) == NO_PORT) {
106 jack_error("Cannot register monitor port for %s", buf);
107 return -1;
108 } else {
109 port = fGraphManager->GetPort(port_index);
110 port->SetLatency(fEngineControl->fBufferSize);
111 fMonitorPortList[i] = port_index;
116 return 0;
119 int JackAudioDriver::Detach()
121 int i;
122 JackLog("JackAudioDriver::Detach\n");
124 for (i = 0; i < fCaptureChannels; i++) {
125 fGraphManager->RemovePort(fClientControl->fRefNum, fCapturePortList[i]);
128 for (i = 0; i < fPlaybackChannels; i++) {
129 fGraphManager->RemovePort(fClientControl->fRefNum, fPlaybackPortList[i]);
130 if (fWithMonitorPorts)
131 fGraphManager->RemovePort(fClientControl->fRefNum, fMonitorPortList[i]);
134 return 0;
137 int JackAudioDriver::Write()
139 for (int i = 0; i < fPlaybackChannels; i++) {
140 if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
141 float* buffer = GetOutputBuffer(i);
142 int size = sizeof(float) * fEngineControl->fBufferSize;
143 // Monitor ports
144 if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0)
145 memcpy(GetMonitorBuffer(i), buffer, size);
148 return 0;
151 int JackAudioDriver::Process()
153 return (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync();
157 The driver ASYNC mode: output buffers computed at the *previous cycle* are used, the server does not
158 synchronize to the end of client graph execution.
161 int JackAudioDriver::ProcessAsync()
163 if (Read() < 0) { // Read input buffers for the current cycle
164 jack_error("ProcessAsync: read error");
165 return 0;
168 if (Write() < 0) { // Write output buffers from the previous cycle
169 jack_error("ProcessAsync: write error");
170 return 0;
173 if (fIsMaster) {
174 fEngine->Process(fLastWaitUst); // fLastWaitUst is set in the "low level" layer
175 fGraphManager->ResumeRefNum(fClientControl, fSynchroTable);
176 ProcessSlaves();
177 } else {
178 fGraphManager->ResumeRefNum(fClientControl, fSynchroTable);
180 return 0;
184 The driver SYNC mode: the server does synchronize to the end of client graph execution,
185 output buffers computed at the *current cycle* are used.
188 int JackAudioDriver::ProcessSync()
190 if (Read() < 0) { // Read input buffers for the current cycle
191 jack_error("ProcessSync: read error");
192 return 0;
195 if (fIsMaster) {
197 if (fEngine->Process(fLastWaitUst)) { // fLastWaitUst is set in the "low level" layer
198 fGraphManager->ResumeRefNum(fClientControl, fSynchroTable);
199 if (ProcessSlaves() < 0)
200 jack_error("JackAudioDriver::ProcessSync ProcessSlaves error, engine may now behave abnormally!!");
201 if (fGraphManager->SuspendRefNum(fClientControl, fSynchroTable, fEngineControl->fTimeOutUsecs) < 0)
202 jack_error("JackAudioDriver::ProcessSync SuspendRefNum error, engine may now behave abnormally!!");
203 } else { // Graph not finished: do not activate it
204 jack_error("JackAudioDriver::ProcessSync: error");
207 if (Write() < 0) // Write output buffers for the current cycle
208 jack_error("Process: write error");
210 } else {
211 fGraphManager->ResumeRefNum(fClientControl, fSynchroTable);
213 return 0;
216 void JackAudioDriver::NotifyXRun(jack_time_t callback_usecs)
218 fEngine->NotifyXRun(callback_usecs);
221 jack_default_audio_sample_t* JackAudioDriver::GetInputBuffer(int port_index)
223 assert(fCapturePortList[port_index]);
224 return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[port_index], fEngineControl->fBufferSize);
227 jack_default_audio_sample_t* JackAudioDriver::GetOutputBuffer(int port_index)
229 assert(fPlaybackPortList[port_index]);
230 return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[port_index], fEngineControl->fBufferSize);
233 jack_default_audio_sample_t* JackAudioDriver::GetMonitorBuffer(int port_index)
235 assert(fPlaybackPortList[port_index]);
236 return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fMonitorPortList[port_index], fEngineControl->fBufferSize);
239 } // end of namespace