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