Jack2  1.9.8
JackFFADODriver.cpp
1 /*
2 Copyright (C) 2001 Paul Davis
3 Copyright (C) 2004 Grame
4 Copyright (C) 2007 Pieter Palmers
5 Copyright (C) 2009 Devin Anderson
6 
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 #include <iostream>
24 #include <unistd.h>
25 #include <math.h>
26 #include <stdio.h>
27 #include <memory.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <stdarg.h>
32 #include <signal.h>
33 #include <sys/types.h>
34 #include <sys/time.h>
35 #include <regex.h>
36 #include <string.h>
37 
38 #include "JackFFADODriver.h"
39 #include "JackFFADOMidiInputPort.h"
40 #include "JackFFADOMidiOutputPort.h"
41 #include "JackEngineControl.h"
42 #include "JackClientControl.h"
43 #include "JackPort.h"
44 #include "JackGraphManager.h"
45 #include "JackCompilerDeps.h"
46 #include "JackLockedEngine.h"
47 
48 namespace Jack
49 {
50 
51 #define FIREWIRE_REQUIRED_FFADO_API_VERSION 8
52 
53 #define jack_get_microseconds GetMicroSeconds
54 
55 int
56 JackFFADODriver::ffado_driver_read (ffado_driver_t * driver, jack_nframes_t nframes)
57 {
58  channel_t chn;
59  jack_default_audio_sample_t* buf = NULL;
60 
61  printEnter();
62  for (chn = 0; chn < driver->capture_nchannels; chn++) {
63  // if nothing connected, don't process
64  if (fGraphManager->GetConnectionsNum(fCapturePortList[chn]) == 0) {
65  buf = (jack_default_audio_sample_t*)driver->scratchbuffer;
66  // we always have to specify a valid buffer
67  ffado_streaming_set_capture_stream_buffer(driver->dev, chn, (char *)(buf));
68  // notify the streaming system that it can (but doesn't have to) skip
69  // this channel
70  ffado_streaming_capture_stream_onoff(driver->dev, chn, 0);
71  } else {
72  if (driver->capture_channels[chn].stream_type == ffado_stream_type_audio) {
73  buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[chn], nframes);
74 
75  /* if the returned buffer is invalid, use the dummy buffer */
76  if (!buf) buf = (jack_default_audio_sample_t*)driver->scratchbuffer;
77 
78  ffado_streaming_set_capture_stream_buffer(driver->dev, chn, (char *)(buf));
79  ffado_streaming_capture_stream_onoff(driver->dev, chn, 1);
80  } else if (driver->capture_channels[chn].stream_type == ffado_stream_type_midi) {
81  ffado_streaming_set_capture_stream_buffer(driver->dev, chn,
82  (char *)(driver->capture_channels[chn].midi_buffer));
83  ffado_streaming_capture_stream_onoff(driver->dev, chn, 1);
84  } else { // always have a valid buffer
85  ffado_streaming_set_capture_stream_buffer(driver->dev, chn, (char *)(driver->scratchbuffer));
86  // don't process what we don't use
87  ffado_streaming_capture_stream_onoff(driver->dev, chn, 0);
88  }
89  }
90  }
91 
92  /* now transfer the buffers */
93  ffado_streaming_transfer_capture_buffers(driver->dev);
94 
95  /* process the midi data */
96  for (chn = 0; chn < driver->capture_nchannels; chn++) {
97  if (driver->capture_channels[chn].stream_type == ffado_stream_type_midi) {
98  JackFFADOMidiInputPort *midi_input = (JackFFADOMidiInputPort *) driver->capture_channels[chn].midi_input;
99  JackMidiBuffer *buffer = (JackMidiBuffer *) fGraphManager->GetBuffer(fCapturePortList[chn], nframes);
100  midi_input->Process(buffer, driver->capture_channels[chn].midi_buffer, nframes);
101  }
102  }
103 
104  printExit();
105  return 0;
106 }
107 
108 int
109 JackFFADODriver::ffado_driver_write (ffado_driver_t * driver, jack_nframes_t nframes)
110 {
111  channel_t chn;
112  jack_default_audio_sample_t* buf;
113  printEnter();
114 
115  driver->process_count++;
116 
117  for (chn = 0; chn < driver->playback_nchannels; chn++) {
118  if (fGraphManager->GetConnectionsNum(fPlaybackPortList[chn]) == 0) {
119  buf = (jack_default_audio_sample_t*)driver->nullbuffer;
120  // we always have to specify a valid buffer
121  ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(buf));
122  // notify the streaming system that it can (but doesn't have to) skip
123  // this channel
124  ffado_streaming_playback_stream_onoff(driver->dev, chn, 0);
125  } else {
126  if (driver->playback_channels[chn].stream_type == ffado_stream_type_audio) {
127  buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[chn], nframes);
128  /* use the silent buffer if there is no valid jack buffer */
129  if (!buf) buf = (jack_default_audio_sample_t*)driver->nullbuffer;
130  ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(buf));
131  ffado_streaming_playback_stream_onoff(driver->dev, chn, 1);
132  } else if (driver->playback_channels[chn].stream_type == ffado_stream_type_midi) {
133  uint32_t *midi_buffer = driver->playback_channels[chn].midi_buffer;
134  memset(midi_buffer, 0, nframes * sizeof(uint32_t));
135  buf = (jack_default_audio_sample_t *) fGraphManager->GetBuffer(fPlaybackPortList[chn], nframes);
136  ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(midi_buffer));
137  ffado_streaming_playback_stream_onoff(driver->dev, chn, buf ? 1 : 0);
138  JackFFADOMidiOutputPort *midi_output = (JackFFADOMidiOutputPort *) driver->playback_channels[chn].midi_output;
139  midi_output->Process((JackMidiBuffer *) buf, midi_buffer, nframes);
140 
141  } else { // always have a valid buffer
142  ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(driver->nullbuffer));
143  ffado_streaming_playback_stream_onoff(driver->dev, chn, 0);
144  }
145  }
146  }
147  ffado_streaming_transfer_playback_buffers(driver->dev);
148  printExit();
149  return 0;
150 }
151 
152 jack_nframes_t
153 JackFFADODriver::ffado_driver_wait (ffado_driver_t *driver, int extra_fd, int *status,
154  float *delayed_usecs)
155 {
156  jack_time_t wait_enter;
157  jack_time_t wait_ret;
158  ffado_wait_response response;
159 
160  printEnter();
161 
162  wait_enter = jack_get_microseconds ();
163  if (wait_enter > driver->wait_next) {
164  /*
165  * This processing cycle was delayed past the
166  * next due interrupt! Do not account this as
167  * a wakeup delay:
168  */
169  driver->wait_next = 0;
170  driver->wait_late++;
171  }
172 // *status = -2; interrupt
173 // *status = -3; timeout
174 // *status = -4; extra FD
175 
176  response = ffado_streaming_wait(driver->dev);
177 
178  wait_ret = jack_get_microseconds ();
179 
180  if (driver->wait_next && wait_ret > driver->wait_next) {
181  *delayed_usecs = wait_ret - driver->wait_next;
182  }
183  driver->wait_last = wait_ret;
184  driver->wait_next = wait_ret + driver->period_usecs;
185 // driver->engine->transport_cycle_start (driver->engine, wait_ret);
186 
187  if(response == ffado_wait_ok) {
188  // all good
189  *status = 0;
190  } else if (response == ffado_wait_xrun) {
191  // xrun happened, but it's handled
192  *status = 0;
193  return 0;
194  } else if (response == ffado_wait_error) {
195  // an error happened (unhandled xrun)
196  // this should be fatal
197  jack_error("JackFFADODriver::ffado_driver_wait - unhandled xrun");
198  *status = -1;
199  return 0;
200  } else if (response == ffado_wait_shutdown) {
201  // ffado requested shutdown (e.g. device unplugged)
202  // this should be fatal
203  jack_error("JackFFADODriver::ffado_driver_wait - shutdown requested "
204  "(device unplugged?)");
205  *status = -1;
206  return 0;
207  } else {
208  // unknown response code. should be fatal
209  // this should be fatal
210  jack_error("JackFFADODriver::ffado_driver_wait - unexpected error "
211  "code '%d' returned from 'ffado_streaming_wait'", response);
212  *status = -1;
213  return 0;
214  }
215 
216  fBeginDateUst = wait_ret;
217 
218  printExit();
219  return driver->period_size;
220 }
221 
222 int
223 JackFFADODriver::ffado_driver_start (ffado_driver_t *driver)
224 {
225  int retval = 0;
226 
227  if ((retval = ffado_streaming_start(driver->dev))) {
228  printError("Could not start streaming threads");
229 
230  return retval;
231  }
232  return 0;
233 }
234 
235 int
236 JackFFADODriver::ffado_driver_stop (ffado_driver_t *driver)
237 {
238  int retval = 0;
239 
240  if ((retval = ffado_streaming_stop(driver->dev))) {
241  printError("Could not stop streaming threads");
242  return retval;
243  }
244 
245  return 0;
246 }
247 
248 int
249 JackFFADODriver::ffado_driver_restart (ffado_driver_t *driver)
250 {
251  if (Stop())
252  return -1;
253  return Start();
254 }
255 
256 int
257 JackFFADODriver::SetBufferSize (jack_nframes_t nframes)
258 {
259  printError("Buffer size change requested but not supported!!!");
260 
261  /*
262  driver->period_size = nframes;
263  driver->period_usecs =
264  (jack_time_t) floor ((((float) nframes) / driver->sample_rate)
265  * 1000000.0f);
266  */
267 
268  /* tell the engine to change its buffer size */
269  //driver->engine->set_buffer_size (driver->engine, nframes);
270 
271  return -1; // unsupported
272 }
273 
274 typedef void (*JackDriverFinishFunction) (jack_driver_t *);
275 
277 JackFFADODriver::ffado_driver_new (const char *name,
278  ffado_jack_settings_t *params)
279 {
280  ffado_driver_t *driver;
281 
282  assert(params);
283 
284  if (ffado_get_api_version() != FIREWIRE_REQUIRED_FFADO_API_VERSION) {
285  printError("Incompatible libffado version! (%s)", ffado_get_version());
286  return NULL;
287  }
288 
289  printMessage("Starting FFADO backend (%s)", ffado_get_version());
290 
291  driver = (ffado_driver_t*)calloc (1, sizeof (ffado_driver_t));
292 
293  /* Setup the jack interfaces */
294  jack_driver_nt_init ((jack_driver_nt_t *) driver);
295 
296  /* driver->nt_attach = (JackDriverNTAttachFunction) ffado_driver_attach;
297  driver->nt_detach = (JackDriverNTDetachFunction) ffado_driver_detach;
298  driver->nt_start = (JackDriverNTStartFunction) ffado_driver_start;
299  driver->nt_stop = (JackDriverNTStopFunction) ffado_driver_stop;
300  driver->nt_run_cycle = (JackDriverNTRunCycleFunction) ffado_driver_run_cycle;
301  driver->null_cycle = (JackDriverNullCycleFunction) ffado_driver_null_cycle;
302  driver->write = (JackDriverReadFunction) ffado_driver_write;
303  driver->read = (JackDriverReadFunction) ffado_driver_read;
304  driver->nt_bufsize = (JackDriverNTBufSizeFunction) ffado_driver_bufsize;
305  */
306 
307  /* copy command line parameter contents to the driver structure */
308  memcpy(&driver->settings, params, sizeof(ffado_jack_settings_t));
309 
310  /* prepare all parameters */
311  driver->sample_rate = params->sample_rate;
312  driver->period_size = params->period_size;
313  fBeginDateUst = 0;
314 
315  driver->period_usecs =
316  (jack_time_t) floor ((((float) driver->period_size) * 1000000.0f) / driver->sample_rate);
317 
318 // driver->client = client;
319  driver->engine = NULL;
320 
321  memset(&driver->device_options, 0, sizeof(driver->device_options));
322  driver->device_options.sample_rate = params->sample_rate;
323  driver->device_options.period_size = params->period_size;
324  driver->device_options.nb_buffers = params->buffer_size;
325  driver->device_options.verbose = params->verbose_level;
326  driver->capture_frame_latency = params->capture_frame_latency;
327  driver->playback_frame_latency = params->playback_frame_latency;
328  driver->device_options.snoop_mode = params->snoop_mode;
329 
330  debugPrint(DEBUG_LEVEL_STARTUP, " Driver compiled on %s %s", __DATE__, __TIME__);
331  debugPrint(DEBUG_LEVEL_STARTUP, " Created driver %s", name);
332  debugPrint(DEBUG_LEVEL_STARTUP, " period_size: %d", driver->device_options.period_size);
333  debugPrint(DEBUG_LEVEL_STARTUP, " period_usecs: %d", driver->period_usecs);
334  debugPrint(DEBUG_LEVEL_STARTUP, " sample rate: %d", driver->device_options.sample_rate);
335  debugPrint(DEBUG_LEVEL_STARTUP, " verbose level: %d", driver->device_options.verbose);
336 
337  return (ffado_driver_t *) driver;
338 }
339 
340 void
341 JackFFADODriver::ffado_driver_delete (ffado_driver_t *driver)
342 {
343  free (driver);
344 }
345 
346 int JackFFADODriver::Attach()
347 {
348  JackPort* port;
349  jack_port_id_t port_index;
350  char buf[REAL_JACK_PORT_NAME_SIZE];
351  char portname[REAL_JACK_PORT_NAME_SIZE];
352  jack_latency_range_t range;
353 
354  ffado_driver_t* driver = (ffado_driver_t*)fDriver;
355 
356  jack_log("JackFFADODriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
357 
358  g_verbose = (fEngineControl->fVerbose ? 1 : 0);
359 
360  /* preallocate some buffers such that they don't have to be allocated
361  in RT context (or from the stack)
362  */
363  /* the null buffer is a buffer that contains one period of silence */
364  driver->nullbuffer = (ffado_sample_t *)calloc(driver->period_size, sizeof(ffado_sample_t));
365  if (driver->nullbuffer == NULL) {
366  printError("could not allocate memory for null buffer");
367  return -1;
368  }
369  /* calloc should do this, but it can't hurt to be sure */
370  memset(driver->nullbuffer, 0, driver->period_size*sizeof(ffado_sample_t));
371 
372  /* the scratch buffer is a buffer of one period that can be used as dummy memory */
373  driver->scratchbuffer = (ffado_sample_t *)calloc(driver->period_size, sizeof(ffado_sample_t));
374  if (driver->scratchbuffer == NULL) {
375  printError("could not allocate memory for scratch buffer");
376  return -1;
377  }
378 
379  /* packetizer thread options */
380  driver->device_options.realtime = (fEngineControl->fRealTime ? 1 : 0);
381 
382  driver->device_options.packetizer_priority = fEngineControl->fServerPriority +
383  FFADO_RT_PRIORITY_PACKETIZER_RELATIVE;
384  if (driver->device_options.packetizer_priority > 98) {
385  driver->device_options.packetizer_priority = 98;
386  }
387 
388  // initialize the thread
389  driver->dev = ffado_streaming_init(driver->device_info, driver->device_options);
390 
391  if (!driver->dev) {
392  printError("FFADO: Error creating virtual device");
393  return -1;
394  }
395 
396  if (driver->device_options.realtime) {
397  printMessage("Streaming thread running with Realtime scheduling, priority %d",
398  driver->device_options.packetizer_priority);
399  } else {
400  printMessage("Streaming thread running without Realtime scheduling");
401  }
402 
403  ffado_streaming_set_audio_datatype(driver->dev, ffado_audio_datatype_float);
404 
405  /* ports */
406 
407  // capture
408  driver->capture_nchannels = ffado_streaming_get_nb_capture_streams(driver->dev);
409  driver->capture_channels = (ffado_capture_channel_t *)calloc(driver->capture_nchannels, sizeof(ffado_capture_channel_t));
410  if (driver->capture_channels == NULL) {
411  printError("could not allocate memory for capture channel list");
412  return -1;
413  }
414 
415  fCaptureChannels = 0;
416  for (channel_t chn = 0; chn < driver->capture_nchannels; chn++) {
417  ffado_streaming_get_capture_stream_name(driver->dev, chn, portname, sizeof(portname));
418 
419  driver->capture_channels[chn].stream_type = ffado_streaming_get_capture_stream_type(driver->dev, chn);
420  if (driver->capture_channels[chn].stream_type == ffado_stream_type_audio) {
421  snprintf(buf, sizeof(buf), "firewire_pcm:%s_in", portname);
422  printMessage ("Registering audio capture port %s", buf);
423  if (fEngine->PortRegister(fClientControl.fRefNum, buf,
424  JACK_DEFAULT_AUDIO_TYPE,
425  CaptureDriverFlags,
426  fEngineControl->fBufferSize, &port_index) < 0) {
427  jack_error("driver: cannot register port for %s", buf);
428  return -1;
429  }
430 
431  // setup port parameters
432  if (ffado_streaming_set_capture_stream_buffer(driver->dev, chn, NULL)) {
433  printError(" cannot configure initial port buffer for %s", buf);
434  }
435  ffado_streaming_capture_stream_onoff(driver->dev, chn, 0);
436 
437  port = fGraphManager->GetPort(port_index);
438  range.min = range.max = driver->period_size + driver->capture_frame_latency;
439  port->SetLatencyRange(JackCaptureLatency, &range);
440  // capture port aliases (jackd1 style port names)
441  snprintf(buf, sizeof(buf), "%s:capture_%i", fClientControl.fName, (int) chn + 1);
442  port->SetAlias(buf);
443  fCapturePortList[chn] = port_index;
444  jack_log("JackFFADODriver::Attach fCapturePortList[i] %ld ", port_index);
445  fCaptureChannels++;
446  } else if (driver->capture_channels[chn].stream_type == ffado_stream_type_midi) {
447  snprintf(buf, sizeof(buf), "firewire_pcm:%s_in", portname);
448  printMessage ("Registering midi capture port %s", buf);
449  if (fEngine->PortRegister(fClientControl.fRefNum, buf,
450  JACK_DEFAULT_MIDI_TYPE,
451  CaptureDriverFlags,
452  fEngineControl->fBufferSize, &port_index) < 0) {
453  jack_error("driver: cannot register port for %s", buf);
454  return -1;
455  }
456 
457  // setup port parameters
458  if (ffado_streaming_set_capture_stream_buffer(driver->dev, chn, NULL)) {
459  printError(" cannot configure initial port buffer for %s", buf);
460  }
461  if (ffado_streaming_capture_stream_onoff(driver->dev, chn, 0)) {
462  printError(" cannot enable port %s", buf);
463  }
464 
465  driver->capture_channels[chn].midi_input = new JackFFADOMidiInputPort();
466  // setup the midi buffer
467  driver->capture_channels[chn].midi_buffer = (uint32_t *)calloc(driver->period_size, sizeof(uint32_t));
468 
469  port = fGraphManager->GetPort(port_index);
470  range.min = range.max = driver->period_size + driver->capture_frame_latency;
471  port->SetLatencyRange(JackCaptureLatency, &range);
472  fCapturePortList[chn] = port_index;
473  jack_log("JackFFADODriver::Attach fCapturePortList[i] %ld ", port_index);
474  fCaptureChannels++;
475  } else {
476  printMessage ("Don't register capture port %s", portname);
477  }
478  }
479 
480  // playback
481  driver->playback_nchannels = ffado_streaming_get_nb_playback_streams(driver->dev);
482  driver->playback_channels = (ffado_playback_channel_t *)calloc(driver->playback_nchannels, sizeof(ffado_playback_channel_t));
483  if (driver->playback_channels == NULL) {
484  printError("could not allocate memory for playback channel list");
485  return -1;
486  }
487 
488  fPlaybackChannels = 0;
489  for (channel_t chn = 0; chn < driver->playback_nchannels; chn++) {
490  ffado_streaming_get_playback_stream_name(driver->dev, chn, portname, sizeof(portname));
491 
492  driver->playback_channels[chn].stream_type = ffado_streaming_get_playback_stream_type(driver->dev, chn);
493 
494  if (driver->playback_channels[chn].stream_type == ffado_stream_type_audio) {
495  snprintf(buf, sizeof(buf), "firewire_pcm:%s_out", portname);
496  printMessage ("Registering audio playback port %s", buf);
497  if (fEngine->PortRegister(fClientControl.fRefNum, buf,
498  JACK_DEFAULT_AUDIO_TYPE,
499  PlaybackDriverFlags,
500  fEngineControl->fBufferSize, &port_index) < 0) {
501  jack_error("driver: cannot register port for %s", buf);
502  return -1;
503  }
504 
505  // setup port parameters
506  if (ffado_streaming_set_playback_stream_buffer(driver->dev, chn, NULL)) {
507  printError(" cannot configure initial port buffer for %s", buf);
508  }
509  if (ffado_streaming_playback_stream_onoff(driver->dev, chn, 0)) {
510  printError(" cannot enable port %s", buf);
511  }
512 
513  port = fGraphManager->GetPort(port_index);
514  // Add one buffer more latency if "async" mode is used...
515  range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency;
516  port->SetLatencyRange(JackPlaybackLatency, &range);
517  // playback port aliases (jackd1 style port names)
518  snprintf(buf, sizeof(buf), "%s:playback_%i", fClientControl.fName, (int) chn + 1);
519  port->SetAlias(buf);
520  fPlaybackPortList[chn] = port_index;
521  jack_log("JackFFADODriver::Attach fPlaybackPortList[i] %ld ", port_index);
522  fPlaybackChannels++;
523  } else if (driver->playback_channels[chn].stream_type == ffado_stream_type_midi) {
524  snprintf(buf, sizeof(buf), "firewire_pcm:%s_out", portname);
525  printMessage ("Registering midi playback port %s", buf);
526 
527  if (fEngine->PortRegister(fClientControl.fRefNum, buf,
528  JACK_DEFAULT_MIDI_TYPE,
529  PlaybackDriverFlags,
530  fEngineControl->fBufferSize, &port_index) < 0) {
531  jack_error("driver: cannot register port for %s", buf);
532  return -1;
533  }
534 
535  // setup port parameters
536  if (ffado_streaming_set_playback_stream_buffer(driver->dev, chn, NULL)) {
537  printError(" cannot configure initial port buffer for %s", buf);
538  }
539  if (ffado_streaming_playback_stream_onoff(driver->dev, chn, 0)) {
540  printError(" cannot enable port %s", buf);
541  }
542  // setup the midi buffer
543 
544  // This constructor optionally accepts arguments for the
545  // non-realtime buffer size and the realtime buffer size. Ideally,
546  // these would become command-line options for the FFADO driver.
547  driver->playback_channels[chn].midi_output = new JackFFADOMidiOutputPort();
548 
549  driver->playback_channels[chn].midi_buffer = (uint32_t *)calloc(driver->period_size, sizeof(uint32_t));
550 
551  port = fGraphManager->GetPort(port_index);
552  range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency;
553  port->SetLatencyRange(JackPlaybackLatency, &range);
554  fPlaybackPortList[chn] = port_index;
555  jack_log("JackFFADODriver::Attach fPlaybackPortList[i] %ld ", port_index);
556  fPlaybackChannels++;
557  } else {
558  printMessage ("Don't register playback port %s", portname);
559  }
560  }
561 
562  assert(fCaptureChannels < DRIVER_PORT_NUM);
563  assert(fPlaybackChannels < DRIVER_PORT_NUM);
564 
565  if (ffado_streaming_prepare(driver->dev)) {
566  printError("Could not prepare streaming device!");
567  return -1;
568  }
569 
570  // this makes no sense...
571  assert(fCaptureChannels + fPlaybackChannels > 0);
572  return 0;
573 }
574 
575 int JackFFADODriver::Detach()
576 {
577  channel_t chn;
578  ffado_driver_t* driver = (ffado_driver_t*)fDriver;
579  jack_log("JackFFADODriver::Detach");
580 
581  // finish the libfreebob streaming
582  ffado_streaming_finish(driver->dev);
583  driver->dev = NULL;
584 
585  // free all internal buffers
586  for (chn = 0; chn < driver->capture_nchannels; chn++) {
587  if (driver->capture_channels[chn].midi_buffer)
588  free(driver->capture_channels[chn].midi_buffer);
589  if (driver->capture_channels[chn].midi_input)
590  delete ((JackFFADOMidiInputPort *) (driver->capture_channels[chn].midi_input));
591  }
592  free(driver->capture_channels);
593 
594  for (chn = 0; chn < driver->playback_nchannels; chn++) {
595  if (driver->playback_channels[chn].midi_buffer)
596  free(driver->playback_channels[chn].midi_buffer);
597  if (driver->playback_channels[chn].midi_output)
598  delete ((JackFFADOMidiOutputPort *) (driver->playback_channels[chn].midi_output));
599  }
600  free(driver->playback_channels);
601 
602  free(driver->nullbuffer);
603  free(driver->scratchbuffer);
604 
605  return JackAudioDriver::Detach(); // Generic JackAudioDriver Detach
606 }
607 
608 int JackFFADODriver::Open(ffado_jack_settings_t *params)
609 {
610  // Generic JackAudioDriver Open
611  if (JackAudioDriver::Open(
612  params->period_size, params->sample_rate,
613  params->playback_ports, params->playback_ports,
614  0, 0, 0, "", "",
615  params->capture_frame_latency, params->playback_frame_latency) != 0) {
616  return -1;
617  }
618 
619  fDriver = (jack_driver_t *)ffado_driver_new ("ffado_pcm", params);
620 
621  if (fDriver) {
622  // FFADO driver may have changed the in/out values
623  //fCaptureChannels = ((ffado_driver_t *)fDriver)->capture_nchannels_audio;
624  //fPlaybackChannels = ((ffado_driver_t *)fDriver)->playback_nchannels_audio;
625  return 0;
626  } else {
627  JackAudioDriver::Close();
628  return -1;
629  }
630 }
631 
632 int JackFFADODriver::Close()
633 {
634  // Generic audio driver close
635  int res = JackAudioDriver::Close();
636 
637  ffado_driver_delete((ffado_driver_t*)fDriver);
638  return res;
639 }
640 
641 int JackFFADODriver::Start()
642 {
643  int res = JackAudioDriver::Start();
644  if (res >= 0) {
645  res = ffado_driver_start((ffado_driver_t *)fDriver);
646  if (res < 0) {
647  JackAudioDriver::Stop();
648  }
649  }
650  return res;
651 }
652 
653 int JackFFADODriver::Stop()
654 {
655  int res = ffado_driver_stop((ffado_driver_t *)fDriver);
656  if (JackAudioDriver::Stop() < 0) {
657  res = -1;
658  }
659  return res;
660 }
661 
662 int JackFFADODriver::Read()
663 {
664  printEnter();
665 
666  /* Taken from ffado_driver_run_cycle */
667  ffado_driver_t* driver = (ffado_driver_t*)fDriver;
668  int wait_status = 0;
669  fDelayedUsecs = 0.f;
670 
671 retry:
672 
673  jack_nframes_t nframes = ffado_driver_wait(driver, -1, &wait_status,
674  &fDelayedUsecs);
675 
676  if ((wait_status < 0)) {
677  printError( "wait status < 0! (= %d)", wait_status);
678  return -1;
679  }
680 
681  if (nframes == 0) {
682  /* we detected an xrun and restarted: notify
683  * clients about the delay.
684  */
685  jack_log("FFADO XRun");
686  NotifyXRun(fBeginDateUst, fDelayedUsecs);
687  goto retry; /* recoverable error*/
688  }
689 
690  if (nframes != fEngineControl->fBufferSize)
691  jack_log("JackFFADODriver::Read warning nframes = %ld", nframes);
692 
693  // Has to be done before read
694  JackDriver::CycleIncTime();
695 
696  printExit();
697  return ffado_driver_read((ffado_driver_t *)fDriver, fEngineControl->fBufferSize);
698 }
699 
700 int JackFFADODriver::Write()
701 {
702  printEnter();
703  int res = ffado_driver_write((ffado_driver_t *)fDriver, fEngineControl->fBufferSize);
704  printExit();
705  return res;
706 }
707 
708 void
709 JackFFADODriver::jack_driver_init (jack_driver_t *driver)
710 {
711  memset (driver, 0, sizeof (*driver));
712 
713  driver->attach = 0;
714  driver->detach = 0;
715  driver->write = 0;
716  driver->read = 0;
717  driver->null_cycle = 0;
718  driver->bufsize = 0;
719  driver->start = 0;
720  driver->stop = 0;
721 }
722 
723 void
724 JackFFADODriver::jack_driver_nt_init (jack_driver_nt_t * driver)
725 {
726  memset (driver, 0, sizeof (*driver));
727 
728  jack_driver_init ((jack_driver_t *) driver);
729 
730  driver->attach = 0;
731  driver->detach = 0;
732  driver->bufsize = 0;
733  driver->stop = 0;
734  driver->start = 0;
735 
736  driver->nt_bufsize = 0;
737  driver->nt_start = 0;
738  driver->nt_stop = 0;
739  driver->nt_attach = 0;
740  driver->nt_detach = 0;
741  driver->nt_run_cycle = 0;
742 }
743 
744 } // end of namespace
745 
746 
747 #ifdef __cplusplus
748 extern "C"
749 {
750 #endif
751 
752  SERVER_EXPORT const jack_driver_desc_t *
753  driver_get_descriptor () {
754  jack_driver_desc_t * desc;
757 
758  desc = jack_driver_descriptor_construct("firewire", JackDriverMaster, "Linux FFADO API based audio backend", &filler);
759 
760  strcpy(value.str, "hw:0");
761  jack_driver_descriptor_add_parameter(
762  desc,
763  &filler,
764  "device",
765  'd',
766  JackDriverParamString,
767  &value,
768  NULL,
769  "The FireWire device to use.",
770  "The FireWire device to use. Please consult the FFADO documentation for more info.");
771 
772  value.ui = 1024;
773  jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
774 
775  value.ui = 3;
776  jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods of playback latency", NULL);
777 
778  value.ui = 48000U;
779  jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
780 
781  value.i = 0;
782  jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamBool, &value, NULL, "Provide capture ports.", NULL);
783  jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamBool, &value, NULL, "Provide playback ports.", NULL);
784 
785  value.i = 1;
786  jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports.", NULL);
787 
788  value.ui = 0;
789  jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency (frames)", NULL);
790  jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency (frames)", NULL);
791 
792  value.ui = 0;
793  jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "Number of input channels to provide (note: currently ignored)", NULL);
794  jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "Number of output channels to provide (note: currently ignored)", NULL);
795 
796  value.ui = 3;
797  jack_driver_descriptor_add_parameter(desc, &filler, "verbose", 'v', JackDriverParamUInt, &value, NULL, "libffado verbose level", NULL);
798 
799  value.i = 0;
800  jack_driver_descriptor_add_parameter(desc, &filler, "snoop", 'X', JackDriverParamBool, &value, NULL, "Snoop firewire traffic", NULL);
801 
802  return desc;
803  }
804 
805  SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) {
806  const JSList * node;
807  const jack_driver_param_t * param;
808 
809  ffado_jack_settings_t cmlparams;
810 
811  char *device_name=(char*)"hw:0";
812 
813  cmlparams.period_size_set = 0;
814  cmlparams.sample_rate_set = 0;
815  cmlparams.buffer_size_set = 0;
816 
817  /* default values */
818  cmlparams.period_size = 1024;
819  cmlparams.sample_rate = 48000;
820  cmlparams.buffer_size = 3;
821  cmlparams.playback_ports = 0;
822  cmlparams.capture_ports = 0;
823  cmlparams.playback_frame_latency = 0;
824  cmlparams.capture_frame_latency = 0;
825 
826  cmlparams.verbose_level = 0;
827 
828  cmlparams.slave_mode = 0;
829  cmlparams.snoop_mode = 0;
830  cmlparams.device_info = NULL;
831 
832  for (node = params; node; node = jack_slist_next (node)) {
833  param = (jack_driver_param_t *) node->data;
834 
835  switch (param->character) {
836  case 'd':
837  device_name = const_cast<char*>(param->value.str);
838  break;
839  case 'p':
840  cmlparams.period_size = param->value.ui;
841  cmlparams.period_size_set = 1;
842  break;
843  case 'n':
844  cmlparams.buffer_size = param->value.ui;
845  cmlparams.buffer_size_set = 1;
846  break;
847  case 'r':
848  cmlparams.sample_rate = param->value.ui;
849  cmlparams.sample_rate_set = 1;
850  break;
851  case 'i':
852  cmlparams.capture_ports = param->value.ui;
853  break;
854  case 'o':
855  cmlparams.playback_ports = param->value.ui;
856  break;
857  case 'I':
858  cmlparams.capture_frame_latency = param->value.ui;
859  break;
860  case 'O':
861  cmlparams.playback_frame_latency = param->value.ui;
862  break;
863  case 'x':
864  cmlparams.slave_mode = param->value.ui;
865  break;
866  case 'X':
867  cmlparams.snoop_mode = param->value.i;
868  break;
869  case 'v':
870  cmlparams.verbose_level = param->value.ui;
871  }
872  }
873 
874  /* duplex is the default */
875  if (!cmlparams.playback_ports && !cmlparams.capture_ports) {
876  cmlparams.playback_ports = 1;
877  cmlparams.capture_ports = 1;
878  }
879 
880  // temporary
881  cmlparams.device_info = device_name;
882 
883  Jack::JackFFADODriver* ffado_driver = new Jack::JackFFADODriver("system", "firewire_pcm", engine, table);
884  Jack::JackDriverClientInterface* threaded_driver = new Jack::JackThreadedDriver(ffado_driver);
885  // Special open for FFADO driver...
886  if (ffado_driver->Open(&cmlparams) == 0) {
887  return threaded_driver;
888  } else {
889  delete threaded_driver; // Delete the decorated driver
890  return NULL;
891  }
892  }
893 
894 #ifdef __cplusplus
895 }
896 #endif
897 
898