Blame src/libout123/modules/jack.c

Packit c32a2d
/*
Packit c32a2d
	jack: audio output via JACK Audio Connection Kit
Packit c32a2d
Packit c32a2d
	copyright 2006-2016 by the mpg123 project - free software under the terms of the LGPL 2.1
Packit c32a2d
	see COPYING and AUTHORS files in distribution or http://mpg123.org
Packit c32a2d
	initially written by Nicholas J. Humfrey
Packit c32a2d
Packit c32a2d
	I reworked the processing logic. Only one ringbuffer, deinterleaving in the
Packit c32a2d
	processing callback. A semaphore to avoid using usleep() for waiting. Up
Packit c32a2d
	to 99 channels. Only float input (ensures that libmpg123 selects f32
Packit c32a2d
	encoding). This is still a hack to shoehorn the JACK API into our model.
Packit c32a2d
Packit c32a2d
	Damn. I'm wary of he semaphore. I'm sure I constructed a deadlock there.
Packit c32a2d
	There's always a deadlock. --ThOr
Packit c32a2d
*/
Packit c32a2d
Packit c32a2d
#include "out123_int.h"
Packit c32a2d
Packit c32a2d
#include <math.h>
Packit c32a2d
Packit c32a2d
#include <jack/jack.h>
Packit c32a2d
#include <jack/ringbuffer.h>
Packit c32a2d
/* Using some pthread to provide synchronization between process callback
Packit c32a2d
   and writer part. The JACK API is not meant for this. Libpthread is
Packit c32a2d
   pulled in as libjack dependency anyway. */
Packit c32a2d
#include <semaphore.h>
Packit c32a2d
#include <sys/errno.h>
Packit c32a2d
Packit c32a2d
#include "debug.h"
Packit c32a2d
Packit c32a2d
typedef struct {
Packit c32a2d
	int alive;
Packit c32a2d
	sem_t sem; /* semaphore to avoid busy waiting */
Packit c32a2d
	int channels;
Packit c32a2d
	int encoding;
Packit c32a2d
	int framesize;
Packit c32a2d
	jack_default_audio_sample_t **ports_buf;
Packit c32a2d
	jack_port_t **ports;
Packit c32a2d
	jack_ringbuffer_t *rb;
Packit c32a2d
	size_t rb_size; /* in bytes */
Packit c32a2d
	jack_client_t *client;
Packit c32a2d
	char *procbuf;
Packit c32a2d
	size_t procbuf_frames; /* in PCM frames */
Packit c32a2d
} jack_handle_t, *jack_handle_ptr;
Packit c32a2d
Packit c32a2d
static jack_handle_t* alloc_jack_handle(out123_handle *ao)
Packit c32a2d
{
Packit c32a2d
	jack_handle_t *handle=NULL;
Packit c32a2d
	int i;
Packit c32a2d
Packit c32a2d
	handle = malloc(sizeof(jack_handle_t));
Packit c32a2d
	if (!handle)
Packit c32a2d
		return NULL;
Packit c32a2d
	handle->channels = ao->channels;
Packit c32a2d
	handle->encoding = ao->format;
Packit c32a2d
	handle->framesize = ao->framesize;
Packit c32a2d
	handle->rb = NULL;
Packit c32a2d
	handle->ports_buf = malloc( sizeof(jack_default_audio_sample_t*)
Packit c32a2d
	*	ao->channels );
Packit c32a2d
	handle->ports = malloc(sizeof(jack_port_t*)*ao->channels);
Packit c32a2d
	if(!handle->ports_buf || !handle->ports)
Packit c32a2d
	{
Packit c32a2d
		if(handle->ports_buf)
Packit c32a2d
			free(handle->ports_buf);
Packit c32a2d
		if(handle->ports)
Packit c32a2d
			free(handle->ports);
Packit c32a2d
		free(handle);
Packit c32a2d
		return NULL;
Packit c32a2d
	}
Packit c32a2d
	for(i=0; i<ao->channels; ++i)
Packit c32a2d
	{
Packit c32a2d
		handle->ports_buf[i] = NULL;
Packit c32a2d
		handle->ports[i] = NULL;
Packit c32a2d
	}
Packit c32a2d
	if(sem_init(&handle->sem, 0, 0))
Packit c32a2d
	{
Packit c32a2d
		if(!AOQUIET)
Packit c32a2d
			error("Semaphore init failed.");
Packit c32a2d
		free(handle->ports_buf);
Packit c32a2d
		free(handle->ports);
Packit c32a2d
		free(handle);
Packit c32a2d
		return NULL;
Packit c32a2d
	}
Packit c32a2d
	handle->alive = 0;
Packit c32a2d
	handle->client = NULL;
Packit c32a2d
	handle->procbuf = NULL;
Packit c32a2d
	handle->rb_size = 0;
Packit c32a2d
	handle->procbuf_frames = 0;
Packit c32a2d
Packit c32a2d
	return handle;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
Packit c32a2d
static void free_jack_handle( jack_handle_t* handle )
Packit c32a2d
{
Packit c32a2d
	int i;
Packit c32a2d
Packit c32a2d
	if(handle->ports)
Packit c32a2d
	{
Packit c32a2d
		if(handle->client)
Packit c32a2d
		for(i=0; i<handle->channels; i++)
Packit c32a2d
		{
Packit c32a2d
			/* Close the port for channel*/
Packit c32a2d
			if(handle->ports[i])
Packit c32a2d
				jack_port_unregister(handle->client, handle->ports[i]);
Packit c32a2d
		}
Packit c32a2d
		free(handle->ports);
Packit c32a2d
	}
Packit c32a2d
	if(handle->ports_buf)
Packit c32a2d
		free(handle->ports_buf);
Packit c32a2d
	/* Free up the ring buffer for channel*/
Packit c32a2d
	if(handle->rb)
Packit c32a2d
		jack_ringbuffer_free(handle->rb);
Packit c32a2d
	if (handle->client)
Packit c32a2d
		jack_client_close(handle->client);
Packit c32a2d
	if (handle->procbuf)
Packit c32a2d
		free(handle->procbuf);
Packit c32a2d
	sem_destroy(&handle->sem);
Packit c32a2d
	free(handle);
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
Packit c32a2d
static int process_callback( jack_nframes_t nframes, void *arg )
Packit c32a2d
{
Packit c32a2d
	int c;
Packit c32a2d
	jack_handle_t* handle = (jack_handle_t*)arg;
Packit c32a2d
	size_t to_read = nframes;
Packit c32a2d
Packit c32a2d
	for(c=0; c<handle->channels; ++c)
Packit c32a2d
		handle->ports_buf[c] =
Packit c32a2d
			jack_port_get_buffer(handle->ports[c], nframes);
Packit c32a2d
Packit c32a2d
	/* One ringbuffer to rule them all, getting interleaved data piecewise
Packit c32a2d
	   and appending to non-interleaved buffers. */
Packit c32a2d
	while(to_read)
Packit c32a2d
	{
Packit c32a2d
		/* Need to read into temporary storage, then deinterleave to JACK
Packit c32a2d
		   buffers. */
Packit c32a2d
		size_t got_piece;
Packit c32a2d
		size_t avail_piece;
Packit c32a2d
		size_t piece = to_read > handle->procbuf_frames
Packit c32a2d
		?	handle->procbuf_frames
Packit c32a2d
		:	to_read;
Packit c32a2d
		/* Ensure we get only full PCM frames by checking available byte count
Packit c32a2d
		   and reducing expectation. */
Packit c32a2d
		avail_piece = jack_ringbuffer_read_space(handle->rb)/handle->framesize;
Packit c32a2d
		got_piece = jack_ringbuffer_read( handle->rb
Packit c32a2d
		,	handle->procbuf, (avail_piece > piece ? piece : avail_piece)
Packit c32a2d
		*	handle->framesize ) / handle->framesize;
Packit c32a2d
		debug2( "fetched %"SIZE_P" frames from ringbuffer (wanted %"SIZE_P")"
Packit c32a2d
		,	(size_p)got_piece, (size_p)piece );
Packit c32a2d
		/* If this is the last piece, fill up, not time to wait. */
Packit c32a2d
		if(to_read > piece)
Packit c32a2d
			piece = got_piece; /* We got further loop cycle(s) to get the rest. */
Packit c32a2d
		else
Packit c32a2d
		{
Packit c32a2d
			if(piece > got_piece)
Packit c32a2d
			{
Packit c32a2d
				debug("filling up with zeros");
Packit c32a2d
				bzero( handle->procbuf+got_piece*handle->framesize
Packit c32a2d
				,	(piece-got_piece)*handle->framesize );
Packit c32a2d
			}
Packit c32a2d
		}
Packit c32a2d
		/* Now extract the pieces for the channels. */
Packit c32a2d
		for (c=0; c < handle->channels; ++c)
Packit c32a2d
		{
Packit c32a2d
			size_t n;
Packit c32a2d
			jack_default_audio_sample_t *dst = handle->ports_buf[c];
Packit c32a2d
			if(handle->encoding == MPG123_ENC_FLOAT_32)
Packit c32a2d
			{
Packit c32a2d
				float* src = (float*)handle->procbuf;
Packit c32a2d
				for(n=0; n
Packit c32a2d
					*(dst++) = src[(n*handle->channels)+c];
Packit c32a2d
			}
Packit c32a2d
			else /* MPG123_ENC_FLOAT_64 */
Packit c32a2d
			{
Packit c32a2d
				double* src = (double*)handle->procbuf;
Packit c32a2d
				for(n=0; n
Packit c32a2d
					*(dst++) = src[(n*handle->channels)+c];
Packit c32a2d
			}
Packit c32a2d
			/* Store output buffer offset. */
Packit c32a2d
			handle->ports_buf[c] = dst;
Packit c32a2d
		}
Packit c32a2d
		/* Give the writer a hint about the time passed. */
Packit c32a2d
		sem_post(&handle->sem);
Packit c32a2d
		to_read -= piece;
Packit c32a2d
	}
Packit c32a2d
	/* Success*/
Packit c32a2d
	return 0;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
/* This is triggered on server shutdown and very much necessary to avoid
Packit c32a2d
   out123 hanging on the processor semaphore. */
Packit c32a2d
static void shutdown_callback(void *arg)
Packit c32a2d
{
Packit c32a2d
	jack_handle_t* handle = (jack_handle_t*)arg;
Packit c32a2d
	handle->alive = 0;
Packit c32a2d
	sem_post(&handle->sem);
Packit c32a2d
	debug("shutdown_callback()");
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
/* connect to jack ports named in the NULL-terminated wishlist */
Packit c32a2d
static int real_connect_jack_ports(out123_handle *ao
Packit c32a2d
,	jack_handle_t* handle, const char** wishlist)
Packit c32a2d
{
Packit c32a2d
	const char **wish = wishlist;
Packit c32a2d
	int ch, err;
Packit c32a2d
	int ch_wrap = 0, wish_wrap = 0;
Packit c32a2d
Packit c32a2d
	if(!wish)
Packit c32a2d
		return 0;
Packit c32a2d
	if(wish != NULL && *wish == NULL)
Packit c32a2d
		return 1; /* success, nothing connected as wanted */
Packit c32a2d
	ch=0;
Packit c32a2d
	/* Connect things as long as there are sources or sinks left. */
Packit c32a2d
	while(!wish_wrap || !ch_wrap)
Packit c32a2d
	{
Packit c32a2d
		const char* in = jack_port_name(handle->ports[ch]);
Packit c32a2d
Packit c32a2d
		if((err = jack_connect(handle->client, in, *wish)) != 0 && err != EEXIST)
Packit c32a2d
		{
Packit c32a2d
			if(!AOQUIET)
Packit c32a2d
				error4( "connect_jack_ports(): failed to jack_connect() ch%i (%s) to %s: %d"
Packit c32a2d
				,	ch, in ? in : "<nil>", *wish, err );
Packit c32a2d
			return 0;
Packit c32a2d
		}
Packit c32a2d
		/*
Packit c32a2d
			Increment channel and wishlist, both possibly wrapping around, to
Packit c32a2d
			ensure we connected all channels to some output port and provided
Packit c32a2d
			some input to all ports in the wishlist. Both cases of less channels
Packit c32a2d
			than output ports (splitting) and more channels	than output ports
Packit c32a2d
			(downmix) are sensible.
Packit c32a2d
		*/
Packit c32a2d
		if(++ch == handle->channels)
Packit c32a2d
		{
Packit c32a2d
			ch = 0;
Packit c32a2d
			++ch_wrap;
Packit c32a2d
		}
Packit c32a2d
		if(!*(++wish))
Packit c32a2d
		{
Packit c32a2d
			wish = wishlist;
Packit c32a2d
			++wish_wrap;
Packit c32a2d
		}
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	return 1;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
/* crude way of automatically connecting up jack ports */
Packit c32a2d
/* 0 on error */
Packit c32a2d
static int autoconnect_jack_ports(out123_handle *ao, jack_handle_t* handle)
Packit c32a2d
{
Packit c32a2d
	const char **all_ports;
Packit c32a2d
	unsigned int ch=0;
Packit c32a2d
	int err,i;
Packit c32a2d
Packit c32a2d
	/* Get a list of all the jack ports*/
Packit c32a2d
	all_ports = jack_get_ports (handle->client, NULL, NULL, JackPortIsInput);
Packit c32a2d
	if(!all_ports)
Packit c32a2d
	{
Packit c32a2d
		if(!AOQUIET)
Packit c32a2d
			error("connect_jack_ports(): jack_get_ports() returned NULL.");
Packit c32a2d
		return 0;
Packit c32a2d
	}
Packit c32a2d
	/* Step through each port name*/
Packit c32a2d
	for (i = 0; all_ports[i]; ++i)
Packit c32a2d
	{
Packit c32a2d
		const char* in = jack_port_name( handle->ports[ch] );
Packit c32a2d
		const char* out = all_ports[i];
Packit c32a2d
Packit c32a2d
		if ((err = jack_connect(handle->client, in, out)) != 0 && err != EEXIST)
Packit c32a2d
		{
Packit c32a2d
			if(!AOQUIET)
Packit c32a2d
				error1("connect_jack_ports(): failed to jack_connect() ports: %d",err);
Packit c32a2d
			return 0;
Packit c32a2d
		}
Packit c32a2d
Packit c32a2d
		/* Found enough ports ?*/
Packit c32a2d
		if (++ch >= handle->channels) break;
Packit c32a2d
	}
Packit c32a2d
	jack_free(all_ports);
Packit c32a2d
	return 1;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
Packit c32a2d
static int connect_jack_ports(out123_handle *ao
Packit c32a2d
,	jack_handle_t* handle)
Packit c32a2d
{
Packit c32a2d
	debug1("connect_jack_ports with dev=%s", ao->device ? ao->device : "<nil>");
Packit c32a2d
	if(ao->device==NULL || strcmp(ao->device, "auto")==0)
Packit c32a2d
		return autoconnect_jack_ports(ao, handle);
Packit c32a2d
	else
Packit c32a2d
	{
Packit c32a2d
		/* Parse device for a set of ports, comma separated. */
Packit c32a2d
		const char** wishlist; /* Channels and end marker. */
Packit c32a2d
		int wish_channels = 1; /* Numper of entries in wishlist. */
Packit c32a2d
		char *devcopy, *chr;
Packit c32a2d
		int ret;
Packit c32a2d
		int c;
Packit c32a2d
		size_t len;
Packit c32a2d
		len = strlen(ao->device);
Packit c32a2d
		/* We connect as many JACK ports as desired, possibly duplicating. */
Packit c32a2d
		for(chr=ao->device; *chr; ++chr)
Packit c32a2d
			if(*chr == ',')
Packit c32a2d
				++wish_channels;
Packit c32a2d
		debug1("wish_channels: %i", wish_channels);
Packit c32a2d
		wishlist = malloc(sizeof(char*)*(wish_channels+1));
Packit c32a2d
		devcopy = compat_strdup(ao->device);
Packit c32a2d
		if(devcopy == NULL || wishlist == NULL)
Packit c32a2d
		{
Packit c32a2d
			if(devcopy)
Packit c32a2d
				free(devcopy);
Packit c32a2d
			if(wishlist)
Packit c32a2d
				free(wishlist);
Packit c32a2d
			if(!AOQUIET)
Packit c32a2d
				error("OOM");
Packit c32a2d
			return 0;
Packit c32a2d
		}
Packit c32a2d
Packit c32a2d
		for(c=0;c<=wish_channels;++c)
Packit c32a2d
			wishlist[c] = NULL;
Packit c32a2d
		if(len && strcmp(devcopy, "none"))
Packit c32a2d
		{
Packit c32a2d
			size_t i=0;
Packit c32a2d
			wishlist[0] = devcopy;
Packit c32a2d
			for(c=0;c
Packit c32a2d
			{
Packit c32a2d
				while(devcopy[i] != 0 && devcopy[i] != ',') ++i;
Packit c32a2d
				debug2("devcopy[%"SIZE_P"]=%i", i, devcopy[i]);
Packit c32a2d
				if(devcopy[i] == ',')
Packit c32a2d
				{
Packit c32a2d
					/* Terminate previous port name, assign next one. */
Packit c32a2d
					devcopy[i++] = 0;
Packit c32a2d
					debug2("terminaled wish %i: %s", c, wishlist[c]);
Packit c32a2d
					if(c+1 < wish_channels)
Packit c32a2d
						wishlist[c+1] = devcopy+i;
Packit c32a2d
				}
Packit c32a2d
				else
Packit c32a2d
					break;
Packit c32a2d
			}
Packit c32a2d
		}
Packit c32a2d
		if(wishlist[0] == NULL && !AOQUIET)
Packit c32a2d
			warning("Not connecting up jack ports as requested.");
Packit c32a2d
Packit c32a2d
		ret = real_connect_jack_ports(ao, handle, wishlist);
Packit c32a2d
		free(devcopy);
Packit c32a2d
		free(wishlist);
Packit c32a2d
		return ret;
Packit c32a2d
	}
Packit c32a2d
	return 1;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void drain_jack(out123_handle *ao)
Packit c32a2d
{
Packit c32a2d
	jack_handle_t *handle = (jack_handle_t*)ao->userptr;
Packit c32a2d
Packit c32a2d
	debug("drain_jack().");
Packit c32a2d
Packit c32a2d
	do errno = 0;
Packit c32a2d
	while(sem_trywait(&handle->sem) == 0 || errno == EINTR);
Packit c32a2d
	/* For some reason, a single byte is reserved by JACK?! */
Packit c32a2d
	while(  handle && handle->alive && handle->rb
Packit c32a2d
	     && jack_ringbuffer_write_space(handle->rb)+1 < handle->rb_size )
Packit c32a2d
	{
Packit c32a2d
		debug2( "JACK close wait %"SIZE_P" < %"SIZE_P"\n"
Packit c32a2d
		,	(size_p)jack_ringbuffer_write_space(handle->rb)
Packit c32a2d
		,	(size_p)handle->rb_size );
Packit c32a2d
		sem_wait(&handle->sem);
Packit c32a2d
	}
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static int close_jack(out123_handle *ao)
Packit c32a2d
{
Packit c32a2d
	jack_handle_t *handle = (jack_handle_t*)ao->userptr;
Packit c32a2d
Packit c32a2d
	debug("close_jack().");
Packit c32a2d
	/* Close and shutdown*/
Packit c32a2d
	if(handle)
Packit c32a2d
	{
Packit c32a2d
		free_jack_handle(handle);
Packit c32a2d
		ao->userptr = NULL;
Packit c32a2d
	}
Packit c32a2d
	return 0;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
Packit c32a2d
static int open_jack(out123_handle *ao)
Packit c32a2d
{
Packit c32a2d
	jack_handle_t *handle=NULL;
Packit c32a2d
	jack_options_t jopt = JackNullOption|JackNoStartServer;
Packit c32a2d
	jack_status_t jstat = 0;
Packit c32a2d
	unsigned int i;
Packit c32a2d
	char *realname;
Packit c32a2d
Packit c32a2d
	debug("jack open");
Packit c32a2d
	if(!ao)
Packit c32a2d
		return -1;
Packit c32a2d
Packit c32a2d
	/* Return if already open*/
Packit c32a2d
	if(ao->userptr)
Packit c32a2d
	{
Packit c32a2d
		if(!AOQUIET)
Packit c32a2d
			error("audio device is already open.");
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* The initial open lets me choose the settings. */
Packit c32a2d
	if (ao->format==-1)
Packit c32a2d
	{
Packit c32a2d
		ao->format = MPG123_ENC_FLOAT_32;
Packit c32a2d
		ao->channels = 2;
Packit c32a2d
		/* Really need a framesize defined for callback. */
Packit c32a2d
		ao->framesize = 2*4;
Packit c32a2d
	}
Packit c32a2d
	else if(!(ao->format & MPG123_ENC_FLOAT))
Packit c32a2d
	{
Packit c32a2d
		if(!AOQUIET)
Packit c32a2d
			error("JACK only wants float!");
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* Create some storage for ourselves*/
Packit c32a2d
	if((handle = alloc_jack_handle(ao)) == NULL)
Packit c32a2d
		return -1;
Packit c32a2d
	ao->userptr = (void*)handle;
Packit c32a2d
Packit c32a2d
	/* Register with Jack*/
Packit c32a2d
	if((handle->client = jack_client_open(ao->name, jopt, &jstat)) == 0)
Packit c32a2d
	{
Packit c32a2d
		if(!AOQUIET)
Packit c32a2d
			error1("Failed to open jack client: 0x%x", jstat);
Packit c32a2d
		close_jack(ao);
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	realname = jack_get_client_name(handle->client);
Packit c32a2d
	/* Display the unique client name allocated to us */
Packit c32a2d
	if(AOVERBOSE(1))
Packit c32a2d
		fprintf( stderr, "Registered as JACK client %s.\n"
Packit c32a2d
		,	realname ? realname : "<nil>" );
Packit c32a2d
Packit c32a2d
	/* Just make sure. */
Packit c32a2d
	ao->rate   = jack_get_sample_rate(handle->client);
Packit c32a2d
Packit c32a2d
	/* Check the sample rate is correct*/
Packit c32a2d
	if (jack_get_sample_rate( handle->client ) != (jack_nframes_t)ao->rate)
Packit c32a2d
	{
Packit c32a2d
		if(!AOQUIET)
Packit c32a2d
			error("JACK Sample Rate is different to sample rate of file.");
Packit c32a2d
		close_jack(ao);
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* Register ports with Jack*/
Packit c32a2d
	if(handle->channels > 0 && handle->channels < 100)
Packit c32a2d
	{
Packit c32a2d
		for(i=0;i<handle->channels;++i)
Packit c32a2d
		{
Packit c32a2d
			char numbuf[3]; /* two digits, zero byte */
Packit c32a2d
			sprintf(numbuf, "%d", i+1);
Packit c32a2d
			if( !(handle->ports[i] = jack_port_register( handle->client
Packit c32a2d
			                         , numbuf, JACK_DEFAULT_AUDIO_TYPE
Packit c32a2d
			                         , JackPortIsOutput, 0 )) )
Packit c32a2d
			{
Packit c32a2d
				if(!AOQUIET)
Packit c32a2d
					error1("Cannot register JACK output port '%s'.", numbuf);
Packit c32a2d
				close_jack(ao);
Packit c32a2d
				return -1;
Packit c32a2d
			}
Packit c32a2d
		}
Packit c32a2d
	}
Packit c32a2d
	else
Packit c32a2d
	{
Packit c32a2d
		if(!AOQUIET)
Packit c32a2d
			error1("excessive number of output channels (%d).", handle->channels);
Packit c32a2d
		close_jack(ao);
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* Use device_buffer parameter for ring buffer, but ensure that two
Packit c32a2d
	   JACK buffers fit in there. We do not support that buffer increasing
Packit c32a2d
	   later on. */
Packit c32a2d
	handle->rb_size = (size_t)( ao->device_buffer
Packit c32a2d
	*	jack_get_sample_rate(handle->client)
Packit c32a2d
	+	0.5 ); /* PCM frames */
Packit c32a2d
	handle->procbuf_frames = jack_get_buffer_size(handle->client);
Packit c32a2d
	if(handle->rb_size < 2*handle->procbuf_frames)
Packit c32a2d
		handle->rb_size = 2*handle->procbuf_frames;
Packit c32a2d
	debug1("JACK ringbuffer for %"SIZE_P" PCM frames", (size_p)handle->rb_size);
Packit c32a2d
	/* Convert to bytes. */
Packit c32a2d
	handle->rb_size *= handle->framesize;
Packit c32a2d
	handle->rb = jack_ringbuffer_create(handle->rb_size);
Packit c32a2d
	handle->procbuf = malloc(handle->procbuf_frames*handle->framesize);
Packit c32a2d
	if(!handle->rb || !handle->procbuf)
Packit c32a2d
	{
Packit c32a2d
		if(!AOQUIET)
Packit c32a2d
			error("failed to allocate buffers");
Packit c32a2d
		close_jack(ao);
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* Set the callbacks*/
Packit c32a2d
	jack_set_process_callback(handle->client, process_callback, (void*)handle);
Packit c32a2d
	jack_on_shutdown(handle->client, shutdown_callback, (void*)handle);
Packit c32a2d
	handle->alive = 1;
Packit c32a2d
	/* Activate client*/
Packit c32a2d
	if(jack_activate(handle->client))
Packit c32a2d
	{
Packit c32a2d
		if(!AOQUIET)
Packit c32a2d
			error("Can't activate client.");
Packit c32a2d
		close_jack(ao);
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* Connect up the portsm, return */
Packit c32a2d
	if(!connect_jack_ports(ao, handle))
Packit c32a2d
	{
Packit c32a2d
		/* deregistering of ports will not work but should just fail, then,
Packit c32a2d
		   and let the rest clean up */
Packit c32a2d
		close_jack(ao);
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	debug("Jack open successful.\n");
Packit c32a2d
	ao->realname = compat_strdup(realname);
Packit c32a2d
	return 0;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
Packit c32a2d
/* Jack prefers floats, I actually assume it does _only_ float/double
Packit c32a2d
   (as it is nowadays)! */
Packit c32a2d
static int get_formats_jack(out123_handle *ao)
Packit c32a2d
{
Packit c32a2d
	jack_handle_t *handle = (jack_handle_t*)ao->userptr;
Packit c32a2d
Packit c32a2d
	if(jack_get_sample_rate(handle->client) != (jack_nframes_t)ao->rate)
Packit c32a2d
		return 0;
Packit c32a2d
	else
Packit c32a2d
		return MPG123_ENC_FLOAT_32|MPG123_ENC_FLOAT_64;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static int write_jack(out123_handle *ao, unsigned char *buf, int len)
Packit c32a2d
{
Packit c32a2d
	jack_handle_t *handle = (jack_handle_t*)ao->userptr;
Packit c32a2d
	size_t bytes_left;
Packit c32a2d
	unsigned int strike = 0;
Packit c32a2d
Packit c32a2d
	bytes_left = len;
Packit c32a2d
	while(bytes_left && handle->alive)
Packit c32a2d
	{
Packit c32a2d
		size_t piece;
Packit c32a2d
Packit c32a2d
		debug("writing to ringbuffer");
Packit c32a2d
		/* No help: piece1 = jack_ringbuffer_write_space(handle->rb); */
Packit c32a2d
		piece = jack_ringbuffer_write(handle->rb, (char*)buf, bytes_left);
Packit c32a2d
		debug1("wrote %"SIZE_P" B", (size_p)piece);
Packit c32a2d
		buf += piece;
Packit c32a2d
		bytes_left -= piece;
Packit c32a2d
		/* Allow nothing being written some times, but not too often. 
Packit c32a2d
		   Don't know how often in a row that would be supposed to happen. */
Packit c32a2d
		if(!piece)
Packit c32a2d
		{
Packit c32a2d
			if(++strike > 100)
Packit c32a2d
			{
Packit c32a2d
				if(!AOQUIET)
Packit c32a2d
					error("Cannot write to ringbuffer.");
Packit c32a2d
				break;
Packit c32a2d
			}
Packit c32a2d
			/* Avoid busy waiting and semaphore accumulation:
Packit c32a2d
			   Wait once on the semaphore, then clear it. We count on it being
Packit c32a2d
			   posted by the process callback and we are going to push new data
Packit c32a2d
			   so that that one gets the chance. */
Packit c32a2d
			sem_wait(&handle->sem);
Packit c32a2d
			do errno = 0;
Packit c32a2d
			while(sem_trywait(&handle->sem) == 0 || errno == EINTR);
Packit c32a2d
		}
Packit c32a2d
		else
Packit c32a2d
			strike = 0;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	return len-bytes_left;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void flush_jack(out123_handle *ao)
Packit c32a2d
{
Packit c32a2d
	jack_handle_t *handle = (jack_handle_t*)ao->userptr;
Packit c32a2d
	/* Reset the ring buffers*/
Packit c32a2d
	jack_ringbuffer_reset(handle->rb);
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static int init_jack(out123_handle* ao)
Packit c32a2d
{
Packit c32a2d
	if (ao==NULL)
Packit c32a2d
		return -1;
Packit c32a2d
	/* Set callbacks */
Packit c32a2d
	ao->open = open_jack;
Packit c32a2d
	ao->flush = flush_jack;
Packit c32a2d
	ao->drain = drain_jack;
Packit c32a2d
	ao->write = write_jack;
Packit c32a2d
	ao->get_formats = get_formats_jack;
Packit c32a2d
	ao->close = close_jack;
Packit c32a2d
	ao->propflags |= OUT123_PROP_PERSISTENT;
Packit c32a2d
	/* Success */
Packit c32a2d
	return 0;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
/* 
Packit c32a2d
	Module information data structure
Packit c32a2d
*/
Packit c32a2d
mpg123_module_t mpg123_output_module_info = {
Packit c32a2d
	/* api_version */	MPG123_MODULE_API_VERSION,
Packit c32a2d
	/* name */			"jack",
Packit c32a2d
	/* description */	"Output audio using JACK (JACK Audio Connection Kit).",
Packit c32a2d
	/* revision */		"$Rev:$",
Packit c32a2d
	/* handle */		NULL,
Packit c32a2d
Packit c32a2d
	/* init_output */	init_jack
Packit c32a2d
};