#include #include #include #include #include #include "audio.h" #include "audio_internal.h" typedef struct _SinkFileContext { FILE *fp; } SinkFileContext; AudioPipelineStatus sink_file_push(AudioPipelineElement *self, AudioBuffer *buffer) { SinkFileContext *context = (SinkFileContext *)self->ctx; size_t bytes = fwrite(buffer->data, 1, buffer->buf_size, context->fp); return (bytes != buffer->buf_size) ? PipelineError : PipelineRunning; } AudioPipelineStatus sink_file_link(AudioPipelineElement *self, AudioPipelineElement *source) { SinkFileContext *context = (SinkFileContext *)self->ctx; if (context->fp != NULL) { fseek(context->fp, 0, SEEK_SET); if (ftruncate(fileno(context->fp), 0) != 0) { fprintf(stderr, "WARN: ftruncate failed with %d\n", errno); } } source->next = self; return PipelineStopped; } char *sink_file_describe(AudioPipelineElement *self) { return "file sink"; } void sink_file_destroy(AudioPipelineElement *self) { SinkFileContext *context = (SinkFileContext *)self->ctx; fclose(context->fp); free(self->ctx); free(self); } AudioPipelineElement *audio_sink_file(char *filename) { AudioPipelineElement *self = calloc(1, sizeof(AudioPipelineElement)); SinkFileContext *context = calloc(1, sizeof(SinkFileContext)); context->fp = fopen(filename, "wb"); if (context->fp == NULL) { fprintf(stderr, "ERROR: Cannot open file %s, errno=%d", filename, errno); free(context); free(self); return NULL; } self->ctx = context; self->describe = sink_file_describe; self->start = sink_nop; self->reset = sink_nop; self->stop = sink_nop; self->push = sink_file_push; self->link = sink_file_link; self->destroy = sink_file_destroy; self->type = AudioElementSink; return self; }