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.
22 #pragma warning (disable : 4786)
25 #include "JackAudioDriver.h"
27 #include "JackError.h"
28 #include "JackEngineControl.h"
29 #include "JackClientControl.h"
31 #include "JackGraphManager.h"
32 #include "JackEngine.h"
38 JackAudioDriver::JackAudioDriver(const char* name
, JackEngine
* engine
, JackSynchro
** table
)
39 : JackDriver(name
, engine
, table
),
42 fWithMonitorPorts(false)
45 JackAudioDriver::~JackAudioDriver()
48 int JackAudioDriver::Open(jack_nframes_t nframes
,
49 jack_nframes_t samplerate
,
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()
69 jack_port_id_t port_index
;
70 char buf
[JACK_PORT_NAME_SIZE
];
71 unsigned long port_flags
= JackPortIsOutput
| JackPortIsPhysical
| JackPortIsTerminal
;
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
);
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
);
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
);
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
);
109 port
= fGraphManager
->GetPort(port_index
);
110 port
->SetLatency(fEngineControl
->fBufferSize
);
111 fMonitorPortList
[i
] = port_index
;
119 int JackAudioDriver::Detach()
122 JackLog("JackAudioDriver::Detach\n");
124 for (i
= 0; i
< fCaptureChannels
; i
++) {
125 fGraphManager
->ReleasePort(fClientControl
->fRefNum
, fCapturePortList
[i
]);
128 for (i
= 0; i
< fPlaybackChannels
; i
++) {
129 fGraphManager
->ReleasePort(fClientControl
->fRefNum
, fPlaybackPortList
[i
]);
130 if (fWithMonitorPorts
)
131 fGraphManager
->ReleasePort(fClientControl
->fRefNum
, fMonitorPortList
[i
]);
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
;
144 if (fWithMonitorPorts
&& fGraphManager
->GetConnectionsNum(fMonitorPortList
[i
]) > 0)
145 memcpy(GetMonitorBuffer(i
), buffer
, size
);
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");
168 if (Write() < 0) { // Write output buffers from the previous cycle
169 jack_error("ProcessAsync: write error");
174 fEngine
->Process(fLastWaitUst
); // fLastWaitUst is set in the "low level" layer
175 fGraphManager
->ResumeRefNum(fClientControl
, fSynchroTable
);
178 fGraphManager
->ResumeRefNum(fClientControl
, fSynchroTable
);
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");
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");
211 fGraphManager
->ResumeRefNum(fClientControl
, fSynchroTable
);
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