aboutsummaryrefslogtreecommitdiffstats
path: root/src/output
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2011-09-16 23:31:48 +0200
committerMax Kellermann <max@duempel.org>2011-09-19 09:41:21 +0200
commit74617389c88ccf630b8cce4b54d9e2fa5afb2259 (patch)
tree3d05faad2c2b3b2e9e885f2c391a35fe8f06553a /src/output
parentb4a8b8c0d4bf82fc56572c3f8e79108d22d78132 (diff)
downloadmpd-74617389c88ccf630b8cce4b54d9e2fa5afb2259.tar.gz
mpd-74617389c88ccf630b8cce4b54d9e2fa5afb2259.tar.xz
mpd-74617389c88ccf630b8cce4b54d9e2fa5afb2259.zip
output_plugin: the plugin allocates the audio_output object
Pass audio_output objects around instead of void pointers. This will give some more control to the plugin, and prepares for non-blocking audio outputs.
Diffstat (limited to 'src/output')
-rw-r--r--src/output/alsa_output_plugin.c41
-rw-r--r--src/output/ao_output_plugin.c35
-rw-r--r--src/output/ffado_output_plugin.c35
-rw-r--r--src/output/fifo_output_plugin.c38
-rw-r--r--src/output/httpd_internal.h3
-rw-r--r--src/output/httpd_output_plugin.c68
-rw-r--r--src/output/jack_output_plugin.c49
-rw-r--r--src/output/mvp_output_plugin.c41
-rw-r--r--src/output/null_output_plugin.c36
-rw-r--r--src/output/openal_output_plugin.c36
-rw-r--r--src/output/oss_output_plugin.c49
-rw-r--r--src/output/osx_output_plugin.c37
-rw-r--r--src/output/pipe_output_plugin.c32
-rw-r--r--src/output/pulse_output_plugin.c53
-rw-r--r--src/output/raop_output_plugin.c44
-rw-r--r--src/output/recorder_output_plugin.c34
-rw-r--r--src/output/roar_output_plugin.c41
-rw-r--r--src/output/shout_output_plugin.c63
-rw-r--r--src/output/solaris_output_plugin.c37
-rw-r--r--src/output/winmm_output_plugin.c40
20 files changed, 492 insertions, 320 deletions
diff --git a/src/output/alsa_output_plugin.c b/src/output/alsa_output_plugin.c
index fb0498e96..41293272d 100644
--- a/src/output/alsa_output_plugin.c
+++ b/src/output/alsa_output_plugin.c
@@ -43,6 +43,8 @@ typedef snd_pcm_sframes_t alsa_writei_t(snd_pcm_t * pcm, const void *buffer,
snd_pcm_uframes_t size);
struct alsa_data {
+ struct audio_output base;
+
/** the configured name of the ALSA device; NULL for the
default device */
char *device;
@@ -143,23 +145,27 @@ alsa_configure(struct alsa_data *ad, const struct config_param *param)
#endif
}
-static void *
-alsa_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- const struct config_param *param,
- G_GNUC_UNUSED GError **error)
+static struct audio_output *
+alsa_init(const struct config_param *param, GError **error_r)
{
struct alsa_data *ad = alsa_data_new();
+ if (!ao_base_init(&ad->base, &alsa_output_plugin, param, error_r)) {
+ g_free(ad);
+ return NULL;
+ }
+
alsa_configure(ad, param);
- return ad;
+ return &ad->base;
}
static void
-alsa_finish(void *data)
+alsa_finish(struct audio_output *ao)
{
- struct alsa_data *ad = data;
+ struct alsa_data *ad = (struct alsa_data *)ao;
+ ao_base_finish(&ad->base);
alsa_data_free(ad);
/* free libasound's config cache */
@@ -530,9 +536,9 @@ error:
}
static bool
-alsa_open(void *data, struct audio_format *audio_format, GError **error)
+alsa_open(struct audio_output *ao, struct audio_format *audio_format, GError **error)
{
- struct alsa_data *ad = data;
+ struct alsa_data *ad = (struct alsa_data *)ao;
int err;
bool success;
@@ -594,9 +600,9 @@ alsa_recover(struct alsa_data *ad, int err)
}
static void
-alsa_drain(void *data)
+alsa_drain(struct audio_output *ao)
{
- struct alsa_data *ad = data;
+ struct alsa_data *ad = (struct alsa_data *)ao;
if (snd_pcm_state(ad->pcm) != SND_PCM_STATE_RUNNING)
return;
@@ -628,9 +634,9 @@ alsa_drain(void *data)
}
static void
-alsa_cancel(void *data)
+alsa_cancel(struct audio_output *ao)
{
- struct alsa_data *ad = data;
+ struct alsa_data *ad = (struct alsa_data *)ao;
ad->period_position = 0;
@@ -638,17 +644,18 @@ alsa_cancel(void *data)
}
static void
-alsa_close(void *data)
+alsa_close(struct audio_output *ao)
{
- struct alsa_data *ad = data;
+ struct alsa_data *ad = (struct alsa_data *)ao;
snd_pcm_close(ad->pcm);
}
static size_t
-alsa_play(void *data, const void *chunk, size_t size, GError **error)
+alsa_play(struct audio_output *ao, const void *chunk, size_t size,
+ GError **error)
{
- struct alsa_data *ad = data;
+ struct alsa_data *ad = (struct alsa_data *)ao;
size /= ad->frame_size;
diff --git a/src/output/ao_output_plugin.c b/src/output/ao_output_plugin.c
index e85d97d6e..c0790681e 100644
--- a/src/output/ao_output_plugin.c
+++ b/src/output/ao_output_plugin.c
@@ -33,6 +33,8 @@ static const ao_sample_format OUR_AO_FORMAT_INITIALIZER;
static unsigned ao_output_ref;
struct ao_data {
+ struct audio_output base;
+
size_t write_size;
int driver;
ao_option *options;
@@ -79,12 +81,17 @@ ao_output_error(GError **error_r)
"%s", error);
}
-static void *
-ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- const struct config_param *param,
+static struct audio_output *
+ao_output_init(const struct config_param *param,
GError **error)
{
struct ao_data *ad = g_new(struct ao_data, 1);
+
+ if (!ao_base_init(&ad->base, &ao_output_plugin, param, error)) {
+ g_free(ad);
+ return NULL;
+ }
+
ao_info *ai;
const char *value;
@@ -107,6 +114,7 @@ ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
g_set_error(error, ao_output_quark(), 0,
"\"%s\" is not a valid ao driver",
value);
+ ao_base_finish(&ad->base);
g_free(ad);
return NULL;
}
@@ -114,6 +122,7 @@ ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
if ((ai = ao_driver_info(ad->driver)) == NULL) {
g_set_error(error, ao_output_quark(), 0,
"problems getting driver info");
+ ao_base_finish(&ad->base);
g_free(ad);
return NULL;
}
@@ -132,6 +141,7 @@ ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
g_set_error(error, ao_output_quark(), 0,
"problems parsing options \"%s\"",
options[i]);
+ ao_base_finish(&ad->base);
g_free(ad);
return NULL;
}
@@ -145,15 +155,16 @@ ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
g_strfreev(options);
}
- return ad;
+ return &ad->base;
}
static void
-ao_output_finish(void *data)
+ao_output_finish(struct audio_output *ao)
{
- struct ao_data *ad = (struct ao_data *)data;
+ struct ao_data *ad = (struct ao_data *)ao;
ao_free_options(ad->options);
+ ao_base_finish(&ad->base);
g_free(ad);
ao_output_ref--;
@@ -163,19 +174,19 @@ ao_output_finish(void *data)
}
static void
-ao_output_close(void *data)
+ao_output_close(struct audio_output *ao)
{
- struct ao_data *ad = (struct ao_data *)data;
+ struct ao_data *ad = (struct ao_data *)ao;
ao_close(ad->device);
}
static bool
-ao_output_open(void *data, struct audio_format *audio_format,
+ao_output_open(struct audio_output *ao, struct audio_format *audio_format,
GError **error)
{
ao_sample_format format = OUR_AO_FORMAT_INITIALIZER;
- struct ao_data *ad = (struct ao_data *)data;
+ struct ao_data *ad = (struct ao_data *)ao;
switch (audio_format->format) {
case SAMPLE_FORMAT_S8:
@@ -227,10 +238,10 @@ static int ao_play_deconst(ao_device *device, const void *output_samples,
}
static size_t
-ao_output_play(void *data, const void *chunk, size_t size,
+ao_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error)
{
- struct ao_data *ad = (struct ao_data *)data;
+ struct ao_data *ad = (struct ao_data *)ao;
if (size > ad->write_size)
size = ad->write_size;
diff --git a/src/output/ffado_output_plugin.c b/src/output/ffado_output_plugin.c
index af74419a9..ba239a4ad 100644
--- a/src/output/ffado_output_plugin.c
+++ b/src/output/ffado_output_plugin.c
@@ -54,6 +54,8 @@ struct mpd_ffado_stream {
};
struct mpd_ffado_device {
+ struct audio_output base;
+
char *device_name;
int verbose;
unsigned period_size, nb_buffers;
@@ -83,21 +85,26 @@ ffado_output_quark(void)
return g_quark_from_static_string("ffado_output");
}
-static void *
-ffado_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- const struct config_param *param,
+static struct audio_output *
+ffado_init(const struct config_param *param,
GError **error_r)
{
g_debug("using libffado version %s, API=%d",
ffado_get_version(), ffado_get_api_version());
struct mpd_ffado_device *fd = g_new(struct mpd_ffado_device, 1);
+ if (!ao_base_init(&fd->base, &ffado_output_plugin, param, error_r)) {
+ g_free(fd);
+ return NULL;
+ }
+
fd->device_name = config_dup_block_string(param, "device", NULL);
fd->verbose = config_get_block_unsigned(param, "verbose", 0);
fd->period_size = config_get_block_unsigned(param, "period_size",
1024);
if (fd->period_size == 0 || fd->period_size > 1024 * 1024) {
+ ao_base_finish(&fd->base);
g_set_error(error_r, ffado_output_quark(), 0,
"invalid period_size setting");
return false;
@@ -105,20 +112,22 @@ ffado_init(G_GNUC_UNUSED const struct audio_format *audio_format,
fd->nb_buffers = config_get_block_unsigned(param, "nb_buffers", 3);
if (fd->nb_buffers == 0 || fd->nb_buffers > 1024) {
+ ao_base_finish(&fd->base);
g_set_error(error_r, ffado_output_quark(), 0,
"invalid nb_buffers setting");
return false;
}
- return fd;
+ return &fd->base;
}
static void
-ffado_finish(void *data)
+ffado_finish(struct audio_output *ao)
{
- struct mpd_ffado_device *fd = data;
+ struct mpd_ffado_device *fd = (struct mpd_ffado_device *)ao;
g_free(fd->device_name);
+ ao_base_finish(&fd->base);
g_free(fd);
}
@@ -228,9 +237,10 @@ ffado_configure(struct mpd_ffado_device *fd, struct audio_format *audio_format,
}
static bool
-ffado_open(void *data, struct audio_format *audio_format, GError **error_r)
+ffado_open(struct audio_output *ao, struct audio_format *audio_format,
+ GError **error_r)
{
- struct mpd_ffado_device *fd = data;
+ struct mpd_ffado_device *fd = (struct mpd_ffado_device *)ao;
/* will be converted to floating point, choose best input
format */
@@ -274,9 +284,9 @@ ffado_open(void *data, struct audio_format *audio_format, GError **error_r)
}
static void
-ffado_close(void *data)
+ffado_close(struct audio_output *ao)
{
- struct mpd_ffado_device *fd = data;
+ struct mpd_ffado_device *fd = (struct mpd_ffado_device *)ao;
ffado_streaming_stop(fd->dev);
ffado_streaming_finish(fd->dev);
@@ -288,9 +298,10 @@ ffado_close(void *data)
}
static size_t
-ffado_play(void *data, const void *chunk, size_t size, GError **error_r)
+ffado_play(struct audio_output *ao, const void *chunk, size_t size,
+ GError **error_r)
{
- struct mpd_ffado_device *fd = data;
+ struct mpd_ffado_device *fd = (struct mpd_ffado_device *)ao;
/* wait for prefious buffer to finish (if it was full) */
diff --git a/src/output/fifo_output_plugin.c b/src/output/fifo_output_plugin.c
index db250e81c..f7c88cdc8 100644
--- a/src/output/fifo_output_plugin.c
+++ b/src/output/fifo_output_plugin.c
@@ -39,6 +39,8 @@
#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;
@@ -176,9 +178,8 @@ 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,
+static struct audio_output *
+fifo_output_init(const struct config_param *param,
GError **error_r)
{
struct fifo_data *fd;
@@ -197,28 +198,35 @@ fifo_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
fd = fifo_data_new();
fd->path = path;
+ 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);
@@ -226,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;
@@ -252,10 +260,10 @@ fifo_output_cancel(void *data)
}
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)
@@ -274,7 +282,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;
diff --git a/src/output/httpd_internal.h b/src/output/httpd_internal.h
index 3e6e9768d..5dcb8ab9b 100644
--- a/src/output/httpd_internal.h
+++ b/src/output/httpd_internal.h
@@ -25,6 +25,7 @@
#ifndef MPD_OUTPUT_HTTPD_INTERNAL_H
#define MPD_OUTPUT_HTTPD_INTERNAL_H
+#include "output_internal.h"
#include "timer.h"
#include <glib.h>
@@ -34,6 +35,8 @@
struct httpd_client;
struct httpd_output {
+ struct audio_output base;
+
/**
* True if the audio output is open and accepts client
* connections.
diff --git a/src/output/httpd_output_plugin.c b/src/output/httpd_output_plugin.c
index abbd78ad2..ab663badf 100644
--- a/src/output/httpd_output_plugin.c
+++ b/src/output/httpd_output_plugin.c
@@ -79,12 +79,16 @@ httpd_output_unbind(struct httpd_output *httpd)
g_mutex_unlock(httpd->mutex);
}
-static void *
-httpd_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- const struct config_param *param,
+static struct audio_output *
+httpd_output_init(const struct config_param *param,
GError **error)
{
struct httpd_output *httpd = g_new(struct httpd_output, 1);
+ if (!ao_base_init(&httpd->base, &httpd_output_plugin, param, error)) {
+ g_free(httpd);
+ return NULL;
+ }
+
const char *encoder_name, *bind_to_address;
const struct encoder_plugin *encoder_plugin;
guint port;
@@ -104,6 +108,7 @@ httpd_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
if (encoder_plugin == NULL) {
g_set_error(error, httpd_output_quark(), 0,
"No such encoder: %s", encoder_name);
+ ao_base_finish(&httpd->base);
g_free(httpd);
return NULL;
}
@@ -121,8 +126,11 @@ httpd_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
? server_socket_add_host(httpd->server_socket, bind_to_address,
port, error)
: server_socket_add_port(httpd->server_socket, port, error);
- if (!success)
+ if (!success) {
+ ao_base_finish(&httpd->base);
+ g_free(httpd);
return NULL;
+ }
/* initialize metadata */
httpd->metadata = NULL;
@@ -131,8 +139,11 @@ httpd_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
/* initialize encoder */
httpd->encoder = encoder_init(encoder_plugin, param, error);
- if (httpd->encoder == NULL)
+ if (httpd->encoder == NULL) {
+ ao_base_finish(&httpd->base);
+ g_free(httpd);
return NULL;
+ }
/* determine content type */
httpd->content_type = encoder_get_mime_type(httpd->encoder);
@@ -142,13 +153,13 @@ httpd_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
httpd->mutex = g_mutex_new();
- return httpd;
+ return &httpd->base;
}
static void
-httpd_output_finish(void *data)
+httpd_output_finish(struct audio_output *ao)
{
- struct httpd_output *httpd = data;
+ struct httpd_output *httpd = (struct httpd_output *)ao;
if (httpd->metadata)
page_unref(httpd->metadata);
@@ -156,6 +167,7 @@ httpd_output_finish(void *data)
encoder_finish(httpd->encoder);
server_socket_free(httpd->server_socket);
g_mutex_free(httpd->mutex);
+ ao_base_finish(&httpd->base);
g_free(httpd);
}
@@ -287,26 +299,26 @@ httpd_output_encoder_open(struct httpd_output *httpd,
}
static bool
-httpd_output_enable(void *data, GError **error_r)
+httpd_output_enable(struct audio_output *ao, GError **error_r)
{
- struct httpd_output *httpd = data;
+ struct httpd_output *httpd = (struct httpd_output *)ao;
return httpd_output_bind(httpd, error_r);
}
static void
-httpd_output_disable(void *data)
+httpd_output_disable(struct audio_output *ao)
{
- struct httpd_output *httpd = data;
+ struct httpd_output *httpd = (struct httpd_output *)ao;
httpd_output_unbind(httpd);
}
static bool
-httpd_output_open(void *data, struct audio_format *audio_format,
+httpd_output_open(struct audio_output *ao, struct audio_format *audio_format,
GError **error)
{
- struct httpd_output *httpd = data;
+ struct httpd_output *httpd = (struct httpd_output *)ao;
bool success;
g_mutex_lock(httpd->mutex);
@@ -339,9 +351,10 @@ httpd_client_delete(gpointer data, G_GNUC_UNUSED gpointer user_data)
httpd_client_free(client);
}
-static void httpd_output_close(void *data)
+static void
+httpd_output_close(struct audio_output *ao)
{
- struct httpd_output *httpd = data;
+ struct httpd_output *httpd = (struct httpd_output *)ao;
g_mutex_lock(httpd->mutex);
@@ -380,9 +393,9 @@ httpd_output_send_header(struct httpd_output *httpd,
}
static unsigned
-httpd_output_delay(void *data)
+httpd_output_delay(struct audio_output *ao)
{
- struct httpd_output *httpd = data;
+ struct httpd_output *httpd = (struct httpd_output *)ao;
return httpd->timer->started
? timer_delay(httpd->timer)
@@ -458,9 +471,10 @@ httpd_output_encode_and_play(struct httpd_output *httpd,
}
static size_t
-httpd_output_play(void *data, const void *chunk, size_t size, GError **error)
+httpd_output_play(struct audio_output *ao, const void *chunk, size_t size,
+ GError **error)
{
- struct httpd_output *httpd = data;
+ struct httpd_output *httpd = (struct httpd_output *)ao;
bool has_clients;
g_mutex_lock(httpd->mutex);
@@ -484,9 +498,9 @@ httpd_output_play(void *data, const void *chunk, size_t size, GError **error)
}
static bool
-httpd_output_pause(void *data)
+httpd_output_pause(struct audio_output *ao)
{
- struct httpd_output *httpd = data;
+ struct httpd_output *httpd = (struct httpd_output *)ao;
g_mutex_lock(httpd->mutex);
bool has_clients = httpd->clients != NULL;
@@ -494,7 +508,7 @@ httpd_output_pause(void *data)
if (has_clients) {
static const char silence[1020];
- return httpd_output_play(data, silence, sizeof(silence),
+ return httpd_output_play(ao, silence, sizeof(silence),
NULL) > 0;
} else {
g_usleep(100000);
@@ -512,9 +526,9 @@ httpd_send_metadata(gpointer data, gpointer user_data)
}
static void
-httpd_output_tag(void *data, const struct tag *tag)
+httpd_output_tag(struct audio_output *ao, const struct tag *tag)
{
- struct httpd_output *httpd = data;
+ struct httpd_output *httpd = (struct httpd_output *)ao;
assert(tag != NULL);
@@ -571,9 +585,9 @@ httpd_client_cancel_callback(gpointer data, G_GNUC_UNUSED gpointer user_data)
}
static void
-httpd_output_cancel(void *data)
+httpd_output_cancel(struct audio_output *ao)
{
- struct httpd_output *httpd = data;
+ struct httpd_output *httpd = (struct httpd_output *)ao;
g_mutex_lock(httpd->mutex);
g_list_foreach(httpd->clients, httpd_client_cancel_callback, NULL);
diff --git a/src/output/jack_output_plugin.c b/src/output/jack_output_plugin.c
index 189b52a6f..cd769088b 100644
--- a/src/output/jack_output_plugin.c
+++ b/src/output/jack_output_plugin.c
@@ -44,6 +44,8 @@ enum {
static const size_t jack_sample_size = sizeof(jack_default_audio_sample_t);
struct jack_data {
+ struct audio_output base;
+
/**
* libjack options passed to jack_client_open().
*/
@@ -292,14 +294,18 @@ parse_port_list(int line, const char *source, char **dest, GError **error_r)
return n;
}
-static void *
-mpd_jack_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- const struct config_param *param, GError **error_r)
+static struct audio_output *
+mpd_jack_init(const struct config_param *param, GError **error_r)
{
- struct jack_data *jd;
+ struct jack_data *jd = g_new(struct jack_data, 1);
+
+ if (!ao_base_init(&jd->base, &jack_output_plugin, param, error_r)) {
+ g_free(jd);
+ return NULL;
+ }
+
const char *value;
- jd = g_new(struct jack_data, 1);
jd->options = JackNullOption;
jd->name = config_get_block_string(param, "client_name", NULL);
@@ -362,13 +368,13 @@ mpd_jack_init(G_GNUC_UNUSED const struct audio_format *audio_format,
jack_set_info_function(mpd_jack_info);
#endif
- return jd;
+ return &jd->base;
}
static void
-mpd_jack_finish(void *data)
+mpd_jack_finish(struct audio_output *ao)
{
- struct jack_data *jd = data;
+ struct jack_data *jd = (struct jack_data *)ao;
for (unsigned i = 0; i < jd->num_source_ports; ++i)
g_free(jd->source_ports[i]);
@@ -376,13 +382,14 @@ mpd_jack_finish(void *data)
for (unsigned i = 0; i < jd->num_destination_ports; ++i)
g_free(jd->destination_ports[i]);
+ ao_base_finish(&jd->base);
g_free(jd);
}
static bool
-mpd_jack_enable(void *data, GError **error_r)
+mpd_jack_enable(struct audio_output *ao, GError **error_r)
{
- struct jack_data *jd = (struct jack_data *)data;
+ struct jack_data *jd = (struct jack_data *)ao;
for (unsigned i = 0; i < jd->num_source_ports; ++i)
jd->ringbuffer[i] = NULL;
@@ -391,9 +398,9 @@ mpd_jack_enable(void *data, GError **error_r)
}
static void
-mpd_jack_disable(void *data)
+mpd_jack_disable(struct audio_output *ao)
{
- struct jack_data *jd = (struct jack_data *)data;
+ struct jack_data *jd = (struct jack_data *)ao;
if (jd->client != NULL)
mpd_jack_disconnect(jd);
@@ -556,9 +563,10 @@ mpd_jack_start(struct jack_data *jd, GError **error_r)
}
static bool
-mpd_jack_open(void *data, struct audio_format *audio_format, GError **error_r)
+mpd_jack_open(struct audio_output *ao, struct audio_format *audio_format,
+ GError **error_r)
{
- struct jack_data *jd = data;
+ struct jack_data *jd = (struct jack_data *)ao;
assert(jd != NULL);
@@ -577,9 +585,9 @@ mpd_jack_open(void *data, struct audio_format *audio_format, GError **error_r)
}
static void
-mpd_jack_close(G_GNUC_UNUSED void *data)
+mpd_jack_close(G_GNUC_UNUSED struct audio_output *ao)
{
- struct jack_data *jd = data;
+ struct jack_data *jd = (struct jack_data *)ao;
mpd_jack_stop(jd);
}
@@ -649,9 +657,10 @@ mpd_jack_write_samples(struct jack_data *jd, const void *src,
}
static size_t
-mpd_jack_play(void *data, const void *chunk, size_t size, GError **error_r)
+mpd_jack_play(struct audio_output *ao, const void *chunk, size_t size,
+ GError **error_r)
{
- struct jack_data *jd = data;
+ struct jack_data *jd = (struct jack_data *)ao;
const size_t frame_size = audio_format_frame_size(&jd->audio_format);
size_t space = 0, space1;
@@ -693,9 +702,9 @@ mpd_jack_play(void *data, const void *chunk, size_t size, GError **error_r)
}
static bool
-mpd_jack_pause(void *data)
+mpd_jack_pause(struct audio_output *ao)
{
- struct jack_data *jd = data;
+ struct jack_data *jd = (struct jack_data *)ao;
if (jd->shutdown)
return false;
diff --git a/src/output/mvp_output_plugin.c b/src/output/mvp_output_plugin.c
index 6f058b53e..aec09248f 100644
--- a/src/output/mvp_output_plugin.c
+++ b/src/output/mvp_output_plugin.c
@@ -70,6 +70,8 @@ typedef struct {
#define MVP_GET_AUD_REGS _IOW('a',28,aud_ctl_regs_t*)
struct mvp_data {
+ struct audio_output base;
+
struct audio_format audio_format;
int fd;
};
@@ -131,21 +133,26 @@ mvp_output_test_default_device(void)
return false;
}
-static void *
-mvp_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- G_GNUC_UNUSED const struct config_param *param,
- G_GNUC_UNUSED GError **error)
+static struct audio_output *
+mvp_output_init(G_GNUC_UNUSED const struct config_param *param, GError **error)
{
struct mvp_data *md = g_new(struct mvp_data, 1);
+
+ if (!ao_base_init(&md->base, &mvp_output_plugin, param, error)) {
+ g_free(md);
+ return NULL;
+ }
+
md->fd = -1;
- return md;
+ return &md->base;
}
static void
-mvp_output_finish(void *data)
+mvp_output_finish(struct audio_output *ao)
{
- struct mvp_data *md = data;
+ struct mvp_data *md = (struct mvp_data *)ao;
+ ao_base_finish(&md->base);
g_free(md);
}
@@ -226,9 +233,10 @@ mvp_set_pcm_params(struct mvp_data *md, struct audio_format *audio_format,
}
static bool
-mvp_output_open(void *data, struct audio_format *audio_format, GError **error)
+mvp_output_open(struct audio_output *ao, struct audio_format *audio_format,
+ GError **error)
{
- struct mvp_data *md = data;
+ struct mvp_data *md = (struct mvp_data *)ao;
long long int stc = 0;
int mix[5] = { 0, 2, 7, 1, 0 };
bool success;
@@ -274,17 +282,17 @@ mvp_output_open(void *data, struct audio_format *audio_format, GError **error)
return true;
}
-static void mvp_output_close(void *data)
+static void mvp_output_close(struct audio_output *ao)
{
- struct mvp_data *md = data;
+ struct mvp_data *md = (struct mvp_data *)ao;
if (md->fd >= 0)
close(md->fd);
md->fd = -1;
}
-static void mvp_output_cancel(void *data)
+static void mvp_output_cancel(struct audio_output *ao)
{
- struct mvp_data *md = data;
+ struct mvp_data *md = (struct mvp_data *)ao;
if (md->fd >= 0) {
ioctl(md->fd, MVP_SET_AUD_RESET, 0x11);
close(md->fd);
@@ -293,16 +301,17 @@ static void mvp_output_cancel(void *data)
}
static size_t
-mvp_output_play(void *data, const void *chunk, size_t size, GError **error)
+mvp_output_play(struct audio_output *ao, const void *chunk, size_t size,
+ GError **error)
{
- struct mvp_data *md = data;
+ struct mvp_data *md = (struct mvp_data *)ao;
ssize_t ret;
/* reopen the device since it was closed by dropBufferedAudio */
if (md->fd < 0) {
bool success;
- success = mvp_output_open(md, &md->audio_format, error);
+ success = mvp_output_open(ao, &md->audio_format, error);
if (!success)
return 0;
}
diff --git a/src/output/null_output_plugin.c b/src/output/null_output_plugin.c
index 94c0c5321..e680e617c 100644
--- a/src/output/null_output_plugin.c
+++ b/src/output/null_output_plugin.c
@@ -27,39 +27,45 @@
#include <assert.h>
struct null_data {
+ struct audio_output base;
+
bool sync;
struct timer *timer;
};
-static void *
-null_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- G_GNUC_UNUSED const struct config_param *param,
- G_GNUC_UNUSED GError **error)
+static struct audio_output *
+null_init(const struct config_param *param, GError **error_r)
{
struct null_data *nd = g_new(struct null_data, 1);
+ if (!ao_base_init(&nd->base, &null_output_plugin, param, error_r)) {
+ g_free(nd);
+ return NULL;
+ }
+
nd->sync = config_get_block_bool(param, "sync", true);
nd->timer = NULL;
- return nd;
+ return &nd->base;
}
static void
-null_finish(void *data)
+null_finish(struct audio_output *ao)
{
- struct null_data *nd = data;
+ struct null_data *nd = (struct null_data *)ao;
assert(nd->timer == NULL);
+ ao_base_finish(&nd->base);
g_free(nd);
}
static bool
-null_open(void *data, struct audio_format *audio_format,
+null_open(struct audio_output *ao, struct audio_format *audio_format,
G_GNUC_UNUSED GError **error)
{
- struct null_data *nd = data;
+ struct null_data *nd = (struct null_data *)ao;
if (nd->sync)
nd->timer = timer_new(audio_format);
@@ -68,9 +74,9 @@ null_open(void *data, struct audio_format *audio_format,
}
static void
-null_close(void *data)
+null_close(struct audio_output *ao)
{
- struct null_data *nd = data;
+ struct null_data *nd = (struct null_data *)ao;
if (nd->timer != NULL) {
timer_free(nd->timer);
@@ -79,10 +85,10 @@ null_close(void *data)
}
static size_t
-null_play(void *data, G_GNUC_UNUSED const void *chunk, size_t size,
+null_play(struct audio_output *ao, G_GNUC_UNUSED const void *chunk, size_t size,
G_GNUC_UNUSED GError **error)
{
- struct null_data *nd = data;
+ struct null_data *nd = (struct null_data *)ao;
struct timer *timer = nd->timer;
if (!nd->sync)
@@ -99,9 +105,9 @@ null_play(void *data, G_GNUC_UNUSED const void *chunk, size_t size,
}
static void
-null_cancel(void *data)
+null_cancel(struct audio_output *ao)
{
- struct null_data *nd = data;
+ struct null_data *nd = (struct null_data *)ao;
if (!nd->sync)
return;
diff --git a/src/output/openal_output_plugin.c b/src/output/openal_output_plugin.c
index 56afc4463..1473659f0 100644
--- a/src/output/openal_output_plugin.c
+++ b/src/output/openal_output_plugin.c
@@ -39,6 +39,8 @@
#define NUM_BUFFERS 16
struct openal_data {
+ struct audio_output base;
+
const char *device_name;
ALCdevice *device;
ALCcontext *context;
@@ -126,10 +128,8 @@ openal_unqueue_buffers(struct openal_data *od)
}
}
-static void *
-openal_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- const struct config_param *param,
- G_GNUC_UNUSED GError **error)
+static struct audio_output *
+openal_init(const struct config_param *param, GError **error_r)
{
const char *device_name = config_get_block_string(param, "device", NULL);
struct openal_data *od;
@@ -139,24 +139,30 @@ openal_init(G_GNUC_UNUSED const struct audio_format *audio_format,
}
od = g_new(struct openal_data, 1);
+ if (!ao_base_init(&od->base, &openal_output_plugin, param, error_r)) {
+ g_free(od);
+ return NULL;
+ }
+
od->device_name = device_name;
- return od;
+ return &od->base;
}
static void
-openal_finish(void *data)
+openal_finish(struct audio_output *ao)
{
- struct openal_data *od = data;
+ struct openal_data *od = (struct openal_data *)ao;
+ ao_base_finish(&od->base);
g_free(od);
}
static bool
-openal_open(void *data, struct audio_format *audio_format,
+openal_open(struct audio_output *ao, struct audio_format *audio_format,
GError **error)
{
- struct openal_data *od = data;
+ struct openal_data *od = (struct openal_data *)ao;
od->format = openal_audio_format(audio_format);
@@ -198,9 +204,9 @@ openal_open(void *data, struct audio_format *audio_format,
}
static void
-openal_close(void *data)
+openal_close(struct audio_output *ao)
{
- struct openal_data *od = data;
+ struct openal_data *od = (struct openal_data *)ao;
timer_free(od->timer);
alcMakeContextCurrent(od->context);
@@ -211,10 +217,10 @@ openal_close(void *data)
}
static size_t
-openal_play(void *data, const void *chunk, size_t size,
+openal_play(struct audio_output *ao, const void *chunk, size_t size,
G_GNUC_UNUSED GError **error)
{
- struct openal_data *od = data;
+ struct openal_data *od = (struct openal_data *)ao;
ALuint buffer;
ALint num, state;
@@ -257,9 +263,9 @@ openal_play(void *data, const void *chunk, size_t size,
}
static void
-openal_cancel(void *data)
+openal_cancel(struct audio_output *ao)
{
- struct openal_data *od = data;
+ struct openal_data *od = (struct openal_data *)ao;
od->filled = 0;
alcMakeContextCurrent(od->context);
diff --git a/src/output/oss_output_plugin.c b/src/output/oss_output_plugin.c
index c9aef52a6..c8fce84ea 100644
--- a/src/output/oss_output_plugin.c
+++ b/src/output/oss_output_plugin.c
@@ -52,6 +52,8 @@
#endif
struct oss_data {
+ struct audio_output base;
+
int fd;
const char *device;
@@ -143,7 +145,7 @@ oss_output_test_default_device(void)
return false;
}
-static void *
+static struct audio_output *
oss_open_default(GError **error)
{
int i;
@@ -154,8 +156,14 @@ oss_open_default(GError **error)
ret[i] = oss_stat_device(default_devices[i], &err[i]);
if (ret[i] == OSS_STAT_NO_ERROR) {
struct oss_data *od = oss_data_new();
+ if (!ao_base_init(&od->base, &oss_output_plugin, NULL,
+ error)) {
+ g_free(od);
+ return NULL;
+ }
+
od->device = default_devices[i];
- return od;
+ return &od->base;
}
}
@@ -185,26 +193,31 @@ oss_open_default(GError **error)
return NULL;
}
-static void *
-oss_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- const struct config_param *param,
- GError **error)
+static struct audio_output *
+oss_output_init(const struct config_param *param, GError **error)
{
const char *device = config_get_block_string(param, "device", NULL);
if (device != NULL) {
struct oss_data *od = oss_data_new();
+ if (!ao_base_init(&od->base, &oss_output_plugin, param,
+ error)) {
+ g_free(od);
+ return NULL;
+ }
+
od->device = device;
- return od;
+ return &od->base;
}
return oss_open_default(error);
}
static void
-oss_output_finish(void *data)
+oss_output_finish(struct audio_output *ao)
{
- struct oss_data *od = data;
+ struct oss_data *od = (struct oss_data *)ao;
+ ao_base_finish(&od->base);
oss_data_free(od);
}
@@ -607,9 +620,10 @@ oss_reopen(struct oss_data *od, GError **error_r)
}
static bool
-oss_output_open(void *data, struct audio_format *audio_format, GError **error)
+oss_output_open(struct audio_output *ao, struct audio_format *audio_format,
+ GError **error)
{
- struct oss_data *od = data;
+ struct oss_data *od = (struct oss_data *)ao;
od->fd = open_cloexec(od->device, O_WRONLY, 0);
if (od->fd < 0) {
@@ -629,17 +643,17 @@ oss_output_open(void *data, struct audio_format *audio_format, GError **error)
}
static void
-oss_output_close(void *data)
+oss_output_close(struct audio_output *ao)
{
- struct oss_data *od = data;
+ struct oss_data *od = (struct oss_data *)ao;
oss_close(od);
}
static void
-oss_output_cancel(void *data)
+oss_output_cancel(struct audio_output *ao)
{
- struct oss_data *od = data;
+ struct oss_data *od = (struct oss_data *)ao;
if (od->fd >= 0) {
ioctl(od->fd, SNDCTL_DSP_RESET, 0);
@@ -648,9 +662,10 @@ oss_output_cancel(void *data)
}
static size_t
-oss_output_play(void *data, const void *chunk, size_t size, GError **error)
+oss_output_play(struct audio_output *ao, const void *chunk, size_t size,
+ GError **error)
{
- struct oss_data *od = data;
+ struct oss_data *od = (struct oss_data *)ao;
ssize_t ret;
/* reopen the device since it was closed by dropBufferedAudio */
diff --git a/src/output/osx_output_plugin.c b/src/output/osx_output_plugin.c
index f33148c25..f07aedc08 100644
--- a/src/output/osx_output_plugin.c
+++ b/src/output/osx_output_plugin.c
@@ -29,6 +29,8 @@
#define G_LOG_DOMAIN "osx"
struct osx_output {
+ struct audio_output base;
+
/* configuration settings */
OSType component_subtype;
/* only applicable with kAudioUnitSubType_HALOutput */
@@ -80,12 +82,14 @@ osx_output_configure(struct osx_output *oo, const struct config_param *param)
}
}
-static void *
-osx_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- G_GNUC_UNUSED const struct config_param *param,
- G_GNUC_UNUSED GError **error)
+static struct audio_output *
+osx_output_init(const struct config_param *param, GError **error_r)
{
struct osx_output *oo = g_new(struct osx_output, 1);
+ if (!ao_base_init(&oo->base, &osx_output_plugin, param, error_r)) {
+ g_free(oo);
+ return NULL;
+ }
osx_output_configure(oo, param);
oo->mutex = g_mutex_new();
@@ -96,12 +100,13 @@ osx_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
oo->buffer = NULL;
oo->buffer_size = 0;
- return oo;
+ return &oo->base;
}
-static void osx_output_finish(void *data)
+static void
+osx_output_finish(struct audio_output *ao)
{
- struct osx_output *od = data;
+ struct osx_output *od = (struct osx_output *)ao;
g_free(od->buffer);
g_mutex_free(od->mutex);
@@ -109,18 +114,20 @@ static void osx_output_finish(void *data)
g_free(od);
}
-static void osx_output_cancel(void *data)
+static void
+osx_output_cancel(struct audio_output *ao)
{
- struct osx_output *od = data;
+ struct osx_output *od = (struct osx_output *)ao;
g_mutex_lock(od->mutex);
od->len = 0;
g_mutex_unlock(od->mutex);
}
-static void osx_output_close(void *data)
+static void
+osx_output_close(struct audio_output *ao)
{
- struct osx_output *od = data;
+ struct osx_output *od = (struct osx_output *)ao;
AudioOutputUnitStop(od->au);
AudioUnitUninitialize(od->au);
@@ -266,9 +273,9 @@ done:
}
static bool
-osx_output_open(void *data, struct audio_format *audio_format, GError **error)
+osx_output_open(struct audio_output *ao, struct audio_format *audio_format, GError **error)
{
- struct osx_output *od = data;
+ struct osx_output *od = (struct osx_output *)ao;
ComponentDescription desc;
Component comp;
AURenderCallbackStruct callback;
@@ -385,10 +392,10 @@ osx_output_open(void *data, struct audio_format *audio_format, GError **error)
}
static size_t
-osx_output_play(void *data, const void *chunk, size_t size,
+osx_output_play(struct audio_output *ao, const void *chunk, size_t size,
G_GNUC_UNUSED GError **error)
{
- struct osx_output *od = data;
+ struct osx_output *od = (struct osx_output *)ao;
size_t start, nbytes;
g_mutex_lock(od->mutex);
diff --git a/src/output/pipe_output_plugin.c b/src/output/pipe_output_plugin.c
index 08f195068..90c5a5331 100644
--- a/src/output/pipe_output_plugin.c
+++ b/src/output/pipe_output_plugin.c
@@ -25,6 +25,8 @@
#include <errno.h>
struct pipe_output {
+ struct audio_output base;
+
char *cmd;
FILE *fh;
};
@@ -38,13 +40,17 @@ pipe_output_quark(void)
return g_quark_from_static_string("pipe_output");
}
-static void *
-pipe_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- const struct config_param *param,
+static struct audio_output *
+pipe_output_init(const struct config_param *param,
GError **error)
{
struct pipe_output *pd = g_new(struct pipe_output, 1);
+ if (!ao_base_init(&pd->base, &pipe_output_plugin, param, error)) {
+ g_free(pd);
+ return NULL;
+ }
+
pd->cmd = config_dup_block_string(param, "command", NULL);
if (pd->cmd == NULL) {
g_set_error(error, pipe_output_quark(), 0,
@@ -52,23 +58,25 @@ pipe_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
return NULL;
}
- return pd;
+ return &pd->base;
}
static void
-pipe_output_finish(void *data)
+pipe_output_finish(struct audio_output *ao)
{
- struct pipe_output *pd = data;
+ struct pipe_output *pd = (struct pipe_output *)ao;
g_free(pd->cmd);
+ ao_base_finish(&pd->base);
g_free(pd);
}
static bool
-pipe_output_open(void *data, G_GNUC_UNUSED struct audio_format *audio_format,
+pipe_output_open(struct audio_output *ao,
+ G_GNUC_UNUSED struct audio_format *audio_format,
G_GNUC_UNUSED GError **error)
{
- struct pipe_output *pd = data;
+ struct pipe_output *pd = (struct pipe_output *)ao;
pd->fh = popen(pd->cmd, "w");
if (pd->fh == NULL) {
@@ -82,17 +90,17 @@ pipe_output_open(void *data, G_GNUC_UNUSED struct audio_format *audio_format,
}
static void
-pipe_output_close(void *data)
+pipe_output_close(struct audio_output *ao)
{
- struct pipe_output *pd = data;
+ struct pipe_output *pd = (struct pipe_output *)ao;
pclose(pd->fh);
}
static size_t
-pipe_output_play(void *data, const void *chunk, size_t size, GError **error)
+pipe_output_play(struct audio_output *ao, const void *chunk, size_t size, GError **error)
{
- struct pipe_output *pd = data;
+ struct pipe_output *pd = (struct pipe_output *)ao;
size_t ret;
ret = fwrite(chunk, 1, size, pd->fh);
diff --git a/src/output/pulse_output_plugin.c b/src/output/pulse_output_plugin.c
index 22e21d729..0dc9be0e4 100644
--- a/src/output/pulse_output_plugin.c
+++ b/src/output/pulse_output_plugin.c
@@ -46,6 +46,8 @@
#endif
struct pulse_output {
+ struct audio_output base;
+
const char *name;
const char *server;
const char *sink;
@@ -342,16 +344,19 @@ pulse_output_setup_context(struct pulse_output *po, GError **error_r)
return true;
}
-static void *
-pulse_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- const struct config_param *param,
- G_GNUC_UNUSED GError **error_r)
+static struct audio_output *
+pulse_output_init(const struct config_param *param, GError **error_r)
{
struct pulse_output *po;
g_setenv("PULSE_PROP_media.role", "music", true);
po = g_new(struct pulse_output, 1);
+ if (!ao_base_init(&po->base, &pulse_output_plugin, param, error_r)) {
+ g_free(po);
+ return NULL;
+ }
+
po->name = config_get_block_string(param, "name", "mpd_pulse");
po->server = config_get_block_string(param, "server", NULL);
po->sink = config_get_block_string(param, "sink", NULL);
@@ -361,21 +366,22 @@ pulse_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
po->context = NULL;
po->stream = NULL;
- return po;
+ return &po->base;
}
static void
-pulse_output_finish(void *data)
+pulse_output_finish(struct audio_output *ao)
{
- struct pulse_output *po = data;
+ struct pulse_output *po = (struct pulse_output *)ao;
+ ao_base_finish(&po->base);
g_free(po);
}
static bool
-pulse_output_enable(void *data, GError **error_r)
+pulse_output_enable(struct audio_output *ao, GError **error_r)
{
- struct pulse_output *po = data;
+ struct pulse_output *po = (struct pulse_output *)ao;
assert(po->mainloop == NULL);
assert(po->context == NULL);
@@ -419,9 +425,9 @@ pulse_output_enable(void *data, GError **error_r)
}
static void
-pulse_output_disable(void *data)
+pulse_output_disable(struct audio_output *ao)
{
- struct pulse_output *po = data;
+ struct pulse_output *po = (struct pulse_output *)ao;
assert(po->mainloop != NULL);
@@ -573,10 +579,10 @@ pulse_output_setup_stream(struct pulse_output *po, const pa_sample_spec *ss,
}
static bool
-pulse_output_open(void *data, struct audio_format *audio_format,
+pulse_output_open(struct audio_output *ao, struct audio_format *audio_format,
GError **error_r)
{
- struct pulse_output *po = data;
+ struct pulse_output *po = (struct pulse_output *)ao;
pa_sample_spec ss;
int error;
@@ -647,9 +653,9 @@ pulse_output_open(void *data, struct audio_format *audio_format,
}
static void
-pulse_output_close(void *data)
+pulse_output_close(struct audio_output *ao)
{
- struct pulse_output *po = data;
+ struct pulse_output *po = (struct pulse_output *)ao;
pa_operation *o;
assert(po->mainloop != NULL);
@@ -796,9 +802,10 @@ pulse_output_stream_pause(struct pulse_output *po, bool pause,
}
static size_t
-pulse_output_play(void *data, const void *chunk, size_t size, GError **error_r)
+pulse_output_play(struct audio_output *ao, const void *chunk, size_t size,
+ GError **error_r)
{
- struct pulse_output *po = data;
+ struct pulse_output *po = (struct pulse_output *)ao;
int error;
assert(po->mainloop != NULL);
@@ -866,9 +873,9 @@ pulse_output_play(void *data, const void *chunk, size_t size, GError **error_r)
}
static void
-pulse_output_cancel(void *data)
+pulse_output_cancel(struct audio_output *ao)
{
- struct pulse_output *po = data;
+ struct pulse_output *po = (struct pulse_output *)ao;
pa_operation *o;
assert(po->mainloop != NULL);
@@ -898,9 +905,9 @@ pulse_output_cancel(void *data)
}
static bool
-pulse_output_pause(void *data)
+pulse_output_pause(struct audio_output *ao)
{
- struct pulse_output *po = data;
+ struct pulse_output *po = (struct pulse_output *)ao;
GError *error = NULL;
assert(po->mainloop != NULL);
@@ -945,12 +952,12 @@ pulse_output_test_default_device(void)
struct pulse_output *po;
bool success;
- po = pulse_output_init(NULL, NULL, NULL);
+ po = (struct pulse_output *)pulse_output_init(NULL, NULL);
if (po == NULL)
return false;
success = pulse_output_wait_connection(po, NULL);
- pulse_output_finish(po);
+ pulse_output_finish(&po->base);
return success;
}
diff --git a/src/output/raop_output_plugin.c b/src/output/raop_output_plugin.c
index 772112e51..dce7b5beb 100644
--- a/src/output/raop_output_plugin.c
+++ b/src/output/raop_output_plugin.c
@@ -79,6 +79,8 @@ struct encrypt_data {
/*********************************************************************/
struct raop_data {
+ struct audio_output base;
+
struct rtspcl_data *rtspcl;
const char *addr; // target host address
short rtsp_port;
@@ -209,9 +211,13 @@ raop_session_new(GError **error_r)
}
static struct raop_data *
-new_raop_data(GError **error_r)
+new_raop_data(const struct config_param *param, GError **error_r)
{
struct raop_data *ret = g_new(struct raop_data, 1);
+ if (!ao_base_init(&ret->base, &raop_output_plugin, param, error_r)) {
+ g_free(ret);
+ return NULL;
+ }
ret->control_mutex = g_mutex_new();
@@ -223,6 +229,7 @@ new_raop_data(GError **error_r)
if (raop_session == NULL &&
(raop_session = raop_session_new(error_r)) == NULL) {
g_mutex_free(ret->control_mutex);
+ ao_base_finish(&ret->base);
g_free(ret);
return NULL;
}
@@ -721,10 +728,8 @@ send_audio_data(int fd, GError **error_r)
return true;
}
-static void *
-raop_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- G_GNUC_UNUSED const struct config_param *param,
- GError **error_r)
+static struct audio_output *
+raop_output_init(const struct config_param *param, GError **error_r)
{
const char *host = config_get_block_string(param, "host", NULL);
if (host == NULL) {
@@ -735,14 +740,14 @@ raop_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
struct raop_data *rd;
- rd = new_raop_data(error_r);
+ rd = new_raop_data(param, error_r);
if (rd == NULL)
return NULL;
rd->addr = host;
rd->rtsp_port = config_get_block_unsigned(param, "port", 5000);
rd->volume = config_get_block_unsigned(param, "volume", 75);
- return rd;
+ return &rd->base;
}
static bool
@@ -755,14 +760,15 @@ raop_set_volume_local(struct raop_data *rd, int volume, GError **error_r)
static void
-raop_output_finish(void *data)
+raop_output_finish(struct audio_output *ao)
{
- struct raop_data *rd = data;
+ struct raop_data *rd = (struct raop_data *)ao;
if (rd->rtspcl)
rtspcl_close(rd->rtspcl);
g_mutex_free(rd->control_mutex);
+ ao_base_finish(&rd->base);
g_free(rd);
}
@@ -797,11 +803,11 @@ raop_set_volume(struct raop_data *rd, unsigned volume, GError **error_r)
}
static void
-raop_output_cancel(void *data)
+raop_output_cancel(struct audio_output *ao)
{
//flush
struct key_data kd;
- struct raop_data *rd = (struct raop_data *) data;
+ struct raop_data *rd = (struct raop_data *)ao;
int flush_diff = 1;
rd->started = 0;
@@ -825,9 +831,9 @@ raop_output_cancel(void *data)
}
static bool
-raop_output_pause(void *data)
+raop_output_pause(struct audio_output *ao)
{
- struct raop_data *rd = (struct raop_data *) data;
+ struct raop_data *rd = (struct raop_data *)ao;
rd->paused = true;
return true;
@@ -870,10 +876,10 @@ raop_output_remove(struct raop_data *rd)
}
static void
-raop_output_close(void *data)
+raop_output_close(struct audio_output *ao)
{
//teardown
- struct raop_data *rd = data;
+ struct raop_data *rd = (struct raop_data *)ao;
raop_output_remove(rd);
@@ -887,10 +893,10 @@ raop_output_close(void *data)
static bool
-raop_output_open(void *data, struct audio_format *audio_format, GError **error_r)
+raop_output_open(struct audio_output *ao, struct audio_format *audio_format, GError **error_r)
{
//setup, etc.
- struct raop_data *rd = data;
+ struct raop_data *rd = (struct raop_data *)ao;
g_mutex_lock(raop_session->list_mutex);
if (raop_session->raop_list == NULL) {
@@ -940,11 +946,11 @@ raop_output_open(void *data, struct audio_format *audio_format, GError **error_r
}
static size_t
-raop_output_play(void *data, const void *chunk, size_t size,
+raop_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error_r)
{
//raopcl_send_sample
- struct raop_data *rd = data;
+ struct raop_data *rd = (struct raop_data *)ao;
size_t rval = 0, orig_size = size;
rd->paused = false;
diff --git a/src/output/recorder_output_plugin.c b/src/output/recorder_output_plugin.c
index 981f92e44..00adc5d19 100644
--- a/src/output/recorder_output_plugin.c
+++ b/src/output/recorder_output_plugin.c
@@ -35,6 +35,8 @@
#define G_LOG_DOMAIN "recorder"
struct recorder_output {
+ struct audio_output base;
+
/**
* The configured encoder plugin.
*/
@@ -65,11 +67,16 @@ recorder_output_quark(void)
return g_quark_from_static_string("recorder_output");
}
-static void *
-recorder_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- const struct config_param *param, GError **error_r)
+static struct audio_output *
+recorder_output_init(const struct config_param *param, GError **error_r)
{
struct recorder_output *recorder = g_new(struct recorder_output, 1);
+ if (!ao_base_init(&recorder->base, &recorder_output_plugin, param,
+ error_r)) {
+ g_free(recorder);
+ return NULL;
+ }
+
const char *encoder_name;
const struct encoder_plugin *encoder_plugin;
@@ -96,19 +103,21 @@ recorder_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
if (recorder->encoder == NULL)
goto failure;
- return recorder;
+ return &recorder->base;
failure:
+ ao_base_finish(&recorder->base);
g_free(recorder);
return NULL;
}
static void
-recorder_output_finish(void *data)
+recorder_output_finish(struct audio_output *ao)
{
- struct recorder_output *recorder = data;
+ struct recorder_output *recorder = (struct recorder_output *)ao;
encoder_finish(recorder->encoder);
+ ao_base_finish(&recorder->base);
g_free(recorder);
}
@@ -155,10 +164,11 @@ recorder_output_encoder_to_file(struct recorder_output *recorder,
}
static bool
-recorder_output_open(void *data, struct audio_format *audio_format,
+recorder_output_open(struct audio_output *ao,
+ struct audio_format *audio_format,
GError **error_r)
{
- struct recorder_output *recorder = data;
+ struct recorder_output *recorder = (struct recorder_output *)ao;
bool success;
/* create the output file */
@@ -186,9 +196,9 @@ recorder_output_open(void *data, struct audio_format *audio_format,
}
static void
-recorder_output_close(void *data)
+recorder_output_close(struct audio_output *ao)
{
- struct recorder_output *recorder = data;
+ struct recorder_output *recorder = (struct recorder_output *)ao;
/* flush the encoder and write the rest to the file */
@@ -203,10 +213,10 @@ recorder_output_close(void *data)
}
static size_t
-recorder_output_play(void *data, const void *chunk, size_t size,
+recorder_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error_r)
{
- struct recorder_output *recorder = data;
+ struct recorder_output *recorder = (struct recorder_output *)ao;
return encoder_write(recorder->encoder, chunk, size, error_r) &&
recorder_output_encoder_to_file(recorder, error_r)
diff --git a/src/output/roar_output_plugin.c b/src/output/roar_output_plugin.c
index c6f3e99f5..d15569fd5 100644
--- a/src/output/roar_output_plugin.c
+++ b/src/output/roar_output_plugin.c
@@ -38,6 +38,8 @@
typedef struct roar
{
+ struct audio_output base;
+
roar_vs_t * vss;
int err;
char *host;
@@ -114,34 +116,39 @@ roar_configure(struct roar * self, const struct config_param *param)
: ROAR_ROLE_MUSIC;
}
-static void *
-roar_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- const struct config_param *param,
- G_GNUC_UNUSED GError **error)
+static struct audio_output *
+roar_init(const struct config_param *param, GError **error_r)
{
struct roar *self = g_new0(struct roar, 1);
+
+ if (!ao_base_init(&self->base, &roar_output_plugin, param, error_r)) {
+ g_free(self);
+ return NULL;
+ }
+
self->lock = g_mutex_new();
self->err = ROAR_ERROR_NONE;
roar_configure(self, param);
- return self;
+ return &self->base;
}
static void
-roar_finish(void *data)
+roar_finish(struct audio_output *ao)
{
- roar_t * self = data;
+ struct roar *self = (struct roar *)ao;
g_free(self->host);
g_free(self->name);
g_mutex_free(self->lock);
+ ao_base_finish(&self->base);
g_free(self);
}
static bool
-roar_open(void *data, struct audio_format *audio_format, GError **error)
+roar_open(struct audio_output *ao, struct audio_format *audio_format, GError **error)
{
- roar_t * self = data;
+ struct roar *self = (struct roar *)ao;
g_mutex_lock(self->lock);
if (roar_simple_connect(&(self->con), self->host, self->name) < 0)
@@ -205,9 +212,9 @@ roar_open(void *data, struct audio_format *audio_format, GError **error)
}
static void
-roar_close(void *data)
+roar_close(struct audio_output *ao)
{
- roar_t * self = data;
+ struct roar *self = (struct roar *)ao;
g_mutex_lock(self->lock);
self->alive = false;
@@ -246,9 +253,9 @@ roar_cancel_locked(struct roar *self)
}
static void
-roar_cancel(void *data)
+roar_cancel(struct audio_output *ao)
{
- roar_t * self = data;
+ struct roar *self = (struct roar *)ao;
g_mutex_lock(self->lock);
roar_cancel_locked(self);
@@ -256,9 +263,9 @@ roar_cancel(void *data)
}
static size_t
-roar_play(void *data, const void *chunk, size_t size, GError **error)
+roar_play(struct audio_output *ao, const void *chunk, size_t size, GError **error)
{
- struct roar * self = data;
+ struct roar *self = (struct roar *)ao;
ssize_t rc;
if (self->vss == NULL)
@@ -323,9 +330,9 @@ roar_tag_convert(enum tag_type type, bool *is_uuid)
}
static void
-roar_send_tag(void *data, const struct tag *meta)
+roar_send_tag(struct audio_output *ao, const struct tag *meta)
{
- struct roar * self = data;
+ struct roar *self = (struct roar *)ao;
if (self->vss == NULL)
return;
diff --git a/src/output/shout_output_plugin.c b/src/output/shout_output_plugin.c
index 299f5b24d..35356d659 100644
--- a/src/output/shout_output_plugin.c
+++ b/src/output/shout_output_plugin.c
@@ -42,6 +42,8 @@ struct shout_buffer {
};
struct shout_data {
+ struct audio_output base;
+
shout_t *shout_conn;
shout_metadata_t *shout_meta;
@@ -108,9 +110,8 @@ static void free_shout_data(struct shout_data *sd)
} \
}
-static void *
-my_shout_init_driver(const struct audio_format *audio_format,
- const struct config_param *param,
+static struct audio_output *
+my_shout_init_driver(const struct config_param *param,
GError **error)
{
struct shout_data *sd;
@@ -129,15 +130,23 @@ my_shout_init_driver(const struct audio_format *audio_format,
const struct block_param *block_param;
int public;
- if (audio_format == NULL ||
- !audio_format_fully_defined(audio_format)) {
+ sd = new_shout_data();
+
+ if (!ao_base_init(&sd->base, &shout_output_plugin, param, error)) {
+ free_shout_data(sd);
+ return NULL;
+ }
+
+ const struct audio_format *audio_format =
+ &sd->base.config_audio_format;
+ if (!audio_format_fully_defined(audio_format)) {
g_set_error(error, shout_output_quark(), 0,
"Need full audio format specification");
+ ao_base_finish(&sd->base);
+ free_shout_data(sd);
return NULL;
}
- sd = new_shout_data();
-
if (shout_init_count == 0)
shout_init();
@@ -307,9 +316,10 @@ my_shout_init_driver(const struct audio_format *audio_format,
}
}
- return sd;
+ return &sd->base;
failure:
+ ao_base_finish(&sd->base);
free_shout_data(sd);
return NULL;
}
@@ -379,12 +389,14 @@ static void close_shout_conn(struct shout_data * sd)
}
}
-static void my_shout_finish_driver(void *data)
+static void
+my_shout_finish_driver(struct audio_output *ao)
{
- struct shout_data *sd = (struct shout_data *)data;
+ struct shout_data *sd = (struct shout_data *)ao;
encoder_finish(sd->encoder);
+ ao_base_finish(&sd->base);
free_shout_data(sd);
shout_init_count--;
@@ -393,17 +405,19 @@ static void my_shout_finish_driver(void *data)
shout_shutdown();
}
-static void my_shout_drop_buffered_audio(void *data)
+static void
+my_shout_drop_buffered_audio(struct audio_output *ao)
{
G_GNUC_UNUSED
- struct shout_data *sd = (struct shout_data *)data;
+ struct shout_data *sd = (struct shout_data *)ao;
/* needs to be implemented for shout */
}
-static void my_shout_close_device(void *data)
+static void
+my_shout_close_device(struct audio_output *ao)
{
- struct shout_data *sd = (struct shout_data *)data;
+ struct shout_data *sd = (struct shout_data *)ao;
close_shout_conn(sd);
}
@@ -430,10 +444,10 @@ shout_connect(struct shout_data *sd, GError **error)
}
static bool
-my_shout_open_device(void *data, struct audio_format *audio_format,
+my_shout_open_device(struct audio_output *ao, struct audio_format *audio_format,
GError **error)
{
- struct shout_data *sd = (struct shout_data *)data;
+ struct shout_data *sd = (struct shout_data *)ao;
bool ret;
ret = shout_connect(sd, error);
@@ -453,9 +467,9 @@ my_shout_open_device(void *data, struct audio_format *audio_format,
}
static unsigned
-my_shout_delay(void *data)
+my_shout_delay(struct audio_output *ao)
{
- struct shout_data *sd = (struct shout_data *)data;
+ struct shout_data *sd = (struct shout_data *)ao;
int delay = shout_delay(sd->shout_conn);
if (delay < 0)
@@ -465,9 +479,10 @@ my_shout_delay(void *data)
}
static size_t
-my_shout_play(void *data, const void *chunk, size_t size, GError **error)
+my_shout_play(struct audio_output *ao, const void *chunk, size_t size,
+ GError **error)
{
- struct shout_data *sd = (struct shout_data *)data;
+ struct shout_data *sd = (struct shout_data *)ao;
return encoder_write(sd->encoder, chunk, size, error) &&
write_page(sd, error)
@@ -476,11 +491,11 @@ my_shout_play(void *data, const void *chunk, size_t size, GError **error)
}
static bool
-my_shout_pause(void *data)
+my_shout_pause(struct audio_output *ao)
{
static const char silence[1020];
- return my_shout_play(data, silence, sizeof(silence), NULL);
+ return my_shout_play(ao, silence, sizeof(silence), NULL);
}
static void
@@ -509,10 +524,10 @@ shout_tag_to_metadata(const struct tag *tag, char *dest, size_t size)
snprintf(dest, size, "%s - %s", artist, title);
}
-static void my_shout_set_tag(void *data,
+static void my_shout_set_tag(struct audio_output *ao,
const struct tag *tag)
{
- struct shout_data *sd = (struct shout_data *)data;
+ struct shout_data *sd = (struct shout_data *)ao;
bool ret;
GError *error = NULL;
diff --git a/src/output/solaris_output_plugin.c b/src/output/solaris_output_plugin.c
index efa7a4e32..796c7806d 100644
--- a/src/output/solaris_output_plugin.c
+++ b/src/output/solaris_output_plugin.c
@@ -36,6 +36,8 @@
#define G_LOG_DOMAIN "solaris_output"
struct solaris_output {
+ struct audio_output base;
+
/* configuration */
const char *device;
@@ -60,31 +62,35 @@ solaris_output_test_default_device(void)
access("/dev/audio", W_OK) == 0;
}
-static void *
-solaris_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- const struct config_param *param,
- G_GNUC_UNUSED GError **error)
+static struct audio_output *
+solaris_output_init(const struct config_param *param, GError **error_r)
{
struct solaris_output *so = g_new(struct solaris_output, 1);
+ if (!ao_base_init(&so->base, &solaris_output_plugin, param, error_r)) {
+ g_free(so);
+ return NULL;
+ }
+
so->device = config_get_block_string(param, "device", "/dev/audio");
- return so;
+ return &so->base;
}
static void
-solaris_output_finish(void *data)
+solaris_output_finish(struct audio_output *ao)
{
- struct solaris_output *so = data;
+ struct solaris_output *so = (struct solaris_output *)ao;
+ ao_base_finish(&so->base);
g_free(so);
}
static bool
-solaris_output_open(void *data, struct audio_format *audio_format,
+solaris_output_open(struct audio_output *ao, struct audio_format *audio_format,
GError **error)
{
- struct solaris_output *so = data;
+ struct solaris_output *so = (struct solaris_output *)ao;
struct audio_info info;
int ret, flags;
@@ -135,17 +141,18 @@ solaris_output_open(void *data, struct audio_format *audio_format,
}
static void
-solaris_output_close(void *data)
+solaris_output_close(struct audio_output *ao)
{
- struct solaris_output *so = data;
+ struct solaris_output *so = (struct solaris_output *)ao;
close(so->fd);
}
static size_t
-solaris_output_play(void *data, const void *chunk, size_t size, GError **error)
+solaris_output_play(struct audio_output *ao, const void *chunk, size_t size,
+ GError **error)
{
- struct solaris_output *so = data;
+ struct solaris_output *so = (struct solaris_output *)ao;
ssize_t nbytes;
nbytes = write(so->fd, chunk, size);
@@ -159,9 +166,9 @@ solaris_output_play(void *data, const void *chunk, size_t size, GError **error)
}
static void
-solaris_output_cancel(void *data)
+solaris_output_cancel(struct audio_output *ao)
{
- struct solaris_output *so = data;
+ struct solaris_output *so = (struct solaris_output *)ao;
ioctl(so->fd, I_FLUSH);
}
diff --git a/src/output/winmm_output_plugin.c b/src/output/winmm_output_plugin.c
index d11a23e6d..66e693dd4 100644
--- a/src/output/winmm_output_plugin.c
+++ b/src/output/winmm_output_plugin.c
@@ -38,6 +38,8 @@ struct winmm_buffer {
};
struct winmm_output {
+ struct audio_output base;
+
UINT device_id;
HWAVEOUT handle;
@@ -101,30 +103,34 @@ get_device_id(const char *device_name)
return WAVE_MAPPER;
}
-static void *
-winmm_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- G_GNUC_UNUSED const struct config_param *param,
- G_GNUC_UNUSED GError **error)
+static struct audio_output *
+winmm_output_init(const struct config_param *param, GError **error_r)
{
struct winmm_output *wo = g_new(struct winmm_output, 1);
+ if (!ao_base_init(&wo->base, &winmm_output_plugin, param, error_r)) {
+ g_free(wo);
+ return NULL;
+ }
+
const char *device = config_get_block_string(param, "device", NULL);
wo->device_id = get_device_id(device);
- return wo;
+ return &wo->base;
}
static void
-winmm_output_finish(void *data)
+winmm_output_finish(struct audio_output *ao)
{
- struct winmm_output *wo = data;
+ struct winmm_output *wo = (struct winmm_output *)ao;
+ ao_base_finish(&wo->base);
g_free(wo);
}
static bool
-winmm_output_open(void *data, struct audio_format *audio_format,
+winmm_output_open(struct audio_output *ao, struct audio_format *audio_format,
GError **error_r)
{
- struct winmm_output *wo = data;
+ struct winmm_output *wo = (struct winmm_output *)ao;
wo->event = CreateEvent(NULL, false, false, NULL);
if (wo->event == NULL) {
@@ -180,9 +186,9 @@ winmm_output_open(void *data, struct audio_format *audio_format,
}
static void
-winmm_output_close(void *data)
+winmm_output_close(struct audio_output *ao)
{
- struct winmm_output *wo = data;
+ struct winmm_output *wo = (struct winmm_output *)ao;
for (unsigned i = 0; i < G_N_ELEMENTS(wo->buffers); ++i)
pcm_buffer_deinit(&wo->buffers[i].buffer);
@@ -253,9 +259,9 @@ winmm_drain_buffer(struct winmm_output *wo, struct winmm_buffer *buffer,
}
static size_t
-winmm_output_play(void *data, const void *chunk, size_t size, GError **error_r)
+winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, GError **error_r)
{
- struct winmm_output *wo = data;
+ struct winmm_output *wo = (struct winmm_output *)ao;
/* get the next buffer from the ring and prepare it */
struct winmm_buffer *buffer = &wo->buffers[wo->next_buffer];
@@ -308,18 +314,18 @@ winmm_stop(struct winmm_output *wo)
}
static void
-winmm_output_drain(void *data)
+winmm_output_drain(struct audio_output *ao)
{
- struct winmm_output *wo = data;
+ struct winmm_output *wo = (struct winmm_output *)ao;
if (!winmm_drain_all_buffers(wo, NULL))
winmm_stop(wo);
}
static void
-winmm_output_cancel(void *data)
+winmm_output_cancel(struct audio_output *ao)
{
- struct winmm_output *wo = data;
+ struct winmm_output *wo = (struct winmm_output *)ao;
winmm_stop(wo);
}