You need to sign in or sign up before continuing.
Commit 29c7681c authored by Warren Dukes's avatar Warren Dukes

jack patch from anarch (and some type fixes for mp4 and acc plugins)

git-svn-id: https://svn.musicpd.org/mpd/trunk@4912 09075e82-0dd4-0310-85a5-a0d7c8717e4f
parent e9f51778
......@@ -69,6 +69,7 @@ AC_ARG_ENABLE(ipv6,[ --disable-ipv6 disable IPv6 support (default: ena
AC_ARG_ENABLE(sun,[ --disable-sun disable sun support (default: enable)],[enable_sun=$enableval],[enable_sun=yes])
AC_ARG_ENABLE(oss,[ --disable-oss disable OSS support (default: enable)],[enable_oss=$enableval],[enable_oss=yes])
AC_ARG_ENABLE(alsa,[ --disable-alsa disable ALSA support (default: enable)],[enable_alsa=$enableval],[enable_alsa=yes])
AC_ARG_ENABLE(jack,[ --disable-jack disable jack support (default: enable)],[enable_jack=$enableval],[enable_jack=yes])
AC_ARG_ENABLE(pulse,[ --disable-pulse disable support for the PulseAudio sound server (default: enable)],[enable_pulse=$enableval],[enable_pulse=yes])
AC_ARG_ENABLE(mvp,[ --enable-mvp enable support for Hauppauge Media MVP (default: disable)],[enable_mvp=$enableval],[enable_mvp=no])
AC_ARG_ENABLE(oggvorbis,[ --disable-oggvorbis disable Ogg Vorbis support (default: enable)],[enable_oggvorbis=$enableval],enable_oggvorbis=yes)
......@@ -190,6 +191,14 @@ if test x$enable_alsa = xyes; then
AM_PATH_ALSA(0.9.0,[AC_DEFINE(HAVE_ALSA,1,[Define to enable ALSA support]) MPD_LIBS="$MPD_LIBS $ALSA_LIBS" MPD_CFLAGS="$MPD_CFLAGS $ALSA_CFLAGS"],enable_alsa=no)
fi
if test "x$enable_jack" = "xyes"; then
PKG_CHECK_MODULES(JACK, [jack >= 0.4],
[AC_DEFINE(HAVE_JACK,1,[Define to enable JACK support])
MPD_LIBS="$MPD_LIBS $JACK_LIBS"
MPD_CFLAGS="$MPD_CFLAGS $JACK_CFLAGS"],
[enable_jack=no])
fi
if test x$enable_iconv = xyes; then
if test "x$iconv_libraries" != "x" ; then
ICONV_LIBS="-L$iconv_libraries"
......@@ -601,6 +610,12 @@ else
echo " ALSA support ..................disabled"
fi
if test x$enable_jack = xyes; then
echo " JACK support ..................enabled"
else
echo " JACK support ..................disabled"
fi
if test x$enable_sun = xyes; then
echo " Sun support ...................enabled"
else
......@@ -640,6 +655,7 @@ if test x$enable_ao = xno &&
test x$enable_alsa = xno &&
test x$enable_osx = xno &&
test x$enable_pulse = xno &&
test x$enable_jack = xno &&
test x$enable_mvp = xno; then
AC_MSG_ERROR([No Audio Output types configured!])
fi
......
......@@ -8,7 +8,8 @@ mpd_audioOutputs = \
audioOutputs/audioOutput_osx.c \
audioOutputs/audioOutput_pulse.c \
audioOutputs/audioOutput_mvp.c \
audioOutputs/audioOutput_shout.c
audioOutputs/audioOutput_shout.c \
audioOutputs/audioOutput_jack.c
mpd_inputPlugins = \
inputPlugins/_flac_common.c \
......
......@@ -96,6 +96,7 @@ extern AudioOutputPlugin osxPlugin;
extern AudioOutputPlugin pulsePlugin;
extern AudioOutputPlugin mvpPlugin;
extern AudioOutputPlugin shoutPlugin;
extern AudioOutputPlugin jackPlugin;
void loadAudioDrivers(void)
{
......@@ -107,6 +108,7 @@ void loadAudioDrivers(void)
loadAudioOutputPlugin(&pulsePlugin);
loadAudioOutputPlugin(&mvpPlugin);
loadAudioOutputPlugin(&shoutPlugin);
loadAudioOutputPlugin(&jackPlugin);
}
/* make sure initPlayerData is called before this function!! */
......
/* jack plug in for the Music Player Daemon (MPD)
* (c)2006 by anarch(anarchsss@gmail.com)
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../audioOutput.h"
#ifdef HAVE_JACK
#include <stdlib.h>
#include <errno.h>
#include "../conf.h"
#include "../log.h"
#include "../sig_handlers.h"
#include <sys/types.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
#include <unistd.h>
#include <jack/jack.h>
#include <jack/types.h>
#include <jack/ringbuffer.h>
#define MIN(a, b) ((a) < (b) ? (a) : (b))
int ringbuf_sz = 32768;
char *ports[2] = {NULL, NULL};
typedef struct _JackData {
jack_options_t options;
jack_port_t *ports[2];
jack_client_t *client;
jack_default_audio_sample_t **in;
jack_ringbuffer_t *ringbuffer[2];
int bps;
int shutdown;
int nports;
int our_xrun;
} JackData;
JackData *jd = NULL;
static JackData *newJackData (void)
{
JackData *ret;
ret = calloc (sizeof (JackData), 1);
ret->options = JackNullOption;
return ret;
}
static void disconnect_jack (JackData *jd)
{
jack_deactivate (jd->client);
jack_client_close (jd->client);
ERROR ("disconnect_jack (pid=%d)\n", getpid ());
}
static void jack_finishDriver (AudioOutput * audioOutput)
{
JackData *jd = audioOutput->data;
disconnect_jack (jd);
free (jd);
free (ports[0]);
free (ports[1]);
}
static int srate (jack_nframes_t rate, void *data)
{
JackData *jd = (JackData *) ((AudioOutput*) data)->data;
AudioFormat *audioFormat = &(((AudioOutput*) data)->outAudioFormat);
audioFormat->sampleRate = (int) jack_get_sample_rate (jd->client);
return 0;
}
static int process (jack_nframes_t nframes, void *arg)
{
size_t i;
JackData *jd = (JackData *) arg;
jack_default_audio_sample_t *out[2];
size_t avail_data, avail_frames;
if ( nframes <= 0 )
return 0;
out[0] = jack_port_get_buffer (jd->ports[0], nframes);
out[1] = jack_port_get_buffer (jd->ports[1], nframes);
avail_data = jack_ringbuffer_read_space (jd->ringbuffer[1]);
if ( avail_data > 0 ) {
avail_frames = avail_data / sizeof (jack_default_audio_sample_t);
if (avail_frames > nframes) {
avail_frames = nframes;
avail_data = nframes * sizeof (jack_default_audio_sample_t);
}
jack_ringbuffer_read (jd->ringbuffer[0], (char *)out[0], avail_data);
jack_ringbuffer_read (jd->ringbuffer[1], (char *)out[1], avail_data);
if (avail_frames < nframes) {
jd->our_xrun = 1;
for (i = avail_frames; i < nframes; i++) {
out[0][i] = out[1][i] = 0.0;
}
}
} else {
//ERROR ("avail_data=%d, no play (pid=%d)!\n", avail_data, getpid ());
for (i = 0; i < nframes; i++) {
out[0][i] = 0.0;
out[1][i] = 0.0;
}
}
return 0;
}
static void shutdown_callback (void *arg)
{
JackData *jd = (JackData *) arg;
jd->shutdown = 1;
}
static void set_audioformat (AudioOutput *audioOutput)
{
JackData *jd = audioOutput->data;
AudioFormat *audioFormat = &audioOutput->outAudioFormat;
audioFormat->sampleRate = (int) jack_get_sample_rate (jd->client);
ERROR ("samplerate = %d\n", audioFormat->sampleRate);
jd->nports = audioFormat->channels = 2;
audioFormat->bits = 16;
jd->bps = audioFormat->channels *
audioFormat->channels *
audioFormat->sampleRate;
}
static int connect_jack (AudioOutput *audioOutput)
{
JackData *jd = audioOutput->data;
const char **jports;
if ( (jd->client = jack_client_new ("mpd")) == NULL ) {
ERROR ("jack server not running?\n");
return -1;
}
jd->ringbuffer[0] = jack_ringbuffer_create (ringbuf_sz);
jd->ringbuffer[1] = jack_ringbuffer_create (ringbuf_sz);
jack_set_process_callback (jd->client, process, (void *)jd);
jack_set_sample_rate_callback (jd->client, (JackProcessCallback)srate,
(void *)audioOutput);
jack_on_shutdown (jd->client, shutdown_callback, (void *)jd);
if ( jack_activate (jd->client) ) {
ERROR ("cannot activate client");
jack_ringbuffer_free (jd->ringbuffer[0]);
jack_ringbuffer_free (jd->ringbuffer[1]);
return -1;
}
jd->ports[0] = jack_port_register (jd->client, "left",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
if ( !jd->ports[0] ) {
ERROR ("Cannot register output port.\n");
jack_ringbuffer_free (jd->ringbuffer[0]);
jack_ringbuffer_free (jd->ringbuffer[1]);
return -1;
}
jd->ports[1] = jack_port_register (jd->client, "right",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
if ( !jd->ports[1] ) {
ERROR ("Cannot register output port.\n");
jack_ringbuffer_free (jd->ringbuffer[0]);
jack_ringbuffer_free (jd->ringbuffer[1]);
return -1;
}
memset (jd->ringbuffer[0]->buf, 0, jd->ringbuffer[0]->size);
memset (jd->ringbuffer[1]->buf, 0, jd->ringbuffer[1]->size);
/* hay que buscar que hay */
if ( !ports[1] && (jports = jack_get_ports (jd->client, NULL, NULL,
JackPortIsPhysical|
JackPortIsInput)) ) {
ports[0] = (char *) jports[0];
ports[1] = (char *) ( jports[1] ? jports[1] : jports[0] );
ERROR ("jports: %s %s\n", ports[0], ports[1]);
free (jports);
}
if ( ports[1] ) {
if ( (jack_connect (jd->client, "mpd:left", ports[0])) != 0 ) {
ERROR ("%s is not a valid Jack Client / Port ", ports[0]);
jack_ringbuffer_free (jd->ringbuffer[0]);
jack_ringbuffer_free (jd->ringbuffer[1]);
return -1;
}
if ( (jack_connect (jd->client, "mpd:right", ports[1])) != 0 ) {
ERROR ("%s is not a valid Jack Client / Port ", ports[1]);
jack_ringbuffer_free (jd->ringbuffer[0]);
jack_ringbuffer_free (jd->ringbuffer[1]);
return -1;
}
}
ERROR ("connect_jack (pid=%d)\n", getpid ());
return 1;
}
static int jack_initDriver (AudioOutput *audioOutput, ConfigParam *param)
{
BlockParam *bp;
char *endptr;
int val;
char *cp = NULL;
if ( param ) {
bp = getBlockParam (param, "ports");
if ( bp ) {
cp = strdup (bp->value);
ports[0] = strdup (strtok (cp, " ,"));
ports[1] = strdup (strtok (NULL, " ,"));
free (cp);
}
bp = getBlockParam (param, "ringbuffer_size");
if ( bp ) {
errno = 0;
val = strtol (bp->value, &endptr, 10);
if ( errno == 0 && endptr != bp->value) {
ringbuf_sz = val;
ERROR ("ringbuffer_size=%d\n", ringbuf_sz);
} else {
ERROR ("%s is not a number; ringbuf_size=%d\n",
bp->value, ringbuf_sz);
}
}
}
ERROR ("jack_initDriver (pid=%d)\n", getpid ());
return 0;
}
static int jack_testDefault(void)
{
return 0;
}
static int jack_openDevice (AudioOutput *audioOutput)
{
if ( !jd ) {
jd = newJackData ();
audioOutput->data = jd;
if ( !connect_jack (audioOutput) ) {
free (jd);
return -1;
}
}
set_audioformat (audioOutput);
audioOutput->open = 1;
ERROR ("jack_openDevice (pid=%d)!\n", getpid ());
return 0;
}
static void jack_closeDevice(AudioOutput * audioOutput)
{
audioOutput->open = 0;
ERROR ("jack_closeDevice (pid=%d)!\n", getpid ());
}
static void jack_dropBufferedAudio (AudioOutput * audioOutput)
{
}
static int jack_playAudio(AudioOutput * audioOutput, char *buff, int size)
{
JackData *jd = audioOutput->data;
size_t remain = size;
size_t pos = 0;
if ( jd->shutdown ) {
ERROR ("Refusing to play, because there is no client thread.\n");
return 0;
}
if ( jd->our_xrun ) {
ERROR ("xrun\n");
jd->our_xrun = 0;
}
while (remain && !jd->shutdown) {
size_t space;
if ( (space = jack_ringbuffer_write_space (jd->ringbuffer[0]))
> sizeof (jack_default_audio_sample_t) ) {
size_t to_write;
to_write = MIN (space, remain);
remain -= to_write;
to_write /= 4;
//ERROR ("\t\tto_write=%d remain=%d (%d)\n", to_write, remain, to_write * 2 * 2);
while (to_write--) {
jack_default_audio_sample_t sample;
sample = *(short *)(buff + pos);
sample /= 32768;
pos += 2;
jack_ringbuffer_write (jd->ringbuffer[0],
(char *)&sample,
sizeof (sample));
sample = *(short *)(buff + pos);
sample /= 32768;
pos += 2;
jack_ringbuffer_write (jd->ringbuffer[1],
(char *)&sample,
sizeof (sample));
}
} else {
usleep (ringbuf_sz / (float)(jd->bps) * 100000.0);
}
}
return 0;
}
AudioOutputPlugin jackPlugin = {
"jack",
jack_testDefault,
jack_initDriver,
jack_finishDriver,
jack_openDevice,
jack_playAudio,
jack_dropBufferedAudio,
jack_closeDevice,
NULL, /* sendMetadataFunc */
};
#else /* HAVE JACK */
DISABLED_AUDIO_OUTPUT_PLUGIN(jackPlugin)
#endif /* HAVE_JACK */
......@@ -237,7 +237,7 @@ static float getAacFloatTotalTime(char *file)
size_t fileread, tagsize;
faacDecHandle decoder;
faacDecConfigurationPtr config;
unsigned int sampleRate;
unsigned long sampleRate;
unsigned char channels;
InputStream inStream;
long bread;
......@@ -293,7 +293,7 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
faacDecFrameInfo frameInfo;
faacDecConfigurationPtr config;
long bread;
unsigned int sampleRate;
unsigned long sampleRate;
unsigned char channels;
int eof = 0;
unsigned int sampleCount;
......
......@@ -100,7 +100,7 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
faacDecConfigurationPtr config;
unsigned char *mp4Buffer;
unsigned int mp4BufferSize;
uint32_t sampleRate;
unsigned long sampleRate;
unsigned char channels;
long sampleId;
long numSamples;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment