]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - afh_common.c
afh: Constify definition of audio format handlers.
[paraslash.git] / afh_common.c
index fb4759a518c07a0d733c32422fe386c1af0cd6af..a267f58b106b9f0df09d3a8dad99368c3c519401 100644 (file)
 #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};
 
@@ -44,50 +29,21 @@ 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.
@@ -110,7 +66,7 @@ static inline int next_audio_format(int format)
                format++;
                if (format >= NUM_AUDIO_FORMATS)
                        return format;
-               if (afl[format].init)
+               if (afl[format]->get_file_info)
                        return format;
        }
 }
@@ -119,21 +75,6 @@ static inline int next_audio_format(int 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.
  *
@@ -147,7 +88,7 @@ void afh_init(void)
  */
 bool afh_supports_dynamic_chunks(int audio_format_id)
 {
-       return afl[audio_format_id].get_chunk;
+       return afl[audio_format_id]->get_chunk;
 }
 
 /**
@@ -164,8 +105,8 @@ 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];
+               for (j = 0; afl[i]->suffixes[j]; j++) {
+                       const char *p = afl[i]->suffixes[j];
                        int plen = strlen(p);
                        if (len < plen + 1)
                                continue;
@@ -187,7 +128,7 @@ static int get_file_info(int format, const char *path, char *data,
        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));
@@ -308,7 +249,7 @@ __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)
 {
-       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;
@@ -345,7 +286,7 @@ __must_check int afh_get_chunk(long unsigned chunk_num, struct afh_info *afhi,
  */
 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;
@@ -408,7 +349,7 @@ int32_t afh_get_start_chunk(int32_t approx_chunk_num,
 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;
@@ -431,7 +372,7 @@ void afh_get_header(struct afh_info *afhi, uint8_t audio_format_id,
  */
 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);
@@ -535,7 +476,7 @@ void set_max_chunk_size(struct afh_info *afhi)
 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);