Jack2 1.9.8
|
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