80 lines
2.2 KiB
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;
|
|
}
|