}
static const char * const aac_suffixes[] = {"m4a", "mp4", NULL};
+
/**
- * the init function of the aac audio format handler
+ * The audio format handler for the Advanced Audio Codec.
*
- * \param afh pointer to the struct to initialize
+ * This is only compiled in if the faad library is installed.
*/
-void aac_afh_init(struct audio_format_handler *afh)
-{
- afh->get_file_info = aac_get_file_info,
- afh->suffixes = aac_suffixes;
- afh->rewrite_tags = aac_afh_rewrite_tags;
- afh->open = aac_afh_open;
- afh->get_chunk = aac_afh_get_chunk;
- afh->close = aac_afh_close;
-}
+const struct audio_format_handler aac_afh = {
+ .get_file_info = aac_get_file_info,
+ .suffixes = aac_suffixes,
+ .rewrite_tags = aac_afh_rewrite_tags,
+ .open = aac_afh_open,
+ .get_chunk = aac_afh_get_chunk,
+ .close = aac_afh_close,
+};
loglevel = OPT_UINT32_VAL(LOGLEVEL);
version_handle_flag("afh", OPT_GIVEN(VERSION));
handle_help_flags();
- afh_init();
for (i = 0; i < lls_num_inputs(lpr); i++) {
int ret2;
const char *path = lls_input(i, lpr);
* in the other part of this struct.
*/
struct audio_format_handler {
- /**
- * Pointer to the audio format handler's init function.
- *
- * Must initialize all function pointers and is assumed to succeed.
- */
- void (*init)(struct audio_format_handler*);
/** Typical file endings for files that can be handled by this afh. */
const char * const *suffixes;
/**
int output_fd, const char *filename);
};
-void afh_init(void);
int guess_audio_format(const char *name);
int compute_afhi(const char *path, char *data, size_t size,
int fd, struct afh_info *afhi);
#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));
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;
*/
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);
/** See \ref recv_init(). */
const struct receiver lsg_recv_cmd_com_afh_user_data = {
- .init = afh_init,
.open = afh_recv_open,
.close = afh_recv_close,
.pre_select = afh_recv_pre_select,
static const char * const flac_suffixes[] = {"flac", NULL};
/**
- * The init function of the flac audio format handler.
+ * The audio format handler for flac (free lossless audio decoder).
*
- * \param afh pointer to the struct to initialize
+ * It depends on libflac and on libogg.
*/
-void flac_afh_init(struct audio_format_handler *afh)
-{
- afh->get_file_info = flac_get_file_info,
- afh->suffixes = flac_suffixes;
- afh->rewrite_tags = flac_rewrite_tags;
-}
+const struct audio_format_handler flac_afh = {
+ .get_file_info = flac_get_file_info,
+ .suffixes = flac_suffixes,
+ .rewrite_tags = flac_rewrite_tags,
+};
static const char * const mp3_suffixes[] = {"mp3", NULL};
/**
- * the init function of the mp3 audio format handler
+ * The mp3 audio format handler.
*
- * \param afh pointer to the struct to initialize
+ * It does not depend on any libraries and is hence always compiled in.
*/
-void mp3_afh_init(struct audio_format_handler *afh)
-{
- afh->get_file_info = mp3_get_file_info;
- afh->suffixes = mp3_suffixes;
+const struct audio_format_handler mp3_afh = {
+ .get_file_info = mp3_get_file_info,
+ .suffixes = mp3_suffixes,
#ifdef HAVE_LIBID3TAG
- afh->rewrite_tags = mp3_rewrite_tags;
+ .rewrite_tags = mp3_rewrite_tags,
#endif /* HAVE_LIBID3TAG */
-}
+};
static const char * const ogg_suffixes[] = {"ogg", NULL};
/**
- * The init function of the ogg vorbis audio format handler.
+ * The ogg vorbis audio format handler.
*
- * \param afh Pointer to the struct to initialize.
+ * It should actually be called vorbis because the ogg container format is also
+ * employed for the speex and flac codecs. Both the ogg and the vorbis
+ * libraries must be installed to get this audio format handler.
*/
-void ogg_afh_init(struct audio_format_handler *afh)
-{
- afh->get_file_info = ogg_vorbis_get_file_info;
- afh->get_header = vorbis_get_header;
- afh->suffixes = ogg_suffixes;
- afh->rewrite_tags = vorbis_rewrite_tags;
-}
+const struct audio_format_handler ogg_afh = {
+ .get_file_info = ogg_vorbis_get_file_info,
+ .get_header = vorbis_get_header,
+ .suffixes = ogg_suffixes,
+ .rewrite_tags = vorbis_rewrite_tags
+};
}
/**
- * The init function of the ogg/opus audio format handler.
+ * The audio format handler for ogg/opus.
*
- * \param afh Pointer to the struct to initialize.
+ * The opus codec was standardized by the Internet Engineering Task Force and
+ * is described in RFC 6716 (2012). The audio format handler depends on the ogg
+ * and the opus libraries.
*/
-void opus_afh_init(struct audio_format_handler *afh)
-{
- afh->get_file_info = opus_get_file_info,
- afh->get_header = opus_get_header;
- afh->suffixes = opus_suffixes;
- afh->rewrite_tags = opus_rewrite_tags;
-}
+const struct audio_format_handler opus_afh = {
+ .get_file_info = opus_get_file_info,
+ .get_header = opus_get_header,
+ .suffixes = opus_suffixes,
+ .rewrite_tags = opus_rewrite_tags,
+};
sched.default_timeout.tv_sec = 5;
parse_config_or_die(argc, argv);
- AFH_RECV->init();
session_open();
num_inputs = lls_num_inputs(play_lpr);
init_shuffle_map();
init_ipc_or_die(); /* init mmd struct, mmd and log mutex */
daemon_set_start_time();
daemon_set_hooks(pre_log_hook, post_log_hook);
- PARA_NOTICE_LOG("initializing audio format handlers\n");
- afh_init();
-
/*
* Although afs uses its own signal handling we must ignore SIGUSR1
* _before_ the afs child process gets born by init_afs() below. It's
static const char * const speex_suffixes[] = {"spx", "speex", NULL};
/**
- * The init function of the ogg/speex audio format handler.
+ * The ogg/speex audio format handler.
*
- * \param afh Pointer to the struct to initialize.
+ * This codec is considered obsolete because the opus codec surpasses its
+ * performance in all areas. It is only compiled in if both the ogg and the
+ * speex library are installed.
*/
-void spx_afh_init(struct audio_format_handler *afh)
-{
- afh->get_file_info = spx_get_file_info,
- afh->suffixes = speex_suffixes;
- afh->rewrite_tags = spx_rewrite_tags;
-}
+const struct audio_format_handler spx_afh = {
+ .get_file_info = spx_get_file_info,
+ .suffixes = speex_suffixes,
+ .rewrite_tags = spx_rewrite_tags,
+};
static const char * const wma_suffixes[] = {"wma", NULL};
/**
- * The init function of the wma audio format handler.
+ * The audio format handler for Windows Media Audio.
*
- * \param afh Pointer to the struct to initialize.
+ * Only WMA version 2 is supported. This audio format handler does not depend
+ * on any third party libraries and is therefore always compiled in.
*/
-void wma_afh_init(struct audio_format_handler *afh)
-{
- afh->get_file_info = wma_get_file_info;
- afh->suffixes = wma_suffixes;
- afh->rewrite_tags = wma_rewrite_tags;
-}
+const struct audio_format_handler wma_afh = {
+ .get_file_info = wma_get_file_info,
+ .suffixes = wma_suffixes,
+ .rewrite_tags = wma_rewrite_tags,
+};