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