150 lines
3.9 KiB
C
150 lines
3.9 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stddef.h>
|
|
#include "audio.h"
|
|
#include "audio_internal.h"
|
|
|
|
AudioPipelineStatus audio_pipeline_start(AudioPipeline *pipeline) {
|
|
AudioPipelineStatus result = pipeline->source->start(pipeline->source);
|
|
|
|
pipeline->status = result;
|
|
if (pipeline->statusCallback != NULL) {
|
|
pipeline->statusCallback(pipeline, result);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
AudioPipelineStatus audio_pipeline_reset(AudioPipeline *pipeline) {
|
|
AudioPipelineStatus result = pipeline->source->reset(pipeline->source);
|
|
|
|
pipeline->status = result;
|
|
if (pipeline->statusCallback != NULL) {
|
|
pipeline->statusCallback(pipeline, result);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
AudioPipelineStatus audio_pipeline_stop(AudioPipeline *pipeline) {
|
|
AudioPipelineStatus result = pipeline->source->stop(pipeline->source);
|
|
|
|
pipeline->status = result;
|
|
if (pipeline->statusCallback != NULL) {
|
|
pipeline->statusCallback(pipeline, result);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
AudioPipeline *audio_pipeline_assemble(AudioPipelineElement *source, ...) {
|
|
va_list list, list_backup;
|
|
AudioPipelineElement *item, *last;
|
|
AudioPipeline *pipeline = malloc(sizeof(AudioPipeline));
|
|
|
|
pipeline->start = audio_pipeline_start;
|
|
pipeline->reset = audio_pipeline_reset;
|
|
pipeline->stop = audio_pipeline_stop;
|
|
pipeline->source = source;
|
|
pipeline->status = PipelineStopped;
|
|
pipeline->statusCallback = NULL;
|
|
|
|
va_start(list, source);
|
|
va_copy(list_backup, list);
|
|
|
|
if (source == NULL) {
|
|
fprintf(stderr, "ERROR: Source did not initialize, giving up!\n");
|
|
goto fail;
|
|
}
|
|
source->pipeline = pipeline;
|
|
last = source;
|
|
|
|
item = va_arg(list, AudioPipelineElement *);
|
|
while (item != NULL) {
|
|
if (item->type == AudioElementSource) {
|
|
fprintf(stderr, "ERROR: You cannot have a source in the middle of the pipeline, offending element: %s\n", item->describe(item));
|
|
goto fail;
|
|
}
|
|
AudioPipelineStatus result = item->link(item, last);
|
|
if (result != PipelineStopped) {
|
|
fprintf(stderr, "ERROR: Could not link audio pipeline elements %s and %s\n", last->describe(last), item->describe(item));
|
|
goto fail;
|
|
}
|
|
item->pipeline = pipeline;
|
|
last = item;
|
|
if (item->type == AudioElementSink) {
|
|
break;
|
|
}
|
|
item = va_arg(list, AudioPipelineElement *);
|
|
}
|
|
|
|
if (last->type != AudioElementSink) {
|
|
fprintf(stderr, "ERROR: Pipeline has no sink!\n");
|
|
goto fail;
|
|
}
|
|
|
|
pipeline->sink = last;
|
|
va_end(list);
|
|
va_end(list_backup);
|
|
|
|
return pipeline;
|
|
|
|
fail:
|
|
va_end(list);
|
|
item = va_arg(list_backup, AudioPipelineElement *);
|
|
|
|
while (item != NULL) {
|
|
item->destroy(item);
|
|
item = va_arg(list_backup, AudioPipelineElement *);
|
|
}
|
|
if (pipeline->source != NULL) {
|
|
pipeline->source->destroy(pipeline->source);
|
|
}
|
|
free(pipeline);
|
|
va_end(list_backup);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void audio_pipeline_destroy(AudioPipeline *pipeline) {
|
|
pipeline->stop(pipeline);
|
|
|
|
AudioPipelineElement *item = pipeline->source->next;
|
|
while (item != NULL) {
|
|
AudioPipelineElement *next = item->next;
|
|
item->destroy(item);
|
|
item = next;
|
|
}
|
|
pipeline->source->destroy(pipeline->source);
|
|
|
|
free(pipeline);
|
|
}
|
|
|
|
AudioBuffer *alloc_audio_buffer(uint32_t size) {
|
|
AudioBuffer *buffer = malloc(sizeof(AudioBuffer));
|
|
if (buffer == NULL) {
|
|
return NULL;
|
|
}
|
|
buffer->buf_size = size;
|
|
|
|
if (size > 0) {
|
|
buffer->data = calloc(1, size);
|
|
if (buffer->data == NULL) {
|
|
free(buffer);
|
|
return NULL;
|
|
}
|
|
} else {
|
|
buffer->data = NULL;
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
void free_audio_buffer(AudioBuffer *buffer) {
|
|
if (buffer == NULL) {
|
|
return;
|
|
}
|
|
if (buffer->data != NULL) {
|
|
free(buffer->data);
|
|
}
|
|
free(buffer);
|
|
}
|