#include "string.h"
#include "afh.h"
-typedef void afh_init_func(struct audio_format_handler *);
-
-/*
- * Declaration of the audio format handler init functions.
- *
- * These symbols are referenced in the afl array below.
- *
- * Most audio format handlers depend on an external library and are not
- * compiled in if the library is not installed. Hence it is well possible that
- * not all of these functions are defined. It does not hurt to declare them
- * anyway, and this avoids another set of ifdefs.
- */
-extern afh_init_func mp3_afh_init, ogg_afh_init, aac_afh_init, wma_afh_init,
- spx_afh_init, flac_afh_init, opus_afh_init;
-
/** The list of all status items */
const char *status_item_list[] = {STATUS_ITEMS};
AUDIO_FORMAT(flac) \
AUDIO_FORMAT(opus) \
+/** \cond audio_format_handler */
#define AUDIO_FORMAT(_fmt) #_fmt,
static const char * const audio_format_names[] = {ALL_AUDIO_FORMATS};
#undef AUDIO_FORMAT
-
-/*
- * It can be detected whether an audio format is compiled in by checking if the
- * init function pointer is NULL.
- */
-static struct audio_format_handler afl[] = {
- {
- .init = mp3_afh_init,
- },
- {
-#if defined(HAVE_OGG) && defined(HAVE_VORBIS)
- .init = ogg_afh_init,
-#endif
- },
- {
-#if defined(HAVE_FAAD)
- .init = aac_afh_init,
-#endif
- },
- {
- .init = wma_afh_init,
- },
- {
-#if defined(HAVE_OGG) && defined(HAVE_SPEEX)
- .init = spx_afh_init,
-#endif
- },
- {
-#if defined(HAVE_OGG) && defined(HAVE_FLAC)
- .init = flac_afh_init,
-#endif
- },
- {
-#if defined(HAVE_OGG) && defined(HAVE_OPUS)
- .init = opus_afh_init,
-#endif
- },
-};
-
-/** This includes audio formats not compiled in. */
+/* Weak declarations must be public. */
+#define AUDIO_FORMAT(_fmt) \
+ struct audio_format_handler _fmt ## _afh __attribute__ ((weak)) \
+ = {.get_file_info = NULL};
+ALL_AUDIO_FORMATS
+#undef AUDIO_FORMAT
+#define AUDIO_FORMAT(_fmt) & _fmt ## _afh,
+static struct audio_format_handler *afl[] = {ALL_AUDIO_FORMATS};
+#undef AUDIO_FORMAT
#define NUM_AUDIO_FORMATS (ARRAY_SIZE(afl))
+/** \endcond audio_format_handler */
/**
* Get the name of the given audio format.
format++;
if (format >= NUM_AUDIO_FORMATS)
return format;
- if (afl[format].init)
+ if (afl[format]->get_file_info)
return format;
}
}
#define FOR_EACH_AUDIO_FORMAT(i) \
for (i = 0; i < NUM_AUDIO_FORMATS; i = next_audio_format(i))
-/**
- * Call the init function of each supported audio format handler.
- */
-void afh_init(void)
-{
- int i;
-
- PARA_NOTICE_LOG("supported audio formats: %s\n", AUDIO_FORMAT_HANDLERS);
- FOR_EACH_AUDIO_FORMAT(i) {
- PARA_INFO_LOG("initializing %s handler\n",
- audio_format_name(i));
- afl[i].init(&afl[i]);
- }
-}
-
/**
* Tell whether an audio format handler provides chunk tables.
*
*/
bool afh_supports_dynamic_chunks(int audio_format_id)
{
- return afl[audio_format_id].get_chunk;
+ return afl[audio_format_id]->get_chunk;
}
/**
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];
+ for (j = 0; afl[i]->suffixes[j]; j++) {
+ const char *p = afl[i]->suffixes[j];
int plen = strlen(p);
if (len < plen + 1)
continue;
const char *fmt = audio_format_name(format);
memset(afhi, 0, sizeof(*afhi));
- ret = afl[format].get_file_info(data, size, fd, afhi);
+ ret = afl[format]->get_file_info(data, size, fd, afhi);
if (ret < 0) {
PARA_WARNING_LOG("%s: %s format not detected: %s\n",
path, fmt, para_strerror(-ret));
free(afhi->tags.comment);
}
-static inline size_t get_chunk_len(long unsigned chunk_num,
+static inline uint32_t get_chunk_len(long unsigned chunk_num,
const struct afh_info *afhi)
{
return afhi->chunk_table[chunk_num + 1] - afhi->chunk_table[chunk_num];
*/
__must_check int afh_get_chunk(long unsigned chunk_num, struct afh_info *afhi,
uint8_t audio_format_id, const void *map, size_t mapsize,
- const char **buf, size_t *len, void **afh_context)
+ const char **buf, uint32_t *len, void **afh_context)
{
- struct audio_format_handler *afh = afl + audio_format_id;
+ struct audio_format_handler *afh = afl[audio_format_id];
if (afh_supports_dynamic_chunks(audio_format_id)) {
int ret;
*/
void afh_close(void *afh_context, uint8_t audio_format_id)
{
- struct audio_format_handler *afh = afl + audio_format_id;
+ struct audio_format_handler *afh = afl[audio_format_id];
if (!afh_supports_dynamic_chunks(audio_format_id))
return;
void afh_get_header(struct afh_info *afhi, uint8_t audio_format_id,
void *map, size_t mapsize, char **buf, size_t *len)
{
- struct audio_format_handler *afh = afl + audio_format_id;
+ struct audio_format_handler *afh = afl[audio_format_id];
if (!map || !afhi || !afhi->header_len) {
*buf = NULL;
*/
void afh_free_header(char *header_buf, uint8_t audio_format_id)
{
- struct audio_format_handler *afh = afl + audio_format_id;
+ struct audio_format_handler *afh = afl[audio_format_id];
if (afh->get_header)
free(header_buf);
int afh_rewrite_tags(int audio_format_id, void *map, size_t mapsize,
struct taginfo *tags, int output_fd, const char *filename)
{
- struct audio_format_handler *afh = afl + audio_format_id;
+ struct audio_format_handler *afh = afl[audio_format_id];
if (!afh->rewrite_tags)
return -ERRNO_TO_PARA_ERROR(ENOTSUP);