Jack2 1.9.8

JackFFADODriver.cpp

00001 /*
00002 Copyright (C) 2001 Paul Davis
00003 Copyright (C) 2004 Grame
00004 Copyright (C) 2007 Pieter Palmers
00005 Copyright (C) 2009 Devin Anderson
00006 
00007 This program is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 This program is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with this program; if not, write to the Free Software
00019 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020 
00021 */
00022 
00023 #include <iostream>
00024 #include <unistd.h>
00025 #include <math.h>
00026 #include <stdio.h>
00027 #include <memory.h>
00028 #include <unistd.h>
00029 #include <stdlib.h>
00030 #include <errno.h>
00031 #include <stdarg.h>
00032 #include <signal.h>
00033 #include <sys/types.h>
00034 #include <sys/time.h>
00035 #include <regex.h>
00036 #include <string.h>
00037 
00038 #include "JackFFADODriver.h"
00039 #include "JackFFADOMidiInputPort.h"
00040 #include "JackFFADOMidiOutputPort.h"
00041 #include "JackEngineControl.h"
00042 #include "JackClientControl.h"
00043 #include "JackPort.h"
00044 #include "JackGraphManager.h"
00045 #include "JackCompilerDeps.h"
00046 #include "JackLockedEngine.h"
00047 
00048 namespace Jack
00049 {
00050 
00051 #define FIREWIRE_REQUIRED_FFADO_API_VERSION 8
00052 
00053 #define jack_get_microseconds GetMicroSeconds
00054 
00055 int
00056 JackFFADODriver::ffado_driver_read (ffado_driver_t * driver, jack_nframes_t nframes)
00057 {
00058     channel_t chn;
00059     jack_default_audio_sample_t* buf = NULL;
00060 
00061     printEnter();
00062     for (chn = 0; chn < driver->capture_nchannels; chn++) {
00063         // if nothing connected, don't process
00064         if (fGraphManager->GetConnectionsNum(fCapturePortList[chn]) == 0) {
00065             buf = (jack_default_audio_sample_t*)driver->scratchbuffer;
00066             // we always have to specify a valid buffer
00067             ffado_streaming_set_capture_stream_buffer(driver->dev, chn, (char *)(buf));
00068             // notify the streaming system that it can (but doesn't have to) skip
00069             // this channel
00070             ffado_streaming_capture_stream_onoff(driver->dev, chn, 0);
00071         } else {
00072             if (driver->capture_channels[chn].stream_type == ffado_stream_type_audio) {
00073                 buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[chn],  nframes);
00074 
00075                 /* if the returned buffer is invalid, use the dummy buffer */
00076                 if (!buf) buf = (jack_default_audio_sample_t*)driver->scratchbuffer;
00077 
00078                 ffado_streaming_set_capture_stream_buffer(driver->dev, chn, (char *)(buf));
00079                 ffado_streaming_capture_stream_onoff(driver->dev, chn, 1);
00080             } else if (driver->capture_channels[chn].stream_type == ffado_stream_type_midi) {
00081                 ffado_streaming_set_capture_stream_buffer(driver->dev, chn,
00082                         (char *)(driver->capture_channels[chn].midi_buffer));
00083                 ffado_streaming_capture_stream_onoff(driver->dev, chn, 1);
00084             } else { // always have a valid buffer
00085                 ffado_streaming_set_capture_stream_buffer(driver->dev, chn, (char *)(driver->scratchbuffer));
00086                 // don't process what we don't use
00087                 ffado_streaming_capture_stream_onoff(driver->dev, chn, 0);
00088             }
00089         }
00090     }
00091 
00092     /* now transfer the buffers */
00093     ffado_streaming_transfer_capture_buffers(driver->dev);
00094 
00095     /* process the midi data */
00096     for (chn = 0; chn < driver->capture_nchannels; chn++) {
00097         if (driver->capture_channels[chn].stream_type == ffado_stream_type_midi) {
00098             JackFFADOMidiInputPort *midi_input = (JackFFADOMidiInputPort *) driver->capture_channels[chn].midi_input;
00099             JackMidiBuffer *buffer = (JackMidiBuffer *) fGraphManager->GetBuffer(fCapturePortList[chn], nframes);
00100             midi_input->Process(buffer, driver->capture_channels[chn].midi_buffer, nframes);
00101         }
00102     }
00103 
00104     printExit();
00105     return 0;
00106 }
00107 
00108 int
00109 JackFFADODriver::ffado_driver_write (ffado_driver_t * driver, jack_nframes_t nframes)
00110 {
00111     channel_t chn;
00112     jack_default_audio_sample_t* buf;
00113     printEnter();
00114 
00115     driver->process_count++;
00116 
00117     for (chn = 0; chn < driver->playback_nchannels; chn++) {
00118         if (fGraphManager->GetConnectionsNum(fPlaybackPortList[chn]) == 0) {
00119             buf = (jack_default_audio_sample_t*)driver->nullbuffer;
00120             // we always have to specify a valid buffer
00121             ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(buf));
00122             // notify the streaming system that it can (but doesn't have to) skip
00123             // this channel
00124             ffado_streaming_playback_stream_onoff(driver->dev, chn, 0);
00125         } else {
00126             if (driver->playback_channels[chn].stream_type == ffado_stream_type_audio) {
00127                 buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[chn], nframes);
00128                 /* use the silent buffer if there is no valid jack buffer */
00129                 if (!buf) buf = (jack_default_audio_sample_t*)driver->nullbuffer;
00130                 ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(buf));
00131                 ffado_streaming_playback_stream_onoff(driver->dev, chn, 1);
00132             } else if (driver->playback_channels[chn].stream_type == ffado_stream_type_midi) {
00133                 uint32_t *midi_buffer = driver->playback_channels[chn].midi_buffer;
00134                 memset(midi_buffer, 0, nframes * sizeof(uint32_t));
00135                 buf = (jack_default_audio_sample_t *) fGraphManager->GetBuffer(fPlaybackPortList[chn], nframes);
00136                 ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(midi_buffer));
00137                 ffado_streaming_playback_stream_onoff(driver->dev, chn, buf ? 1 : 0);
00138                 JackFFADOMidiOutputPort *midi_output = (JackFFADOMidiOutputPort *) driver->playback_channels[chn].midi_output;
00139                 midi_output->Process((JackMidiBuffer *) buf, midi_buffer, nframes);
00140 
00141             } else { // always have a valid buffer
00142                 ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(driver->nullbuffer));
00143                 ffado_streaming_playback_stream_onoff(driver->dev, chn, 0);
00144             }
00145         }
00146     }
00147     ffado_streaming_transfer_playback_buffers(driver->dev);
00148     printExit();
00149     return 0;
00150 }
00151 
00152 jack_nframes_t
00153 JackFFADODriver::ffado_driver_wait (ffado_driver_t *driver, int extra_fd, int *status,
00154                                     float *delayed_usecs)
00155 {
00156     jack_time_t wait_enter;
00157     jack_time_t wait_ret;
00158     ffado_wait_response response;
00159 
00160     printEnter();
00161 
00162     wait_enter = jack_get_microseconds ();
00163     if (wait_enter > driver->wait_next) {
00164         /*
00165                 * This processing cycle was delayed past the
00166                 * next due interrupt!  Do not account this as
00167                 * a wakeup delay:
00168                 */
00169         driver->wait_next = 0;
00170         driver->wait_late++;
00171     }
00172 // *status = -2; interrupt
00173 // *status = -3; timeout
00174 // *status = -4; extra FD
00175 
00176     response = ffado_streaming_wait(driver->dev);
00177 
00178     wait_ret = jack_get_microseconds ();
00179 
00180     if (driver->wait_next && wait_ret > driver->wait_next) {
00181         *delayed_usecs = wait_ret - driver->wait_next;
00182     }
00183     driver->wait_last = wait_ret;
00184     driver->wait_next = wait_ret + driver->period_usecs;
00185 //         driver->engine->transport_cycle_start (driver->engine, wait_ret);
00186 
00187     if(response == ffado_wait_ok) {
00188        // all good
00189        *status = 0;
00190     } else if (response == ffado_wait_xrun) {
00191         // xrun happened, but it's handled
00192         *status = 0;
00193         return 0;
00194     } else if (response == ffado_wait_error) {
00195         // an error happened (unhandled xrun)
00196         // this should be fatal
00197         jack_error("JackFFADODriver::ffado_driver_wait - unhandled xrun");
00198         *status = -1;
00199         return 0;
00200     } else if (response == ffado_wait_shutdown) {
00201         // ffado requested shutdown (e.g. device unplugged)
00202         // this should be fatal
00203         jack_error("JackFFADODriver::ffado_driver_wait - shutdown requested "
00204                    "(device unplugged?)");
00205         *status = -1;
00206         return 0;
00207     } else {
00208         // unknown response code. should be fatal
00209         // this should be fatal
00210         jack_error("JackFFADODriver::ffado_driver_wait - unexpected error "
00211                    "code '%d' returned from 'ffado_streaming_wait'", response);
00212         *status = -1;
00213         return 0;
00214     }
00215 
00216     fBeginDateUst = wait_ret;
00217 
00218     printExit();
00219     return driver->period_size;
00220 }
00221 
00222 int
00223 JackFFADODriver::ffado_driver_start (ffado_driver_t *driver)
00224 {
00225     int retval = 0;
00226 
00227     if ((retval = ffado_streaming_start(driver->dev))) {
00228         printError("Could not start streaming threads");
00229 
00230         return retval;
00231     }
00232     return 0;
00233 }
00234 
00235 int
00236 JackFFADODriver::ffado_driver_stop (ffado_driver_t *driver)
00237 {
00238     int retval = 0;
00239 
00240     if ((retval = ffado_streaming_stop(driver->dev))) {
00241         printError("Could not stop streaming threads");
00242         return retval;
00243     }
00244 
00245     return 0;
00246 }
00247 
00248 int
00249 JackFFADODriver::ffado_driver_restart (ffado_driver_t *driver)
00250 {
00251     if (Stop())
00252         return -1;
00253     return Start();
00254 }
00255 
00256 int
00257 JackFFADODriver::SetBufferSize (jack_nframes_t nframes)
00258 {
00259     printError("Buffer size change requested but not supported!!!");
00260 
00261     /*
00262     driver->period_size = nframes;
00263     driver->period_usecs =
00264             (jack_time_t) floor ((((float) nframes) / driver->sample_rate)
00265                                  * 1000000.0f);
00266     */
00267 
00268     /* tell the engine to change its buffer size */
00269     //driver->engine->set_buffer_size (driver->engine, nframes);
00270 
00271     return -1; // unsupported
00272 }
00273 
00274 typedef void (*JackDriverFinishFunction) (jack_driver_t *);
00275 
00276 ffado_driver_t *
00277 JackFFADODriver::ffado_driver_new (const char *name,
00278                                    ffado_jack_settings_t *params)
00279 {
00280     ffado_driver_t *driver;
00281 
00282     assert(params);
00283 
00284     if (ffado_get_api_version() != FIREWIRE_REQUIRED_FFADO_API_VERSION) {
00285         printError("Incompatible libffado version! (%s)", ffado_get_version());
00286         return NULL;
00287     }
00288 
00289     printMessage("Starting FFADO backend (%s)", ffado_get_version());
00290 
00291     driver = (ffado_driver_t*)calloc (1, sizeof (ffado_driver_t));
00292 
00293     /* Setup the jack interfaces */
00294     jack_driver_nt_init ((jack_driver_nt_t *) driver);
00295 
00296     /*        driver->nt_attach    = (JackDriverNTAttachFunction)   ffado_driver_attach;
00297             driver->nt_detach    = (JackDriverNTDetachFunction)   ffado_driver_detach;
00298             driver->nt_start     = (JackDriverNTStartFunction)    ffado_driver_start;
00299             driver->nt_stop      = (JackDriverNTStopFunction)     ffado_driver_stop;
00300             driver->nt_run_cycle = (JackDriverNTRunCycleFunction) ffado_driver_run_cycle;
00301             driver->null_cycle   = (JackDriverNullCycleFunction)  ffado_driver_null_cycle;
00302             driver->write        = (JackDriverReadFunction)       ffado_driver_write;
00303             driver->read         = (JackDriverReadFunction)       ffado_driver_read;
00304             driver->nt_bufsize   = (JackDriverNTBufSizeFunction)  ffado_driver_bufsize;
00305             */
00306 
00307     /* copy command line parameter contents to the driver structure */
00308     memcpy(&driver->settings, params, sizeof(ffado_jack_settings_t));
00309 
00310     /* prepare all parameters */
00311     driver->sample_rate = params->sample_rate;
00312     driver->period_size = params->period_size;
00313     fBeginDateUst = 0;
00314 
00315     driver->period_usecs =
00316         (jack_time_t) floor ((((float) driver->period_size) * 1000000.0f) / driver->sample_rate);
00317 
00318 //         driver->client = client;
00319     driver->engine = NULL;
00320 
00321     memset(&driver->device_options, 0, sizeof(driver->device_options));
00322     driver->device_options.sample_rate = params->sample_rate;
00323     driver->device_options.period_size = params->period_size;
00324     driver->device_options.nb_buffers = params->buffer_size;
00325     driver->device_options.verbose = params->verbose_level;
00326     driver->capture_frame_latency = params->capture_frame_latency;
00327     driver->playback_frame_latency = params->playback_frame_latency;
00328     driver->device_options.snoop_mode = params->snoop_mode;
00329 
00330     debugPrint(DEBUG_LEVEL_STARTUP, " Driver compiled on %s %s", __DATE__, __TIME__);
00331     debugPrint(DEBUG_LEVEL_STARTUP, " Created driver %s", name);
00332     debugPrint(DEBUG_LEVEL_STARTUP, "            period_size:   %d", driver->device_options.period_size);
00333     debugPrint(DEBUG_LEVEL_STARTUP, "            period_usecs:  %d", driver->period_usecs);
00334     debugPrint(DEBUG_LEVEL_STARTUP, "            sample rate:   %d", driver->device_options.sample_rate);
00335     debugPrint(DEBUG_LEVEL_STARTUP, "            verbose level: %d", driver->device_options.verbose);
00336 
00337     return (ffado_driver_t *) driver;
00338 }
00339 
00340 void
00341 JackFFADODriver::ffado_driver_delete (ffado_driver_t *driver)
00342 {
00343     free (driver);
00344 }
00345 
00346 int JackFFADODriver::Attach()
00347 {
00348     JackPort* port;
00349     jack_port_id_t port_index;
00350     char buf[REAL_JACK_PORT_NAME_SIZE];
00351     char portname[REAL_JACK_PORT_NAME_SIZE];
00352     jack_latency_range_t range;
00353 
00354     ffado_driver_t* driver = (ffado_driver_t*)fDriver;
00355 
00356     jack_log("JackFFADODriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
00357 
00358     g_verbose = (fEngineControl->fVerbose ? 1 : 0);
00359 
00360     /* preallocate some buffers such that they don't have to be allocated
00361        in RT context (or from the stack)
00362      */
00363     /* the null buffer is a buffer that contains one period of silence */
00364     driver->nullbuffer = (ffado_sample_t *)calloc(driver->period_size, sizeof(ffado_sample_t));
00365     if (driver->nullbuffer == NULL) {
00366         printError("could not allocate memory for null buffer");
00367         return -1;
00368     }
00369     /* calloc should do this, but it can't hurt to be sure */
00370     memset(driver->nullbuffer, 0, driver->period_size*sizeof(ffado_sample_t));
00371 
00372     /* the scratch buffer is a buffer of one period that can be used as dummy memory */
00373     driver->scratchbuffer = (ffado_sample_t *)calloc(driver->period_size, sizeof(ffado_sample_t));
00374     if (driver->scratchbuffer == NULL) {
00375         printError("could not allocate memory for scratch buffer");
00376         return -1;
00377     }
00378 
00379     /* packetizer thread options */
00380     driver->device_options.realtime = (fEngineControl->fRealTime ? 1 : 0);
00381 
00382     driver->device_options.packetizer_priority = fEngineControl->fServerPriority +
00383             FFADO_RT_PRIORITY_PACKETIZER_RELATIVE;
00384     if (driver->device_options.packetizer_priority > 98) {
00385         driver->device_options.packetizer_priority = 98;
00386     }
00387 
00388     // initialize the thread
00389     driver->dev = ffado_streaming_init(driver->device_info, driver->device_options);
00390 
00391     if (!driver->dev) {
00392         printError("FFADO: Error creating virtual device");
00393         return -1;
00394     }
00395 
00396     if (driver->device_options.realtime) {
00397         printMessage("Streaming thread running with Realtime scheduling, priority %d",
00398                      driver->device_options.packetizer_priority);
00399     } else {
00400         printMessage("Streaming thread running without Realtime scheduling");
00401     }
00402 
00403     ffado_streaming_set_audio_datatype(driver->dev, ffado_audio_datatype_float);
00404 
00405     /* ports */
00406 
00407     // capture
00408     driver->capture_nchannels = ffado_streaming_get_nb_capture_streams(driver->dev);
00409     driver->capture_channels = (ffado_capture_channel_t *)calloc(driver->capture_nchannels, sizeof(ffado_capture_channel_t));
00410     if (driver->capture_channels == NULL) {
00411         printError("could not allocate memory for capture channel list");
00412         return -1;
00413     }
00414 
00415     fCaptureChannels = 0;
00416     for (channel_t chn = 0; chn < driver->capture_nchannels; chn++) {
00417         ffado_streaming_get_capture_stream_name(driver->dev, chn, portname, sizeof(portname));
00418 
00419         driver->capture_channels[chn].stream_type = ffado_streaming_get_capture_stream_type(driver->dev, chn);
00420         if (driver->capture_channels[chn].stream_type == ffado_stream_type_audio) {
00421             snprintf(buf, sizeof(buf), "firewire_pcm:%s_in", portname);
00422             printMessage ("Registering audio capture port %s", buf);
00423             if (fEngine->PortRegister(fClientControl.fRefNum, buf,
00424                               JACK_DEFAULT_AUDIO_TYPE,
00425                               CaptureDriverFlags,
00426                               fEngineControl->fBufferSize, &port_index) < 0) {
00427                 jack_error("driver: cannot register port for %s", buf);
00428                 return -1;
00429             }
00430 
00431             // setup port parameters
00432             if (ffado_streaming_set_capture_stream_buffer(driver->dev, chn, NULL)) {
00433                 printError(" cannot configure initial port buffer for %s", buf);
00434             }
00435             ffado_streaming_capture_stream_onoff(driver->dev, chn, 0);
00436 
00437             port = fGraphManager->GetPort(port_index);
00438             range.min = range.max = driver->period_size + driver->capture_frame_latency;
00439             port->SetLatencyRange(JackCaptureLatency, &range);
00440             // capture port aliases (jackd1 style port names)
00441             snprintf(buf, sizeof(buf), "%s:capture_%i", fClientControl.fName, (int) chn + 1);
00442             port->SetAlias(buf);
00443             fCapturePortList[chn] = port_index;
00444             jack_log("JackFFADODriver::Attach fCapturePortList[i] %ld ", port_index);
00445             fCaptureChannels++;
00446         } else if (driver->capture_channels[chn].stream_type == ffado_stream_type_midi) {
00447             snprintf(buf, sizeof(buf), "firewire_pcm:%s_in", portname);
00448             printMessage ("Registering midi capture port %s", buf);
00449             if (fEngine->PortRegister(fClientControl.fRefNum, buf,
00450                               JACK_DEFAULT_MIDI_TYPE,
00451                               CaptureDriverFlags,
00452                               fEngineControl->fBufferSize, &port_index) < 0) {
00453                 jack_error("driver: cannot register port for %s", buf);
00454                 return -1;
00455             }
00456 
00457             // setup port parameters
00458             if (ffado_streaming_set_capture_stream_buffer(driver->dev, chn, NULL)) {
00459                 printError(" cannot configure initial port buffer for %s", buf);
00460             }
00461             if (ffado_streaming_capture_stream_onoff(driver->dev, chn, 0)) {
00462                 printError(" cannot enable port %s", buf);
00463             }
00464 
00465             driver->capture_channels[chn].midi_input = new JackFFADOMidiInputPort();
00466             // setup the midi buffer
00467             driver->capture_channels[chn].midi_buffer = (uint32_t *)calloc(driver->period_size, sizeof(uint32_t));
00468 
00469             port = fGraphManager->GetPort(port_index);
00470             range.min = range.max = driver->period_size + driver->capture_frame_latency;
00471             port->SetLatencyRange(JackCaptureLatency, &range);
00472             fCapturePortList[chn] = port_index;
00473             jack_log("JackFFADODriver::Attach fCapturePortList[i] %ld ", port_index);
00474             fCaptureChannels++;
00475         } else {
00476             printMessage ("Don't register capture port %s", portname);
00477         }
00478     }
00479 
00480     // playback
00481     driver->playback_nchannels = ffado_streaming_get_nb_playback_streams(driver->dev);
00482     driver->playback_channels = (ffado_playback_channel_t *)calloc(driver->playback_nchannels, sizeof(ffado_playback_channel_t));
00483     if (driver->playback_channels == NULL) {
00484         printError("could not allocate memory for playback channel list");
00485         return -1;
00486     }
00487 
00488     fPlaybackChannels = 0;
00489     for (channel_t chn = 0; chn < driver->playback_nchannels; chn++) {
00490         ffado_streaming_get_playback_stream_name(driver->dev, chn, portname, sizeof(portname));
00491 
00492         driver->playback_channels[chn].stream_type = ffado_streaming_get_playback_stream_type(driver->dev, chn);
00493 
00494         if (driver->playback_channels[chn].stream_type == ffado_stream_type_audio) {
00495             snprintf(buf, sizeof(buf), "firewire_pcm:%s_out", portname);
00496             printMessage ("Registering audio playback port %s", buf);
00497             if (fEngine->PortRegister(fClientControl.fRefNum, buf,
00498                               JACK_DEFAULT_AUDIO_TYPE,
00499                               PlaybackDriverFlags,
00500                               fEngineControl->fBufferSize, &port_index) < 0) {
00501                 jack_error("driver: cannot register port for %s", buf);
00502                 return -1;
00503             }
00504 
00505             // setup port parameters
00506             if (ffado_streaming_set_playback_stream_buffer(driver->dev, chn, NULL)) {
00507                 printError(" cannot configure initial port buffer for %s", buf);
00508             }
00509             if (ffado_streaming_playback_stream_onoff(driver->dev, chn, 0)) {
00510                 printError(" cannot enable port %s", buf);
00511             }
00512 
00513             port = fGraphManager->GetPort(port_index);
00514             // Add one buffer more latency if "async" mode is used...
00515             range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency;
00516             port->SetLatencyRange(JackPlaybackLatency, &range);
00517             // playback port aliases (jackd1 style port names)
00518             snprintf(buf, sizeof(buf), "%s:playback_%i", fClientControl.fName, (int) chn + 1);
00519             port->SetAlias(buf);
00520             fPlaybackPortList[chn] = port_index;
00521             jack_log("JackFFADODriver::Attach fPlaybackPortList[i] %ld ", port_index);
00522             fPlaybackChannels++;
00523         } else if (driver->playback_channels[chn].stream_type == ffado_stream_type_midi) {
00524             snprintf(buf, sizeof(buf), "firewire_pcm:%s_out", portname);
00525             printMessage ("Registering midi playback port %s", buf);
00526 
00527             if (fEngine->PortRegister(fClientControl.fRefNum, buf,
00528                               JACK_DEFAULT_MIDI_TYPE,
00529                               PlaybackDriverFlags,
00530                               fEngineControl->fBufferSize, &port_index) < 0) {
00531                 jack_error("driver: cannot register port for %s", buf);
00532                 return -1;
00533             }
00534 
00535             // setup port parameters
00536             if (ffado_streaming_set_playback_stream_buffer(driver->dev, chn, NULL)) {
00537                 printError(" cannot configure initial port buffer for %s", buf);
00538             }
00539             if (ffado_streaming_playback_stream_onoff(driver->dev, chn, 0)) {
00540                 printError(" cannot enable port %s", buf);
00541             }
00542             // setup the midi buffer
00543 
00544             // This constructor optionally accepts arguments for the
00545             // non-realtime buffer size and the realtime buffer size.  Ideally,
00546             // these would become command-line options for the FFADO driver.
00547             driver->playback_channels[chn].midi_output = new JackFFADOMidiOutputPort();
00548 
00549             driver->playback_channels[chn].midi_buffer = (uint32_t *)calloc(driver->period_size, sizeof(uint32_t));
00550 
00551             port = fGraphManager->GetPort(port_index);
00552             range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency;
00553             port->SetLatencyRange(JackPlaybackLatency, &range);
00554             fPlaybackPortList[chn] = port_index;
00555             jack_log("JackFFADODriver::Attach fPlaybackPortList[i] %ld ", port_index);
00556             fPlaybackChannels++;
00557         } else {
00558             printMessage ("Don't register playback port %s", portname);
00559         }
00560     }
00561 
00562     assert(fCaptureChannels < DRIVER_PORT_NUM);
00563     assert(fPlaybackChannels < DRIVER_PORT_NUM);
00564 
00565     if (ffado_streaming_prepare(driver->dev)) {
00566         printError("Could not prepare streaming device!");
00567         return -1;
00568     }
00569 
00570     // this makes no sense...
00571     assert(fCaptureChannels + fPlaybackChannels > 0);
00572     return 0;
00573 }
00574 
00575 int JackFFADODriver::Detach()
00576 {
00577     channel_t chn;
00578     ffado_driver_t* driver = (ffado_driver_t*)fDriver;
00579     jack_log("JackFFADODriver::Detach");
00580 
00581     // finish the libfreebob streaming
00582     ffado_streaming_finish(driver->dev);
00583     driver->dev = NULL;
00584 
00585     // free all internal buffers
00586     for (chn = 0; chn < driver->capture_nchannels; chn++) {
00587         if (driver->capture_channels[chn].midi_buffer)
00588             free(driver->capture_channels[chn].midi_buffer);
00589         if (driver->capture_channels[chn].midi_input)
00590             delete ((JackFFADOMidiInputPort *) (driver->capture_channels[chn].midi_input));
00591     }
00592     free(driver->capture_channels);
00593 
00594     for (chn = 0; chn < driver->playback_nchannels; chn++) {
00595         if (driver->playback_channels[chn].midi_buffer)
00596             free(driver->playback_channels[chn].midi_buffer);
00597         if (driver->playback_channels[chn].midi_output)
00598             delete ((JackFFADOMidiOutputPort *) (driver->playback_channels[chn].midi_output));
00599     }
00600     free(driver->playback_channels);
00601 
00602     free(driver->nullbuffer);
00603     free(driver->scratchbuffer);
00604 
00605     return JackAudioDriver::Detach();  // Generic JackAudioDriver Detach
00606 }
00607 
00608 int JackFFADODriver::Open(ffado_jack_settings_t *params)
00609 {
00610     // Generic JackAudioDriver Open
00611     if (JackAudioDriver::Open(
00612                 params->period_size, params->sample_rate,
00613                 params->playback_ports, params->playback_ports,
00614                 0, 0, 0, "", "",
00615                 params->capture_frame_latency, params->playback_frame_latency) != 0) {
00616         return -1;
00617     }
00618 
00619     fDriver = (jack_driver_t *)ffado_driver_new ("ffado_pcm", params);
00620 
00621     if (fDriver) {
00622         // FFADO driver may have changed the in/out values
00623         //fCaptureChannels = ((ffado_driver_t *)fDriver)->capture_nchannels_audio;
00624         //fPlaybackChannels = ((ffado_driver_t *)fDriver)->playback_nchannels_audio;
00625         return 0;
00626     } else {
00627         JackAudioDriver::Close();
00628         return -1;
00629     }
00630 }
00631 
00632 int JackFFADODriver::Close()
00633 {
00634     // Generic audio driver close
00635     int res = JackAudioDriver::Close();
00636 
00637     ffado_driver_delete((ffado_driver_t*)fDriver);
00638     return res;
00639 }
00640 
00641 int JackFFADODriver::Start()
00642 {
00643     int res = JackAudioDriver::Start();
00644     if (res >= 0) {
00645         res = ffado_driver_start((ffado_driver_t *)fDriver);
00646         if (res < 0) {
00647             JackAudioDriver::Stop();
00648         }
00649     }
00650     return res;
00651 }
00652 
00653 int JackFFADODriver::Stop()
00654 {
00655     int res = ffado_driver_stop((ffado_driver_t *)fDriver);
00656     if (JackAudioDriver::Stop() < 0) {
00657         res = -1;
00658     }
00659     return res;
00660 }
00661 
00662 int JackFFADODriver::Read()
00663 {
00664     printEnter();
00665 
00666     /* Taken from ffado_driver_run_cycle */
00667     ffado_driver_t* driver = (ffado_driver_t*)fDriver;
00668     int wait_status = 0;
00669     fDelayedUsecs = 0.f;
00670 
00671 retry:
00672 
00673     jack_nframes_t nframes = ffado_driver_wait(driver, -1, &wait_status,
00674                              &fDelayedUsecs);
00675 
00676     if ((wait_status < 0)) {
00677         printError( "wait status < 0! (= %d)", wait_status);
00678         return -1;
00679     }
00680 
00681     if (nframes == 0) {
00682         /* we detected an xrun and restarted: notify
00683          * clients about the delay.
00684          */
00685         jack_log("FFADO XRun");
00686         NotifyXRun(fBeginDateUst, fDelayedUsecs);
00687         goto retry; /* recoverable error*/
00688     }
00689 
00690     if (nframes != fEngineControl->fBufferSize)
00691         jack_log("JackFFADODriver::Read warning nframes = %ld", nframes);
00692 
00693     // Has to be done before read
00694     JackDriver::CycleIncTime();
00695 
00696     printExit();
00697     return ffado_driver_read((ffado_driver_t *)fDriver, fEngineControl->fBufferSize);
00698 }
00699 
00700 int JackFFADODriver::Write()
00701 {
00702     printEnter();
00703     int res = ffado_driver_write((ffado_driver_t *)fDriver, fEngineControl->fBufferSize);
00704     printExit();
00705     return res;
00706 }
00707 
00708 void
00709 JackFFADODriver::jack_driver_init (jack_driver_t *driver)
00710 {
00711     memset (driver, 0, sizeof (*driver));
00712 
00713     driver->attach = 0;
00714     driver->detach = 0;
00715     driver->write = 0;
00716     driver->read = 0;
00717     driver->null_cycle = 0;
00718     driver->bufsize = 0;
00719     driver->start = 0;
00720     driver->stop = 0;
00721 }
00722 
00723 void
00724 JackFFADODriver::jack_driver_nt_init (jack_driver_nt_t * driver)
00725 {
00726     memset (driver, 0, sizeof (*driver));
00727 
00728     jack_driver_init ((jack_driver_t *) driver);
00729 
00730     driver->attach = 0;
00731     driver->detach = 0;
00732     driver->bufsize = 0;
00733     driver->stop = 0;
00734     driver->start = 0;
00735 
00736     driver->nt_bufsize = 0;
00737     driver->nt_start = 0;
00738     driver->nt_stop = 0;
00739     driver->nt_attach = 0;
00740     driver->nt_detach = 0;
00741     driver->nt_run_cycle = 0;
00742 }
00743 
00744 } // end of namespace
00745 
00746 
00747 #ifdef __cplusplus
00748 extern "C"
00749 {
00750 #endif
00751 
00752     SERVER_EXPORT const jack_driver_desc_t *
00753     driver_get_descriptor () {
00754         jack_driver_desc_t * desc;
00755         jack_driver_desc_filler_t filler;
00756         jack_driver_param_value_t value;
00757 
00758         desc = jack_driver_descriptor_construct("firewire", JackDriverMaster, "Linux FFADO API based audio backend", &filler);
00759 
00760         strcpy(value.str, "hw:0");
00761         jack_driver_descriptor_add_parameter(
00762             desc,
00763             &filler,
00764             "device",
00765             'd',
00766             JackDriverParamString,
00767             &value,
00768             NULL,
00769             "The FireWire device to use.",
00770             "The FireWire device to use. Please consult the FFADO documentation for more info.");
00771 
00772         value.ui = 1024;
00773         jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
00774 
00775         value.ui = 3;
00776         jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods of playback latency", NULL);
00777 
00778         value.ui = 48000U;
00779         jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
00780 
00781         value.i = 0;
00782         jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamBool, &value, NULL, "Provide capture ports.", NULL);
00783         jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamBool, &value, NULL, "Provide playback ports.", NULL);
00784 
00785         value.i = 1;
00786         jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports.", NULL);
00787 
00788         value.ui = 0;
00789         jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency (frames)", NULL);
00790         jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency (frames)", NULL);
00791 
00792         value.ui = 0;
00793         jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "Number of input channels to provide (note: currently ignored)", NULL);
00794         jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "Number of output channels to provide (note: currently ignored)", NULL);
00795 
00796         value.ui = 3;
00797         jack_driver_descriptor_add_parameter(desc, &filler, "verbose", 'v', JackDriverParamUInt, &value, NULL, "libffado verbose level", NULL);
00798 
00799         value.i = 0;
00800         jack_driver_descriptor_add_parameter(desc, &filler, "snoop", 'X', JackDriverParamBool, &value, NULL, "Snoop firewire traffic", NULL);
00801 
00802         return desc;
00803     }
00804 
00805     SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) {
00806         const JSList * node;
00807         const jack_driver_param_t * param;
00808 
00809         ffado_jack_settings_t cmlparams;
00810 
00811         char *device_name=(char*)"hw:0";
00812 
00813         cmlparams.period_size_set = 0;
00814         cmlparams.sample_rate_set = 0;
00815         cmlparams.buffer_size_set = 0;
00816 
00817         /* default values */
00818         cmlparams.period_size = 1024;
00819         cmlparams.sample_rate = 48000;
00820         cmlparams.buffer_size = 3;
00821         cmlparams.playback_ports = 0;
00822         cmlparams.capture_ports = 0;
00823         cmlparams.playback_frame_latency = 0;
00824         cmlparams.capture_frame_latency = 0;
00825 
00826         cmlparams.verbose_level = 0;
00827 
00828         cmlparams.slave_mode = 0;
00829         cmlparams.snoop_mode = 0;
00830         cmlparams.device_info = NULL;
00831 
00832         for (node = params; node; node = jack_slist_next (node)) {
00833             param = (jack_driver_param_t *) node->data;
00834 
00835             switch (param->character) {
00836                 case 'd':
00837                     device_name = const_cast<char*>(param->value.str);
00838                     break;
00839                 case 'p':
00840                     cmlparams.period_size = param->value.ui;
00841                     cmlparams.period_size_set = 1;
00842                     break;
00843                 case 'n':
00844                     cmlparams.buffer_size = param->value.ui;
00845                     cmlparams.buffer_size_set = 1;
00846                     break;
00847                 case 'r':
00848                     cmlparams.sample_rate = param->value.ui;
00849                     cmlparams.sample_rate_set = 1;
00850                     break;
00851                 case 'i':
00852                     cmlparams.capture_ports = param->value.ui;
00853                     break;
00854                 case 'o':
00855                     cmlparams.playback_ports = param->value.ui;
00856                     break;
00857                 case 'I':
00858                     cmlparams.capture_frame_latency = param->value.ui;
00859                     break;
00860                 case 'O':
00861                     cmlparams.playback_frame_latency = param->value.ui;
00862                     break;
00863                 case 'x':
00864                     cmlparams.slave_mode = param->value.ui;
00865                     break;
00866                 case 'X':
00867                     cmlparams.snoop_mode = param->value.i;
00868                     break;
00869                 case 'v':
00870                     cmlparams.verbose_level = param->value.ui;
00871             }
00872         }
00873 
00874         /* duplex is the default */
00875         if (!cmlparams.playback_ports && !cmlparams.capture_ports) {
00876             cmlparams.playback_ports = 1;
00877             cmlparams.capture_ports = 1;
00878         }
00879 
00880         // temporary
00881         cmlparams.device_info = device_name;
00882 
00883         Jack::JackFFADODriver* ffado_driver = new Jack::JackFFADODriver("system", "firewire_pcm", engine, table);
00884         Jack::JackDriverClientInterface* threaded_driver = new Jack::JackThreadedDriver(ffado_driver);
00885         // Special open for FFADO driver...
00886         if (ffado_driver->Open(&cmlparams) == 0) {
00887             return threaded_driver;
00888         } else {
00889             delete threaded_driver; // Delete the decorated driver
00890             return NULL;
00891         }
00892     }
00893 
00894 #ifdef __cplusplus
00895 }
00896 #endif
00897 
00898