aboutsummaryrefslogtreecommitdiffstats
path: root/src/output/fifo_output_plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/output/fifo_output_plugin.c')
-rw-r--r--src/output/fifo_output_plugin.c92
1 files changed, 52 insertions, 40 deletions
diff --git a/src/output/fifo_output_plugin.c b/src/output/fifo_output_plugin.c
index f4217ec4d..022be0b4a 100644
--- a/src/output/fifo_output_plugin.c
+++ b/src/output/fifo_output_plugin.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2010 The Music Player Daemon Project
+ * Copyright (C) 2003-2011 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -18,6 +18,7 @@
*/
#include "config.h"
+#include "fifo_output_plugin.h"
#include "output_api.h"
#include "utils.h"
#include "timer.h"
@@ -38,11 +39,13 @@
#define FIFO_BUFFER_SIZE 65536 /* pipe capacity on Linux >= 2.6.11 */
struct fifo_data {
+ struct audio_output base;
+
char *path;
int input;
int output;
bool created;
- Timer *timer;
+ struct timer *timer;
};
/**
@@ -80,7 +83,7 @@ static void fifo_delete(struct fifo_data *fd)
if (unlink(fd->path) < 0) {
g_warning("Could not remove FIFO \"%s\": %s",
- fd->path, strerror(errno));
+ fd->path, g_strerror(errno));
return;
}
@@ -112,7 +115,7 @@ fifo_make(struct fifo_data *fd, GError **error)
if (mkfifo(fd->path, 0666) < 0) {
g_set_error(error, fifo_output_quark(), errno,
"Couldn't create FIFO \"%s\": %s",
- fd->path, strerror(errno));
+ fd->path, g_strerror(errno));
return false;
}
@@ -134,7 +137,7 @@ fifo_check(struct fifo_data *fd, GError **error)
g_set_error(error, fifo_output_quark(), errno,
"Failed to stat FIFO \"%s\": %s",
- fd->path, strerror(errno));
+ fd->path, g_strerror(errno));
return false;
}
@@ -158,7 +161,7 @@ fifo_open(struct fifo_data *fd, GError **error)
if (fd->input < 0) {
g_set_error(error, fifo_output_quark(), errno,
"Could not open FIFO \"%s\" for reading: %s",
- fd->path, strerror(errno));
+ fd->path, g_strerror(errno));
fifo_close(fd);
return false;
}
@@ -167,7 +170,7 @@ fifo_open(struct fifo_data *fd, GError **error)
if (fd->output < 0) {
g_set_error(error, fifo_output_quark(), errno,
"Could not open FIFO \"%s\" for writing: %s",
- fd->path, strerror(errno));
+ fd->path, g_strerror(errno));
fifo_close(fd);
return false;
}
@@ -175,54 +178,55 @@ fifo_open(struct fifo_data *fd, GError **error)
return true;
}
-static void *
-fifo_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- const struct config_param *param,
- GError **error)
+static struct audio_output *
+fifo_output_init(const struct config_param *param,
+ GError **error_r)
{
struct fifo_data *fd;
- char *value, *path;
-
- value = config_dup_block_string(param, "path", NULL);
- if (value == NULL) {
- g_set_error(error, fifo_output_quark(), errno,
- "No \"path\" parameter specified");
- return NULL;
- }
- path = parsePath(value);
- g_free(value);
+ GError *error = NULL;
+ char *path = config_dup_block_path(param, "path", &error);
if (!path) {
- g_set_error(error, fifo_output_quark(), errno,
- "Could not parse \"path\" parameter");
+ if (error != NULL)
+ g_propagate_error(error_r, error);
+ else
+ g_set_error(error_r, fifo_output_quark(), 0,
+ "No \"path\" parameter specified");
return NULL;
}
fd = fifo_data_new();
fd->path = path;
- if (!fifo_open(fd, error)) {
+ if (!ao_base_init(&fd->base, &fifo_output_plugin, param, error_r)) {
+ fifo_data_free(fd);
+ return NULL;
+ }
+
+ if (!fifo_open(fd, error_r)) {
+ ao_base_finish(&fd->base);
fifo_data_free(fd);
return NULL;
}
- return fd;
+ return &fd->base;
}
static void
-fifo_output_finish(void *data)
+fifo_output_finish(struct audio_output *ao)
{
- struct fifo_data *fd = (struct fifo_data *)data;
+ struct fifo_data *fd = (struct fifo_data *)ao;
fifo_close(fd);
+ ao_base_finish(&fd->base);
fifo_data_free(fd);
}
static bool
-fifo_output_open(void *data, struct audio_format *audio_format,
+fifo_output_open(struct audio_output *ao, struct audio_format *audio_format,
G_GNUC_UNUSED GError **error)
{
- struct fifo_data *fd = (struct fifo_data *)data;
+ struct fifo_data *fd = (struct fifo_data *)ao;
fd->timer = timer_new(audio_format);
@@ -230,17 +234,17 @@ fifo_output_open(void *data, struct audio_format *audio_format,
}
static void
-fifo_output_close(void *data)
+fifo_output_close(struct audio_output *ao)
{
- struct fifo_data *fd = (struct fifo_data *)data;
+ struct fifo_data *fd = (struct fifo_data *)ao;
timer_free(fd->timer);
}
static void
-fifo_output_cancel(void *data)
+fifo_output_cancel(struct audio_output *ao)
{
- struct fifo_data *fd = (struct fifo_data *)data;
+ struct fifo_data *fd = (struct fifo_data *)ao;
char buf[FIFO_BUFFER_SIZE];
int bytes = 1;
@@ -251,22 +255,29 @@ fifo_output_cancel(void *data)
if (bytes < 0 && errno != EAGAIN) {
g_warning("Flush of FIFO \"%s\" failed: %s",
- fd->path, strerror(errno));
+ fd->path, g_strerror(errno));
}
}
+static unsigned
+fifo_output_delay(struct audio_output *ao)
+{
+ struct fifo_data *fd = (struct fifo_data *)ao;
+
+ return fd->timer->started
+ ? timer_delay(fd->timer)
+ : 0;
+}
+
static size_t
-fifo_output_play(void *data, const void *chunk, size_t size,
+fifo_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error)
{
- struct fifo_data *fd = (struct fifo_data *)data;
+ struct fifo_data *fd = (struct fifo_data *)ao;
ssize_t bytes;
if (!fd->timer->started)
timer_start(fd->timer);
- else
- timer_sync(fd->timer);
-
timer_add(fd->timer, size);
while (true) {
@@ -278,7 +289,7 @@ fifo_output_play(void *data, const void *chunk, size_t size,
switch (errno) {
case EAGAIN:
/* The pipe is full, so empty it */
- fifo_output_cancel(fd);
+ fifo_output_cancel(&fd->base);
continue;
case EINTR:
continue;
@@ -298,6 +309,7 @@ const struct audio_output_plugin fifo_output_plugin = {
.finish = fifo_output_finish,
.open = fifo_output_open,
.close = fifo_output_close,
+ .delay = fifo_output_delay,
.play = fifo_output_play,
.cancel = fifo_output_cancel,
};