Commit b496239e authored by J. Alexander Treuman's avatar J. Alexander Treuman

Adding FIFO audio output. This is pretty much identical to the old one,

except that it now uses a timer for throttling. git-svn-id: https://svn.musicpd.org/mpd/trunk@6621 09075e82-0dd4-0310-85a5-a0d7c8717e4f
parent 1928a404
ver 0.14.0 (????/??/??)
* New null audio output plugin
* New null audio output
* Zeroconf support using Bonjour
* New zeroconf_enabled option so that Zeroconf support can be disabled
* Enable the AAC input plugin if support for it has been compiled in
......@@ -8,6 +8,7 @@ ver 0.14.0 (????/??/??)
* Fix a bug where closing an ALSA dmix device could cause MPD to hang
* Make the shout output block while trying to connect instead of failing
* New timeout parameter for shout outputs to define a connection timeout
* New FIFO audio output
ver 0.13.0 (2007/5/28)
* New JACK audio output
......
......@@ -69,6 +69,7 @@ AC_ARG_ENABLE(oss,[ --disable-oss disable OSS support (default: enabl
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(fifo,[ --disable-fifo disable support for writing audio to a FIFO (default: enable)],[enable_fifo=$enableval],[enable_fifo=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)
AC_ARG_ENABLE(oggflac,[ --disable-oggflac disable OggFLAC support (default: enable)],[enable_oggflac=$enableval],enable_oggflac=yes)
......@@ -197,6 +198,12 @@ if test x$enable_lsr = xyes; then
[enable_lsr=no;AC_MSG_WARN([libsamplerate not found -- disabling])])
fi
if test x$enable_fifo = xyes; then
AC_CHECK_FUNC([mkfifo],
[enable_fifo=yes;AC_DEFINE([HAVE_FIFO], 1, [Define to enable support for writing audio to a FIFO])],
[enable_fifo=no;AC_MSG_WARN([mkfifo not found -- disabling support for writing audio to a FIFO])])
fi
if test x$enable_mvp = xyes; then
AC_DEFINE(HAVE_MVP,1,[Define to enable Hauppauge Media MVP support])
fi
......@@ -664,6 +671,12 @@ else
echo " PulseAudio support ............disabled"
fi
if test x$enable_fifo = xyes; then
echo " FIFO support ..................enabled"
else
echo " FIFO support ..................disabled"
fi
if test x$enable_mvp = xyes; then
echo " Media MVP support .............enabled"
else
......@@ -685,6 +698,7 @@ if test x$enable_ao = xno &&
test x$enable_osx = xno &&
test x$enable_pulse = xno &&
test x$enable_jack = xno &&
test x$enable_fifo = xno &&
test x$enable_mvp = xno; then
AC_MSG_ERROR([No Audio Output types configured!])
fi
......
......@@ -335,6 +335,17 @@ default is "".
This specifies how many bytes to write to the audio device at once. This
parameter is to work around a bug in older versions of libao on sound cards
with very small buffers. The default is 1024.
.SH REQUIRED FIFO OUTPUT PARAMETERS
.TP
.B path <path>
This specifies the path of the FIFO to output to. Must be an absolute path.
If the path does not exist it will be created when mpd is started, and removed
when mpd is stopped. The FIFO will be created with the same user and group as
mpd is running as. Default permissions can be modified by using the builtin
shell command "umask". If a FIFO already exists at the specified path it will
be reused, and will \fBnot\fP be removed when mpd is stopped. You can use the
"mkfifo" command to create this, and then you may modify the permissions to
your liking.
.SH REQUIRED SHOUT OUTPUT PARAMETERS
.TP
.B name <name>
......
......@@ -2,14 +2,15 @@ bin_PROGRAMS = mpd
SUBDIRS = $(MP4FF_SUBDIR)
mpd_audioOutputs = \
audioOutputs/audioOutput_shout.c \
audioOutputs/audioOutput_null.c \
audioOutputs/audioOutput_fifo.c \
audioOutputs/audioOutput_alsa.c \
audioOutputs/audioOutput_ao.c \
audioOutputs/audioOutput_oss.c \
audioOutputs/audioOutput_osx.c \
audioOutputs/audioOutput_pulse.c \
audioOutputs/audioOutput_mvp.c \
audioOutputs/audioOutput_shout.c \
audioOutputs/audioOutput_jack.c
mpd_inputPlugins = \
......
......@@ -94,6 +94,7 @@ void loadAudioDrivers(void)
initAudioOutputPlugins();
loadAudioOutputPlugin(&shoutPlugin);
loadAudioOutputPlugin(&nullPlugin);
loadAudioOutputPlugin(&fifoPlugin);
loadAudioOutputPlugin(&alsaPlugin);
loadAudioOutputPlugin(&aoPlugin);
loadAudioOutputPlugin(&ossPlugin);
......
......@@ -107,6 +107,7 @@ void printAllOutputPluginTypes(FILE * fp);
extern AudioOutputPlugin shoutPlugin;
extern AudioOutputPlugin nullPlugin;
extern AudioOutputPlugin fifoPlugin;
extern AudioOutputPlugin alsaPlugin;
extern AudioOutputPlugin aoPlugin;
extern AudioOutputPlugin ossPlugin;
......
/* the Music Player Daemon (MPD)
* Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org
*
* 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"
#include <stdlib.h>
#ifdef HAVE_FIFO
#include "../log.h"
#include "../conf.h"
#include "../utils.h"
#include "../timer.h"
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#define FIFO_BUFFER_SIZE 65536 /* pipe capacity on Linux >= 2.6.11 */
typedef struct _FifoData {
char *path;
int input;
int output;
int created;
Timer *timer;
} FifoData;
static FifoData *newFifoData()
{
FifoData *ret;
ret = xmalloc(sizeof(FifoData));
ret->path = NULL;
ret->input = -1;
ret->output = -1;
ret->created = 0;
ret->timer = NULL;
return ret;
}
static void freeFifoData(FifoData *fd)
{
if (fd->path)
free(fd->path);
if (fd->timer)
timer_free(fd->timer);
free(fd);
}
static void removeFifo(FifoData *fd)
{
DEBUG("Removing FIFO \"%s\"\n", fd->path);
if (unlink(fd->path) < 0) {
ERROR("Could not remove FIFO \"%s\": %s\n",
fd->path, strerror(errno));
return;
}
fd->created = 0;
}
static void closeFifo(FifoData *fd)
{
struct stat st;
if (fd->input >= 0) {
close(fd->input);
fd->input = -1;
}
if (fd->output >= 0) {
close(fd->output);
fd->output = -1;
}
if (fd->created && (stat(fd->path, &st) == 0))
removeFifo(fd);
}
static int makeFifo(FifoData *fd)
{
if (mkfifo(fd->path, 0666) < 0) {
ERROR("Couldn't create FIFO \"%s\": %s\n",
fd->path, strerror(errno));
return -1;
}
fd->created = 1;
return 0;
}
static int checkFifo(FifoData *fd)
{
struct stat st;
if (stat(fd->path, &st) < 0) {
if (errno == ENOENT) {
/* Path doesn't exist */
return makeFifo(fd);
}
ERROR("Failed to stat FIFO \"%s\": %s\n",
fd->path, strerror(errno));
return -1;
}
if (!S_ISFIFO(st.st_mode)) {
ERROR("\"%s\" already exists, but is not a FIFO\n", fd->path);
return -1;
}
return 0;
}
static int openFifo(FifoData *fd)
{
if (checkFifo(fd) < 0)
return -1;
fd->input = open(fd->path, O_RDONLY|O_NONBLOCK);
if (fd->input < 0) {
ERROR("Could not open FIFO \"%s\" for reading: %s\n",
fd->path, strerror(errno));
closeFifo(fd);
return -1;
}
fd->output = open(fd->path, O_WRONLY|O_NONBLOCK);
if (fd->output < 0) {
ERROR("Could not open FIFO \"%s\" for writing: %s\n",
fd->path, strerror(errno));
closeFifo(fd);
return -1;
}
return 0;
}
static int fifo_initDriver(AudioOutput *audioOutput, ConfigParam *param)
{
FifoData *fd;
BlockParam *path = NULL;
if (param)
path = getBlockParam(param, "path");
if (!path) {
FATAL("No \"path\" parameter specified for fifo output "
"defined at line %i\n", param->line);
}
if (path->value[0] != '/') {
FATAL("\"path\" parameter for fifo output is not an absolute "
"path at line %i\n", param->line);
}
fd = newFifoData();
fd->path = xstrdup(path->value);
audioOutput->data = fd;
if (openFifo(fd) < 0) {
freeFifoData(fd);
return -1;
}
return 0;
}
static void fifo_finishDriver(AudioOutput *audioOutput)
{
FifoData *fd = (FifoData *)audioOutput->data;
closeFifo(fd);
freeFifoData(fd);
}
static int fifo_openDevice(AudioOutput *audioOutput)
{
FifoData *fd = (FifoData *)audioOutput->data;
if (fd->timer)
timer_free(fd->timer);
fd->timer = timer_new(&audioOutput->outAudioFormat);
audioOutput->open = 1;
return 0;
}
static void fifo_closeDevice(AudioOutput *audioOutput)
{
FifoData *fd = (FifoData *)audioOutput->data;
if (fd->timer) {
timer_free(fd->timer);
fd->timer = NULL;
}
audioOutput->open = 0;
}
static void fifo_dropBufferedAudio(AudioOutput *audioOutput)
{
FifoData *fd = (FifoData *)audioOutput->data;
char buf[FIFO_BUFFER_SIZE];
int bytes = 1;
timer_reset(fd->timer);
while (bytes > 0 && errno != EINTR)
bytes = read(fd->input, buf, FIFO_BUFFER_SIZE);
if (bytes < 0 && errno != EAGAIN) {
WARNING("Flush of FIFO \"%s\" failed: %s\n",
fd->path, strerror(errno));
}
}
static int fifo_playAudio(AudioOutput *audioOutput, char *playChunk, int size)
{
FifoData *fd = (FifoData *)audioOutput->data;
int offset = 0;
int bytes;
if (!fd->timer->started)
timer_start(fd->timer);
else
timer_sync(fd->timer);
timer_add(fd->timer, size);
while (size) {
bytes = write(fd->output, playChunk + offset, size);
if (bytes < 0) {
switch (errno) {
case EAGAIN:
/* The pipe is full, so empty it */
fifo_dropBufferedAudio(audioOutput);
continue;
case EINTR:
continue;
}
ERROR("Closing FIFO output \"%s\" due to write error: "
"%s\n", fd->path, strerror(errno));
fifo_closeDevice(audioOutput);
return -1;
}
size -= bytes;
offset += bytes;
}
return 0;
}
AudioOutputPlugin fifoPlugin = {
"fifo",
NULL, /* testDefaultDeviceFunc */
fifo_initDriver,
fifo_finishDriver,
fifo_openDevice,
fifo_playAudio,
fifo_dropBufferedAudio,
fifo_closeDevice,
NULL, /* sendMetadataFunc */
};
#else /* HAVE_FIFO */
DISABLED_AUDIO_OUTPUT_PLUGIN(fifoPlugin)
#endif /* !HAVE_FIFO */
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