From: Andre Noll Date: Tue, 23 Oct 2007 16:19:59 +0000 (+0200) Subject: Add missing afh_common.c. X-Git-Tag: v0.3.0~245 X-Git-Url: http://git.tue.mpg.de/?a=commitdiff_plain;h=f445bae93b0e609ac241c1fa3c9c16569ac7cb85;p=paraslash.git Add missing afh_common.c. dooh, it's easy to miss including an essential file. --- diff --git a/afh_common.c b/afh_common.c new file mode 100644 index 00000000..13bcd0d3 --- /dev/null +++ b/afh_common.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 1997-2007 Andre Noll + * + * Licensed under the GPL v2. For licencing details see COPYING. + */ +/* \file afh_common.c: Common audio format handler functions. */ + +#include /* mmap */ +#include /* gettimeofday */ +#include +#include + +#include "para.h" +#include "error.h" +#include "string.h" +#include "afh.h" + +/* The mp3 audio format handler does not need any libs. */ +void mp3_init(struct audio_format_handler *); + +#ifdef HAVE_OGGVORBIS + void ogg_init(struct audio_format_handler *); +#endif +#ifdef HAVE_FAAD + void aac_afh_init(struct audio_format_handler *); +#endif + +/** + * The list of supported audio formats. + * + * We always define the full array of audio formats even if some audio formats + * were not compiled in. This is because for each audio file the number of its + * audio format is stored in the database. We don't want that numbers to become + * stale just because the user installed a new version of paraslash that + * supports a different set of audio formats. + * + * It can still be easily detected whether an audio format is compiled in by + * checking if the init function pointer is not \p NULL. + */ +static struct audio_format_handler afl[] = { + { + .name = "mp3", + .init = mp3_init, + }, + { + .name = "ogg", +#ifdef HAVE_OGGVORBIS + .init = ogg_init, +#endif + }, + { + .name = "aac", +#ifdef HAVE_FAAD + .init = aac_afh_init, +#endif + }, + { + .name = NULL, + } +}; + +static inline int next_audio_format(int format) +{ + for (;;) { + if (!afl[format].name) + return format; + format++; + if (afl[format].init) + return format; + } + +} + +/** Iterate over each supported audio format. */ +#define FOR_EACH_AUDIO_FORMAT(i) for (i = 0; afl[i].name; i = next_audio_format(i)) + +void afh_init(void) +{ + int i; + + PARA_DEBUG_LOG("supported audio formats: %s\n", + SUPPORTED_AUDIO_FORMATS); + FOR_EACH_AUDIO_FORMAT(i) { + PARA_NOTICE_LOG("initializing %s handler\n", + audio_format_name(i)); + afl[i].init(&afl[i]); + } +} + + +/** + * guess the audio format judging from filename + * + * \param name the filename + * + * \return This function returns -1 if it has no idea what kind of audio + * file this might be. Otherwise the (non-negative) number of the audio format + * is returned. + */ +int guess_audio_format(const char *name) +{ + int i,j, len = strlen(name); + + FOR_EACH_AUDIO_FORMAT(i) { + for (j = 0; afl[i].suffixes[j]; j++) { + const char *p = afl[i].suffixes[j]; + int plen = strlen(p); + if (len < plen + 1) + continue; + if (name[len - plen - 1] != '.') + continue; + if (strcasecmp(name + len - plen, p)) + continue; +// PARA_DEBUG_LOG("might be %s\n", audio_format_name(i)); + return i; + } + } + return -E_BAD_AUDIO_FILE_SUFFIX; +} + +/** + * Call get_file_info() to obtain an afhi structure. + * + * \param path The full path of the audio file. + * \param data Pointer to the contents of the (mapped) file. + * \param size The file size in bytes. + * \param afhi Result pointer. + * + * \return The number of the audio format on success, \p -E_AUDIO_FORMAT if no + * compiled in audio format handler is able to handler the file. + * + * This function tries to find an audio format handler that can interpret the + * file given by \a data and \a size. + * + * It first tries to determine the audio format from the filename given by \a + * path. If this doesn't work, all other audio format handlers are tried until + * one is found that can handle the file. + */ +int compute_afhi(const char *path, char *data, size_t size, + struct audio_format_info *afhi) +{ + int ret, i, format = guess_audio_format(path); + + if (format >= 0) { + ret = afl[format].get_file_info(data, size, afhi); + if (ret >= 0) + return format; + } + FOR_EACH_AUDIO_FORMAT(i) { + if (i == format) /* we already tried this one to no avail */ + continue; + ret = afl[i].get_file_info(data, size, afhi); + if (ret >= 0) + return i; + PARA_WARNING_LOG("%s\n", PARA_STRERROR(-ret)); + } + return -E_AUDIO_FORMAT; +} + +/** + * Get the name of the given audio format. + * + * \param i The audio format number. + * + * This returns a pointer to statically allocated memory so it + * must not be freed by the caller. + */ +const char *audio_format_name(int i) +{ + //PARA_NOTICE_LOG("array size: %u¸ requested: %d\n", ARRAY_SIZE(afl), i); + assert(i < 0 || i < ARRAY_SIZE(afl) - 1); + return i >= 0? afl[i].name : "(none)"; +} +