diff -rupN jack-1.9.8.old/linux/firewire/JackFFADODriver.cpp jack-1.9.8/linux/firewire/JackFFADODriver.cpp --- jack-1.9.8.old/linux/firewire/JackFFADODriver.cpp 2011-12-19 06:54:27.000000000 -0500 +++ jack-1.9.8/linux/firewire/JackFFADODriver.cpp 2012-03-25 01:38:58.246513167 -0400 @@ -3,6 +3,7 @@ Copyright (C) 2001 Paul Davis Copyright (C) 2004 Grame Copyright (C) 2007 Pieter Palmers Copyright (C) 2009 Devin Anderson +Copyright (C) 2012 Jonathan Woithe, Adrian Knoth This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,10 +46,20 @@ Foundation, Inc., 675 Mass Ave, Cambridg #include "JackCompilerDeps.h" #include "JackLockedEngine.h" +// FFADO_API_VERSION was first defined with API_VERSION 9, so all previous +// headers do not provide this define. +#ifndef FFADO_API_VERSION +extern "C" int ffado_streaming_set_period_size(ffado_device_t *dev, + unsigned int period) __attribute__((__weak__)); +#endif + namespace Jack { +// Basic functionality requires API version 8. If version 9 or later +// is present the buffers can be resized at runtime. #define FIREWIRE_REQUIRED_FFADO_API_VERSION 8 +#define FIREWIRE_REQUIRED_FFADO_API_VERSION_FOR_SETBUFSIZE 9 #define jack_get_microseconds GetMicroSeconds @@ -253,22 +264,96 @@ JackFFADODriver::ffado_driver_restart (f return Start(); } +void +JackFFADODriver::UpdateLatencies(void) +{ + jack_latency_range_t range; + ffado_driver_t* driver = (ffado_driver_t*)fDriver; + + for (int i = 0; i < fCaptureChannels; i++) { + range.min = range.max = driver->period_size + driver->capture_frame_latency; + fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &range); + } + + for (int i = 0; i < fPlaybackChannels; i++) { + // Add one buffer more latency if "async" mode is used... + range.min = range.max = (driver->period_size * + (driver->device_options.nb_buffers - 1)) + + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency; + fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &range); + // Monitor port + if (fWithMonitorPorts) { + range.min = range.max =driver->period_size; + fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &range); + } + } +} + int JackFFADODriver::SetBufferSize (jack_nframes_t nframes) { - printError("Buffer size change requested but not supported!!!"); + ffado_driver_t* driver = (ffado_driver_t*)fDriver; + signed int chn; + + // The speed of this function isn't critical; we can afford the + // time to check the FFADO API version. + if (ffado_get_api_version() < FIREWIRE_REQUIRED_FFADO_API_VERSION_FOR_SETBUFSIZE || + ffado_streaming_set_period_size == NULL) { + printError("unsupported on current version of FFADO; please upgrade FFADO"); + return -1; + } - /* driver->period_size = nframes; driver->period_usecs = (jack_time_t) floor ((((float) nframes) / driver->sample_rate) * 1000000.0f); - */ + + + // Reallocate the null and scratch buffers. + driver->nullbuffer = (ffado_sample_t*) calloc(driver->period_size, sizeof(ffado_sample_t)); + if(driver->nullbuffer == NULL) { + printError("could not allocate memory for null buffer"); + return -1; + } + driver->scratchbuffer = (ffado_sample_t*) calloc(driver->period_size, sizeof(ffado_sample_t)); + if(driver->scratchbuffer == NULL) { + printError("could not allocate memory for scratch buffer"); + return -1; + } + + // MIDI buffers need reallocating + for (chn = 0; chn < driver->capture_nchannels; chn++) { + if(driver->capture_channels[chn].stream_type == ffado_stream_type_midi) { + // setup the midi buffer + if (driver->capture_channels[chn].midi_buffer != NULL) + free(driver->capture_channels[chn].midi_buffer); + driver->capture_channels[chn].midi_buffer = (ffado_sample_t*) calloc(driver->period_size, sizeof(uint32_t)); + } + } + for (chn = 0; chn < driver->playback_nchannels; chn++) { + if(driver->playback_channels[chn].stream_type == ffado_stream_type_midi) { + if (driver->playback_channels[chn].midi_buffer != NULL) + free(driver->playback_channels[chn].midi_buffer); + driver->playback_channels[chn].midi_buffer = (ffado_sample_t*) calloc(driver->period_size, sizeof(uint32_t)); + } + } + + // Notify FFADO of the period size change + if (ffado_streaming_set_period_size(driver->dev, nframes) != 0) { + printError("could not alter FFADO device period size"); + return -1; + } + + // This is needed to give the shadow variables a chance to + // properly update to the changes. + sleep(1); /* tell the engine to change its buffer size */ - //driver->engine->set_buffer_size (driver->engine, nframes); + JackAudioDriver::SetBufferSize(nframes); // Generic change, never fails + + UpdateLatencies(); - return -1; // unsupported + return 0; } typedef void (*JackDriverFinishFunction) (jack_driver_t *); @@ -281,7 +366,7 @@ JackFFADODriver::ffado_driver_new (const assert(params); - if (ffado_get_api_version() != FIREWIRE_REQUIRED_FFADO_API_VERSION) { + if (ffado_get_api_version() < FIREWIRE_REQUIRED_FFADO_API_VERSION) { printError("Incompatible libffado version! (%s)", ffado_get_version()); return NULL; } @@ -349,7 +434,6 @@ int JackFFADODriver::Attach() jack_port_id_t port_index; char buf[REAL_JACK_PORT_NAME_SIZE]; char portname[REAL_JACK_PORT_NAME_SIZE]; - jack_latency_range_t range; ffado_driver_t* driver = (ffado_driver_t*)fDriver; @@ -435,8 +519,6 @@ int JackFFADODriver::Attach() ffado_streaming_capture_stream_onoff(driver->dev, chn, 0); port = fGraphManager->GetPort(port_index); - range.min = range.max = driver->period_size + driver->capture_frame_latency; - port->SetLatencyRange(JackCaptureLatency, &range); // capture port aliases (jackd1 style port names) snprintf(buf, sizeof(buf), "%s:capture_%i", fClientControl.fName, (int) chn + 1); port->SetAlias(buf); @@ -466,9 +548,6 @@ int JackFFADODriver::Attach() // setup the midi buffer driver->capture_channels[chn].midi_buffer = (uint32_t *)calloc(driver->period_size, sizeof(uint32_t)); - port = fGraphManager->GetPort(port_index); - range.min = range.max = driver->period_size + driver->capture_frame_latency; - port->SetLatencyRange(JackCaptureLatency, &range); fCapturePortList[chn] = port_index; jack_log("JackFFADODriver::Attach fCapturePortList[i] %ld ", port_index); fCaptureChannels++; @@ -512,8 +591,6 @@ int JackFFADODriver::Attach() port = fGraphManager->GetPort(port_index); // Add one buffer more latency if "async" mode is used... - range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency; - port->SetLatencyRange(JackPlaybackLatency, &range); // playback port aliases (jackd1 style port names) snprintf(buf, sizeof(buf), "%s:playback_%i", fClientControl.fName, (int) chn + 1); port->SetAlias(buf); @@ -548,9 +625,6 @@ int JackFFADODriver::Attach() driver->playback_channels[chn].midi_buffer = (uint32_t *)calloc(driver->period_size, sizeof(uint32_t)); - port = fGraphManager->GetPort(port_index); - range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency; - port->SetLatencyRange(JackPlaybackLatency, &range); fPlaybackPortList[chn] = port_index; jack_log("JackFFADODriver::Attach fPlaybackPortList[i] %ld ", port_index); fPlaybackChannels++; @@ -559,6 +633,8 @@ int JackFFADODriver::Attach() } } + UpdateLatencies(); + assert(fCaptureChannels < DRIVER_PORT_NUM); assert(fPlaybackChannels < DRIVER_PORT_NUM); diff -rupN jack-1.9.8.old/linux/firewire/JackFFADODriver.h jack-1.9.8/linux/firewire/JackFFADODriver.h --- jack-1.9.8.old/linux/firewire/JackFFADODriver.h 2011-12-19 06:54:27.000000000 -0500 +++ jack-1.9.8/linux/firewire/JackFFADODriver.h 2012-03-25 01:38:05.708754669 -0400 @@ -2,6 +2,7 @@ Copyright (C) 2001 Paul Davis Copyright (C) 2004 Grame Copyright (C) 2007 Pieter Palmers +Copyright (C) 2012 Adrian Knoth This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -59,6 +60,7 @@ class JackFFADODriver : public JackAudio void jack_driver_init (jack_driver_t *driver); void jack_driver_nt_init (jack_driver_nt_t * driver); + void UpdateLatencies(); public: @@ -80,6 +82,12 @@ class JackFFADODriver : public JackAudio int Read(); int Write(); + // BufferSize can be changed + bool IsFixedBufferSize() + { + return false; + } + int SetBufferSize(jack_nframes_t nframes); };