diff options
Diffstat (limited to 'src/output/fifo_output_plugin.c')
-rw-r--r-- | src/output/fifo_output_plugin.c | 92 |
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, }; |