audiolib/audio/audio_sink_libao.c

80 lines
2.2 KiB
C

#include <stdlib.h>
#include <string.h>
#include <ao/ao.h>
#include "audio.h"
#include "audio_internal.h"
typedef struct _SinkLibaoContext {
ao_device *device;
ao_sample_format format;
} SinkLibaoContext;
AudioPipelineStatus sink_libao_push(AudioPipelineElement *self, AudioBuffer *buffer) {
SinkLibaoContext *context = (SinkLibaoContext *)self->ctx;
if (context->device == NULL) {
int default_driver = ao_default_driver_id();
context->device = ao_open_live(default_driver, &context->format, NULL);
if (context->device == NULL) {
fprintf(stderr, "Error opening device.\n");
return PipelineError;
}
}
int result = ao_play(context->device, (char *)buffer->data, buffer->buf_size);
return (result == 0) ? PipelineError : PipelineRunning;
}
AudioPipelineStatus sink_libao_link(AudioPipelineElement *self, AudioPipelineElement *source) {
SinkLibaoContext *context = (SinkLibaoContext *)self->ctx;
if (context->device != NULL) {
ao_close(context->device);
context->device = NULL;
}
memset(&context->format, 0, sizeof(ao_sample_format));
context->format.bits = source->bits_per_sample;
context->format.channels = source->channels;
context->format.rate = source->sample_rate;
context->format.byte_format = AO_FMT_LITTLE;
source->next = self;
return PipelineStopped;
}
char *sink_libao_describe(AudioPipelineElement *self) {
return "libao sink";
}
void sink_libao_destroy(AudioPipelineElement *self) {
SinkLibaoContext *context = (SinkLibaoContext *)self->ctx;
ao_close(context->device);
ao_shutdown();
free(self->ctx);
free(self);
}
AudioPipelineElement *audio_sink_libao(void) {
AudioPipelineElement *self = calloc(1, sizeof(AudioPipelineElement));
SinkLibaoContext *context = calloc(1, sizeof(SinkLibaoContext));
ao_initialize();
self->ctx = context;
self->describe = sink_libao_describe;
self->start = sink_nop;
self->reset = sink_nop;
self->stop = sink_nop;
self->push = sink_libao_push;
self->link = sink_libao_link;
self->destroy = sink_libao_destroy;
self->type = AudioElementSink;
return self;
}