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