1 /*
2 Copyright (C) 2005-2007 Remon Sijrier
3
4 This file is part of Traverso
5
6 Traverso is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
20 $Id: JackDriver.cpp,v 1.24 2007/12/07 13:21:49 r_sijrier Exp $
21 */
22
23 #include "JackDriver.h"
24
25 #include <jack/jack.h>
26
27 #if defined (ALSA_SUPPORT)
28 #include "AlsaDriver.h"
29 #endif
30
31 #include "AudioDevice.h"
32 #include "AudioChannel.h"
33
34 // Always put me below _all_ includes, this is needed
35 // in case we run with memory leak detection enabled!
36 #include "Debugger.h"
37
JackDriver(AudioDevice * dev,int rate,nframes_t bufferSize)38 JackDriver::JackDriver( AudioDevice * dev , int rate, nframes_t bufferSize)
39 : Driver(dev, rate, bufferSize)
40 {
41 read = MakeDelegate(this, &JackDriver::_read);
42 write = MakeDelegate(this, &JackDriver::_write);
43 run_cycle = RunCycleCallback(this, &JackDriver::_run_cycle);
44 m_running = false;
45 }
46
~JackDriver()47 JackDriver::~JackDriver( )
48 {
49 PENTER;
50 if (m_running == 0) {
51 jack_client_close (client);
52 }
53 }
54
_read(nframes_t nframes)55 int JackDriver::_read( nframes_t nframes )
56 {
57 int portNumber = 0;
58 for (int i=0; i<captureChannels.size(); ++i) {
59 AudioChannel* chan = captureChannels.at(i);
60 if (!chan->has_data()) {
61 portNumber++;
62 continue;
63 }
64 memcpy (chan->get_data(), jack_port_get_buffer (inputPorts[portNumber], nframes), sizeof (jack_default_audio_sample_t) * nframes);
65 portNumber++;
66 }
67 return 1;
68 }
69
_write(nframes_t nframes)70 int JackDriver::_write( nframes_t nframes )
71 {
72 int portNumber = 0;
73 for (int i=0; i<playbackChannels.size(); ++i) {
74 AudioChannel* chan = playbackChannels.at(i);
75
76 /* if (!chan->has_data()) {
77 portNumber++;
78 continue;
79 }*/
80 memcpy ( jack_port_get_buffer (outputPorts[portNumber], nframes), chan->get_data(), sizeof (jack_default_audio_sample_t) * nframes);
81 chan->silence_buffer(nframes);
82 portNumber++;
83 }
84 return 1;
85 }
86
setup(bool capture,bool playback,const QString &)87 int JackDriver::setup(bool capture, bool playback, const QString& )
88 {
89 PENTER;
90
91 Q_UNUSED(capture);
92 Q_UNUSED(playback);
93
94 const char **inputports;
95 const char **outputports;
96 const char *client_name = "Traverso";
97 // const char *server_name = NULL;
98 int inputPortCount = 0;
99 int outputPortCount = 0;
100 client = 0;
101 AudioChannel* channel;
102 char buf[32];
103 int port_flags;
104 capture_frame_latency = playback_frame_latency =0;
105
106
107 printf("Connecting to the Jack server...\n");
108
109 if ( (client = jack_client_new (client_name)) == NULL) {
110 device->message(tr("Jack Driver: Couldn't connect to the jack server, is jack running?"), AudioDevice::WARNING);
111 return -1;
112 }
113
114
115 /*********** INPUT PORTS STUFF *************/
116 /******************************************/
117
118 //Get all the input ports of Jack
119 if ((inputports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == 0) {
120 inputPorts = 0;
121 }
122
123 if (inputports) {
124 for (inputPortCount = 0; inputports[inputPortCount]; ++inputPortCount)
125 ;
126 free (inputports);
127 }
128
129
130 inputPorts = (jack_port_t **) malloc (sizeof (jack_port_t *) * inputPortCount);
131
132 for (int i = 0; i < inputPortCount; i++) {
133 char name[64];
134
135 sprintf (name, "input_%d", i+1);
136
137 if ((inputPorts[i] = jack_port_register (client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)) == 0) {
138 fprintf (stderr, "cannot register input port \"%s\"!\n", name);
139 jack_client_close (client);
140 return -1;
141 }
142 }
143
144
145 /*********** OUTPUT PORTS STUFF *************/
146 /******************************************/
147
148 //Get all the input ports of Jack
149 if ((outputports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput)) == 0) {
150 outputPorts = 0;
151 }
152
153 if (outputports) {
154 for (outputPortCount = 0; outputports[outputPortCount]; ++outputPortCount)
155 ;
156 free (outputports);
157 }
158
159
160 outputPorts = (jack_port_t **) malloc (sizeof (jack_port_t *) * outputPortCount);
161
162 for (int i = 0; i < outputPortCount; i++) {
163 char name[64];
164
165 sprintf (name, "output_%d", i+1);
166
167 if ((outputPorts[i] = jack_port_register (client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) == 0) {
168 fprintf (stderr, "cannot register output port \"%s\"!\n", name);
169 jack_client_close (client);
170 return -1;
171 }
172 }
173
174
175 port_flags = PortIsInput|PortIsPhysical|PortIsTerminal;
176 for (int chn = 0; chn < inputPortCount; chn++) {
177
178 snprintf (buf, sizeof(buf) - 1, "capture_%d", chn+1);
179
180 channel = device->register_capture_channel(buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, frames_per_cycle, chn);
181 channel->set_latency( frames_per_cycle + capture_frame_latency );
182 captureChannels.append(channel);
183 }
184
185
186 port_flags = PortIsOutput|PortIsPhysical|PortIsTerminal;
187 for (int chn = 0; chn < outputPortCount; chn++) {
188
189 snprintf (buf, sizeof(buf) - 1, "playback_%d", chn+1);
190
191 channel = device->register_playback_channel(buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, frames_per_cycle, chn);
192 channel->set_latency( frames_per_cycle + capture_frame_latency );
193 playbackChannels.append(channel);
194 }
195
196
197 device->set_buffer_size( jack_get_buffer_size(client) );
198 device->set_sample_rate (jack_get_sample_rate(client));
199
200 jack_set_process_callback (client, _process_callback, this);
201 jack_set_xrun_callback (client, _xrun_callback, this);
202 jack_set_buffer_size_callback (client, _bufsize_callback, this);
203 jack_on_shutdown(client, _on_jack_shutdown_callback, this);
204
205 update_config();
206
207 device->message(tr("Jack Driver: Connected successfully to the jack server!"), AudioDevice::INFO);
208
209 return 1;
210 }
211
attach()212 int JackDriver::attach( )
213 {
214 PENTER;
215 return 1;
216 }
217
start()218 int JackDriver::start( )
219 {
220 PENTER;
221 if (jack_activate (client)) {
222 //if jack_active() != 0, something went wrong!
223 return -1;
224 }
225
226 m_running = 1;
227 return 1;
228 }
229
stop()230 int JackDriver::stop( )
231 {
232 PENTER;
233 m_running = 0;
234 return 1;
235 }
236
process_callback(nframes_t nframes)237 int JackDriver::process_callback (nframes_t nframes)
238 {
239 jack_position_t pos;
240 jack_transport_state_t state = jack_transport_query (client, &pos);
241
242 transport_state_t tranportstate;
243 tranportstate.tranport = state;
244 tranportstate.location = TimeRef(pos.frame, audiodevice().get_sample_rate());
245 tranportstate.realtime = true;
246
247 device->transport_control(tranportstate);
248
249 device->run_cycle( nframes, 0.0);
250 return 0;
251 }
252
jack_sync_callback(jack_transport_state_t state,jack_position_t * pos)253 int JackDriver::jack_sync_callback (jack_transport_state_t state, jack_position_t* pos)
254 {
255 transport_state_t tranportstate;
256 tranportstate.tranport = state;
257 tranportstate.location = TimeRef(pos->frame, audiodevice().get_sample_rate());
258 tranportstate.isSlave = true;
259 tranportstate.realtime = true;
260
261 return device->transport_control(tranportstate);
262 }
263
264
265 // Is there a way to get the device name from Jack? Can't find it :-(
266 // Since Jack uses ALSA, we ask it from ALSA directly :-)
get_device_name()267 QString JackDriver::get_device_name( )
268 {
269 #if defined (ALSA_SUPPORT)
270 return AlsaDriver::alsa_device_name(false);
271 #endif
272 return "AudioDevice";
273 }
274
get_device_longname()275 QString JackDriver::get_device_longname( )
276 {
277 #if defined (ALSA_SUPPORT)
278 return AlsaDriver::alsa_device_name(true);
279 #endif
280 return "AudioDevice";
281 }
282
_xrun_callback(void * arg)283 int JackDriver::_xrun_callback( void * arg )
284 {
285 JackDriver* driver = static_cast<JackDriver *> (arg);
286 if (driver->m_running) {
287 driver->device->xrun();
288 }
289 return 0;
290 }
291
_process_callback(nframes_t nframes,void * arg)292 int JackDriver::_process_callback (nframes_t nframes, void *arg)
293 {
294 JackDriver* driver = static_cast<JackDriver *> (arg);
295 if (!driver->m_running) {
296 return 0;
297 }
298
299 return driver->process_callback (nframes);
300 }
301
_bufsize_callback(nframes_t nframes,void * arg)302 int JackDriver::_bufsize_callback( nframes_t nframes, void * arg )
303 {
304 JackDriver* driver = static_cast<JackDriver *> (arg);
305 driver->device->set_buffer_size( nframes );
306
307 emit driver->device->driverParamsChanged();
308 return 0;
309 }
310
get_cpu_load()311 float JackDriver::get_cpu_load( )
312 {
313 return jack_cpu_load(client);
314 }
315
_on_jack_shutdown_callback(void * arg)316 void JackDriver::_on_jack_shutdown_callback( void * arg )
317 {
318 JackDriver* driver = static_cast<JackDriver *> (arg);
319 driver->m_running = -1;
320 }
321
_jack_sync_callback(jack_transport_state_t state,jack_position_t * pos,void * arg)322 int JackDriver::_jack_sync_callback (jack_transport_state_t state, jack_position_t* pos, void* arg)
323 {
324 return static_cast<JackDriver*> (arg)->jack_sync_callback (state, pos);
325 }
326
update_config()327 void JackDriver::update_config()
328 {
329 m_isSlave = device->get_driver_property("jackslave", false).toBool();
330
331 if (m_isSlave) {
332 jack_set_sync_callback (client, _jack_sync_callback, this);
333 } else {
334 jack_set_sync_callback(client, NULL, this);
335 }
336 }
337
338 //eof
339
340