summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2008-09-24 07:20:55 +0200
committerMax Kellermann <max@duempel.org>2008-09-24 07:20:55 +0200
commitacc4a0ba2dd0be3f28c4ca009e08d1cc1bbc534a (patch)
tree7d4ea0359c85f67d0366fb58ae80c8aa35f3a473
parent63fb1efb5cd6665b73ced155ba89a5c7f094d9ab (diff)
output: make "struct audio_output" opaque for output plugins
We have eliminated direct accesses to the audio_output struct from the all output plugins. Make it opaque for them, and move its real declaration to output_internal.h, similar to decoder_internal.h. Pass the opaque structure to plugin.init() only, which will return the plugin's data pointer on success, and NULL on failure. This data pointer will be passed to all other methods instead of the audio_output struct.
-rw-r--r--src/Makefile.am1
-rw-r--r--src/audio.c1
-rw-r--r--src/audioOutputs/audioOutput_alsa.c33
-rw-r--r--src/audioOutputs/audioOutput_ao.c35
-rw-r--r--src/audioOutputs/audioOutput_fifo.c35
-rw-r--r--src/audioOutputs/audioOutput_jack.c57
-rw-r--r--src/audioOutputs/audioOutput_null.c43
-rw-r--r--src/audioOutputs/audioOutput_oss.c48
-rw-r--r--src/audioOutputs/audioOutput_pulse.c58
-rw-r--r--src/audioOutputs/audioOutput_shout.c50
-rw-r--r--src/output_api.c1
-rw-r--r--src/output_api.h54
-rw-r--r--src/output_control.c3
-rw-r--r--src/output_init.c4
-rw-r--r--src/output_internal.h58
-rw-r--r--src/output_thread.c12
16 files changed, 267 insertions, 226 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 8c9508a23..5fc4be55f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,6 +35,7 @@ mpd_headers = \
ack.h \
audio.h \
audioOutput.h \
+ output_internal.h \
output_api.h \
output_list.h \
output_thread.h \
diff --git a/src/audio.c b/src/audio.c
index 8c74c3cc8..7917ca526 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -20,6 +20,7 @@
#include "audio_format.h"
#include "output_api.h"
#include "output_control.h"
+#include "output_internal.h"
#include "log.h"
#include "path.h"
#include "client.h"
diff --git a/src/audioOutputs/audioOutput_alsa.c b/src/audioOutputs/audioOutput_alsa.c
index b6d00f176..98a7155d3 100644
--- a/src/audioOutputs/audioOutput_alsa.c
+++ b/src/audioOutputs/audioOutput_alsa.c
@@ -72,9 +72,9 @@ static void freeAlsaData(AlsaData * ad)
free(ad);
}
-static int alsa_initDriver(struct audio_output *audioOutput,
- mpd_unused const struct audio_format *audio_format,
- ConfigParam * param)
+static void *alsa_initDriver(mpd_unused struct audio_output *ao,
+ mpd_unused const struct audio_format *audio_format,
+ ConfigParam * param)
{
/* no need for pthread_once thread-safety when reading config */
static int free_global_registered;
@@ -98,14 +98,13 @@ static int alsa_initDriver(struct audio_output *audioOutput,
if ((bp = getBlockParam(param, "period_time")))
ad->period_time = atoi(bp->value);
}
- audioOutput->data = ad;
- return 0;
+ return ad;
}
-static void alsa_finishDriver(struct audio_output *audioOutput)
+static void alsa_finishDriver(void *data)
{
- AlsaData *ad = audioOutput->data;
+ AlsaData *ad = data;
freeAlsaData(ad);
}
@@ -137,10 +136,9 @@ static snd_pcm_format_t get_bitformat(const struct audio_format *af)
return SND_PCM_FORMAT_UNKNOWN;
}
-static int alsa_openDevice(struct audio_output *audioOutput,
- struct audio_format *audioFormat)
+static int alsa_openDevice(void *data, struct audio_format *audioFormat)
{
- AlsaData *ad = audioOutput->data;
+ AlsaData *ad = data;
snd_pcm_format_t bitformat;
snd_pcm_hw_params_t *hwparams;
snd_pcm_sw_params_t *swparams;
@@ -351,16 +349,16 @@ static int alsa_errorRecovery(AlsaData * ad, int err)
return err;
}
-static void alsa_dropBufferedAudio(struct audio_output *audioOutput)
+static void alsa_dropBufferedAudio(void *data)
{
- AlsaData *ad = audioOutput->data;
+ AlsaData *ad = data;
alsa_errorRecovery(ad, snd_pcm_drop(ad->pcmHandle));
}
-static void alsa_closeDevice(struct audio_output *audioOutput)
+static void alsa_closeDevice(void *data)
{
- AlsaData *ad = audioOutput->data;
+ AlsaData *ad = data;
if (ad->pcmHandle) {
if (snd_pcm_state(ad->pcmHandle) == SND_PCM_STATE_RUNNING) {
@@ -371,10 +369,9 @@ static void alsa_closeDevice(struct audio_output *audioOutput)
}
}
-static int alsa_playAudio(struct audio_output *audioOutput,
- const char *playChunk, size_t size)
+static int alsa_playAudio(void *data, const char *playChunk, size_t size)
{
- AlsaData *ad = audioOutput->data;
+ AlsaData *ad = data;
int ret;
size /= ad->sampleSize;
@@ -395,7 +392,7 @@ static int alsa_playAudio(struct audio_output *audioOutput,
ERROR("closing ALSA device \"%s\" due to write "
"error: %s\n", ad->device,
snd_strerror(-errno));
- alsa_closeDevice(audioOutput);
+ alsa_closeDevice(ad);
return -1;
}
continue;
diff --git a/src/audioOutputs/audioOutput_ao.c b/src/audioOutputs/audioOutput_ao.c
index aeb267cef..e712d582a 100644
--- a/src/audioOutputs/audioOutput_ao.c
+++ b/src/audioOutputs/audioOutput_ao.c
@@ -54,9 +54,9 @@ static void audioOutputAo_error(void)
}
}
-static int audioOutputAo_initDriver(struct audio_output *audioOutput,
- mpd_unused const struct audio_format *audio_format,
- ConfigParam * param)
+static void *audioOutputAo_initDriver(struct audio_output *ao,
+ mpd_unused const struct audio_format *audio_format,
+ ConfigParam * param)
{
ao_info *ai;
char *duplicated;
@@ -69,8 +69,6 @@ static int audioOutputAo_initDriver(struct audio_output *audioOutput,
AoData *ad = newAoData();
BlockParam *blockParam;
- audioOutput->data = ad;
-
if ((blockParam = getBlockParam(param, "write_size"))) {
ad->writeSize = strtol(blockParam->value, &test, 10);
if (*test != '\0') {
@@ -100,7 +98,7 @@ static int audioOutputAo_initDriver(struct audio_output *audioOutput,
}
DEBUG("using ao driver \"%s\" for \"%s\"\n", ai->short_name,
- audio_output_get_name(audioOutput));
+ audio_output_get_name(ao));
blockParam = getBlockParam(param, "options");
@@ -138,7 +136,7 @@ static int audioOutputAo_initDriver(struct audio_output *audioOutput,
}
free(duplicated);
- return 0;
+ return ad;
}
static void freeAoData(AoData * ad)
@@ -147,9 +145,9 @@ static void freeAoData(AoData * ad)
free(ad);
}
-static void audioOutputAo_finishDriver(struct audio_output *audioOutput)
+static void audioOutputAo_finishDriver(void *data)
{
- AoData *ad = (AoData *) audioOutput->data;
+ AoData *ad = (AoData *)data;
freeAoData(ad);
driverInitCount--;
@@ -158,14 +156,14 @@ static void audioOutputAo_finishDriver(struct audio_output *audioOutput)
ao_shutdown();
}
-static void audioOutputAo_dropBufferedAudio(mpd_unused struct audio_output *audioOutput)
+static void audioOutputAo_dropBufferedAudio(mpd_unused void *data)
{
/* not supported by libao */
}
-static void audioOutputAo_closeDevice(struct audio_output *audioOutput)
+static void audioOutputAo_closeDevice(void *data)
{
- AoData *ad = (AoData *) audioOutput->data;
+ AoData *ad = (AoData *)data;
if (ad->device) {
ao_close(ad->device);
@@ -173,14 +171,14 @@ static void audioOutputAo_closeDevice(struct audio_output *audioOutput)
}
}
-static int audioOutputAo_openDevice(struct audio_output *audioOutput,
+static int audioOutputAo_openDevice(void *data,
struct audio_format *audio_format)
{
ao_sample_format format;
- AoData *ad = (AoData *) audioOutput->data;
+ AoData *ad = (AoData *)data;
if (ad->device) {
- audioOutputAo_closeDevice(audioOutput);
+ audioOutputAo_closeDevice(ad);
}
format.bits = audio_format->bits;
@@ -213,11 +211,10 @@ static int ao_play_deconst(ao_device *device, const void *output_samples,
return ao_play(device, u.out, num_bytes);
}
-static int audioOutputAo_play(struct audio_output *audioOutput,
- const char *playChunk, size_t size)
+static int audioOutputAo_play(void *data, const char *playChunk, size_t size)
{
+ AoData *ad = (AoData *)data;
size_t chunk_size;
- AoData *ad = (AoData *) audioOutput->data;
if (ad->device == NULL)
return -1;
@@ -229,7 +226,7 @@ static int audioOutputAo_play(struct audio_output *audioOutput,
if (ao_play_deconst(ad->device, playChunk, chunk_size) == 0) {
audioOutputAo_error();
ERROR("closing audio device due to write error\n");
- audioOutputAo_closeDevice(audioOutput);
+ audioOutputAo_closeDevice(ad);
return -1;
}
diff --git a/src/audioOutputs/audioOutput_fifo.c b/src/audioOutputs/audioOutput_fifo.c
index 38aad8e2c..7a0180741 100644
--- a/src/audioOutputs/audioOutput_fifo.c
+++ b/src/audioOutputs/audioOutput_fifo.c
@@ -151,9 +151,9 @@ static int openFifo(FifoData *fd)
return 0;
}
-static int fifo_initDriver(struct audio_output *audioOutput,
- mpd_unused const struct audio_format *audio_format,
- ConfigParam *param)
+static void *fifo_initDriver(mpd_unused struct audio_output *ao,
+ mpd_unused const struct audio_format *audio_format,
+ ConfigParam *param)
{
FifoData *fd;
BlockParam *blockParam;
@@ -173,28 +173,27 @@ static int fifo_initDriver(struct audio_output *audioOutput,
fd = newFifoData();
fd->path = path;
- audioOutput->data = fd;
if (openFifo(fd) < 0) {
freeFifoData(fd);
- return -1;
+ return NULL;
}
- return 0;
+ return fd;
}
-static void fifo_finishDriver(struct audio_output *audioOutput)
+static void fifo_finishDriver(void *data)
{
- FifoData *fd = (FifoData *)audioOutput->data;
+ FifoData *fd = (FifoData *)data;
closeFifo(fd);
freeFifoData(fd);
}
-static int fifo_openDevice(struct audio_output *audioOutput,
+static int fifo_openDevice(void *data,
struct audio_format *audio_format)
{
- FifoData *fd = (FifoData *)audioOutput->data;
+ FifoData *fd = (FifoData *)data;
if (fd->timer)
timer_free(fd->timer);
@@ -204,9 +203,9 @@ static int fifo_openDevice(struct audio_output *audioOutput,
return 0;
}
-static void fifo_closeDevice(struct audio_output *audioOutput)
+static void fifo_closeDevice(void *data)
{
- FifoData *fd = (FifoData *)audioOutput->data;
+ FifoData *fd = (FifoData *)data;
if (fd->timer) {
timer_free(fd->timer);
@@ -214,9 +213,9 @@ static void fifo_closeDevice(struct audio_output *audioOutput)
}
}
-static void fifo_dropBufferedAudio(struct audio_output *audioOutput)
+static void fifo_dropBufferedAudio(void *data)
{
- FifoData *fd = (FifoData *)audioOutput->data;
+ FifoData *fd = (FifoData *)data;
char buf[FIFO_BUFFER_SIZE];
int bytes = 1;
@@ -231,10 +230,10 @@ static void fifo_dropBufferedAudio(struct audio_output *audioOutput)
}
}
-static int fifo_playAudio(struct audio_output *audioOutput,
+static int fifo_playAudio(void *data,
const char *playChunk, size_t size)
{
- FifoData *fd = (FifoData *)audioOutput->data;
+ FifoData *fd = (FifoData *)data;
size_t offset = 0;
ssize_t bytes;
@@ -251,7 +250,7 @@ static int fifo_playAudio(struct audio_output *audioOutput,
switch (errno) {
case EAGAIN:
/* The pipe is full, so empty it */
- fifo_dropBufferedAudio(audioOutput);
+ fifo_dropBufferedAudio(fd);
continue;
case EINTR:
continue;
@@ -259,7 +258,7 @@ static int fifo_playAudio(struct audio_output *audioOutput,
ERROR("Closing FIFO output \"%s\" due to write error: "
"%s\n", fd->path, strerror(errno));
- fifo_closeDevice(audioOutput);
+ fifo_closeDevice(fd);
return -1;
}
diff --git a/src/audioOutputs/audioOutput_jack.c b/src/audioOutputs/audioOutput_jack.c
index 14b1e92e4..f817bd435 100644
--- a/src/audioOutputs/audioOutput_jack.c
+++ b/src/audioOutputs/audioOutput_jack.c
@@ -29,6 +29,8 @@
static const size_t sample_size = sizeof(jack_default_audio_sample_t);
typedef struct _JackData {
+ struct audio_output *ao;
+
/* configuration */
const char *name;
const char *output_ports[2];
@@ -90,9 +92,8 @@ static void freeJackClient(JackData *jd)
pthread_cond_destroy(&jd->play_audio);
}
-static void freeJackData(struct audio_output *audioOutput)
+static void freeJackData(JackData *jd)
{
- JackData *jd = audioOutput->data;
int i;
assert(jd != NULL);
@@ -111,15 +112,16 @@ static void freeJackData(struct audio_output *audioOutput)
free(jd);
}
-static void jack_finishDriver(struct audio_output *audioOutput)
+static void jack_finishDriver(void *data)
{
- freeJackData(audioOutput);
+ JackData *jd = data;
+ freeJackData(jd);
DEBUG("disconnect_jack (pid=%d)\n", getpid ());
}
static int srate(mpd_unused jack_nframes_t rate, void *data)
{
- JackData *jd = (JackData *) ((struct audio_output *) data)->data;
+ JackData *jd = (JackData *)data;
struct audio_format *audioFormat = jd->audio_format;
audioFormat->sampleRate = (int)jack_get_sample_rate(jd->client);
@@ -182,11 +184,8 @@ static void shutdown_callback(void *arg)
jd->shutdown = 1;
}
-static void set_audioformat(struct audio_output *audioOutput,
- struct audio_format *audioFormat)
+static void set_audioformat(JackData *jd, struct audio_format *audioFormat)
{
- JackData *jd = audioOutput->data;
-
audioFormat->sampleRate = (int) jack_get_sample_rate(jd->client);
DEBUG("samplerate = %d\n", audioFormat->sampleRate);
audioFormat->channels = 2;
@@ -201,9 +200,9 @@ static void error_callback(const char *msg)
ERROR("jack: %s\n", msg);
}
-static int jack_initDriver(struct audio_output *audioOutput,
- mpd_unused const struct audio_format *audio_format,
- ConfigParam *param)
+static void *jack_initDriver(struct audio_output *ao,
+ mpd_unused const struct audio_format *audio_format,
+ ConfigParam *param)
{
JackData *jd;
BlockParam *bp;
@@ -211,11 +210,12 @@ static int jack_initDriver(struct audio_output *audioOutput,
int val;
char *cp = NULL;
- audioOutput->data = newJackData();
- jd = audioOutput->data;
+ jd = newJackData();
+ jd->ao = ao;
DEBUG("jack_initDriver (pid=%d)\n", getpid());
- if ( ! param ) return 0;
+ if (param == NULL)
+ return jd;
if ( (bp = getBlockParam(param, "ports")) ) {
DEBUG("output_ports=%s\n", bp->value);
@@ -261,7 +261,7 @@ static int jack_initDriver(struct audio_output *audioOutput,
DEBUG("name=%s\n", jd->name);
}
- return 0;
+ return jd;
}
static int jack_testDefault(void)
@@ -269,10 +269,8 @@ static int jack_testDefault(void)
return 0;
}
-static int connect_jack(struct audio_output *audioOutput,
- struct audio_format *audio_format)
+static int connect_jack(JackData *jd, struct audio_format *audio_format)
{
- JackData *jd = audioOutput->data;
const char **jports;
char *port_name;
@@ -286,7 +284,7 @@ static int connect_jack(struct audio_output *audioOutput,
jack_set_error_function(error_callback);
jack_set_process_callback(jd->client, process, (void *)jd);
jack_set_sample_rate_callback(jd->client, (JackProcessCallback)srate,
- (void *)audioOutput);
+ (void *)jd);
jack_on_shutdown(jd->client, shutdown_callback, (void *)jd);
if ( jack_activate(jd->client) ) {
@@ -353,40 +351,39 @@ static int connect_jack(struct audio_output *audioOutput,
return 1;
}
-static int jack_openDevice(struct audio_output *audioOutput,
+static int jack_openDevice(void *data,
struct audio_format *audio_format)
{
- JackData *jd = audioOutput->data;
+ JackData *jd = data;
assert(jd != NULL);
- if (jd->client == NULL && connect_jack(audioOutput,
- audio_format) < 0) {
+ if (jd->client == NULL && connect_jack(jd, audio_format) < 0) {
freeJackClient(jd);
return -1;
}
- set_audioformat(audioOutput, audio_format);
+ set_audioformat(jd, audio_format);
DEBUG("jack_openDevice (pid=%d)!\n", getpid ());
return 0;
}
-static void jack_closeDevice(mpd_unused struct audio_output *audioOutput)
+static void jack_closeDevice(mpd_unused void *data)
{
/*jack_finishDriver(audioOutput);*/
DEBUG("jack_closeDevice (pid=%d)\n", getpid());
}
-static void jack_dropBufferedAudio (mpd_unused struct audio_output *audioOutput)
+static void jack_dropBufferedAudio (mpd_unused void *data)
{
}
-static int jack_playAudio(struct audio_output *audioOutput,
+static int jack_playAudio(void *data,
const char *buff, size_t size)
{
- JackData *jd = audioOutput->data;
+ JackData *jd = data;
size_t space;
size_t i;
const short *buffer = (const short *) buff;
@@ -398,7 +395,7 @@ static int jack_playAudio(struct audio_output *audioOutput,
if ( jd->shutdown ) {
ERROR("Refusing to play, because there is no client thread.\n");
freeJackClient(jd);
- audio_output_closed(audioOutput);
+ audio_output_closed(jd->ao);
return 0;
}
diff --git a/src/audioOutputs/audioOutput_null.c b/src/audioOutputs/audioOutput_null.c
index c4c7d339e..564f8b870 100644
--- a/src/audioOutputs/audioOutput_null.c
+++ b/src/audioOutputs/audioOutput_null.c
@@ -18,34 +18,45 @@
#include "../output_api.h"
#include "../timer.h"
+#include "../utils.h"
-static int null_initDriver(struct audio_output *audioOutput,
- mpd_unused const struct audio_format *audio_format,
- mpd_unused ConfigParam *param)
+struct null_data {
+ Timer *timer;
+};
+
+static void *null_initDriver(mpd_unused struct audio_output *audioOutput,
+ mpd_unused const struct audio_format *audio_format,
+ mpd_unused ConfigParam *param)
{
- audioOutput->data = NULL;
- return 0;
+ struct null_data *nd = xmalloc(sizeof(*nd));
+ nd->timer = NULL;
+ return nd;
}
-static int null_openDevice(struct audio_output *audioOutput,
+static int null_openDevice(void *data,
struct audio_format *audio_format)
{
- audioOutput->data = timer_new(audio_format);
+ struct null_data *nd = data;
+
+ nd->timer = timer_new(audio_format);
return 0;
}
-static void null_closeDevice(struct audio_output *audioOutput)
+static void null_closeDevice(void *data)
{
- if (audioOutput->data) {
- timer_free(audioOutput->data);
- audioOutput->data = NULL;
+ struct null_data *nd = data;
+
+ if (nd->timer != NULL) {
+ timer_free(nd->timer);
+ nd->timer = NULL;
}
}
-static int null_playAudio(struct audio_output *audioOutput,
+static int null_playAudio(void *data,
mpd_unused const char *playChunk, size_t size)
{
- Timer *timer = audioOutput->data;
+ struct null_data *nd = data;
+ Timer *timer = nd->timer;
if (!timer->started)
timer_start(timer);
@@ -57,9 +68,11 @@ static int null_playAudio(struct audio_output *audioOutput,
return 0;
}
-static void null_dropBufferedAudio(struct audio_output *audioOutput)
+static void null_dropBufferedAudio(void *data)
{
- timer_reset(audioOutput->data);
+ struct null_data *nd = data;
+
+ timer_reset(nd->timer);
}
const struct audio_output_plugin nullPlugin = {
diff --git a/src/audioOutputs/audioOutput_oss.c b/src/audioOutputs/audioOutput_oss.c
index d2041faa1..f5195ab44 100644
--- a/src/audioOutputs/audioOutput_oss.c
+++ b/src/audioOutputs/audioOutput_oss.c
@@ -333,8 +333,7 @@ static int oss_testDefault(void)
return -1;
}
-static int oss_open_default(mpd_unused struct audio_output *ao,
- ConfigParam *param, OssData *od)
+static void *oss_open_default(ConfigParam *param)
{
int i;
int err[ARRAY_SIZE(default_devices)];
@@ -343,6 +342,7 @@ static int oss_open_default(mpd_unused struct audio_output *ao,
for (i = ARRAY_SIZE(default_devices); --i >= 0; ) {
ret[i] = oss_statDevice(default_devices[i], &err[i]);
if (ret[i] == 0) {
+ OssData *od = newOssData();
od->device = default_devices[i];
return 0;
}
@@ -371,28 +371,27 @@ static int oss_open_default(mpd_unused struct audio_output *ao,
}
}
exit(EXIT_FAILURE);
- return 0; /* some compilers can be dumb... */
+ return NULL; /* some compilers can be dumb... */
}
-static int oss_initDriver(struct audio_output *audioOutput,
- mpd_unused const struct audio_format *audio_format,
- ConfigParam * param)
+static void *oss_initDriver(mpd_unused struct audio_output *audioOutput,
+ mpd_unused const struct audio_format *audio_format,
+ ConfigParam * param)
{
- OssData *od = newOssData();
- audioOutput->data = od;
if (param) {
BlockParam *bp = getBlockParam(param, "device");
if (bp) {
+ OssData *od = newOssData();
od->device = bp->value;
- return 0;
+ return od;
}
}
- return oss_open_default(audioOutput, param, od);
+ return oss_open_default(param);
}
-static void oss_finishDriver(struct audio_output *audioOutput)
+static void oss_finishDriver(void *data)
{
- OssData *od = audioOutput->data;
+ OssData *od = data;
freeOssData(od);
}
@@ -434,10 +433,9 @@ static void oss_close(OssData * od)
od->fd = -1;
}
-static int oss_open(struct audio_output *audioOutput)
+static int oss_open(OssData *od)
{
int tmp;
- OssData *od = audioOutput->data;
if ((od->fd = open(od->device, O_WRONLY)) < 0) {
ERROR("Error opening OSS device \"%s\": %s\n", od->device,
@@ -478,17 +476,17 @@ fail:
return -1;
}
-static int oss_openDevice(struct audio_output *audioOutput,
+static int oss_openDevice(void *data,
struct audio_format *audioFormat)
{
int ret;
- OssData *od = audioOutput->data;
+ OssData *od = data;
od->channels = (mpd_sint8)audioFormat->channels;
od->sampleRate = audioFormat->sampleRate;
od->bits = (mpd_sint8)audioFormat->bits;
- if ((ret = oss_open(audioOutput)) < 0)
+ if ((ret = oss_open(od)) < 0)
return ret;
audioFormat->channels = od->channels;
@@ -501,16 +499,16 @@ static int oss_openDevice(struct audio_output *audioOutput,
return ret;
}
-static void oss_closeDevice(struct audio_output *audioOutput)
+static void oss_closeDevice(void *data)
{
- OssData *od = audioOutput->data;
+ OssData *od = data;
oss_close(od);
}
-static void oss_dropBufferedAudio(struct audio_output *audioOutput)
+static void oss_dropBufferedAudio(void *data)
{
- OssData *od = audioOutput->data;
+ OssData *od = data;
if (od->fd >= 0) {
ioctl(od->fd, SNDCTL_DSP_RESET, 0);
@@ -518,14 +516,14 @@ static void oss_dropBufferedAudio(struct audio_output *audioOutput)
}
}
-static int oss_playAudio(struct audio_output *audioOutput,
+static int oss_playAudio(void *data,
const char *playChunk, size_t size)
{
- OssData *od = audioOutput->data;
+ OssData *od = data;
ssize_t ret;
/* reopen the device since it was closed by dropBufferedAudio */
- if (od->fd < 0 && oss_open(audioOutput) < 0)
+ if (od->fd < 0 && oss_open(od) < 0)
return -1;
while (size > 0) {
@@ -535,7 +533,7 @@ static int oss_playAudio(struct audio_output *audioOutput,
continue;
ERROR("closing oss device \"%s\" due to write error: "
"%s\n", od->device, strerror(errno));
- oss_closeDevice(audioOutput);
+ oss_closeDevice(od);
return -1;
}
playChunk += ret;
diff --git a/src/audioOutputs/audioOutput_pulse.c b/src/audioOutputs/audioOutput_pulse.c
index 8e477a2de..91fea9c60 100644
--- a/src/audioOutputs/audioOutput_pulse.c
+++ b/src/audioOutputs/audioOutput_pulse.c
@@ -30,6 +30,8 @@
#define CONN_ATTEMPT_INTERVAL 60
typedef struct _PulseData {
+ struct audio_output *ao;
+
pa_simple *s;
char *server;
char *sink;
@@ -61,9 +63,9 @@ static void freePulseData(PulseData * pd)
free(pd);
}
-static int pulse_initDriver(struct audio_output *audioOutput,
- mpd_unused const struct audio_format *audio_format,
- ConfigParam * param)
+static void *pulse_initDriver(struct audio_output *ao,
+ mpd_unused const struct audio_format *audio_format,
+ ConfigParam * param)
{
BlockParam *server = NULL;
BlockParam *sink = NULL;
@@ -75,16 +77,18 @@ static int pulse_initDriver(struct audio_output *audioOutput,
}
pd = newPulseData();
+ pd->ao = ao;
pd->server = server ? xstrdup(server->value) : NULL;
pd->sink = sink ? xstrdup(sink->value) : NULL;
- audioOutput->data = pd;
- return 0;
+ return pd;
}
-static void pulse_finishDriver(struct audio_output *audioOutput)
+static void pulse_finishDriver(void *data)
{
- freePulseData((PulseData *) audioOutput->data);
+ PulseData *pd = data;
+
+ freePulseData(pd);
}
static int pulse_testDefault(void)
@@ -110,16 +114,15 @@ static int pulse_testDefault(void)
return 0;
}
-static int pulse_openDevice(struct audio_output *audioOutput,
+static int pulse_openDevice(void *data,
struct audio_format *audioFormat)
{
- PulseData *pd;
+ PulseData *pd = data;
pa_sample_spec ss;
time_t t;
int error;
t = time(NULL);
- pd = audioOutput->data;
if (pd->connAttempts != 0 &&
(t - pd->lastAttempt) < CONN_ATTEMPT_INTERVAL)
@@ -139,11 +142,13 @@ static int pulse_openDevice(struct audio_output *audioOutput,
ss.channels = audioFormat->channels;
pd->s = pa_simple_new(pd->server, MPD_PULSE_NAME, PA_STREAM_PLAYBACK,
- pd->sink, audioOutput->name, &ss, NULL, NULL,
+ pd->sink, audio_output_get_name(pd->ao),
+ &ss, NULL, NULL,
&error);
if (!pd->s) {
ERROR("Cannot connect to server in PulseAudio output "
- "\"%s\" (attempt %i): %s\n", audioOutput->name,
+ "\"%s\" (attempt %i): %s\n",
+ audio_output_get_name(pd->ao),
pd->connAttempts, pa_strerror(error));
return -1;
}
@@ -151,46 +156,47 @@ static int pulse_openDevice(struct audio_output *audioOutput,
pd->connAttempts = 0;
DEBUG("PulseAudio output \"%s\" connected and playing %i bit, %i "
- "channel audio at %i Hz\n", audioOutput->name, audioFormat->bits,
+ "channel audio at %i Hz\n",
+ audio_output_get_name(pd->ao),
+ audioFormat->bits,
audioFormat->channels, audioFormat->sampleRate);
return 0;
}
-static void pulse_dropBufferedAudio(struct audio_output *audioOutput)
+static void pulse_dropBufferedAudio(void *data)
{
- PulseData *pd;
+ PulseData *pd = data;
int error;
- pd = audioOutput->data;
if (pa_simple_flush(pd->s, &error) < 0)
WARNING("Flush failed in PulseAudio output \"%s\": %s\n",
- audioOutput->name, pa_strerror(error));
+ audio_output_get_name(pd->ao),
+ pa_strerror(error));
}
-static void pulse_closeDevice(struct audio_output *audioOutput)
+static void pulse_closeDevice(void *data)
{
- PulseData *pd;
+ PulseData *pd = data;
- pd = audioOutput->data;
if (pd->s) {
pa_simple_drain(pd->s, NULL);
pa_simple_free(pd->s);
}
}
-static int pulse_playAudio(struct audio_output *audioOutput,
+static int pulse_playAudio(void *data,
const char *playChunk, size_t size)
{
- PulseData *pd;
+ PulseData *pd = data;
int error;
- pd = audioOutput->data;
-
if (pa_simple_write(pd->s, playChunk, size, &error) < 0) {
ERROR("PulseAudio output \"%s\" disconnecting due to write "
- "error: %s\n", audioOutput->name, pa_strerror(error));
- pulse_closeDevice(audioOutput);
+ "error: %s\n",
+ audio_output_get_name(pd->ao),
+ pa_strerror(error));
+ pulse_closeDevice(pd);
return -1;
}
diff --git a/src/audioOutputs/audioOutput_shout.c b/src/audioOutputs/audioOutput_shout.c
index 8612cde2f..feb4b4d8f 100644
--- a/src/audioOutputs/audioOutput_shout.c
+++ b/src/audioOutputs/audioOutput_shout.c
@@ -87,9 +87,9 @@ static void free_shout_data(struct shout_data *sd)
} \
}
-static int my_shout_init_driver(struct audio_output *audio_output,
- const struct audio_format *audio_format,
- ConfigParam * param)
+static void *my_shout_init_driver(mpd_unused struct audio_output *audio_output,
+ const struct audio_format *audio_format,
+ ConfigParam *param)
{
struct shout_data *sd;
char *test;
@@ -263,9 +263,11 @@ static int my_shout_init_driver(struct audio_output *audio_output,
}
}
- audio_output->data = sd;
+ if (sd->encoder->init_func(sd) != 0)
+ FATAL("shout: encoder plugin '%s' failed to initialize\n",
+ sd->encoder->name);
- return sd->encoder->init_func(sd);
+ return sd;
}
static int handle_shout_error(struct shout_data *sd, int err)
@@ -325,9 +327,9 @@ static void close_shout_conn(struct shout_data * sd)
sd->opened = 0;
}
-static void my_shout_finish_driver(struct audio_output *audio_output)
+static void my_shout_finish_driver(void *data)
{
- struct shout_data *sd = (struct shout_data *) audio_output->data;
+ struct shout_data *sd = (struct shout_data *)data;
close_shout_conn(sd);
@@ -340,17 +342,17 @@ static void my_shout_finish_driver(struct audio_output *audio_output)
shout_shutdown();
}
-static void my_shout_drop_buffered_audio(struct audio_output *audio_output)
+static void my_shout_drop_buffered_audio(void *data)
{
- struct shout_data *sd = (struct shout_data *)audio_output->data;
+ struct shout_data *sd = (struct shout_data *)data;
timer_reset(sd->timer);
/* needs to be implemented for shout */
}
-static void my_shout_close_device(struct audio_output *audio_output)
+static void my_shout_close_device(void *data)
{
- struct shout_data *sd = (struct shout_data *) audio_output->data;
+ struct shout_data *sd = (struct shout_data *)data;
close_shout_conn(sd);
@@ -416,9 +418,9 @@ static int shout_connect(struct shout_data *sd)
}
}
-static int open_shout_conn(struct audio_output *audio_output)
+static int open_shout_conn(void *data)
{
- struct shout_data *sd = (struct shout_data *) audio_output->data;
+ struct shout_data *sd = (struct shout_data *)data;
int status;
status = shout_connect(sd);
@@ -440,12 +442,12 @@ static int open_shout_conn(struct audio_output *audio_output)
return 0;
}
-static int my_shout_open_device(struct audio_output *audio_output,
+static int my_shout_open_device(void *data,
struct audio_format *audio_format)
{
- struct shout_data *sd = (struct shout_data *) audio_output->data;
+ struct shout_data *sd = (struct shout_data *)data;
- if (!sd->opened && open_shout_conn(audio_output) < 0)
+ if (!sd->opened && open_shout_conn(sd) < 0)
return -1;
if (sd->timer)
@@ -476,10 +478,10 @@ static void send_metadata(struct shout_data * sd)
sd->tag_to_send = 0;
}
-static int my_shout_play(struct audio_output *audio_output,
+static int my_shout_play(void *data,
const char *chunk, size_t size)
{
- struct shout_data *sd = (struct shout_data *) audio_output->data;
+ struct shout_data *sd = (struct shout_data *)data;
int status;
if (!sd->timer->started)
@@ -491,9 +493,9 @@ static int my_shout_play(struct audio_output *audio_output,
send_metadata(sd);
if (!sd->opened) {
- status = open_shout_conn(audio_output);
+ status = open_shout_conn(sd);
if (status < 0) {
- my_shout_close_device(audio_output);
+ my_shout_close_device(sd);
return -1;
} else if (status > 0) {
timer_sync(sd->timer);
@@ -502,22 +504,22 @@ static int my_shout_play(struct audio_output *audio_output,
}
if (sd->encoder->encode_func(sd, chunk, size)) {
- my_shout_close_device(audio_output);
+ my_shout_close_device(sd);
return -1;
}
if (write_page(sd) < 0) {
- my_shout_close_device(audio_output);
+ my_shout_close_device(sd);
return -1;
}
return 0;
}
-static void my_shout_set_tag(struct audio_output *audio_output,
+static void my_shout_set_tag(void *data,
const struct tag *tag)
{
- struct shout_data *sd = (struct shout_data *) audio_output->data;
+ struct shout_data *sd = (struct shout_data *)data;
if (sd->tag)
tag_free(sd->tag);
diff --git a/src/output_api.c b/src/output_api.c
index eabc0bb80..c8225579d 100644
--- a/src/output_api.c
+++ b/src/output_api.c
@@ -17,6 +17,7 @@
*/
#include "output_api.h"
+#include "output_internal.h"
const char *audio_output_get_name(const struct audio_output *ao)
{
diff --git a/src/output_api.h b/src/output_api.h
index c8869c47b..e1dce077d 100644
--- a/src/output_api.h
+++ b/src/output_api.h
@@ -21,12 +21,10 @@
#define OUTPUT_API_H
#include "../config.h"
-#include "pcm_utils.h"
#include "audio_format.h"
#include "tag.h"
#include "conf.h"
#include "log.h"
-#include "notify.h"
#include "os_compat.h"
#define DISABLED_AUDIO_OUTPUT_PLUGIN(plugin) const struct audio_output_plugin plugin;
@@ -38,24 +36,21 @@ struct audio_output_plugin {
int (*test_default_device)(void);
- int (*init)(struct audio_output *ao,
- const struct audio_format *audio_format,
- ConfigParam *param);
+ void *(*init)(struct audio_output *ao,
+ const struct audio_format *audio_format,
+ ConfigParam *param);
- void (*finish)(struct audio_output *ao);
+ void (*finish)(void *data);
- int (*open)(struct audio_output *ao,
- struct audio_format *audio_format);
+ int (*open)(void *data, struct audio_format *audio_format);
- int (*play)(struct audio_output *ao,
- const char *playChunk, size_t size);
+ int (*play)(void *data, const char *playChunk, size_t size);
- void (*cancel)(struct audio_output *ao);
+ void (*cancel)(void *data);
- void (*close)(struct audio_output *ao);
+ void (*close)(void *data);
- void (*send_tag)(struct audio_output *audioOutput,
- const struct tag *tag);
+ void (*send_tag)(void *data, const struct tag *tag);
};
enum audio_output_command {
@@ -68,36 +63,7 @@ enum audio_output_command {
AO_COMMAND_KILL
};
-struct audio_output {
- int open;
- const char *name;
-
- const struct audio_output_plugin *plugin;
-
- struct audio_format inAudioFormat;
- struct audio_format outAudioFormat;
- struct audio_format reqAudioFormat;
- ConvState convState;
- char *convBuffer;
- size_t convBufferLen;
-
- pthread_t thread;
- struct notify notify;
- enum audio_output_command command;
- union {
- struct {
- const char *data;
- size_t size;
- } play;
-
- const struct tag *tag;
- } args;
- int result;
-
- void *data;
-};
-
-extern struct notify audio_output_client_notify;
+struct audio_output;
const char *audio_output_get_name(const struct audio_output *ao);
diff --git a/src/output_control.c b/src/output_control.c
index 2fc692d6b..34e51aa41 100644
--- a/src/output_control.c
+++ b/src/output_control.c
@@ -18,6 +18,7 @@
#include "output_control.h"
#include "output_api.h"
+#include "output_internal.h"
#include "output_thread.h"
#include "pcm_utils.h"
@@ -107,7 +108,7 @@ void audio_output_finish(struct audio_output *audioOutput)
if (audioOutput->thread != 0)
ao_command(audioOutput, AO_COMMAND_KILL);
if (audioOutput->plugin->finish)
- audioOutput->plugin->finish(audioOutput);
+ audioOutput->plugin->finish(audioOutput->data);
if (audioOutput->convBuffer)
free(audioOutput->convBuffer);
}
diff --git a/src/output_init.c b/src/output_init.c
index 25883cee1..6274daa81 100644
--- a/src/output_init.c
+++ b/src/output_init.c
@@ -18,6 +18,7 @@
#include "output_control.h"
#include "output_api.h"
+#include "output_internal.h"
#include "output_list.h"
#include "log.h"
#include "audio.h"
@@ -102,7 +103,8 @@ int audio_output_init(struct audio_output *ao, ConfigParam * param)
notify_init(&ao->notify);
ao->command = AO_COMMAND_NONE;
- if (plugin->init(ao, format ? &ao->reqAudioFormat : NULL, param) != 0)
+ ao->data = plugin->init(ao, format ? &ao->reqAudioFormat : NULL, param);
+ if (ao->data == NULL)
return 0;
return 1;
diff --git a/src/output_internal.h b/src/output_internal.h
new file mode 100644
index 000000000..25094f6fb
--- /dev/null
+++ b/src/output_internal.h
@@ -0,0 +1,58 @@
+/* the Music Player Daemon (MPD)
+ * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
+ * Copyright (C) 2008 Max Kellermann <max@duempel.org>
+ * 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
+ */
+
+#ifndef OUTPUT_INTERNAL_H
+#define OUTPUT_INTERNAL_H
+
+#include "pcm_utils.h"
+#include "notify.h"
+
+struct audio_output {
+ int open;
+ const char *name;
+
+ const struct audio_output_plugin *plugin;
+
+ int convertAudioFormat;
+ struct audio_format inAudioFormat;
+ struct audio_format outAudioFormat;
+ struct audio_format reqAudioFormat;
+ ConvState convState;
+ char *convBuffer;
+ size_t convBufferLen;
+
+ pthread_t thread;
+ struct notify notify;
+ enum audio_output_command command;
+ union {
+ struct {
+ const char *data;
+ size_t size;
+ } play;
+
+ const struct tag *tag;
+ } args;
+ int result;
+
+ void *data;
+};
+
+extern struct notify audio_output_client_notify;
+
+#endif
diff --git a/src/output_thread.c b/src/output_thread.c
index 3f410958c..a92f0bafd 100644
--- a/src/output_thread.c
+++ b/src/output_thread.c
@@ -18,6 +18,7 @@
#include "output_thread.h"
#include "output_api.h"
+#include "output_internal.h"
#include "utils.h"
static void ao_command_finished(struct audio_output *ao)
@@ -58,7 +59,7 @@ static void ao_play(struct audio_output *ao)
if (!audio_format_equals(&ao->inAudioFormat, &ao->outAudioFormat))
convertAudioFormat(ao, &data, &size);
- ao->result = ao->plugin->play(ao, data, size);
+ ao->result = ao->plugin->play(ao->data, data, size);
ao_command_finished(ao);
}
@@ -75,7 +76,8 @@ static void *audio_output_task(void *arg)
case AO_COMMAND_OPEN:
assert(!ao->open);
- ao->result = ao->plugin->open(ao, &ao->outAudioFormat);
+ ao->result = ao->plugin->open(ao->data,
+ &ao->outAudioFormat);
assert(!ao->open);
if (ao->result == 0)
@@ -86,7 +88,7 @@ static void *audio_output_task(void *arg)
case AO_COMMAND_CLOSE:
assert(ao->open);
- ao->plugin->close(ao);
+ ao->plugin->close(ao->data);
ao->open = 0;
ao_command_finished(ao);
break;
@@ -96,12 +98,12 @@ static void *audio_output_task(void *arg)
break;
case AO_COMMAND_CANCEL:
- ao->plugin->cancel(ao);
+ ao->plugin->cancel(ao->data);
ao_command_finished(ao);
break;
case AO_COMMAND_SEND_TAG:
- ao->plugin->send_tag(ao, ao->args.tag);
+ ao->plugin->send_tag(ao->data, ao->args.tag);
ao_command_finished(ao);
break;