ortp_send.o: ortp_send.c
$(CC) -c $(CPPFLAGS) $(DEBUG_CPPFLAGS) @ortp_cppflags@ $<
-oggdec.o: oggdec.c
+oggdec_filter.o: oggdec_filter.c
$(CC) -c $(CPPFLAGS) $(DEBUG_CPPFLAGS) @oggvorbis_cppflags@ $<
ogg_afh.o: ogg_afh.c
$(CC) -c $(CPPFLAGS) $(DEBUG_CPPFLAGS) @oggvorbis_cppflags@ $<
-mp3dec.o: mp3dec.c
+mp3dec_filter.o: mp3dec_filter.c
$(CC) -c $(CPPFLAGS) $(DEBUG_CPPFLAGS) @mad_cppflags@ $<
-aacdec.o: aacdec.c
+aacdec_filter.o: aacdec_filter.c
$(CC) -c $(CPPFLAGS) $(DEBUG_CPPFLAGS) @faad_cppflags@ $<
aac_common.o: aac_common.c
+++ /dev/null
-/*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
-/*
- * based in parts on libfaad, Copyright (C) 2003-2005 M. Bakker,
- * Ahead Software AG
- */
-
-/** \file aacdec.c paraslash's aac (m4a) decoder */
-
-#include "para.h"
-
-#include "list.h"
-#include "sched.h"
-#include "filter.h"
-#include "error.h"
-#include "string.h"
-#include "aac.h"
-
-/** the output buffer size */
-#define AAC_OUTBUF_SIZE (32 * 1024)
-
-/** give up decoding after that many errors */
-#define MAX_ERRORS 20
-
-/**
- * data specific to the aacdec filter
- *
- * \sa filter, filter_node
- */
-struct private_aacdec_data {
- /** the return value of aac_open */
- NeAACDecHandle handle;
- /** info about the currently decoded frame */
- NeAACDecFrameInfo frame_info;
- /** whether this instance of the aac decoder is already initialized */
- int initialized;
- /**
- * return value of aac_find_esds(). Used to call the right aacdec
- * init function
- */
- unsigned long decoder_length;
- /** number of times the decoder returned an error */
- unsigned error_count;
- /** number of bytes already consumed from the imput stream */
- size_t consumed_total;
- /** return value of aac_find_entry_point */
- size_t entry;
-};
-
-static ssize_t aacdec(char *input_buffer, size_t len, struct filter_node *fn)
-{
- struct private_aacdec_data *padd = fn->private_data;
- struct filter_chain *fc = fn->fc;
- int i, ret;
- unsigned char *p, *outbuffer;
- unsigned char *inbuf = (unsigned char*)input_buffer;
- size_t skip, consumed = 0;
-
- if (fn->loaded > fn->bufsize * 3 / 5)
- return 0;
- if (len < 2048 && !*fc->input_error)
- return 0;
-
- if (!padd->initialized) {
- unsigned long rate = 0;
- unsigned char channels = 0;
- ret = aac_find_esds(inbuf, len, &skip, &padd->decoder_length);
- if (ret < 0) {
- PARA_INFO_LOG("%s\n", para_strerror(-ret));
- ret = NeAACDecInit(padd->handle, inbuf,
- len, &rate, &channels);
- PARA_INFO_LOG("decoder init: %d\n", ret);
- if (ret < 0) {
- ret = -E_AACDEC_INIT;
- goto out;
- }
- consumed = ret;
- } else {
- PARA_INFO_LOG("decoder len: %lu\n",
- padd->decoder_length);
- consumed += skip;
- p = inbuf + consumed;
- ret = -E_AACDEC_INIT;
- if (NeAACDecInit2(padd->handle, p,
- padd->decoder_length, &rate,
- &channels) < 0)
- goto out;
- }
- fc->samplerate = rate;
- fc->channels = channels;
- PARA_INFO_LOG("rate: %u, channels: %d\n",
- fc->samplerate, fc->channels);
- padd->initialized = 1;
- }
- if (padd->decoder_length > 0) {
- consumed = 0;
- if (!padd->entry) {
- ret = aac_find_entry_point(inbuf + consumed,
- len - consumed, &skip);
- if (ret < 0) {
- ret = len;
- goto out;
- }
- consumed += skip;
- padd->entry = ret;
- PARA_INFO_LOG("entry: %zu\n", padd->entry);
- }
- ret = len;
- if (padd->consumed_total + len < padd->entry)
- goto out;
- if (padd->consumed_total < padd->entry)
- consumed = padd->entry - padd->consumed_total;
- }
- for (; consumed < len; consumed++)
- if ((inbuf[consumed] & 0xfe) == 0x20)
- break;
- if (consumed >= len)
- goto success;
- p = inbuf + consumed;
- outbuffer = NeAACDecDecode(padd->handle, &padd->frame_info, p,
- len - consumed);
- if (padd->frame_info.error) {
- ret = -E_AAC_DECODE;
- if (padd->error_count++ > MAX_ERRORS)
- goto out;
- PARA_ERROR_LOG("frame_error: %d, consumed: %zu + %zd + %lu\n",
- padd->frame_info.error, padd->consumed_total,
- consumed, padd->frame_info.bytesconsumed);
- PARA_ERROR_LOG("%s\n", NeAACDecGetErrorMessage(
- padd->frame_info.error));
- consumed++; /* catch 21 */
- goto success;
- }
- padd->error_count = 0;
- consumed += padd->frame_info.bytesconsumed;
- ret = consumed;
- if (!padd->frame_info.samples)
- goto out;
- ret = -E_AAC_OVERRUN;
- if (padd->frame_info.samples * 2 + fn->loaded > fn->bufsize)
- goto out;
- for (i = 0; i < padd->frame_info.samples; i++) {
- short *s = (short *)outbuffer;
- write_int16_host_endian(fn->buf + fn->loaded, s[i]);
- fn->loaded += 2;
- }
-success:
- ret = consumed;
-out:
- if (ret > 0)
- padd->consumed_total += ret;
- return ret;
-}
-
-static void aacdec_open(struct filter_node *fn)
-{
- struct private_aacdec_data *padd = para_calloc(sizeof(*padd));
-
- fn->private_data = padd;
- fn->bufsize = AAC_OUTBUF_SIZE;
- fn->buf = para_calloc(fn->bufsize);
- padd->handle = aac_open();
-}
-
-static void aacdec_close(struct filter_node *fn)
-{
- struct private_aacdec_data *padd = fn->private_data;
-
- NeAACDecClose(padd->handle);
- free(fn->buf);
- fn->buf = NULL;
- free(padd);
- fn->private_data = NULL;
-}
-
-/**
- * the init function of the aacdec filter
- *
- * \param f pointer to the filter struct to initialize
- *
- * \sa filter::init
- */
-void aacdec_init(struct filter *f)
-{
- f->open = aacdec_open;
- f->convert = aacdec;
- f->close = aacdec_close;
-}
--- /dev/null
+/*
+ * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+/*
+ * based in parts on libfaad, Copyright (C) 2003-2005 M. Bakker,
+ * Ahead Software AG
+ */
+
+/** \file aacdec_filter.c paraslash's aac (m4a) decoder. */
+
+#include "para.h"
+
+#include "list.h"
+#include "sched.h"
+#include "filter.h"
+#include "error.h"
+#include "string.h"
+#include "aac.h"
+
+/** the output buffer size */
+#define AAC_OUTBUF_SIZE (32 * 1024)
+
+/** give up decoding after that many errors */
+#define MAX_ERRORS 20
+
+/**
+ * data specific to the aacdec filter
+ *
+ * \sa filter, filter_node
+ */
+struct private_aacdec_data {
+ /** the return value of aac_open */
+ NeAACDecHandle handle;
+ /** info about the currently decoded frame */
+ NeAACDecFrameInfo frame_info;
+ /** whether this instance of the aac decoder is already initialized */
+ int initialized;
+ /**
+ * return value of aac_find_esds(). Used to call the right aacdec
+ * init function
+ */
+ unsigned long decoder_length;
+ /** number of times the decoder returned an error */
+ unsigned error_count;
+ /** number of bytes already consumed from the imput stream */
+ size_t consumed_total;
+ /** return value of aac_find_entry_point */
+ size_t entry;
+};
+
+static ssize_t aacdec(char *input_buffer, size_t len, struct filter_node *fn)
+{
+ struct private_aacdec_data *padd = fn->private_data;
+ struct filter_chain *fc = fn->fc;
+ int i, ret;
+ unsigned char *p, *outbuffer;
+ unsigned char *inbuf = (unsigned char*)input_buffer;
+ size_t skip, consumed = 0;
+
+ if (fn->loaded > fn->bufsize * 3 / 5)
+ return 0;
+ if (len < 2048 && !*fc->input_error)
+ return 0;
+
+ if (!padd->initialized) {
+ unsigned long rate = 0;
+ unsigned char channels = 0;
+ ret = aac_find_esds(inbuf, len, &skip, &padd->decoder_length);
+ if (ret < 0) {
+ PARA_INFO_LOG("%s\n", para_strerror(-ret));
+ ret = NeAACDecInit(padd->handle, inbuf,
+ len, &rate, &channels);
+ PARA_INFO_LOG("decoder init: %d\n", ret);
+ if (ret < 0) {
+ ret = -E_AACDEC_INIT;
+ goto out;
+ }
+ consumed = ret;
+ } else {
+ PARA_INFO_LOG("decoder len: %lu\n",
+ padd->decoder_length);
+ consumed += skip;
+ p = inbuf + consumed;
+ ret = -E_AACDEC_INIT;
+ if (NeAACDecInit2(padd->handle, p,
+ padd->decoder_length, &rate,
+ &channels) < 0)
+ goto out;
+ }
+ fc->samplerate = rate;
+ fc->channels = channels;
+ PARA_INFO_LOG("rate: %u, channels: %d\n",
+ fc->samplerate, fc->channels);
+ padd->initialized = 1;
+ }
+ if (padd->decoder_length > 0) {
+ consumed = 0;
+ if (!padd->entry) {
+ ret = aac_find_entry_point(inbuf + consumed,
+ len - consumed, &skip);
+ if (ret < 0) {
+ ret = len;
+ goto out;
+ }
+ consumed += skip;
+ padd->entry = ret;
+ PARA_INFO_LOG("entry: %zu\n", padd->entry);
+ }
+ ret = len;
+ if (padd->consumed_total + len < padd->entry)
+ goto out;
+ if (padd->consumed_total < padd->entry)
+ consumed = padd->entry - padd->consumed_total;
+ }
+ for (; consumed < len; consumed++)
+ if ((inbuf[consumed] & 0xfe) == 0x20)
+ break;
+ if (consumed >= len)
+ goto success;
+ p = inbuf + consumed;
+ outbuffer = NeAACDecDecode(padd->handle, &padd->frame_info, p,
+ len - consumed);
+ if (padd->frame_info.error) {
+ ret = -E_AAC_DECODE;
+ if (padd->error_count++ > MAX_ERRORS)
+ goto out;
+ PARA_ERROR_LOG("frame_error: %d, consumed: %zu + %zd + %lu\n",
+ padd->frame_info.error, padd->consumed_total,
+ consumed, padd->frame_info.bytesconsumed);
+ PARA_ERROR_LOG("%s\n", NeAACDecGetErrorMessage(
+ padd->frame_info.error));
+ consumed++; /* catch 21 */
+ goto success;
+ }
+ padd->error_count = 0;
+ consumed += padd->frame_info.bytesconsumed;
+ ret = consumed;
+ if (!padd->frame_info.samples)
+ goto out;
+ ret = -E_AAC_OVERRUN;
+ if (padd->frame_info.samples * 2 + fn->loaded > fn->bufsize)
+ goto out;
+ for (i = 0; i < padd->frame_info.samples; i++) {
+ short *s = (short *)outbuffer;
+ write_int16_host_endian(fn->buf + fn->loaded, s[i]);
+ fn->loaded += 2;
+ }
+success:
+ ret = consumed;
+out:
+ if (ret > 0)
+ padd->consumed_total += ret;
+ return ret;
+}
+
+static void aacdec_open(struct filter_node *fn)
+{
+ struct private_aacdec_data *padd = para_calloc(sizeof(*padd));
+
+ fn->private_data = padd;
+ fn->bufsize = AAC_OUTBUF_SIZE;
+ fn->buf = para_calloc(fn->bufsize);
+ padd->handle = aac_open();
+}
+
+static void aacdec_close(struct filter_node *fn)
+{
+ struct private_aacdec_data *padd = fn->private_data;
+
+ NeAACDecClose(padd->handle);
+ free(fn->buf);
+ fn->buf = NULL;
+ free(padd);
+ fn->private_data = NULL;
+}
+
+/**
+ * the init function of the aacdec filter
+ *
+ * \param f pointer to the filter struct to initialize
+ *
+ * \sa filter::init
+ */
+void aacdec_filter_init(struct filter *f)
+{
+ f->open = aacdec_open;
+ f->convert = aacdec;
+ f->close = aacdec_close;
+}
#include "vss.h"
#include "fd.h"
#include "ipc.h"
+#include "portable_io.h"
static struct osl_table *audio_file_table;
free(fn->buf);
}
-static void *amp_parse_config(int argc, char **argv)
+static int amp_parse_config(int argc, char **argv, void **config)
{
- struct amp_filter_args_info *conf = para_calloc(sizeof(*conf));
+ struct amp_filter_args_info *amp_conf = para_calloc(sizeof(*amp_conf));
+ int ret = -E_AMP_SYNTAX;
- if (amp_cmdline_parser(argc, argv, conf))
+ if (amp_cmdline_parser(argc, argv, amp_conf))
goto err;
- if (conf->amp_arg < 0)
+ ret = -ERRNO_TO_PARA_ERROR(EINVAL);
+ if (amp_conf->amp_arg < 0)
goto err;
- PARA_NOTICE_LOG("amplification: %u (scaling factor: %1.2f)\n", conf->amp_arg,
- conf->amp_arg / 64.0 + 1.0);
- return conf;
+ PARA_NOTICE_LOG("amplification: %u (scaling factor: %1.2f)\n",
+ amp_conf->amp_arg, amp_conf->amp_arg / 64.0 + 1.0);
+ *config = amp_conf;
+ return 1;
err:
- free(conf);
- return NULL;
+ free(amp_conf);
+ return ret;
}
static void amp_open(struct filter_node *fn)
*
* \param f Pointer to the struct to initialize.
*/
-void amp_init(struct filter *f)
+void amp_filter_init(struct filter *f)
{
f->open = amp_open;
f->close = amp_close;
+++ /dev/null
-/*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
-
-/** \file compress.c Paraslash's dynamic audio range compressor. */
-
-/*
- * Uses ideas of AudioCompress, (C) 2002-2004 M. Hari Nezumi <magenta@trikuare.cx>
- */
-
-#include "para.h"
-#include "compress_filter.cmdline.h"
-#include "list.h"
-#include "sched.h"
-#include "filter.h"
-#include "string.h"
-
-/** The size of the output data buffer. */
-#define COMPRESS_CHUNK_SIZE 40960
-
-extern char *stat_item_values[NUM_STAT_ITEMS];
-
-/** Data specific to the compress filter. */
-struct private_compress_data {
- /** The current multiplier. */
- unsigned current_gain;
- /** Points to the configuration data for this instance of the compress filter. */
- struct compress_filter_args_info *conf;
- /** Maximal admissible gain. */
- unsigned max_gain;
- /** Number of samples already seen. */
- unsigned num_samples;
- /** Absolute value of the maximal sample in the current block. */
- unsigned peak;
-};
-
-static ssize_t compress(char *inbuf, size_t inbuf_len, struct filter_node *fn)
-{
- size_t i, length = PARA_MIN((inbuf_len / 2) * 2,
- (fn->bufsize - fn->loaded) / 2 * 2);
- struct private_compress_data *pcd = fn->private_data;
- int16_t *ip = (int16_t *)inbuf, *op = (int16_t *)(fn->buf + fn->loaded);
- unsigned gain_shift = pcd->conf->inertia_arg + pcd->conf->damp_arg,
- mask = (1 << pcd->conf->blocksize_arg) - 1;
-
- if (!length)
- return 0;
- for (i = 0; i < length / 2; i++) {
- /* be careful in that heat, my dear */
- int sample = *ip++, adjusted_sample = (PARA_ABS(sample) *
- pcd->current_gain) >> gain_shift;
- if (unlikely(adjusted_sample > 32767)) { /* clip */
- PARA_NOTICE_LOG("clip: sample: %d, adjusted sample: %d\n",
- sample, adjusted_sample);
- adjusted_sample = 32767;
- pcd->current_gain = (3 * pcd->current_gain +
- (1 << pcd->conf->inertia_arg)) / 4;
- pcd->peak = 0;
- } else
- pcd->peak = PARA_MAX(pcd->peak, adjusted_sample);
- *op++ = sample >= 0? adjusted_sample : -adjusted_sample;
- if (likely(++pcd->num_samples & mask))
- continue;
-// PARA_DEBUG_LOG("gain: %u, peak: %u\n", pcd->current_gain,
-// pcd->peak);
- if (pcd->peak < pcd->conf->target_level_arg) {
- if (pcd->current_gain < pcd->max_gain)
- pcd->current_gain++;
- } else
- pcd->current_gain = PARA_MAX(pcd->current_gain - 2,
- 1 << pcd->conf->inertia_arg);
- pcd->peak = 0;
- }
- fn->loaded += length;
- return length;
-}
-
-static void close_compress(struct filter_node *fn)
-{
- free(fn->private_data);
- free(fn->buf);
-}
-
-static void *compress_parse_config(int argc, char **argv)
-{
- struct compress_filter_args_info *ret = para_calloc(sizeof(struct compress_filter_args_info));
- if (!compress_cmdline_parser(argc, argv, ret))
- return ret;
- free(ret);
- return NULL;
-}
-
-static void open_compress(struct filter_node *fn)
-{
- struct private_compress_data *pcd = para_calloc(
- sizeof(struct private_compress_data));
- pcd->conf = fn->conf;
- fn->private_data = pcd;
- fn->bufsize = COMPRESS_CHUNK_SIZE;
- fn->buf = para_malloc(fn->bufsize);
- pcd->current_gain = 1 << pcd->conf->inertia_arg;
- pcd->max_gain = 1 << (pcd->conf->inertia_arg + pcd->conf->aggressiveness_arg);
-}
-
-/**
- * The init function of the compress filter.
- *
- * \param f Pointer to the struct to initialize.
- */
-void compress_init(struct filter *f)
-{
- f->open = open_compress;
- f->close = close_compress;
- f->convert = compress;
- f->print_help = compress_cmdline_parser_print_help;
- f->parse_config = compress_parse_config;
-}
--- /dev/null
+/*
+ * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file compress_filter.c Paraslash's dynamic audio range compressor. */
+
+/*
+ * Uses ideas of AudioCompress, (C) 2002-2004 M. Hari Nezumi <magenta@trikuare.cx>
+ */
+
+#include "para.h"
+#include "compress_filter.cmdline.h"
+#include "list.h"
+#include "sched.h"
+#include "filter.h"
+#include "string.h"
+#include "error.h"
+
+/** The size of the output data buffer. */
+#define COMPRESS_CHUNK_SIZE 40960
+
+extern char *stat_item_values[NUM_STAT_ITEMS];
+
+/** Data specific to the compress filter. */
+struct private_compress_data {
+ /** The current multiplier. */
+ unsigned current_gain;
+ /** Points to the configuration data for this instance of the compress filter. */
+ struct compress_filter_args_info *conf;
+ /** Maximal admissible gain. */
+ unsigned max_gain;
+ /** Number of samples already seen. */
+ unsigned num_samples;
+ /** Absolute value of the maximal sample in the current block. */
+ unsigned peak;
+};
+
+static ssize_t compress(char *inbuf, size_t inbuf_len, struct filter_node *fn)
+{
+ size_t i, length = PARA_MIN((inbuf_len / 2) * 2,
+ (fn->bufsize - fn->loaded) / 2 * 2);
+ struct private_compress_data *pcd = fn->private_data;
+ int16_t *ip = (int16_t *)inbuf, *op = (int16_t *)(fn->buf + fn->loaded);
+ unsigned gain_shift = pcd->conf->inertia_arg + pcd->conf->damp_arg,
+ mask = (1 << pcd->conf->blocksize_arg) - 1;
+
+ if (!length)
+ return 0;
+ for (i = 0; i < length / 2; i++) {
+ /* be careful in that heat, my dear */
+ int sample = *ip++, adjusted_sample = (PARA_ABS(sample) *
+ pcd->current_gain) >> gain_shift;
+ if (unlikely(adjusted_sample > 32767)) { /* clip */
+ PARA_NOTICE_LOG("clip: sample: %d, adjusted sample: %d\n",
+ sample, adjusted_sample);
+ adjusted_sample = 32767;
+ pcd->current_gain = (3 * pcd->current_gain +
+ (1 << pcd->conf->inertia_arg)) / 4;
+ pcd->peak = 0;
+ } else
+ pcd->peak = PARA_MAX(pcd->peak, adjusted_sample);
+ *op++ = sample >= 0? adjusted_sample : -adjusted_sample;
+ if (likely(++pcd->num_samples & mask))
+ continue;
+// PARA_DEBUG_LOG("gain: %u, peak: %u\n", pcd->current_gain,
+// pcd->peak);
+ if (pcd->peak < pcd->conf->target_level_arg) {
+ if (pcd->current_gain < pcd->max_gain)
+ pcd->current_gain++;
+ } else
+ pcd->current_gain = PARA_MAX(pcd->current_gain - 2,
+ 1 << pcd->conf->inertia_arg);
+ pcd->peak = 0;
+ }
+ fn->loaded += length;
+ return length;
+}
+
+static void close_compress(struct filter_node *fn)
+{
+ free(fn->private_data);
+ free(fn->buf);
+}
+
+/** TODO: Add sanity checks */
+static int compress_parse_config(int argc, char **argv, void **config)
+{
+ int ret;
+ struct compress_filter_args_info *compress_conf
+ = para_calloc(sizeof(*compress_conf));
+
+ ret = -E_COMPRESS_SYNTAX;
+ if (compress_cmdline_parser(argc, argv, compress_conf))
+ goto err;
+ *config = compress_conf;
+ return 1;
+err:
+ free(compress_conf);
+ return ret;
+}
+
+static void open_compress(struct filter_node *fn)
+{
+ struct private_compress_data *pcd = para_calloc(
+ sizeof(struct private_compress_data));
+ pcd->conf = fn->conf;
+ fn->private_data = pcd;
+ fn->bufsize = COMPRESS_CHUNK_SIZE;
+ fn->buf = para_malloc(fn->bufsize);
+ pcd->current_gain = 1 << pcd->conf->inertia_arg;
+ pcd->max_gain = 1 << (pcd->conf->inertia_arg + pcd->conf->aggressiveness_arg);
+}
+
+/**
+ * The init function of the compress filter.
+ *
+ * \param f Pointer to the struct to initialize.
+ */
+void compress_filter_init(struct filter *f)
+{
+ f->open = open_compress;
+ f->close = close_compress;
+ f->convert = compress;
+ f->print_help = compress_cmdline_parser_print_help;
+ f->parse_config = compress_parse_config;
+}
all_errlist_objs="server mp3_afh afh_common vss command net string signal time
daemon stat crypt http_send close_on_fork ipc acl afh fade amp_filter
dccp_send fd user_list chunk_queue afs osl aft mood score attribute blob ringbuffer
-playlist sha1 rbtree sched audiod grab_client filter_chain wav compress
+playlist sha1 rbtree sched audiod grab_client filter_common wav_filter compress_filter
http_recv dccp_recv recv_common write_common file_write audiod_command
client_common recv stdout filter stdin audioc write client fsck exec send_common"
senders=" http dccp"
filter_cmdline_objs="filter.cmdline compress_filter.cmdline amp_filter.cmdline"
-filter_errlist_objs="filter_chain wav compress filter string stdin stdout sched fd amp_filter"
+filter_errlist_objs="filter_common wav_filter compress_filter filter string stdin stdout sched fd amp_filter"
filter_ldflags=""
filters=" compress wav amp"
http_recv.cmdline dccp_recv.cmdline file_write.cmdline client.cmdline
audiod_command_list amp_filter.cmdline"
audiod_errlist_objs="audiod signal string daemon stat net
- time grab_client filter_chain wav compress amp_filter http_recv dccp_recv
+ time grab_client filter_common wav_filter compress_filter amp_filter http_recv dccp_recv
recv_common fd sched write_common file_write audiod_command crypt
client_common"
audiod_ldflags=""
AC_CHECK_LIB([vorbis], [vorbis_info_init], [], [ have_ogg="no" ])
AC_CHECK_HEADERS([ogg/ogg.h vorbis/codec.h], [], [ have_ogg="no" ])
if test "$have_ogg" = "yes"; then
- all_errlist_objs="$all_errlist_objs oggdec ogg_afh"
+ all_errlist_objs="$all_errlist_objs oggdec_filter ogg_afh"
AC_DEFINE(HAVE_OGGVORBIS, 1, define to 1 to turn on ogg vorbis support)
filters="$filters oggdec"
if test "$OSTYPE" = "Darwin"; then
audiod_cmdline_objs="$audiod_cmdline_objs oggdec_filter.cmdline"
server_errlist_objs="$server_errlist_objs ogg_afh"
- filter_errlist_objs="$filter_errlist_objs oggdec"
- audiod_errlist_objs="$audiod_errlist_objs oggdec"
+ filter_errlist_objs="$filter_errlist_objs oggdec_filter"
+ audiod_errlist_objs="$audiod_errlist_objs oggdec_filter"
afh_errlist_objs="$afh_errlist_objs ogg_afh"
audiod_audio_formats="ogg"
AC_CHECK_LIB([faad], [NeAACDecOpen], [], have_faad=no)
if test "$have_faad" = "yes"; then
AC_DEFINE(HAVE_FAAD, 1, define to 1 if you want to build the aacdec filter)
- all_errlist_objs="$all_errlist_objs aac_common aacdec aac_afh"
- filter_errlist_objs="$filter_errlist_objs aacdec aac_common"
+ all_errlist_objs="$all_errlist_objs aac_common aacdec_filter aac_afh"
+ filter_errlist_objs="$filter_errlist_objs aacdec_filter aac_common"
afh_errlist_objs="$afh_errlist_objs aac_common aac_afh"
- audiod_errlist_objs="$audiod_errlist_objs aacdec aac_common"
+ audiod_errlist_objs="$audiod_errlist_objs aacdec_filter aac_common"
server_errlist_objs="$server_errlist_objs aac_afh aac_common"
server_ldflags="$server_ldflags $faad_libs -lfaad"
filter_ldflags="$filter_ldflags $faad_libs -lfaad"
])
if test "$have_mad" = "yes"; then
AC_DEFINE(HAVE_MAD, 1, define to 1 if you want to build the mp3dec filter)
- all_errlist_objs="$all_errlist_objs mp3dec"
- filter_errlist_objs="$filter_errlist_objs mp3dec"
- audiod_errlist_objs="$audiod_errlist_objs mp3dec"
+ all_errlist_objs="$all_errlist_objs mp3dec_filter"
+ filter_errlist_objs="$filter_errlist_objs mp3dec_filter"
+ audiod_errlist_objs="$audiod_errlist_objs mp3dec_filter"
filter_ldflags="$filter_ldflags $mad_libs -lmad"
audiod_ldflags="$audiod_ldflags $mad_libs -lmad"
audiod_audio_formats="$audiod_audio_formats mp3"
AC_DEFINE_UNQUOTED(INIT_FADE_ERRLISTS,
objlist_to_errlist($fade_errlist_objs), errors used by para_fade)
+
+enum="$(for i in $filters; do printf "${i}_FILTER, " | tr '[a-z]' '[A-Z]'; done)"
+AC_DEFINE_UNQUOTED(FILTER_ENUM, $enum NUM_SUPPORTED_FILTERS,
+ enum of supported filters)
+inits="$(for i in $filters; do printf 'extern void '$i'_filter_init(struct filter *f); '; done)"
+AC_DEFINE_UNQUOTED(DECLARE_FILTER_INITS, $inits, init functions of the supported filters)
+array="$(for i in $filters; do printf '{.name = \"'$i'\", .init = '$i'_filter_init},'; done)"
+AC_DEFINE_UNQUOTED(FILTER_ARRAY, $array, array of supported filters)
+
enum="$(for i in $writers; do printf "${i}_WRITE, " | tr '[a-z]' '[A-Z]'; done)"
AC_DEFINE_UNQUOTED(WRITER_ENUM, $enum NUM_SUPPORTED_WRITERS,
enum of supported writers)
AC_DEFINE_UNQUOTED(DECLARE_WRITER_INITS, $inits, init functions of the supported writers)
array="$(for i in $writers; do printf '{.init = '$i'_write_init},'; done)"
AC_DEFINE_UNQUOTED(WRITER_ARRAY, $array, array of supported writers)
+
enum="$(for i in $audiod_audio_formats; do printf "AUDIO_FORMAT_${i}, " | tr '[a-z]' '[A-Z]'; done)"
AC_DEFINE_UNQUOTED(AUDIOD_AUDIO_FORMATS_ENUM, $enum NUM_AUDIO_FORMATS,
enum of audio formats supported by audiod)
/* these do not need error handling (yet) */
#define SERVER_ERRORS
-#define WAV_ERRORS
-#define COMPRESS_ERRORS
+#define WAV_FILTER_ERRORS
#define TIME_ERRORS
#define CLOSE_ON_FORK_ERRORS
#define DAEMON_ERRORS
#define RECV_ERRORS
#define STDOUT_ERRORS
#define IPC_ERRORS
-#define AMP_FILTER_ERRORS
#define DCCP_SEND_ERRORS
#define HTTP_SEND_ERRORS
extern const char **para_errlist[];
+#define COMPRESS_FILTER_ERRORS \
+ PARA_ERROR(COMPRESS_SYNTAX, "syntax error in compress filter config"), \
+
+
+#define AMP_FILTER_ERRORS \
+ PARA_ERROR(AMP_SYNTAX, "syntax error in amp filter config"), \
+
+
#define SEND_COMMON_ERRORS \
PARA_ERROR(MAX_CLIENTS, "maximal number of clients exceeded"), \
PARA_ERROR(INVALID_AUDIOD_CMD, "invalid command"), \
-#define FILTER_CHAIN_ERRORS \
+#define FILTER_COMMON_ERRORS \
PARA_ERROR(UNSUPPORTED_FILTER, "given filter not supported"), \
PARA_ERROR(BAD_FILTER_OPTIONS, "invalid filter option given"), \
PARA_ERROR(FC_EOF, "filter chain: eof"), \
PARA_ERROR(UNKNOWN_STAT_ITEM, "status item not recognized"), \
-#define OGGDEC_ERRORS \
+#define OGGDEC_FILTER_ERRORS \
PARA_ERROR(OGGDEC_READ, "read from media returned an error"), \
PARA_ERROR(OGGDEC_NOTVORBIS, "bitstream is not vorbis data"), \
PARA_ERROR(OGGDEC_VERSION, "vorbis version mismatch"), \
PARA_ERROR(OGGDEC_BADHEADER, "invalid vorbis bitstream header"), \
PARA_ERROR(OGGDEC_FAULT, "bug or heap/stack corruption"), \
PARA_ERROR(OGGDEC_BADLINK, "invalid stream section or requested link corrupt"), \
+ PARA_ERROR(OGGDEC_SYNTAX, "syntax error in oggdec config"), \
#define GRAB_CLIENT_ERRORS \
PARA_ERROR(GC_VERSION_GIVEN, ""), /* not really an error */ \
-#define MP3DEC_ERRORS \
+#define MP3DEC_FILTER_ERRORS \
PARA_ERROR(MAD_FRAME_DECODE, "mad frame decode error"), \
PARA_ERROR(MP3DEC_OVERRUN, "mp3 output buffer overrun"), \
PARA_ERROR(WRITE_COMMON_SYNTAX, "syntax error in write option"), \
-#define AACDEC_ERRORS \
+#define AACDEC_FILTER_ERRORS \
PARA_ERROR(AACDEC_INIT, "failed to init aac decoder"), \
PARA_ERROR(AAC_DECODE, "aac decode error"), \
PARA_ERROR(AAC_OVERRUN, "aac output buffer overrun"), \
if (!conf.list_filters_given)
return 1;
printf("available filters: ");
- for (i = 0; filters[i].name; i++)
+ FOR_EACH_SUPPORTED_FILTER(i)
printf("%s%s%s", i? " " : "", filters[i].name,
filters[i].parse_config? "*": "");
printf("\nFilters marked with \"*\" have further command line options. Try\n"
* Licensed under the GPL v2. For licencing details see COPYING.
*/
-/** \file filter.h Filter-related structures and exported symbols from filter_chain.c. */
+/** \file filter.h Filter-related structures and exported symbols from filter_common.c. */
+/** The list of supported filters. */
+enum filter_enum {FILTER_ENUM};
/**
* Describes one running instance of a filter.
* Note: As several instances of the same filter may be running at the same
* time, all these filter functions must be reentrant; no static non-constant
* variables may be used.
- * \sa mp3dec.c, oggdec.c, wav.c, compress.c, filter_node
+ * \sa mp3dec_filter.c, oggdec_filter.c, wav_filter.c, compress_filter.c, filter_node
*/
struct filter {
/** The name of the filter. */
/**
* A pointer to the filter's command line parser.
*
- * If this optional function pointer is not NULL, any filter options are passed
- * from the main program to this command line parser once at application
- * startup. The command line parser should check its command line options given
- * by \a argc and \a argv and abort on errors. On success, it should return a
- * pointer to the filter-specific configuration data determined by \a argc and
- * \a argv.
+ * If this optional function pointer is not NULL, any filter options
+ * are passed from the main program to this command line parser once at
+ * application startup. The command line parser should check its
+ * command line options given by \a argc and \a argv and abort on
+ * errors. Success must be indicated by a non-negative return value. In
+ * this case the function should return a pointer to the
+ * filter-specific configuration data determined by \a argc and \a
+ * argv. On failure, a negative paraslash error code must be returned.
*/
- void *(*parse_config)(int argc, char **argv);
+ int (*parse_config)(int argc, char **argv, void **config);
};
void close_filters(struct filter_chain *fc);
#endif
}
+DECLARE_FILTER_INITS
-/** \cond */
-extern struct filter filters[];
-#define DECLARE_EXTERN_FILTER_INIT(name) \
- extern void name ## _init(struct filter *f)
-
-#define FILTER_INIT(filter) { \
- .name = #filter, \
- .init = filter ## _init, \
- .parse_config = NULL, \
- .print_help = NULL \
-},
-
-/* filters that are always present */
-DECLARE_EXTERN_FILTER_INIT(wav);
-DECLARE_EXTERN_FILTER_INIT(compress);
-DECLARE_EXTERN_FILTER_INIT(amp);
-
-/* next the optional filters */
-#ifdef HAVE_MAD
-DECLARE_EXTERN_FILTER_INIT(mp3dec);
-#define MP3DEC_FILTER FILTER_INIT(mp3dec)
-#else
-#define MP3DEC_FILTER
-#endif
-
-#ifdef HAVE_FAAD
-DECLARE_EXTERN_FILTER_INIT(aacdec);
-#define AACDEC_FILTER FILTER_INIT(aacdec)
-#else
-#define AACDEC_FILTER
-#endif
-
-#ifdef HAVE_OGGVORBIS
-DECLARE_EXTERN_FILTER_INIT(oggdec);
-#define OGGDEC_FILTER FILTER_INIT(oggdec)
-#else
-#define OGGDEC_FILTER
-#endif
-/** \endcond */
-
-/** define an array of all available filters */
-#define DEFINE_FILTER_ARRAY(filters) struct filter filters[] = { \
- FILTER_INIT(wav) \
- FILTER_INIT(compress) \
- FILTER_INIT(amp) \
- MP3DEC_FILTER \
- AACDEC_FILTER \
- OGGDEC_FILTER \
- { .name = NULL } };
-
+#define FOR_EACH_SUPPORTED_FILTER(j) for (j = 0; j < NUM_SUPPORTED_FILTERS; j++)
+/** The filter array, one structure for each supported filter. */
+extern struct filter filters[NUM_SUPPORTED_FILTERS];
+++ /dev/null
-/*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
-
-/** \file filter_chain.c Common helper functions for filter input/output. */
-
-#include <sys/types.h>
-#include <dirent.h>
-
-#include "para.h"
-#include "list.h"
-#include "sched.h"
-#include "fd.h"
-#include "filter.h"
-#include "error.h"
-#include "string.h"
-
-DEFINE_FILTER_ARRAY(filters);
-
-/**
- * Call the init function of each supported filter.
- *
- * \param all_filters the array of all supported filters.
- *
- * \sa filter::init
- */
-void filter_init(struct filter *all_filters)
-{
- struct filter *f;
-
- for (f = all_filters; f->name; f++)
- f->init(f);
-}
-
-/**
- * Close and destroy a filter callback.
- *
- * \param fcb The filter callback to close.
- *
- * This removes \a fcb from the list of filter callbacks and calls
- * the close callback associated with \a fcb.
- */
-static void close_filter_callback(struct filter_callback *fcb)
-{
- PARA_NOTICE_LOG("closing filter_callback %p, data: %p\n", fcb, fcb->data);
- list_del(&fcb->node);
- fcb->close(fcb);
-}
-
-/**
- * Close all callbacks of a filter node.
- *
- * \param fn The filter node which contains the filter callbacks to be closed.
- *
- * Call close_filter_callback() for each entry in the filter callback list
- * of \a fn.
- */
-static void close_callbacks(struct filter_node *fn)
-{
- struct filter_callback *fcb, *tmp;
-
- list_for_each_entry_safe(fcb, tmp, &fn->callbacks, node) {
- PARA_INFO_LOG("closing %s filter callback\n",
- filters[fn->filter_num].name);
- close_filter_callback(fcb);
- }
-}
-
-static void call_callbacks(struct filter_node *fn, char *inbuf, size_t inlen,
- char *outbuf, size_t outlen)
-{
- struct filter_callback *fcb, *tmp;
- list_for_each_entry_safe(fcb, tmp, &fn->callbacks, node) {
- int ret;
- if (inlen && fcb->input_cb) {
- ret = fcb->input_cb(inbuf, inlen, fcb);
- if (ret < 0) {
- close_filter_callback(fcb);
- continue;
- }
- }
- if (!outlen || !fcb->output_cb)
- continue;
- ret = fcb->output_cb(outbuf, outlen, fcb);
- if (ret < 0)
- close_filter_callback(fcb);
- }
-}
-
-/**
- * Call the convert function of each filter.
- *
- * \param s Unused.
- * \param t The task identifying the filter chain.
- *
- * This is the core function of the filter subsystem. It loops over the list of
- * filter nodes determined by \a t and calls the filter's convert function if
- * there is input available for the filter node in question. If the convert
- * function consumed some or all of its input data, all registered input
- * callbacks are called. Similarly, if a convert function produced output, all
- * registerd output callbacks get called.
- *
- * On errors a (negative) error code is stored in t->error.
- *
- * \sa filter_node, filter#convert, filter_callback.
- */
-void filter_pre_select(__a_unused struct sched *s, struct task *t)
-{
- struct filter_chain *fc = container_of(t, struct filter_chain, task);
- struct filter_node *fn;
- char *ib;
- size_t *loaded;
- int i, conv, conv_total = 0;
-
- if (fc->output_error && *fc->output_error < 0) {
- t->error = *fc->output_error;
- return;
- }
-again:
- ib = fc->inbuf;
- loaded = fc->in_loaded;
- conv = 0;
- FOR_EACH_FILTER_NODE(fn, fc, i) {
- struct filter *f = filters + fn->filter_num;
- if (fn->loaded < fn->bufsize) {
- size_t size, old_fn_loaded = fn->loaded;
-// PARA_DEBUG_LOG("fc %p loaded: %zd, calling %s convert\n",
-// fc, *loaded, fn->filter->name);
- t->error = f->convert(ib, *loaded, fn);
- if (t->error < 0)
- return;
- size = t->error;
- call_callbacks(fn, ib, size, fn->buf + old_fn_loaded,
- fn->loaded - old_fn_loaded);
- *loaded -= size;
- conv += size;
- if (*loaded && size) {
-// PARA_DEBUG_LOG("moving %zd bytes in input "
-// "buffer for %s filter\n",
-// *loaded, fn->filter->name);
- memmove(ib, ib + size, *loaded);
- }
- }
- ib = fn->buf;
- loaded = &fn->loaded;
- }
- conv_total += conv;
-// PARA_DEBUG_LOG("eof (in/out/fc): %d/%d/%d out_loaded: %zd, "
-// "conv: %d, conv_total: %d\n", *fc->input_eof,
-// fc->output_eof? *fc->output_eof : -42,
-// fc->eof, *fc->out_loaded, conv, conv_total);
- if (conv)
- goto again;
- if (!*fc->input_error)
- return;
- if (*fc->out_loaded)
- return;
- if (*fc->in_loaded && conv_total)
- return;
- t->error = -E_FC_EOF;
-}
-
-/**
- * Close all filter nodes and their callbacks.
- *
- * \param fc The filter chain to close.
- *
- * For each filter node determined by \a fc, call the close function of each
- * registered filter callback as well as the close function of the
- * corresponding filter. Free all resources and destroy all callback lists and
- * the filter node list.
- *
- * \sa filter::close, filter_callback::close
- */
-void close_filters(struct filter_chain *fc)
-{
- struct filter_node *fn;
- int i;
-
- if (!fc)
- return;
- PARA_NOTICE_LOG("closing filter chain %p\n", fc);
- FOR_EACH_FILTER_NODE(fn, fc, i) {
- struct filter *f = filters + fn->filter_num;
- close_callbacks(fn);
- PARA_INFO_LOG("closing %s filter\n", f->name);
- f->close(fn);
- }
- free(fc->filter_nodes);
-}
-
-/*
- * If the filter has a command line parser and options is not NULL, run it.
- * Returns filter_num on success, negative on errors
- */
-static int parse_filter_args(int filter_num, char *options, void **conf)
-{
- struct filter *f = &filters[filter_num];
- int i, argc = 2;
- char **argv;
-
-// PARA_DEBUG_LOG("%s, options: %s, parser: %p\n", f->name,
-// options? options : "(none)", f->parse_config);
- if (!f->parse_config)
- return strlen(options)? -E_BAD_FILTER_OPTIONS : filter_num;
-// PARA_DEBUG_LOG("options: %s\n", options);
- argc = split_args(options, &argv, " \t");
-// PARA_DEBUG_LOG("argc = %d, argv[0]: %s\n", argc, argv[0]);
- for (i = argc - 1; i >= 0; i--)
- argv[i + 1] = argv[i];
- argv[0] = para_strdup(f->name);
- argc += 1;
- *conf = f->parse_config(argc, argv);
- free(argv[0]);
- free(argv);
- return *conf? filter_num : -E_BAD_FILTER_OPTIONS;
-}
-
-/**
- * Check the filter command line options.
- *
- * \param fa The command line options.
- * \param conf Points to the filter configuration upon successful return.
- *
- * Check if \a fa starts with a the name of a supported filter, followed by
- * a colon. If yes, call the command line parser of that filter.
- *
- * \return On success, the number of the filter is returned and \a conf
- * is initialized to point to the filter configuration determined by \a fa.
- * On errors, a negative value is returned.
- *
- * Note: If \a fa specifies a filter that has no command line parser success is
- * returned, and \a conf is initialized to \p NULL.
- *
- * \sa filter::parse_config
- */
-int check_filter_arg(char *fa, void **conf)
-{
- int j;
-
- *conf = NULL;
-// PARA_DEBUG_LOG("arg: %s\n", fa);
- for (j = 0; filters[j].name; j++) {
- const char *name = filters[j].name;
- size_t len = strlen(name);
- char c;
- if (strlen(fa) < len)
- continue;
- if (strncmp(name, fa, len))
- continue;
- c = fa[len];
- if (c && c != ' ')
- continue;
- if (c && !filters[j].parse_config)
- return -E_BAD_FILTER_OPTIONS;
- return parse_filter_args(j, c? fa + len + 1 :
- fa + strlen(fa), conf);
- }
- return -E_UNSUPPORTED_FILTER;
-}
-
--- /dev/null
+/*
+ * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file filter_common.c Common helper functions for filter input/output. */
+
+#include <sys/types.h>
+#include <dirent.h>
+
+#include "para.h"
+#include "list.h"
+#include "sched.h"
+#include "fd.h"
+#include "filter.h"
+#include "error.h"
+#include "string.h"
+
+/** The array of supported filters. */
+struct filter filters[NUM_SUPPORTED_FILTERS] = {FILTER_ARRAY};
+
+/**
+ * Call the init function of each supported filter.
+ *
+ * \param all_filters the array of all supported filters.
+ *
+ * \sa filter::init
+ */
+void filter_init(struct filter *all_filters)
+{
+ int i;
+
+ FOR_EACH_SUPPORTED_FILTER(i)
+ all_filters[i].init(all_filters + i);
+}
+
+/**
+ * Close and destroy a filter callback.
+ *
+ * \param fcb The filter callback to close.
+ *
+ * This removes \a fcb from the list of filter callbacks and calls
+ * the close callback associated with \a fcb.
+ */
+static void close_filter_callback(struct filter_callback *fcb)
+{
+ PARA_NOTICE_LOG("closing filter_callback %p, data: %p\n", fcb, fcb->data);
+ list_del(&fcb->node);
+ fcb->close(fcb);
+}
+
+/**
+ * Close all callbacks of a filter node.
+ *
+ * \param fn The filter node which contains the filter callbacks to be closed.
+ *
+ * Call close_filter_callback() for each entry in the filter callback list
+ * of \a fn.
+ */
+static void close_callbacks(struct filter_node *fn)
+{
+ struct filter_callback *fcb, *tmp;
+
+ list_for_each_entry_safe(fcb, tmp, &fn->callbacks, node) {
+ PARA_INFO_LOG("closing %s filter callback\n",
+ filters[fn->filter_num].name);
+ close_filter_callback(fcb);
+ }
+}
+
+static void call_callbacks(struct filter_node *fn, char *inbuf, size_t inlen,
+ char *outbuf, size_t outlen)
+{
+ struct filter_callback *fcb, *tmp;
+ list_for_each_entry_safe(fcb, tmp, &fn->callbacks, node) {
+ int ret;
+ if (inlen && fcb->input_cb) {
+ ret = fcb->input_cb(inbuf, inlen, fcb);
+ if (ret < 0) {
+ close_filter_callback(fcb);
+ continue;
+ }
+ }
+ if (!outlen || !fcb->output_cb)
+ continue;
+ ret = fcb->output_cb(outbuf, outlen, fcb);
+ if (ret < 0)
+ close_filter_callback(fcb);
+ }
+}
+
+/**
+ * Call the convert function of each filter.
+ *
+ * \param s Unused.
+ * \param t The task identifying the filter chain.
+ *
+ * This is the core function of the filter subsystem. It loops over the list of
+ * filter nodes determined by \a t and calls the filter's convert function if
+ * there is input available for the filter node in question. If the convert
+ * function consumed some or all of its input data, all registered input
+ * callbacks are called. Similarly, if a convert function produced output, all
+ * registerd output callbacks get called.
+ *
+ * On errors a (negative) error code is stored in t->error.
+ *
+ * \sa filter_node, filter#convert, filter_callback.
+ */
+void filter_pre_select(__a_unused struct sched *s, struct task *t)
+{
+ struct filter_chain *fc = container_of(t, struct filter_chain, task);
+ struct filter_node *fn;
+ char *ib;
+ size_t *loaded;
+ int i, conv, conv_total = 0;
+
+ if (fc->output_error && *fc->output_error < 0) {
+ t->error = *fc->output_error;
+ return;
+ }
+again:
+ ib = fc->inbuf;
+ loaded = fc->in_loaded;
+ conv = 0;
+ FOR_EACH_FILTER_NODE(fn, fc, i) {
+ struct filter *f = filters + fn->filter_num;
+ if (fn->loaded < fn->bufsize) {
+ size_t size, old_fn_loaded = fn->loaded;
+// PARA_DEBUG_LOG("fc %p loaded: %zd, calling %s convert\n",
+// fc, *loaded, fn->filter->name);
+ t->error = f->convert(ib, *loaded, fn);
+ if (t->error < 0)
+ return;
+ size = t->error;
+ call_callbacks(fn, ib, size, fn->buf + old_fn_loaded,
+ fn->loaded - old_fn_loaded);
+ *loaded -= size;
+ conv += size;
+ if (*loaded && size) {
+// PARA_DEBUG_LOG("moving %zd bytes in input "
+// "buffer for %s filter\n",
+// *loaded, fn->filter->name);
+ memmove(ib, ib + size, *loaded);
+ }
+ }
+ ib = fn->buf;
+ loaded = &fn->loaded;
+ }
+ conv_total += conv;
+// PARA_DEBUG_LOG("eof (in/out/fc): %d/%d/%d out_loaded: %zd, "
+// "conv: %d, conv_total: %d\n", *fc->input_eof,
+// fc->output_eof? *fc->output_eof : -42,
+// fc->eof, *fc->out_loaded, conv, conv_total);
+ if (conv)
+ goto again;
+ if (!*fc->input_error)
+ return;
+ if (*fc->out_loaded)
+ return;
+ if (*fc->in_loaded && conv_total)
+ return;
+ t->error = -E_FC_EOF;
+}
+
+/**
+ * Close all filter nodes and their callbacks.
+ *
+ * \param fc The filter chain to close.
+ *
+ * For each filter node determined by \a fc, call the close function of each
+ * registered filter callback as well as the close function of the
+ * corresponding filter. Free all resources and destroy all callback lists and
+ * the filter node list.
+ *
+ * \sa filter::close, filter_callback::close
+ */
+void close_filters(struct filter_chain *fc)
+{
+ struct filter_node *fn;
+ int i;
+
+ if (!fc)
+ return;
+ PARA_NOTICE_LOG("closing filter chain %p\n", fc);
+ FOR_EACH_FILTER_NODE(fn, fc, i) {
+ struct filter *f = filters + fn->filter_num;
+ close_callbacks(fn);
+ PARA_INFO_LOG("closing %s filter\n", f->name);
+ f->close(fn);
+ }
+ free(fc->filter_nodes);
+}
+
+/*
+ * If the filter has a command line parser and options is not NULL, run it.
+ * Returns filter_num on success, negative on errors
+ */
+static int parse_filter_args(int filter_num, char *options, void **conf)
+{
+ struct filter *f = &filters[filter_num];
+ int ret, i, argc = 2;
+ char **argv;
+
+// PARA_DEBUG_LOG("%s, options: %s, parser: %p\n", f->name,
+// options? options : "(none)", f->parse_config);
+ if (!f->parse_config)
+ return strlen(options)? -E_BAD_FILTER_OPTIONS : filter_num;
+// PARA_DEBUG_LOG("options: %s\n", options);
+ argc = split_args(options, &argv, " \t");
+// PARA_DEBUG_LOG("argc = %d, argv[0]: %s\n", argc, argv[0]);
+ for (i = argc - 1; i >= 0; i--)
+ argv[i + 1] = argv[i];
+ argv[0] = para_strdup(f->name);
+ argc += 1;
+ ret = f->parse_config(argc, argv, conf);
+ free(argv[0]);
+ free(argv);
+ return ret < 0? ret : filter_num;
+}
+
+/**
+ * Check the filter command line options.
+ *
+ * \param fa The command line options.
+ * \param conf Points to the filter configuration upon successful return.
+ *
+ * Check if \a fa starts with a the name of a supported filter, followed by
+ * a colon. If yes, call the command line parser of that filter.
+ *
+ * \return On success, the number of the filter is returned and \a conf
+ * is initialized to point to the filter configuration determined by \a fa.
+ * On errors, a negative value is returned.
+ *
+ * Note: If \a fa specifies a filter that has no command line parser success is
+ * returned, and \a conf is initialized to \p NULL.
+ *
+ * \sa filter::parse_config
+ */
+int check_filter_arg(char *fa, void **conf)
+{
+ int j;
+
+ *conf = NULL;
+// PARA_DEBUG_LOG("arg: %s\n", fa);
+ FOR_EACH_SUPPORTED_FILTER(j) {
+ const char *name = filters[j].name;
+ size_t len = strlen(name);
+ char c;
+ if (strlen(fa) < len)
+ continue;
+ if (strncmp(name, fa, len))
+ continue;
+ c = fa[len];
+ if (c && c != ' ')
+ continue;
+ if (c && !filters[j].parse_config)
+ return -E_BAD_FILTER_OPTIONS;
+ return parse_filter_args(j, c? fa + len + 1 :
+ fa + strlen(fa), conf);
+ }
+ return -E_UNSUPPORTED_FILTER;
+}
+
/** \file hash.h Inline functions for hash values. */
-#include "portable_io.h"
-
/** hash arrays are always unsigned char. */
#define HASH_TYPE unsigned char
+++ /dev/null
-/*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
-
-/** \file mp3dec.c Paraslash's mp3 decoder. */
-
-#include "para.h"
-#include "list.h"
-#include "sched.h"
-#include "filter.h"
-#include "error.h"
-#include <mad.h>
-#include "string.h"
-
-/** The output buffer size. */
-#define MP3_OUTBUF_SIZE (128 * 1024)
-
-/** Convert a sample value from libmad to a signed short. */
-#define MAD_TO_SHORT(f) (f) >= MAD_F_ONE? SHRT_MAX :\
- (f) <= -MAD_F_ONE? -SHRT_MAX : (signed short) ((f) >> (MAD_F_FRACBITS - 15))
-
-/** Data specific to the mp3dec filter. */
-struct private_mp3dec_data {
- /** Information on the current mp3 stream. */
- struct mad_stream stream;
- /** Information about the frame which is currently decoded. */
- struct mad_frame frame;
- /** Contains the PCM output. */
- struct mad_synth synth;
-};
-
-static ssize_t mp3dec(char *inbuffer, size_t len, struct filter_node *fn)
-{
- int i, ret;
- struct private_mp3dec_data *pmd = fn->private_data;
- size_t copy = PARA_MIN(len, 4096);
-
- if (fn->loaded > fn->bufsize * 4 / 5)
- return 0;
- mad_stream_buffer(&pmd->stream, (unsigned char *) inbuffer, copy);
- pmd->stream.error = 0;
-next_frame:
- ret = mad_header_decode(&pmd->frame.header, &pmd->stream);
- if (ret < 0) {
- if (pmd->stream.error != MAD_ERROR_BUFLEN &&
- pmd->stream.error != MAD_ERROR_LOSTSYNC)
- PARA_DEBUG_LOG("header decode: %s\n",
- mad_stream_errorstr(&pmd->stream));
- goto out;
- }
- fn->fc->samplerate = pmd->frame.header.samplerate;
- fn->fc->channels = MAD_NCHANNELS(&pmd->frame.header);
- ret = mad_frame_decode(&pmd->frame, &pmd->stream);
- if (ret) {
- if (MAD_RECOVERABLE(pmd->stream.error) ||
- pmd->stream.error == MAD_ERROR_BUFLEN) {
- PARA_DEBUG_LOG("frame decode: %s\n",
- mad_stream_errorstr(&pmd->stream));
- goto out;
- }
- PARA_ERROR_LOG("frame decode: %s\n",
- mad_stream_errorstr(&pmd->stream));
- return -E_MAD_FRAME_DECODE;
- }
- mad_synth_frame(&pmd->synth, &pmd->frame);
-
- for (i = 0; i < pmd->synth.pcm.length; i++) {
- int s = MAD_TO_SHORT(pmd->synth.pcm.samples[0][i]);
- write_int16_host_endian(fn->buf + fn->loaded, s);
- fn->loaded += 2;
- if (MAD_NCHANNELS(&pmd->frame.header) == 2) { /* stereo */
- s = MAD_TO_SHORT(pmd->synth.pcm.samples[1][i]);
- write_int16_host_endian(fn->buf + fn->loaded, s);
- fn->loaded += 2;
- }
- if (fn->loaded != fn->bufsize) /* output buffer not full */
- continue;
- PARA_ERROR_LOG("output buffer full: %zd\n", fn->loaded);
- return -E_MP3DEC_OVERRUN;
- }
- if (fn->loaded <= fn->bufsize * 4 / 5)
- goto next_frame;
-out:
- if (pmd->stream.next_frame) { /* we still have some data */
- size_t off = pmd->stream.bufend - pmd->stream.next_frame;
-// PARA_INFO_LOG("off: %zd, rate: %u, returning %zd\n", off,
-// fn->fc->samplerate, copy - off);
- return copy - off;
- }
- return copy;
-}
-
-static void mp3dec_close(struct filter_node *fn)
-{
- struct private_mp3dec_data *pmd = fn->private_data;
-
- mad_synth_finish(&pmd->synth);
- mad_frame_finish(&pmd->frame);
- mad_stream_finish(&pmd->stream);
-
- free(fn->buf);
- fn->buf = NULL;
- free(pmd);
- fn->private_data = NULL;
-}
-
-static void mp3dec_open(struct filter_node *fn)
-{
- struct private_mp3dec_data *pmd = para_calloc(sizeof(*pmd));
-
- fn->private_data = pmd;
- mad_stream_init(&pmd->stream);
- mad_frame_init(&pmd->frame);
- mad_synth_init(&pmd->synth);
- fn->loaded = 0;
- fn->bufsize = MP3_OUTBUF_SIZE;
- fn->buf = para_calloc(fn->bufsize);
-}
-
-/**
- * The init function of the mp3dec filter.
- *
- * \param f Pointer to the filter struct to initialize.
- *
- * \sa filter::init.
- */
-void mp3dec_init(struct filter *f)
-{
- f->open = mp3dec_open;
- f->convert = mp3dec;
- f->close = mp3dec_close;
-}
--- /dev/null
+/*
+ * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file mp3dec_filter.c Paraslash's mp3 decoder. */
+
+#include "para.h"
+#include "list.h"
+#include "sched.h"
+#include "filter.h"
+#include "error.h"
+#include <mad.h>
+#include "string.h"
+
+/** The output buffer size. */
+#define MP3_OUTBUF_SIZE (128 * 1024)
+
+/** Convert a sample value from libmad to a signed short. */
+#define MAD_TO_SHORT(f) (f) >= MAD_F_ONE? SHRT_MAX :\
+ (f) <= -MAD_F_ONE? -SHRT_MAX : (signed short) ((f) >> (MAD_F_FRACBITS - 15))
+
+/** Data specific to the mp3dec filter. */
+struct private_mp3dec_data {
+ /** Information on the current mp3 stream. */
+ struct mad_stream stream;
+ /** Information about the frame which is currently decoded. */
+ struct mad_frame frame;
+ /** Contains the PCM output. */
+ struct mad_synth synth;
+};
+
+static ssize_t mp3dec(char *inbuffer, size_t len, struct filter_node *fn)
+{
+ int i, ret;
+ struct private_mp3dec_data *pmd = fn->private_data;
+ size_t copy = PARA_MIN(len, 4096);
+
+ if (fn->loaded > fn->bufsize * 4 / 5)
+ return 0;
+ mad_stream_buffer(&pmd->stream, (unsigned char *) inbuffer, copy);
+ pmd->stream.error = 0;
+next_frame:
+ ret = mad_header_decode(&pmd->frame.header, &pmd->stream);
+ if (ret < 0) {
+ if (pmd->stream.error != MAD_ERROR_BUFLEN &&
+ pmd->stream.error != MAD_ERROR_LOSTSYNC)
+ PARA_DEBUG_LOG("header decode: %s\n",
+ mad_stream_errorstr(&pmd->stream));
+ goto out;
+ }
+ fn->fc->samplerate = pmd->frame.header.samplerate;
+ fn->fc->channels = MAD_NCHANNELS(&pmd->frame.header);
+ ret = mad_frame_decode(&pmd->frame, &pmd->stream);
+ if (ret) {
+ if (MAD_RECOVERABLE(pmd->stream.error) ||
+ pmd->stream.error == MAD_ERROR_BUFLEN) {
+ PARA_DEBUG_LOG("frame decode: %s\n",
+ mad_stream_errorstr(&pmd->stream));
+ goto out;
+ }
+ PARA_ERROR_LOG("frame decode: %s\n",
+ mad_stream_errorstr(&pmd->stream));
+ return -E_MAD_FRAME_DECODE;
+ }
+ mad_synth_frame(&pmd->synth, &pmd->frame);
+
+ for (i = 0; i < pmd->synth.pcm.length; i++) {
+ int s = MAD_TO_SHORT(pmd->synth.pcm.samples[0][i]);
+ write_int16_host_endian(fn->buf + fn->loaded, s);
+ fn->loaded += 2;
+ if (MAD_NCHANNELS(&pmd->frame.header) == 2) { /* stereo */
+ s = MAD_TO_SHORT(pmd->synth.pcm.samples[1][i]);
+ write_int16_host_endian(fn->buf + fn->loaded, s);
+ fn->loaded += 2;
+ }
+ if (fn->loaded != fn->bufsize) /* output buffer not full */
+ continue;
+ PARA_ERROR_LOG("output buffer full: %zd\n", fn->loaded);
+ return -E_MP3DEC_OVERRUN;
+ }
+ if (fn->loaded <= fn->bufsize * 4 / 5)
+ goto next_frame;
+out:
+ if (pmd->stream.next_frame) { /* we still have some data */
+ size_t off = pmd->stream.bufend - pmd->stream.next_frame;
+// PARA_INFO_LOG("off: %zd, rate: %u, returning %zd\n", off,
+// fn->fc->samplerate, copy - off);
+ return copy - off;
+ }
+ return copy;
+}
+
+static void mp3dec_close(struct filter_node *fn)
+{
+ struct private_mp3dec_data *pmd = fn->private_data;
+
+ mad_synth_finish(&pmd->synth);
+ mad_frame_finish(&pmd->frame);
+ mad_stream_finish(&pmd->stream);
+
+ free(fn->buf);
+ fn->buf = NULL;
+ free(pmd);
+ fn->private_data = NULL;
+}
+
+static void mp3dec_open(struct filter_node *fn)
+{
+ struct private_mp3dec_data *pmd = para_calloc(sizeof(*pmd));
+
+ fn->private_data = pmd;
+ mad_stream_init(&pmd->stream);
+ mad_frame_init(&pmd->frame);
+ mad_synth_init(&pmd->synth);
+ fn->loaded = 0;
+ fn->bufsize = MP3_OUTBUF_SIZE;
+ fn->buf = para_calloc(fn->bufsize);
+}
+
+/**
+ * The init function of the mp3dec filter.
+ *
+ * \param f Pointer to the filter struct to initialize.
+ *
+ * \sa filter::init.
+ */
+void mp3dec_filter_init(struct filter *f)
+{
+ f->open = mp3dec_open;
+ f->convert = mp3dec;
+ f->close = mp3dec_close;
+}
+++ /dev/null
-/*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
-
-/** \file oggdec.c Paraslash's ogg vorbis decoder. */
-
-#include "para.h"
-
-#include "oggdec_filter.cmdline.h"
-#include "list.h"
-#include "sched.h"
-#include "filter.h"
-#include "error.h"
-#include "string.h"
-
-#include <vorbis/vorbisfile.h>
-
-/** Determine byte sex. */
-#ifdef WORDS_BIGENDIAN
-#define ENDIAN 1
-#else
-#define ENDIAN 0
-#endif
-
-/** Data specific to the oggdec filter. */
-struct private_oggdec_data {
- /** Describes an ogg vorbis file. */
- OggVorbis_File *vf;
- /** The input buffer. */
- char *inbuf;
- /** The length of \a inbuf. */
- size_t inbuf_len;
- /** The number of bytes consumed from the input buffer. */
- size_t converted;
-};
-
-static size_t cb_read(void *buf, size_t size, size_t nmemb, void *datasource)
-{
- struct filter_node *fn = datasource;
- struct private_oggdec_data *pod = fn->private_data;
- size_t ret, have = pod->inbuf_len - pod->converted;
- char *p = pod->inbuf + pod->converted;
-
-// PARA_DEBUG_LOG("pod = %p\n", pod);
-// PARA_DEBUG_LOG("vorbis requests %d bytes, have %d\n", size * nmemb, have);
- if (pod->inbuf_len < size) {
- if (*fn->fc->input_error)
- return 0;
- errno = EAGAIN;
- return (size_t)-1;
- }
- ret = PARA_MIN(nmemb, have / size) * size;
- memcpy(buf, p, ret);
- pod->converted += ret;
- return ret;
-}
-
-/*
- * Custom data seeking function.
- *
- * Since we want the data source to be treated as unseekable at all
- * times, the provided seek callback always returns -1 (failure).
- */
-static int cb_seek(__a_unused void *datasource, __a_unused ogg_int64_t offset,
- __a_unused int whence)
-{
- return -1;
-}
-
-static int cb_close(__a_unused void *datasource)
-{
- return 0;
-}
-
-static const ov_callbacks ovc = {
- .read_func = cb_read,
- .seek_func = cb_seek,
- .close_func = cb_close,
- /*
- * The tell function need not be provided if the data IO abstraction is
- * not seekable
- */
- .tell_func = NULL
-};
-
-static void ogg_open(struct filter_node *fn)
-{
- struct private_oggdec_data *pod = para_calloc(
- sizeof(struct private_oggdec_data));
- struct oggdec_filter_args_info *conf = fn->conf;
-
- fn->private_data = pod;
- fn->bufsize = conf->bufsize_arg * 1024;
- fn->buf = para_malloc(fn->bufsize);
-}
-
-static void ogg_close(struct filter_node *fn)
-{
- struct private_oggdec_data *pod = fn->private_data;
- if (pod->vf) {
- PARA_DEBUG_LOG("ov_clearing %p, pod = %p\n", pod->vf, pod);
- ov_clear(pod->vf);
- free(pod->vf);
- pod->vf = NULL;
- } else
- PARA_DEBUG_LOG("nothing to close in fc %p, pod = %p\n", pod->vf, pod);
- free(fn->buf);
- fn->buf = NULL;
- free(fn->private_data);
- fn->private_data = NULL;
-}
-
-static ssize_t ogg_convert(char *inbuffer, size_t len, struct filter_node *fn)
-{
- ssize_t ret;
- struct private_oggdec_data *pod = fn->private_data;
- struct oggdec_filter_args_info *conf = fn->conf;
- /* make the buffer known to the read callback cb_read() */
- pod->inbuf = inbuffer;
- pod->inbuf_len = len;
- pod->converted = 0;
-
- if (!pod->vf) {
- int ib = 1024 * conf->initial_buffer_arg; /* initial buffer */
- if (len <ib && !*fn->fc->input_error) {
- PARA_DEBUG_LOG("initial input buffer %zd/%d, "
- "waiting for more data\n", len, ib);
- return 0;
- }
- pod->vf = para_malloc(sizeof(struct OggVorbis_File));
- PARA_NOTICE_LOG("input buffer: %zd, opening ov callbacks\n", len);
- ret = ov_open_callbacks(fn, pod->vf,
- NULL, /* no initial buffer */
- 0, /* no initial bytes */
- ovc); /* the ov_open_callbacks */
- if (ret == OV_EREAD)
- return -E_OGGDEC_READ;
- if (ret == OV_ENOTVORBIS)
- return -E_OGGDEC_NOTVORBIS;
- if (ret == OV_EVERSION)
- return -E_OGGDEC_VERSION;
- if (ret == OV_EBADHEADER)
- return -E_OGGDEC_BADHEADER;
- if (ret < 0)
- return -E_OGGDEC_FAULT;
- fn->fc->channels = ov_info(pod->vf, 0)->channels;
- fn->fc->samplerate = ov_info(pod->vf, 0)->rate;
- PARA_NOTICE_LOG("%d channels, %d Hz\n", fn->fc->channels,
- fn->fc->samplerate);
- }
- while (fn->loaded < fn->bufsize) {
- int length = fn->bufsize - fn->loaded;
- long read_ret = ov_read(pod->vf, fn->buf + fn->loaded, length,
- ENDIAN, 2 /* 16 bit */, 1 /* signed */, NULL);
- if (read_ret == OV_HOLE || !read_ret)
- return pod->converted;
- if (read_ret < 0)
- return -E_OGGDEC_BADLINK;
- fn->loaded += read_ret;
- }
- return pod->converted;
-}
-
-static void *oggdec_parse_config(int argc, char **argv)
-{
- int ret;
- struct oggdec_filter_args_info *ogg_conf;
-
- ogg_conf = para_calloc(sizeof(*ogg_conf));
- ret = oggdec_cmdline_parser(argc, argv, ogg_conf);
- if (ret)
- goto err;
- if (ogg_conf->bufsize_arg < 0)
- goto err;
- if (ogg_conf->bufsize_arg >= INT_MAX / 1024)
- goto err;
- if (ogg_conf->initial_buffer_arg < 0)
- goto err;
- if (ogg_conf->initial_buffer_arg >= INT_MAX / 1024)
- goto err;
- return ogg_conf;
-err:
- free(ogg_conf);
- return NULL;
-}
-
-/**
- * The init function of the ogg vorbis decoder.
- *
- * \param f Its fields are filled in by the function.
- */
-void oggdec_init(struct filter *f)
-{
- f->open = ogg_open;
- f->close = ogg_close;
- f->convert = ogg_convert;
- f->print_help = oggdec_cmdline_parser_print_help;
- f->parse_config = oggdec_parse_config;
-}
--- /dev/null
+/*
+ * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file oggdec_filter.c Paraslash's ogg vorbis decoder. */
+
+#include "para.h"
+
+#include "oggdec_filter.cmdline.h"
+#include "list.h"
+#include "sched.h"
+#include "filter.h"
+#include "error.h"
+#include "string.h"
+
+#include <vorbis/vorbisfile.h>
+
+/** Determine byte sex. */
+#ifdef WORDS_BIGENDIAN
+#define ENDIAN 1
+#else
+#define ENDIAN 0
+#endif
+
+/** Data specific to the oggdec filter. */
+struct private_oggdec_data {
+ /** Describes an ogg vorbis file. */
+ OggVorbis_File *vf;
+ /** The input buffer. */
+ char *inbuf;
+ /** The length of \a inbuf. */
+ size_t inbuf_len;
+ /** The number of bytes consumed from the input buffer. */
+ size_t converted;
+};
+
+static size_t cb_read(void *buf, size_t size, size_t nmemb, void *datasource)
+{
+ struct filter_node *fn = datasource;
+ struct private_oggdec_data *pod = fn->private_data;
+ size_t ret, have = pod->inbuf_len - pod->converted;
+ char *p = pod->inbuf + pod->converted;
+
+// PARA_DEBUG_LOG("pod = %p\n", pod);
+// PARA_DEBUG_LOG("vorbis requests %d bytes, have %d\n", size * nmemb, have);
+ if (pod->inbuf_len < size) {
+ if (*fn->fc->input_error)
+ return 0;
+ errno = EAGAIN;
+ return (size_t)-1;
+ }
+ ret = PARA_MIN(nmemb, have / size) * size;
+ memcpy(buf, p, ret);
+ pod->converted += ret;
+ return ret;
+}
+
+/*
+ * Custom data seeking function.
+ *
+ * Since we want the data source to be treated as unseekable at all
+ * times, the provided seek callback always returns -1 (failure).
+ */
+static int cb_seek(__a_unused void *datasource, __a_unused ogg_int64_t offset,
+ __a_unused int whence)
+{
+ return -1;
+}
+
+static int cb_close(__a_unused void *datasource)
+{
+ return 0;
+}
+
+static const ov_callbacks ovc = {
+ .read_func = cb_read,
+ .seek_func = cb_seek,
+ .close_func = cb_close,
+ /*
+ * The tell function need not be provided if the data IO abstraction is
+ * not seekable
+ */
+ .tell_func = NULL
+};
+
+static void ogg_open(struct filter_node *fn)
+{
+ struct private_oggdec_data *pod = para_calloc(
+ sizeof(struct private_oggdec_data));
+ struct oggdec_filter_args_info *conf = fn->conf;
+
+ fn->private_data = pod;
+ fn->bufsize = conf->bufsize_arg * 1024;
+ fn->buf = para_malloc(fn->bufsize);
+}
+
+static void ogg_close(struct filter_node *fn)
+{
+ struct private_oggdec_data *pod = fn->private_data;
+ if (pod->vf) {
+ PARA_DEBUG_LOG("ov_clearing %p, pod = %p\n", pod->vf, pod);
+ ov_clear(pod->vf);
+ free(pod->vf);
+ pod->vf = NULL;
+ } else
+ PARA_DEBUG_LOG("nothing to close in fc %p, pod = %p\n", pod->vf, pod);
+ free(fn->buf);
+ fn->buf = NULL;
+ free(fn->private_data);
+ fn->private_data = NULL;
+}
+
+static ssize_t ogg_convert(char *inbuffer, size_t len, struct filter_node *fn)
+{
+ ssize_t ret;
+ struct private_oggdec_data *pod = fn->private_data;
+ struct oggdec_filter_args_info *conf = fn->conf;
+ /* make the buffer known to the read callback cb_read() */
+ pod->inbuf = inbuffer;
+ pod->inbuf_len = len;
+ pod->converted = 0;
+
+ if (!pod->vf) {
+ int ib = 1024 * conf->initial_buffer_arg; /* initial buffer */
+ if (len <ib && !*fn->fc->input_error) {
+ PARA_DEBUG_LOG("initial input buffer %zd/%d, "
+ "waiting for more data\n", len, ib);
+ return 0;
+ }
+ pod->vf = para_malloc(sizeof(struct OggVorbis_File));
+ PARA_NOTICE_LOG("input buffer: %zd, opening ov callbacks\n", len);
+ ret = ov_open_callbacks(fn, pod->vf,
+ NULL, /* no initial buffer */
+ 0, /* no initial bytes */
+ ovc); /* the ov_open_callbacks */
+ if (ret == OV_EREAD)
+ return -E_OGGDEC_READ;
+ if (ret == OV_ENOTVORBIS)
+ return -E_OGGDEC_NOTVORBIS;
+ if (ret == OV_EVERSION)
+ return -E_OGGDEC_VERSION;
+ if (ret == OV_EBADHEADER)
+ return -E_OGGDEC_BADHEADER;
+ if (ret < 0)
+ return -E_OGGDEC_FAULT;
+ fn->fc->channels = ov_info(pod->vf, 0)->channels;
+ fn->fc->samplerate = ov_info(pod->vf, 0)->rate;
+ PARA_NOTICE_LOG("%d channels, %d Hz\n", fn->fc->channels,
+ fn->fc->samplerate);
+ }
+ while (fn->loaded < fn->bufsize) {
+ int length = fn->bufsize - fn->loaded;
+ long read_ret = ov_read(pod->vf, fn->buf + fn->loaded, length,
+ ENDIAN, 2 /* 16 bit */, 1 /* signed */, NULL);
+ if (read_ret == OV_HOLE || !read_ret)
+ return pod->converted;
+ if (read_ret < 0)
+ return -E_OGGDEC_BADLINK;
+ fn->loaded += read_ret;
+ }
+ return pod->converted;
+}
+
+static int oggdec_parse_config(int argc, char **argv, void **config)
+{
+ int ret;
+ struct oggdec_filter_args_info *ogg_conf;
+
+ ogg_conf = para_calloc(sizeof(*ogg_conf));
+ ret = -E_OGGDEC_SYNTAX;
+ if (oggdec_cmdline_parser(argc, argv, ogg_conf))
+ goto err;
+ ret = -ERRNO_TO_PARA_ERROR(EINVAL);
+ if (ogg_conf->bufsize_arg < 0)
+ goto err;
+ if (ogg_conf->bufsize_arg >= INT_MAX / 1024)
+ goto err;
+ if (ogg_conf->initial_buffer_arg < 0)
+ goto err;
+ if (ogg_conf->initial_buffer_arg >= INT_MAX / 1024)
+ goto err;
+ *config = ogg_conf;
+ return 1;
+err:
+ free(ogg_conf);
+ return ret;
+}
+
+/**
+ * The init function of the ogg vorbis decoder.
+ *
+ * \param f Its fields are filled in by the function.
+ */
+void oggdec_filter_init(struct filter *f)
+{
+ f->open = ogg_open;
+ f->close = ogg_close;
+ f->convert = ogg_convert;
+ f->print_help = oggdec_cmdline_parser_print_help;
+ f->parse_config = oggdec_parse_config;
+}
#include "rbtree.h"
#include "osl.h"
#include "string.h"
+#include "portable_io.h"
#include "hash.h"
/** Internal representation of a column of an osl table. */
* The gory details, listed by topic:
*
* - Audio format handlers: \ref send_common.c \ref mp3_afh.c, \ref ogg_afh.c, \ref aac_afh.c,
- * - Decoders: \ref mp3dec.c, \ref oggdec.c, \ref aacdec.c,
- * - Volume normalizer: \ref compress.c,
+ * - Decoders: \ref mp3dec_filter.c, \ref oggdec_filter.c, \ref aacdec_filter.c,
+ * - Volume normalizer: \ref compress_filter.c,
* - Output: \ref alsa_write.c, \ref osx_write.c,
* - http: \ref http_recv.c, \ref http_send.c,
* - ortp: \ref ortp_recv.c, \ref ortp_send.c,
+++ /dev/null
-/*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
-
-/** \file wav.c a filter that inserts a wave header */
-
-#include "para.h"
-
-#include "list.h"
-#include "sched.h"
-#include "filter.h"
-#include "string.h"
-
-/** size of the output buffer */
-#define WAV_OUTBUF_SIZE 81920
-/** a wav header is always 44 bytes */
-#define WAV_HEADER_LEN 44
-/** always write 16 bit header */
-#define BITS 16
-
-/**
- * write a 32 bit unsigned value to a buffer
- *
- * \param buf the buffer to write to
- * \param x the value to write
- */
-#define WRITE_U32(buf, x) (buf)[0] = (unsigned char)((x) & 0xff);\
- (buf)[1] = (unsigned char)(((x) >> 8) & 0xff);\
- (buf)[2] = (unsigned char)(((x) >> 16) & 0xff);\
- (buf)[3] = (unsigned char)(((x) >> 24) & 0xff);
-
-/**
- * write a 16 bit unsigned value to a buffer
- *
- * \param buf the buffer to write to
- * \param x the value to write
- */
-#define WRITE_U16(buf, x) (buf)[0] = (unsigned char)((x) & 0xff);
-
-static void make_wav_header(unsigned int channels, unsigned int samplerate,
- struct filter_node *fn)
-{
-
- char *headbuf = fn->buf;
- unsigned int size = 0x7fffffff;
- int bytespersec = channels * samplerate * BITS / 8;
- int align = channels * BITS / 8;
-
- assert(channels);
- PARA_DEBUG_LOG("writing wave header: %d channels, %d KHz\n", channels, samplerate);
- memset(headbuf, 0, WAV_HEADER_LEN);
- memcpy(headbuf, "RIFF", 4);
- WRITE_U32(headbuf + 4, size - 8);
- memcpy(headbuf + 8, "WAVE", 4);
- memcpy(headbuf + 12, "fmt ", 4);
- WRITE_U32(headbuf + 16, 16);
- WRITE_U16(headbuf + 20, 1); /* format */
- WRITE_U16(headbuf + 22, channels);
- WRITE_U32(headbuf + 24, samplerate);
- WRITE_U32(headbuf + 28, bytespersec);
- WRITE_U16(headbuf + 32, align);
- WRITE_U16(headbuf + 34, BITS);
- memcpy(headbuf + 36, "data", 4);
- WRITE_U32(headbuf + 40, size - 44);
-}
-
-static ssize_t wav_convert(char *inbuf, size_t len, struct filter_node *fn)
-{
- size_t copy;
- int *bof = fn->private_data;
-
- if (*bof) {
- if (!len)
- return 0;
- make_wav_header(fn->fc->channels, fn->fc->samplerate, fn);
- fn->loaded = WAV_HEADER_LEN;
- *bof = 0;
-// return 0;
- }
- copy = PARA_MIN(len, fn->bufsize - fn->loaded);
- memmove(fn->buf + fn->loaded, inbuf, copy);
- fn->loaded += copy;
-// PARA_DEBUG_LOG("len = %d, copy = %d\n", len, copy);
- return copy;
-}
-
-static void wav_close(struct filter_node *fn)
-{
- free(fn->buf);
- fn->buf = NULL;
- free(fn->private_data);
- fn->private_data = NULL;
-}
-
-static void wav_open(struct filter_node *fn)
-{
- int *bof;
-
- fn->bufsize = WAV_OUTBUF_SIZE;
- fn->buf = para_malloc(fn->bufsize);
- fn->private_data = para_malloc(sizeof(int));
- bof = fn->private_data;
- fn->loaded = 0;
- *bof = 1;
- PARA_INFO_LOG("wav filter node: %p, output buffer: %p, loaded: %zd\n",
- fn, fn->buf, fn->loaded);
-}
-
-/**
- * the init function of the wav filter
- *
- * \param f struct to initialize
- */
-void wav_init(struct filter *f)
-{
- f->convert = wav_convert;
- f->close = wav_close;
- f->open = wav_open;
-}
--- /dev/null
+/*
+ * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file wav_filter.c A filter that inserts a wave header. */
+
+#include "para.h"
+
+#include "list.h"
+#include "sched.h"
+#include "filter.h"
+#include "string.h"
+#include "portable_io.h"
+
+/** size of the output buffer */
+#define WAV_OUTBUF_SIZE 81920
+/** a wav header is always 44 bytes */
+#define WAV_HEADER_LEN 44
+/** always write 16 bit header */
+#define BITS 16
+
+static void make_wav_header(unsigned int channels, unsigned int samplerate,
+ struct filter_node *fn)
+{
+
+ char *headbuf = fn->buf;
+ unsigned int size = 0x7fffffff;
+ int bytespersec = channels * samplerate * BITS / 8;
+ int align = channels * BITS / 8;
+
+ assert(channels);
+ PARA_DEBUG_LOG("writing wave header: %d channels, %d KHz\n", channels, samplerate);
+ memset(headbuf, 0, WAV_HEADER_LEN);
+ memcpy(headbuf, "RIFF", 4);
+ write_u32(headbuf + 4, size - 8);
+ memcpy(headbuf + 8, "WAVE", 4);
+ memcpy(headbuf + 12, "fmt ", 4);
+ write_u32(headbuf + 16, 16);
+ write_u16(headbuf + 20, 1); /* format */
+ write_u16(headbuf + 22, channels);
+ write_u32(headbuf + 24, samplerate);
+ write_u32(headbuf + 28, bytespersec);
+ write_u16(headbuf + 32, align);
+ write_u16(headbuf + 34, BITS);
+ memcpy(headbuf + 36, "data", 4);
+ write_u32(headbuf + 40, size - 44);
+}
+
+static ssize_t wav_convert(char *inbuf, size_t len, struct filter_node *fn)
+{
+ size_t copy;
+ int *bof = fn->private_data;
+
+ if (*bof) {
+ if (!len)
+ return 0;
+ make_wav_header(fn->fc->channels, fn->fc->samplerate, fn);
+ fn->loaded = WAV_HEADER_LEN;
+ *bof = 0;
+// return 0;
+ }
+ copy = PARA_MIN(len, fn->bufsize - fn->loaded);
+ memmove(fn->buf + fn->loaded, inbuf, copy);
+ fn->loaded += copy;
+// PARA_DEBUG_LOG("len = %d, copy = %d\n", len, copy);
+ return copy;
+}
+
+static void wav_close(struct filter_node *fn)
+{
+ free(fn->buf);
+ fn->buf = NULL;
+ free(fn->private_data);
+ fn->private_data = NULL;
+}
+
+static void wav_open(struct filter_node *fn)
+{
+ int *bof;
+
+ fn->bufsize = WAV_OUTBUF_SIZE;
+ fn->buf = para_malloc(fn->bufsize);
+ fn->private_data = para_malloc(sizeof(int));
+ bof = fn->private_data;
+ fn->loaded = 0;
+ *bof = 1;
+ PARA_INFO_LOG("wav filter node: %p, output buffer: %p, loaded: %zd\n",
+ fn, fn->buf, fn->loaded);
+}
+
+/**
+ * the init function of the wav filter
+ *
+ * \param f struct to initialize
+ */
+void wav_filter_init(struct filter *f)
+{
+ f->convert = wav_convert;
+ f->close = wav_close;
+ f->open = wav_open;
+}