[Jack-Devel] [PATCH] initial setbufsize support for FFADO driver

PrevNext  Index
DateSun, 11 Mar 2012 00:54:03 +1030
From Jonathan Woithe <[hidden] at just42 dot net>
To[hidden] at lists dot jackaudio dot org
Cc[hidden] at lists dot sf dot net
Follow-UpAdrian Knoth Re: [Jack-Devel] [PATCH] initial setbufsize support for FFADO driver
Follow-UpAdrian Knoth Re: [FFADO-devel] [Jack-Devel] [PATCH] initial setbufsize support for FFADO driver
Hi all

Recent discussion about setbufsize raised the issue that the ffado driver
does not yet support this.  Below is a patch to the jack ffado driver which
contains a first pass at fixing this problem.  I've tested it with only one
device (the Fireface-800, taking it from 1024 to 2048) and it seems to work. 
It undoubtedly requires more testing (particularly the code within libffado)
but obviously this will be made easier for end users if the jackd driver
modifications are pushed into the official jack repo.

The patch provided is against jackd 0.121.3.  It should apply cleanly to
the latest jack source because the ffado driver hasn't changed for a
significant length of time (certainly not in the time since 0.121.3 was
released).

This patch does have an issue though and I'm interested to hear thoughts on
how to solve it.  It turns out that until FFADO svn rev 2078, libffado had
no callable function which allowed the buffer size notification to be sent
(probably because the idea of changing buffer sizes on the fly wasn't
thought of).  To this end, such a function has been added to FFADO svn
r2078: ffado_streaming_set_period_size().  The issue is that clearly this
constitutes a libffado API change - a new function has been added and the
revised jack ffado driver will not compile unless one has a sufficiently
recent version of ffado on the system.  In light of this, what is the best
way of proceeding?

Finally, once the above issue is sorted out there's obviously a need to port
this revised driver function into the jack2 codebase as well.  Who's
responsibility is that these days?  Mine (which could be interesting because
I don't run jack2 on my systems at present)?

Regards
  jonathan

--- jack-audio-connection-kit-0.121.3-orig/drivers/firewire/ffado_driver.c	2011-06-09 09:24:49.000000000 +0930
+++ jack-audio-connection-kit-0.121.3/drivers/firewire/ffado_driver.c	2012-03-11 00:27:30.849870825 +1030
@@ -675,24 +675,63 @@
 static int
 ffado_driver_bufsize (ffado_driver_t* driver, jack_nframes_t nframes)
 {
-	printError("Buffer size change requested but not supported!!!");
+	signed int chn;
 
-	/*
-	 driver->period_size = nframes;  
+	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 = calloc(driver->period_size, sizeof(ffado_sample_t));
+	if(driver->nullbuffer == NULL) {
+		printError("could not allocate memory for null buffer");
+		return -1;
+	}
+	driver->scratchbuffer = 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 = 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 = 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 */
-#if 0
 	if (driver->engine->set_buffer_size (driver->engine, nframes)) {
 		jack_error ("FFADO: cannot set engine buffer size to %d (check MIDI)", nframes);
 		return -1;
 	}
-#endif
 
-	return -1; // unsupported
+	// Other drivers (eg: ALSA) don't seem to adjust latencies via
+	// jack_port_set_latency_range() from the bufsize() callback, so we
+	// won't either.  Is this right?
+
+        return 0;
 }
 
 typedef void (*JackDriverFinishFunction) (jack_driver_t *);
PrevNext  Index

1331389462.29804_0.ltw:2, <20120310142403.GA14492 at marvin dot atrad dot com dot au>