root/jack2/trunk/jackmp/linux/firewire/JackFFADODriver.cpp

Revision 4608, 33.6 kB (checked in by sletz, 3 years ago)

Cleanup.

  • Property svn:eol-style set to native
Line 
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
276 ffado_driver_t *
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;
755         jack_driver_desc_filler_t filler;
756         jack_driver_param_value_t value;
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
Note: See TracBrowser for help on using the browser.