00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00064 if (fGraphManager->GetConnectionsNum(fCapturePortList[chn]) == 0) {
00065 buf = (jack_default_audio_sample_t*)driver->scratchbuffer;
00066
00067 ffado_streaming_set_capture_stream_buffer(driver->dev, chn, (char *)(buf));
00068
00069
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
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 {
00085 ffado_streaming_set_capture_stream_buffer(driver->dev, chn, (char *)(driver->scratchbuffer));
00086
00087 ffado_streaming_capture_stream_onoff(driver->dev, chn, 0);
00088 }
00089 }
00090 }
00091
00092
00093 ffado_streaming_transfer_capture_buffers(driver->dev);
00094
00095
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
00121 ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(buf));
00122
00123
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
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 {
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
00166
00167
00168
00169 driver->wait_next = 0;
00170 driver->wait_late++;
00171 }
00172
00173
00174
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
00186
00187 if(response == ffado_wait_ok) {
00188
00189 *status = 0;
00190 } else if (response == ffado_wait_xrun) {
00191
00192 *status = 0;
00193 return 0;
00194 } else if (response == ffado_wait_error) {
00195
00196
00197 jack_error("JackFFADODriver::ffado_driver_wait - unhandled xrun");
00198 *status = -1;
00199 return 0;
00200 } else if (response == ffado_wait_shutdown) {
00201
00202
00203 jack_error("JackFFADODriver::ffado_driver_wait - shutdown requested "
00204 "(device unplugged?)");
00205 *status = -1;
00206 return 0;
00207 } else {
00208
00209
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
00263
00264
00265
00266
00267
00268
00269
00270
00271 return -1;
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
00294 jack_driver_nt_init ((jack_driver_nt_t *) driver);
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 memcpy(&driver->settings, params, sizeof(ffado_jack_settings_t));
00309
00310
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
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
00361
00362
00363
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
00370 memset(driver->nullbuffer, 0, driver->period_size*sizeof(ffado_sample_t));
00371
00372
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
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
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
00406
00407
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
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
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
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
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
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
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
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
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
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
00543
00544
00545
00546
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
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
00582 ffado_streaming_finish(driver->dev);
00583 driver->dev = NULL;
00584
00585
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();
00606 }
00607
00608 int JackFFADODriver::Open(ffado_jack_settings_t *params)
00609 {
00610
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
00623
00624
00625 return 0;
00626 } else {
00627 JackAudioDriver::Close();
00628 return -1;
00629 }
00630 }
00631
00632 int JackFFADODriver::Close()
00633 {
00634
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
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
00683
00684
00685 jack_log("FFADO XRun");
00686 NotifyXRun(fBeginDateUst, fDelayedUsecs);
00687 goto retry;
00688 }
00689
00690 if (nframes != fEngineControl->fBufferSize)
00691 jack_log("JackFFADODriver::Read warning nframes = %ld", nframes);
00692
00693
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 }
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
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
00875 if (!cmlparams.playback_ports && !cmlparams.capture_ports) {
00876 cmlparams.playback_ports = 1;
00877 cmlparams.capture_ports = 1;
00878 }
00879
00880
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
00886 if (ffado_driver->Open(&cmlparams) == 0) {
00887 return threaded_driver;
00888 } else {
00889 delete threaded_driver;
00890 return NULL;
00891 }
00892 }
00893
00894 #ifdef __cplusplus
00895 }
00896 #endif
00897
00898