From 96e0251234a29a1360c05d5d7dc98b83436b8183 Mon Sep 17 00:00:00 2001 From: Adrian Knoth Date: Sat, 17 Mar 2012 22:36:30 +0100 Subject: [PATCH] [firewire] Allow FFADO backend to change the buffer size This is a port of Jonathan Woithe's patch from jackd1. With sufficiently recent versions of FFADO, it allows to change the buffersize at runtime. --- linux/firewire/JackFFADODriver.cpp | 65 ++++++++++++++++++++++++++++++++---- linux/firewire/JackFFADODriver.h | 6 ++++ 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/linux/firewire/JackFFADODriver.cpp b/linux/firewire/JackFFADODriver.cpp index b33e1cd..085b78a 100644 --- a/linux/firewire/JackFFADODriver.cpp +++ b/linux/firewire/JackFFADODriver.cpp @@ -3,6 +3,7 @@ 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 @@ -48,7 +49,10 @@ 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 @@ -281,19 +285,68 @@ 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 - return -1; // unsupported + UpdateLatencies(); + + return 0; } typedef void (*JackDriverFinishFunction) (jack_driver_t *); @@ -306,7 +359,7 @@ 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; } diff --git a/linux/firewire/JackFFADODriver.h b/linux/firewire/JackFFADODriver.h index cb2a45d..790f4dd 100644 --- a/linux/firewire/JackFFADODriver.h +++ b/linux/firewire/JackFFADODriver.h @@ -82,6 +82,12 @@ class JackFFADODriver : public JackAudioDriver int Read(); int Write(); + // BufferSize can be changed + bool IsFixedBufferSize() + { + return false; + } + int SetBufferSize(jack_nframes_t nframes); }; -- 1.7.10