1 /* the Music Player Daemon (MPD)
2 * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
3 * This project's homepage is: http://www.musicpd.org
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "../audioOutput.h"
35 #include <sys/types.h>
37 #define FIFO_BUFFER_SIZE 65536 /* pipe capacity on Linux >= 2.6.11 */
39 typedef struct _FifoData {
47 static FifoData *newFifoData()
51 ret = xmalloc(sizeof(FifoData));
62 static void freeFifoData(FifoData *fd)
68 timer_free(fd->timer);
73 static void removeFifo(FifoData *fd)
75 DEBUG("Removing FIFO \"%s\"\n", fd->path);
77 if (unlink(fd->path) < 0) {
78 ERROR("Could not remove FIFO \"%s\": %s\n",
79 fd->path, strerror(errno));
86 static void closeFifo(FifoData *fd)
95 if (fd->output >= 0) {
100 if (fd->created && (stat(fd->path, &st) == 0))
104 static int makeFifo(FifoData *fd)
106 if (mkfifo(fd->path, 0666) < 0) {
107 ERROR("Couldn't create FIFO \"%s\": %s\n",
108 fd->path, strerror(errno));
117 static int checkFifo(FifoData *fd)
121 if (stat(fd->path, &st) < 0) {
122 if (errno == ENOENT) {
123 /* Path doesn't exist */
127 ERROR("Failed to stat FIFO \"%s\": %s\n",
128 fd->path, strerror(errno));
132 if (!S_ISFIFO(st.st_mode)) {
133 ERROR("\"%s\" already exists, but is not a FIFO\n", fd->path);
140 static int openFifo(FifoData *fd)
142 if (checkFifo(fd) < 0)
145 fd->input = open(fd->path, O_RDONLY|O_NONBLOCK);
147 ERROR("Could not open FIFO \"%s\" for reading: %s\n",
148 fd->path, strerror(errno));
153 fd->output = open(fd->path, O_WRONLY|O_NONBLOCK);
154 if (fd->output < 0) {
155 ERROR("Could not open FIFO \"%s\" for writing: %s\n",
156 fd->path, strerror(errno));
164 static int fifo_initDriver(AudioOutput *audioOutput, ConfigParam *param)
167 BlockParam *blockParam;
170 blockParam = getBlockParam(param, "path");
172 FATAL("No \"path\" parameter specified for fifo output "
173 "defined at line %i\n", param->line);
176 path = parsePath(blockParam->value);
178 FATAL("Could not parse \"path\" parameter for fifo output "
179 "at line %i\n", blockParam->line);
184 audioOutput->data = fd;
186 if (openFifo(fd) < 0) {
194 static void fifo_finishDriver(AudioOutput *audioOutput)
196 FifoData *fd = (FifoData *)audioOutput->data;
202 static int fifo_openDevice(AudioOutput *audioOutput)
204 FifoData *fd = (FifoData *)audioOutput->data;
207 timer_free(fd->timer);
209 fd->timer = timer_new(&audioOutput->outAudioFormat);
211 audioOutput->open = 1;
216 static void fifo_closeDevice(AudioOutput *audioOutput)
218 FifoData *fd = (FifoData *)audioOutput->data;
221 timer_free(fd->timer);
225 audioOutput->open = 0;
228 static void fifo_dropBufferedAudio(AudioOutput *audioOutput)
230 FifoData *fd = (FifoData *)audioOutput->data;
231 char buf[FIFO_BUFFER_SIZE];
234 timer_reset(fd->timer);
236 while (bytes > 0 && errno != EINTR)
237 bytes = read(fd->input, buf, FIFO_BUFFER_SIZE);
239 if (bytes < 0 && errno != EAGAIN) {
240 WARNING("Flush of FIFO \"%s\" failed: %s\n",
241 fd->path, strerror(errno));
245 static int fifo_playAudio(AudioOutput *audioOutput, char *playChunk, int size)
247 FifoData *fd = (FifoData *)audioOutput->data;
251 if (!fd->timer->started)
252 timer_start(fd->timer);
254 timer_sync(fd->timer);
256 timer_add(fd->timer, size);
259 bytes = write(fd->output, playChunk + offset, size);
263 /* The pipe is full, so empty it */
264 fifo_dropBufferedAudio(audioOutput);
270 ERROR("Closing FIFO output \"%s\" due to write error: "
271 "%s\n", fd->path, strerror(errno));
272 fifo_closeDevice(audioOutput);
283 AudioOutputPlugin fifoPlugin = {
285 NULL, /* testDefaultDeviceFunc */
290 fifo_dropBufferedAudio,
292 NULL, /* sendMetadataFunc */
295 #else /* HAVE_FIFO */
297 DISABLED_AUDIO_OUTPUT_PLUGIN(fifoPlugin)
299 #endif /* !HAVE_FIFO */