]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
Merge branch 'refs/heads/t/openssl-header-check'
authorAndre Noll <maan@tuebingen.mpg.de>
Sat, 2 Nov 2019 15:43:59 +0000 (16:43 +0100)
committerAndre Noll <maan@tuebingen.mpg.de>
Sat, 2 Nov 2019 15:46:49 +0000 (16:46 +0100)
* refs/heads/t/openssl-header-check:
  build: Check also for CRYPTO_cleanup_all_ex_data.
  build: Detect openssl library/header mismatch.

Two simple fixes for FreeBSD. Tested on 12.0-RELEASE-p10.

Cooking for nine months.

36 files changed:
Makefile.real
NEWS.md
aac_afh.c
afh.c
afh.h
afh_common.c
afh_recv.c
aft.c
audiod.c
command.c
compress_filter.c
dccp_recv.c
error.h
flac_afh.c
http_recv.c
interactive.c
ipc.c
m4/lls/afh.suite.m4
m4/lls/filter_cmd.suite.m4
m4/lls/makefile
m4/lls/server_cmd.suite.m4
mixer.c
mp3_afh.c
ogg_afh.c
opus_afh.c
play.c
recv.c
recv.h
recv_common.c
send.h
server.c
spx_afh.c
string.c
t/makefile.test
udp_recv.c
wma_afh.c

index 5df27bad934a58f04b4b6407e868e8898ded4002..7d4eff4fe2eaecc99fb83627a154b9c1672118ca 100644 (file)
@@ -6,6 +6,8 @@ MAKEFLAGS += -Rr
 ifeq ("$(origin CC)", "default")
         CC := cc
 endif
+.ONESHELL:
+.SHELLFLAGS := -ec
 
 LOGLEVELS := LL_DEBUG,LL_INFO,LL_NOTICE,LL_WARNING,LL_ERROR,LL_CRIT,LL_EMERG
 vardir := /var/paraslash
@@ -102,7 +104,7 @@ endif
 
 $(object_dir) $(man_dir) $(dep_dir) $(m4depdir) $(lls_suite_dir) \
        $(yy_build_dir):
-       $(Q) $(MKDIR_P) $@
+       @$(MKDIR_P) $@
 
 CPPFLAGS += -DBINDIR='"$(bindir)"'
 CPPFLAGS += -DCOPYRIGHT_YEAR='"$(COPYRIGHT_YEAR)"'
@@ -148,9 +150,9 @@ STRICT_CFLAGS += $(call cc-option, -Wdiscarded-qualifiers)
 # To put more focus on warnings, be less verbose as default
 # Use 'make V=1' to see the full commands
 ifeq ("$(origin V)", "command line")
-       Q :=
+       SAY =
 else
-       Q := @
+       SAY = @echo '$(strip $(1))'
 endif
 
 audiod_commands := $(addprefix $(lls_suite_dir)/, \
@@ -177,9 +179,9 @@ $(man_dir)/para_write.1: all_commands := $(write_commands)
 
 $(man_dir)/para_%.1: $(lls_suite_dir)/%.lsg.man \
                $(lls_m4_dir)/copyright.m4 | $(man_dir)
-       @[ -z "$(Q)" ] || echo 'LLSMAN $<'
-       $(Q) cat $< $(all_commands) > $@
-       $(Q) $(M4) -D COPYRIGHT_YEAR=$(COPYRIGHT_YEAR) $(lls_m4_dir)/copyright.m4 >> $@
+       $(call SAY, LLSMAN $<)
+       cat $< $(all_commands) > $@
+       $(M4) -D COPYRIGHT_YEAR=$(COPYRIGHT_YEAR) $(lls_m4_dir)/copyright.m4 >> $@
 
 $(object_dir)/%.o: %.c | $(object_dir)
 
@@ -247,8 +249,8 @@ $(object_dir)/mm.o \
 $(object_dir)/compress_filter.o: CFLAGS += -O3
 
 $(object_dir)/%.o: %.c | $(object_dir) $(dep_dir) $(lsg_h) $(yy_h)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ -MMD -MF $(dep_dir)/$(*F).d -MT $@ $(CPPFLAGS) \
+       $(call SAY, CC $<)
+       $(CC) -c -o $@ -MMD -MF $(dep_dir)/$(*F).d -MT $@ $(CPPFLAGS) \
                $(STRICT_CFLAGS) $(CFLAGS) $<
 
 para_recv para_afh para_play para_server: LDFLAGS += $(id3tag_ldflags)
@@ -313,24 +315,24 @@ para_afh para_recv para_server para_play: LDFLAGS += $(iconv_ldflags)
 
 $(foreach exe,$(executables),$(eval para_$(exe): $$($(exe)_objs)))
 $(prefixed_executables):
-       @[ -z "$(Q)" ] || echo 'LD $@'
-       $(Q) $(CC) $^ -o $@ $(LDFLAGS)
+       $(call SAY, LD $@)
+       $(CC) $^ -o $@ $(LDFLAGS)
 
 mostlyclean:
-       @[ -z "$(Q)" ] || echo 'MOSTLYCLEAN'
-       $(Q) rm -f para_*
-       $(Q) rm -rf $(object_dir)
+       $(call SAY, MOSTLYCLEAN)
+       rm -f para_*
+       rm -rf $(object_dir)
 clean: mostlyclean
-       @[ -z "$(Q)" ] || echo 'CLEAN'
-       $(Q) rm -rf $(build_dir)
+       $(call SAY, CLEAN)
+       rm -rf $(build_dir)
 distclean: clean
-       @[ -z "$(Q)" ] || echo 'DISTCLEAN'
-       $(Q) rm -f Makefile autoscan.log config.status config.log
-       $(Q) rm -f config.h configure config.h.in
+       $(call SAY, DISTCLEAN)
+       rm -f Makefile autoscan.log config.status config.log
+       rm -f config.h configure config.h.in
 maintainer-clean: distclean
-       @[ -z "$(Q)" ] || echo 'MAINTAINER-CLEAN'
-       $(Q) rm -f *.tar.bz2 *.tar.xz
-       $(Q) rm -f GPATH GRTAGS GSYMS GTAGS
+       $(call SAY, MAINTAINER-CLEAN)
+       rm -f *.tar.bz2 *.tar.xz
+       rm -f GPATH GRTAGS GSYMS GTAGS
 
 INSTALL ?= install
 INSTALL_PROGRAM ?= $(INSTALL)
@@ -346,14 +348,15 @@ install install-strip: all man
        $(MKDIR_P) $(DESTDIR)$(vardir) >/dev/null 2>&1 || true # not fatal, so don't complain
 
 $(tarball) dist tarball:
-       $(Q) rm -rf $(tarball) $(tarball_pfx)
-       $(Q) git archive --format=tar --prefix=$(tarball_pfx)/ HEAD \
-               | tar --delete $(tarball_delete) > $(tarball_pfx).tar
-       $(Q) $(MKDIR_P) $(tarball_pfx)
-       $(Q) ./GIT-VERSION-GEN > $(tarball_pfx)/VERSION
-       $(Q) cp $(autocrap) $(tarball_pfx)
-       $(Q) tar rf $(tarball_pfx).tar $(tarball_pfx)/*
-       $(Q) xz -9 $(tarball_pfx).tar
-       $(Q) ls -l $(tarball)
-       $(Q) ln -sf $(tarball) paraslash-git.tar.xz
-       $(Q) rm -rf $(tarball_pfx)
+       $(call SAY, DIST)
+       rm -rf $(tarball) $(tarball_pfx)
+       git archive --format=tar --prefix=$(tarball_pfx)/ HEAD \
+          | tar --delete $(tarball_delete) > $(tarball_pfx).tar
+       $(MKDIR_P) $(tarball_pfx)
+       ./GIT-VERSION-GEN > $(tarball_pfx)/VERSION
+       cp $(autocrap) $(tarball_pfx)
+       tar rf $(tarball_pfx).tar $(tarball_pfx)/*
+       xz -9 $(tarball_pfx).tar
+       ls -l $(tarball)
+       ln -sf $(tarball) paraslash-git.tar.xz
+       rm -rf $(tarball_pfx)
diff --git a/NEWS.md b/NEWS.md
index 55ef3be947ee76d6b0937b33988b0cd960c0e985..eda654a6a155e2f4c484bfa3013d7edc7d278aec 100644 (file)
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,6 +1,26 @@
 NEWS
 ====
 
+----------------------------------------------
+0.6.3 (to be announced) "generalized activity"
+----------------------------------------------
+
+- The ff command now accepts a negative argument to instruct the
+  virtual streaming system to jump backwards in the current audio
+  stream. The old syntax (e.g., "ff 30-") is still supported but it
+  is deprecated and no longer documented. The compatibility code is
+  sheduled for removal after 0.7.0.
+- para_afh: New option: --preserve to reset the modification time to
+  the value of the original file after meta data modification.
+- Overhaul of the compress filter code. The refined algorithm should
+  reduce clipping. The meaning of --aggressiveness has changed, see the
+  updated and extended documentation of the compress filter for details.
+- Cleanup of the audio format handler code.
+- We now build the tree using the .ONESHELL feature of GNU make,
+  which results in a significant speedup.
+- Two robustness fixes for FreeBSD.
+
+
 --------------------------------------
 0.6.2 (2018-06-30) "elastic diversity"
 --------------------------------------
index 3315a42d57a5ea9673be88b077daef1275ab49f6..7f2a22a223ce733aa4b49d0a60ff63d1b95bf321 100644 (file)
--- a/aac_afh.c
+++ b/aac_afh.c
@@ -333,17 +333,17 @@ close:
 }
 
 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,
+};
diff --git a/afh.c b/afh.c
index aa6570e1abc33bfe38e9ce87bf87316707263473..567b560a038f0923a663005b447a0fc688c57b2a 100644 (file)
--- a/afh.c
+++ b/afh.c
@@ -113,6 +113,24 @@ static int rewrite_tags(const char *name, int input_fd, void *map,
                        goto out;
        }
        ret = xrename(tmp_name, name);
+       if (ret < 0)
+               goto out;
+       if (OPT_GIVEN(PRESERVE)) {
+               struct timespec times[2]; /* [0]: atime, [1]: mtime */
+               times[0].tv_nsec = UTIME_OMIT;
+               times[1] = sb.st_mtim;
+               /*
+                * We might well have written a file of identical size. If we
+                * keep the mtime as well, we might fool backup applications
+                * like rsync which skip files whose size and mtime haven't
+                * changed. So we change the mtime slightly.
+                */
+               times[1].tv_sec++;
+               if (futimens(output_fd, times) < 0) {
+                       ret = -ERRNO_TO_PARA_ERROR(errno);
+                       goto out;
+               }
+       }
 out:
        if (ret < 0 && output_fd >= 0)
                unlink(tmp_name); /* ignore errors */
@@ -203,7 +221,6 @@ int main(int argc, char **argv)
        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);
diff --git a/afh.h b/afh.h
index d2ac93aec96f95a0ca0bf706327f831520145ee7..881db3c24217beff8d2885e1d62c05f3419aa404 100644 (file)
--- a/afh.h
+++ b/afh.h
@@ -80,14 +80,6 @@ struct audio_file_data {
  * in the other part of this struct.
  */
 struct audio_format_handler {
-       /** Name of the audio format. */
-       const char *name;
-       /**
-        * 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;
        /**
@@ -135,7 +127,6 @@ struct audio_format_handler {
                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);
index bab4d41577952f257ef8c828f9c89c8886a7d2e5..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};
 
 /**
- * The list of supported audio formats.
+ * For each audio file the number of its audio format is stored in the
+ * database. Therefore this list, in particular its order, is part of the ABI.
+ * So it's only OK to append new audio formats. All audio formats are listed
+ * here, regardless of whether the audio format handler is compiled in.
+ */
+#define ALL_AUDIO_FORMATS \
+       AUDIO_FORMAT(mp3) \
+       AUDIO_FORMAT(ogg) \
+       AUDIO_FORMAT(aac) \
+       AUDIO_FORMAT(wma) \
+       AUDIO_FORMAT(spx) \
+       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
+/* 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.
  *
- * 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 these numbers to become
- * stale just because the user installed a new version of paraslash that
- * supports a different set of audio formats.
+ * \param i The audio format number.
  *
- * It can still be easily detected whether an audio format is compiled in by
- * checking if the init function pointer is not \p NULL.
+ * \return This returns a pointer to statically allocated memory so it
+ * must not be freed by the caller.
  */
-static struct audio_format_handler afl[] = {
-       {
-               .name = "mp3",
-               .init = mp3_afh_init,
-       },
-       {
-               .name = "ogg",
-#if defined(HAVE_OGG) && defined(HAVE_VORBIS)
-               .init = ogg_afh_init,
-#endif
-       },
-       {
-               .name = "aac",
-#if defined(HAVE_FAAD)
-               .init = aac_afh_init,
-#endif
-       },
-       {
-               .name = "wma",
-               .init = wma_afh_init,
-       },
-       {
-               .name = "spx",
-#if defined(HAVE_OGG) && defined(HAVE_SPEEX)
-               .init = spx_afh_init,
-#endif
-       },
-       {
-               .name = "flac",
-#if defined(HAVE_OGG) && defined(HAVE_FLAC)
-               .init = flac_afh_init,
-#endif
-       },
-       {
-               .name = "opus",
-#if defined(HAVE_OGG) && defined(HAVE_OPUS)
-               .init = opus_afh_init,
-#endif
-       },
-       {
-               .name = NULL,
-       }
-};
+const char *audio_format_name(int i)
+{
+       if (i < 0 || i >= NUM_AUDIO_FORMATS)
+               return "???";
+       return audio_format_names[i];
+}
 
 static inline int next_audio_format(int format)
 {
        for (;;) {
-               if (!afl[format].name)
-                       return format;
                format++;
-               if (afl[format].init)
+               if (format >= NUM_AUDIO_FORMATS)
+                       return format;
+               if (afl[format]->get_file_info)
                        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))
-
-/**
- * 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]);
-       }
-}
+#define FOR_EACH_AUDIO_FORMAT(i) \
+       for (i = 0; i < NUM_AUDIO_FORMATS; i = next_audio_format(i))
 
 /**
  * Tell whether an audio format handler provides chunk tables.
@@ -127,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;
 }
 
 /**
@@ -144,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;
@@ -160,21 +121,6 @@ int guess_audio_format(const char *name)
        return -E_AUDIO_FORMAT;
 }
 
-/**
- * Get the name of the given audio format.
- *
- * \param i The audio format number.
- *
- * \return This returns a pointer to statically allocated memory so it
- * must not be freed by the caller.
- */
-const char *audio_format_name(int i)
-{
-       if (i < 0 || i >= ARRAY_SIZE(afl) - 1)
-               return "???";
-       return afl[i].name;
-}
-
 static int get_file_info(int format, const char *path, char *data,
                size_t size, int fd, struct afh_info *afhi)
 {
@@ -182,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));
@@ -303,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;
@@ -313,7 +259,7 @@ __must_check int afh_get_chunk(long unsigned chunk_num, struct afh_info *afhi,
                        if (ret < 0)
                                return ret;
                }
-               ret = afl[audio_format_id].get_chunk(chunk_num, *afh_context,
+               ret = afh->get_chunk(chunk_num, *afh_context,
                        buf, len);
                if (ret < 0) {
                        afh->close(*afh_context);
@@ -340,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;
@@ -403,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;
@@ -426,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);
@@ -530,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);
index 6525209bff4119a177eb443f154b4f1f5224845b..4f8ff4974f018ef92e5055ac7a28bf337e3aa301 100644 (file)
@@ -238,9 +238,7 @@ out:
        return ret;
 }
 
-/** 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,
diff --git a/aft.c b/aft.c
index 0db2c5803dfa4c100b092f9c022759f1b85e043b..c04d4f9c99e89afb451afe94be7fcc64461b15e1 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -396,7 +396,7 @@ static void save_chunk_table(struct afh_info *afhi, char *buf)
 {
        uint32_t n;
 
-       if (!afhi->chunk_table)
+       if (!afhi->chunk_table || afhi->chunks_total == 0)
                return;
        for (n = 0; n <= afhi->chunks_total; n++)
                write_u32(buf + 4 * n, afhi->chunk_table[n]);
index b93f29de4498c50f574e55c4c8b3e9a34dfe0aee..a5a774376b37c50eba92a76a02b1389bd6df67f4 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -1451,7 +1451,6 @@ int main(int argc, char *argv[])
        parse_config_or_die();
        crypt_init();
        daemon_set_priority(OPT_UINT32_VAL(PRIORITY));
-       recv_init();
        if (daemon_init_colors_or_die(OPT_UINT32_VAL(COLOR), COLOR_AUTO,
                        COLOR_NO, OPT_GIVEN(LOGFILE))) {
                for (i = 0; i < OPT_GIVEN(LOG_COLOR); i++)
index 67f6bf3c713b5de3d542d96f63848cb0014326dc..481fd0f637352fb21ff97536d426ece42ec0fda3 100644 (file)
--- a/command.c
+++ b/command.c
@@ -663,8 +663,7 @@ EXPORT_SERVER_CMD_HANDLER(nomore);
 static int com_ff(struct command_context *cc, struct lls_parse_result *lpr)
 {
        long promille;
-       int ret, backwards = 0;
-       unsigned i;
+       int i, ret;
        char c, *errctx;
 
        ret = lls(lls_check_arg_count(lpr, 1, 1, &errctx));
@@ -672,20 +671,33 @@ static int com_ff(struct command_context *cc, struct lls_parse_result *lpr)
                send_errctx(cc, errctx);
                return ret;
        }
-       if (!(ret = sscanf(lls_input(0, lpr), "%u%c", &i, &c)))
-               return -E_COMMAND_SYNTAX;
-       if (ret > 1 && c == '-')
-               backwards = 1; /* jmp backwards */
+       ret = para_atoi32(lls_input(0, lpr), &i);
+       if (ret < 0) {
+               if (ret != -E_ATOI_JUNK_AT_END)
+                       return ret;
+               /*
+                * Compatibility code to keep the historic syntax (ff 30-)
+                * working. This can be removed after 0.7.0.
+                */
+               ret = sscanf(lls_input(0, lpr), "%i%c", &i, &c);
+               if (ret <= 0)
+                       return -E_COMMAND_SYNTAX;
+               if (ret > 1 && c == '-') {
+                       PARA_WARNING_LOG("use of obsolete syntax\n");
+                       i = -i;
+               }
+       }
        mutex_lock(mmd_mutex);
        ret = -E_NO_AUDIO_FILE;
        if (!mmd->afd.afhi.chunks_total || !mmd->afd.afhi.seconds_total)
                goto out;
        ret = 1;
        promille = (1000 * mmd->current_chunk) / mmd->afd.afhi.chunks_total;
-       if (backwards)
-               promille -= 1000 * i / mmd->afd.afhi.seconds_total;
-       else
-               promille += 1000 * i / mmd->afd.afhi.seconds_total;
+       /*
+        * We need this cast because without it the expression on the right
+        * hand side is of unsigned type.
+        */
+       promille += 1000 * i / (int)mmd->afd.afhi.seconds_total;
        if (promille < 0)
                promille = 0;
        if (promille > 1000) {
index 69a982ef5a3aff20a10fcebe468a1af5efd33ba4..15bed6dfa33c896421ab17a89ec426669cf4b025 100644 (file)
@@ -48,8 +48,7 @@ static int compress_post_select(__a_unused struct sched *s, void *context)
        size_t length, i;
        int16_t *ip, *op;
        uint32_t inertia = U32_OPTVAL(INERTIA, fn->lpr);
-       unsigned gain_shift = inertia + U32_OPTVAL(DAMP, fn->lpr),
-               mask = (1U << U32_OPTVAL(BLOCKSIZE, fn->lpr)) - 1U;
+       unsigned mask = (1U << U32_OPTVAL(BLOCKSIZE, fn->lpr)) - 1U;
        //inplace = false;
 next_buffer:
        ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL);
@@ -78,19 +77,22 @@ next_buffer:
                        neg = true;
                }
                sample *= pcd->current_gain;
-               sample >>= gain_shift;
+               sample >>= inertia + 1;
                if (sample > 32767) { /* clip */
+                       PARA_WARNING_LOG("clip: %d\n", sample);
                        sample = 32767;
                        pcd->current_gain = (3 * pcd->current_gain +
                                (1 << inertia)) / 4;
                        pcd->peak = 0;
                } else if (sample > pcd->peak)
                        pcd->peak = sample;
+               sample >>= U32_OPTVAL(DAMP, fn->lpr);
                op[i] = neg? -sample : sample;
                if (++pcd->num_samples & mask)
                        continue;
 //             PARA_DEBUG_LOG("gain: %u, peak: %u\n", pcd->current_gain,
 //                     pcd->peak);
+
                if (pcd->peak < U32_OPTVAL(TARGET_LEVEL, fn->lpr)) {
                        if (pcd->current_gain < pcd->max_gain)
                                pcd->current_gain++;
@@ -121,10 +123,43 @@ static void compress_open(struct filter_node *fn)
        fn->private_data = pcd;
        fn->min_iqs = 2; /* 16 bit audio */
        pcd->current_gain = 1U << inertia;
-       pcd->max_gain = 1U << (inertia + aggressiveness);
+       pcd->max_gain = (1U << inertia) * (1.0 + 3.0 * aggressiveness / 10.0);
+}
+
+static void *compress_setup(const struct lls_parse_result *lpr)
+{
+       uint32_t val;
+
+       val = U32_OPTVAL(BLOCKSIZE, lpr);
+       if (val == 0 || val > 31) {
+               PARA_EMERG_LOG("blocksize (%u) out of range\n", val);
+               exit(EXIT_FAILURE);
+       }
+       val = U32_OPTVAL(AGGRESSIVENESS, lpr);
+       if (val > 10) {
+               PARA_EMERG_LOG("aggressiveness (%u) out of range\n", val);
+               exit(EXIT_FAILURE);
+       }
+       val = U32_OPTVAL(INERTIA, lpr);
+       if (val == 0 || val > 14) {
+               PARA_EMERG_LOG("inertia (%u) out of range\n", val);
+               exit(EXIT_FAILURE);
+       }
+       val = U32_OPTVAL(TARGET_LEVEL, lpr);
+       if (val > 32767) {
+               PARA_EMERG_LOG("target-level (%u) out of range\n", val);
+               exit(EXIT_FAILURE);
+       }
+       val = U32_OPTVAL(DAMP, lpr);
+       if (val > 16) {
+               PARA_EMERG_LOG("damp (%u) out of range\n", val);
+               exit(EXIT_FAILURE);
+       }
+       return NULL; /* no need for a config structure */
 }
 
 const struct filter lsg_filter_cmd_com_compress_user_data = {
+       .setup = compress_setup,
        .open = compress_open,
        .close = compress_close,
        .pre_select = generic_filter_pre_select,
index 8a08504a8930de6a0f3f3a89969357eadf6a7c9f..639c93fcbf99bc93ddc054ad43d03f30811270ac 100644 (file)
@@ -151,7 +151,6 @@ out:
        return ret;
 }
 
-/** See \ref recv_init(). */
 const struct receiver lsg_recv_cmd_com_dccp_user_data = {
        .open = dccp_recv_open,
        .close = dccp_recv_close,
diff --git a/error.h b/error.h
index 8f4f9bb134027956fbd438cd102be3fe5d1bea7e..14e5b0726e11e92e80d9ddbcf346504c4b6199c3 100644 (file)
--- a/error.h
+++ b/error.h
@@ -266,11 +266,10 @@ extern const char * const para_errlist[];
  */
 #define SYSTEM_ERROR_BIT 30
 
-/**
- * Like the SYSTEM_ERROR_BIT, but indicates an error from the osl library.
- */
+/** Like SYSTEM_ERROR_BIT, but for errors from the osl library. */
 #define OSL_ERROR_BIT 29
 
+/** Like SYSTEM_ERROR_BIT, but for errors from the lopsub library. */
 #define LLS_ERROR_BIT 28
 
 /** Check whether the system error bit is set. */
index 45373ea1993d743ed56ded45444b3d8bb72fc751..6e23683937f6932aaa739095ef8281fc9075da55 100644 (file)
@@ -515,13 +515,12 @@ free_pfad:
 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,
+};
index 3a723299e78b241a9ac4f44a13caf91651f36b6a..1fb60bad810d86dbbb0098a3714c2caa3d9e835b 100644 (file)
@@ -167,7 +167,6 @@ static int http_recv_open(struct receiver_node *rn)
        return 1;
 }
 
-/** See \ref recv_init(). */
 const struct receiver lsg_recv_cmd_com_http_user_data = {
        .open = http_recv_open,
        .close = http_recv_close,
index 190cdf295130a2d711074e7c5f5927174b312076..a8197308e8323c8fe78546117cc2e9479df0fbfd 100644 (file)
@@ -762,17 +762,25 @@ int i9e_print_completions(struct i9e_completer *completers)
        ci.argc = create_argv(ci.buffer, " ", &ci.argv);
        ci.word_num = compute_word_num(ci.buffer, " ", ci.point);
 
+       /* determine the current word to complete */
        end = ci.buffer + ci.point;
+
+       if (*end == ' ') {
+               if (ci.point == 0 || ci.buffer[ci.point - 1] == ' ') {
+                       ci.word = para_strdup(NULL);
+                       goto create_matches;
+               } else /* The cursor is positioned right after a word */
+                       end--;
+       }
        for (p = end; p > ci.buffer && *p != ' '; p--)
                ; /* nothing */
        if (*p == ' ')
                p++;
-
        n = end - p + 1;
        ci.word = para_malloc(n + 1);
        strncpy(ci.word, p, n);
        ci.word[n] = '\0';
-
+create_matches:
        PARA_DEBUG_LOG("line: %s, point: %d (%c), wordnum: %d, word: %s\n",
                ci.buffer, ci.point, ci.buffer[ci.point], ci.word_num, ci.word);
        if (ci.word_num == 0)
diff --git a/ipc.c b/ipc.c
index 85013a636cb3a7f634d190d9044808454274efd8..8e9dd51a2369e7e60ebd4bda3fa889eaed892248 100644 (file)
--- a/ipc.c
+++ b/ipc.c
@@ -7,7 +7,6 @@
 #include "ipc.h"
 #include <sys/types.h>
 #include <sys/param.h>
-#include <sys/sysctl.h>
 
 #include <sys/ipc.h>
 #include <sys/shm.h>
@@ -194,9 +193,8 @@ int shm_detach(void *addr)
 }
 
 # if defined __FreeBSD__ || defined __NetBSD__
+#include <sys/sysctl.h>
 #      define SYSCTL_SHMMAX_VARIABLE "kern.ipc.shmmax"
-# elif defined __APPLE__
-#      define SYSCTL_SHMMAX_VARIABLE "kern.sysv.shmmax"
 # else
 #      undef SYSCTL_SHMMAX_VARIABLE
 # endif
index cf83b9724d824079e720c1d1a357962c9cd6872a..7ebf208c01552e7b17bfd7a5fff37b6f90051c58 100644 (file)
@@ -62,6 +62,12 @@ version-string = GIT_VERSION()
                        The backup suffix is '~'. That is, a single tilde character is appended
                        to the given file name.
                [/help]
+       [option preserve]
+               summary = preserve modification time
+               [help]
+                       If this option is given, the mtime of the modified file is set to
+                       the value prior to the modification.
+               [/help]
        [option year]
                short_opt = y
                summary = set the year tag
index d269d2374176adef783ca1f78ee0ac4832eb86da..c026a628acdda4adfdbf276ac8c5ca8d527e0d24 100644 (file)
@@ -25,7 +25,7 @@ caption = filters
        purpose = dynamically adjust the volume of an audio stream
        [option blocksize]
                short_opt = b
-               summary = use blocks of size 2**bits
+               summary = adjust volume after each block of size 2**bits (1-31)
                typestr = bits
                arg_info = required_arg
                arg_type = uint32
@@ -35,32 +35,52 @@ caption = filters
                [/help]
        [option aggressiveness]
                short_opt = a
-               summary = controls the maximum amount to amplify by
+               summary = controls the maximum amount to amplify by (0-10)
                typestr = bits
                arg_info = required_arg
                arg_type = uint32
                default_val = 4
+               [help]
+                       This controls the maximal gain factor. Zero means to not amplify
+                       at all while the value 10 corresponds to maximal gain factor which
+                       results in a 4-fold increase in volume.
+               [/help]
        [option inertia]
                short_opt = i
-               summary = how much inertia ramping has
+               summary = how much inertia ramping has (1-14)
                typestr = bits
                arg_info = required_arg
                arg_type = uint32
                default_val = 6
+               [help]
+                       Larger values cause smaller volume adjustments.
+               [/help]
        [option target-level]
                short_opt = t
-               summary = target signal level (0-32768)
+               summary = target signal level (0-32767)
                typestr = level
                arg_info = required_arg
                arg_type = uint32
-               default_val = 20000
+               default_val = 16384
+               [help]
+                       If the peak of the previous block is less than the target level,
+                       volume is increased slightly for the next block. Otherwise it is
+                       decreased. The default value is chosen to minimize clipping. There
+                       is usually no reason to change it.
+               [/help]
        [option damp]
                short_opt = d
-               summary = if non-zero, scale down after normalizing
+               summary = if non-zero, scale down after normalizing (0-16)
                typestr = bits
                arg_info = required_arg
                arg_type = uint32
                default_val = 0
+               [help]
+                       This scales down the volume of the audio stream by factor 2**bits.
+                       This is mostly useful if another audio application (e.g., a video
+                       game) is running in parallel and the relative volume of the audio
+                       stream is too high.
+               [/help]
 [subcommand fecdec]
        purpose = decode a (lossy) input stream using forward error correction
 [subcommand flacdec]
index dd86b51def8cfbeff487def5d883e3a88e0f9078..daf6de92525d334d3c1791e4d0b53907ddd7fb7f 100644 (file)
@@ -2,29 +2,29 @@
 lls_m4_include_dir := $(lls_m4_dir)/include
 
 $(lls_suite_dir)/%.m4d: $(lls_m4_dir)/%.suite.m4 | $(lls_suite_dir)
-       @[ -z "$(Q)" ] || echo 'M4D $<'
-       $(Q) $(M4) -Pg -I $(lls_m4_include_dir) -s $< \
+       $(call SAY, M4D $<)
+       $(M4) -Pg -I $(lls_m4_include_dir) -s $< \
        | awk '{if ($$1 ~ /#line/) {gsub(/"/, "", $$3); if ($$3 != "$<") \
        print "$(lls_suite_dir)/$(*F).suite: " $$3}}' | sort | uniq > $@
 
 $(lls_suite_dir)/%.suite: $(lls_m4_dir)/%.suite.m4 | $(lls_suite_dir)
-       @[ -z "$(Q)" ] || echo 'M4 $<'
-       $(Q) $(M4) -Pg -I $(lls_m4_include_dir) -D GIT_VERSION=$(GIT_VERSION) \
+       $(call SAY, M4 $<)
+       $(M4) -Pg -I $(lls_m4_include_dir) -D GIT_VERSION=$(GIT_VERSION) \
                -D COPYRIGHT_YEAR=$(COPYRIGHT_YEAR) -D LOGLEVELS=$(LOGLEVELS) \
                $< > $@
 
 $(lls_suite_dir)/%.lsg.c: $(lls_suite_dir)/%.suite
-       @[ -z "$(Q)" ] || echo 'LSGC $<'
-       $(Q) $(LOPSUBGEN) --gen-c --output-dir $(lls_suite_dir) < $<
+       $(call SAY, LSGC $<)
+       $(LOPSUBGEN) --gen-c --output-dir $(lls_suite_dir) < $<
 
 $(lls_suite_dir)/%.lsg.h: $(lls_suite_dir)/%.suite
-       @[ -z "$(Q)" ] || echo 'LSGH $<'
-       $(Q) $(LOPSUBGEN) --gen-header --output-dir $(lls_suite_dir) < $<
+       $(call SAY, LSGH $<)
+       $(LOPSUBGEN) --gen-header --output-dir $(lls_suite_dir) < $<
 
 $(lls_suite_dir)/%.lsg.man: $(lls_suite_dir)/%.suite
-       @[ -z "$(Q)" ] || echo 'LSGM $<'
-       $(Q) $(LOPSUBGEN) --gen-man --output-dir $(lls_suite_dir) < $<
+       $(call SAY, LSGM $<)
+       $(LOPSUBGEN) --gen-man --output-dir $(lls_suite_dir) < $<
 
 $(object_dir)/%.o: $(lls_suite_dir)/%.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(STRICT_CFLAGS) $<
+       $(call SAY, CC $<)
+       $(CC) -c -o $@ $(CPPFLAGS) $(STRICT_CFLAGS) $<
index 079589d1f36eee98fb9a0c1252906b5d9b1e43a4..2a39907cee624219d1fb166b07dbf84288f67bb4 100644 (file)
@@ -124,18 +124,18 @@ aux_info_prefix = Permissions:
                summary = enable verbose mode
 
 [subcommand ff]
-       purpose = jump N seconds forward or backward
-       synopsis = n[-]
+       purpose = jump forward or backward in the current audio file
+       synopsis = seconds
        aux_info = VSS_READ | VSS_WRITE
        [description]
-               This sets the 'R' (reposition request) bit of the vss status flags
-               which enqueues a request to jump n seconds forwards or backwards.
-
-               Example:
-
-                    para_client ff 30-
-
-               jumps 30 seconds backwards.
+               This enqueues a request to reposition the audio stream according to
+               the argument, which may be a signed or an unsigned integer. Negative
+               values correspond to backward jumps.
+
+               If a negative number is given whose absolute value exceeds the current
+               postition of the stream, a jump to the beginning of the audio file
+               is performed. If a positive amount of seconds is given which exceeds
+               the remaining time of the audio file, the next audio file is loaded.
 
        [/description]
 
diff --git a/mixer.c b/mixer.c
index d84f6d4e3358ecf2e309fcaaaea692e2e590abc8..efa42b93efb9ce0cf6f277b0f117806845455a26 100644 (file)
--- a/mixer.c
+++ b/mixer.c
@@ -313,7 +313,6 @@ static int com_sleep(const struct mixer *m, struct mixer_handle *h)
                client_cmd("stop");
        if (!fit || !fi_mood) /* nothing to do */
                return 1;
-       change_afs_mode(fi_mood);
        for (;;) {
                time(&t1);
                if (wake_time_epoch <= t1 + fit)
@@ -324,7 +323,11 @@ static int com_sleep(const struct mixer *m, struct mixer_handle *h)
                        (delay % 3600) / 60);
                sleep(delay);
        }
-       client_cmd("play");
+       change_afs_mode(fi_mood);
+       if (sleep_mood) /* currently playing */
+               client_cmd("next");
+       else /* currently stopped */
+               client_cmd("play");
        ret = fade(m, h, fiv, fit);
        PARA_INFO_LOG("fade complete, returning\n");
        return ret;
index 471efd99db36634e1db33763be94ef70c4ae6de4..6ed73c2aaa2e068ee404dea1d16fec8183ee5237 100644 (file)
--- a/mp3_afh.c
+++ b/mp3_afh.c
@@ -683,15 +683,14 @@ static int mp3_get_file_info(char *map, size_t numbytes, int fd,
 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 */
-}
+};
index 93ad14bbf9c0b5cbade554fbf22103ef460956fa..5da339fe162ecec96d21cfa05fbde48b51f2a307 100644 (file)
--- a/ogg_afh.c
+++ b/ogg_afh.c
@@ -173,14 +173,15 @@ static int vorbis_rewrite_tags(const char *map, size_t mapsize,
 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
+};
index ed6fe5c80625487d6d6cc852a349650f4cd80ad8..dca6cfbad1ce3ff8cdf6d820b01bf33bf9a02110 100644 (file)
@@ -291,14 +291,15 @@ static void opus_get_header(void *map, size_t mapsize, char **buf,
 }
 
 /**
- * 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,
+};
diff --git a/play.c b/play.c
index 647367a396b2d96368931af790c45dd4f188b7c1..86edc4d4e4f47bc1bd38197ed5982e97df9f72cf 100644 (file)
--- a/play.c
+++ b/play.c
@@ -1238,12 +1238,8 @@ int main(int argc, char *argv[])
        int ret;
        unsigned num_inputs;
 
-       /* needed this early to make help work */
-       recv_init();
-
        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();
diff --git a/recv.c b/recv.c
index 7b46d78cac4602b1032508818c710fbcd2b0cc98..10d55d218071ccf6a314fc87d4e5f78001012db4 100644 (file)
--- a/recv.c
+++ b/recv.c
@@ -79,7 +79,6 @@ int main(int argc, char *argv[])
        loglevel = OPT_UINT32_VAL(LOGLEVEL, lpr);
        version_handle_flag("recv", OPT_GIVEN(VERSION, lpr));
        handle_help_flag(lpr);
-       recv_init();
        memset(&rn, 0, sizeof(struct receiver_node));
        ret = check_receiver_arg(OPT_STRING_VAL(RECEIVER, lpr), &receiver_lpr);
        if (ret < 0)
diff --git a/recv.h b/recv.h
index f88ebd84897a89df5b748ab86acb399c37917e0a..36b0f1db62e348c9ab7ccdfc3b32ba656d698c5f 100644 (file)
--- a/recv.h
+++ b/recv.h
@@ -39,12 +39,6 @@ struct receiver_node {
  * \sa \ref http_recv.c, \ref udp_recv.c.
  */
 struct receiver {
-       /**
-        * The optional receiver init function.
-        *
-        * Performs any initialization needed before the receiver can be opened.
-        */
-       void (*init)(void);
        /**
         * Open one instance of the receiver.
         *
@@ -114,7 +108,6 @@ struct receiver {
 /** Iterate over all available receivers. */
 #define FOR_EACH_RECEIVER(i) for (i = 1; lls_cmd(i, recv_cmd_suite); i++)
 
-void recv_init(void);
 int check_receiver_arg(const char *ra, struct lls_parse_result **lprp);
 void print_receiver_helps(bool detailed);
 int generic_recv_pre_select(struct sched *s, struct receiver_node *rn);
index 948de4745dda8c62bce88f31ec8362650ae85de0..31fd81f1ec52c3d0b6204e8b3663a7d36e14fbb3 100644 (file)
 #include "recv.h"
 #include "string.h"
 
-/**
- * Call the init function of each paraslash receiver.
- *
- * Receivers employ the user_data feature of the lopsub library: Each receiver
- * of the recv_cmd suite defines a struct receiver as its user data.
- * recv_init() obtains a pointer to this structure by calling lls_user_data().
- * If the receiver has an init function (i.e., if ->init is not NULL), ->init()
- * is called to initialize the receiver.
- */
-void recv_init(void)
-{
-       int i;
-
-       FOR_EACH_RECEIVER(i) {
-               const struct lls_command *cmd = RECV_CMD(i);
-               const struct receiver *r = lls_user_data(cmd);
-               if (r && r->init)
-                       r->init();
-       }
-}
-
 /**
  * Check if the given string is a valid receiver specifier.
  *
diff --git a/send.h b/send.h
index 67b47e48d9e7fd0b96fa4c5c7abd95594c6e2cf0..8f7005cdaa78f0909808932e602fc7de7945dd52 100644 (file)
--- a/send.h
+++ b/send.h
@@ -2,6 +2,10 @@
 
 /** \file send.h Sender-related defines and structures. */
 
+/**
+ * A little preprocessor fu helps to create the sender_subcommand enumeration
+ * below and the list of sender name strings without duplicating the commands.
+ */
 #define SENDER_SUBCOMMANDS \
        SENDER_SUBCOMMAND(add) /**< Add a target (udp only). */ \
        SENDER_SUBCOMMAND(delete) /**< Delete a target (udp only). */ \
        SENDER_SUBCOMMAND(on) /**< Activate the sender. */ \
        SENDER_SUBCOMMAND(off) /**< Deactivate the sender. */ \
 
+/** Concatenate "SENDER_" and the given arg and append a comma. */
 #define SENDER_SUBCOMMAND(_name) SENDER_ ## _name,
+
+/**
+ * Each sender subcommand gets an SENDER_xxx identifier. The identifier is
+ * passed from the sender command handler to the server process via shared
+ * memory.
+ */
 enum sender_subcommand {
-       SENDER_SUBCOMMANDS
+       SENDER_SUBCOMMANDS /**< List of SENDER_xxx identifiers. */
        NUM_SENDER_CMDS /**< Used as array size in struct \ref sender. */
 };
+
 #undef SENDER_SUBCOMMAND
+
+/**
+ * Redefine it to expand to the stringified name of the sender so that
+ * SENDER_SUBCOMMANDS above now expands to the comma-separated list of sender
+ * name strings. This is used in command.c to define and initialize an array of
+ * char pointers.
+ */
 #define SENDER_SUBCOMMAND(_name) #_name,
 
 /**
index 6370cefd086d8351f91e25c411142ba8fea4f65a..e0d50f4f8689e1de283ef80f8341504bcf386d33 100644 (file)
--- a/server.c
+++ b/server.c
@@ -583,9 +583,6 @@ static void server_init(int argc, char **argv, struct server_command_task *sct)
        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
index e23236470a3efdafb01b1179e49817f79427f40f..caeacb1921341b04b26f117d5de6607a80ab95e9 100644 (file)
--- a/spx_afh.c
+++ b/spx_afh.c
@@ -248,13 +248,14 @@ static int spx_rewrite_tags(const char *map, size_t mapsize,
 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,
+};
index 65d2240891afc81f40e6b964d5c0f6b7b25a0ddc..198e9f1d286ee2228638a2a7994fe9e65f41ccac 100644 (file)
--- a/string.c
+++ b/string.c
@@ -199,17 +199,22 @@ __must_check __printf_1_2 __malloc char *make_message(const char *fmt, ...)
 }
 
 /**
- * Free the content of a pointer and set it to \p NULL.
+ * Free the content of a pointer and set it to NULL.
  *
- * This is equivalent to "free(*arg); *arg = NULL;".
+ * \param arg A pointer to the pointer whose content should be freed.
  *
- * \param arg The pointer whose content should be freed.
+ * If arg is NULL, the function returns immediately. Otherwise it frees the
+ * memory pointed to by *arg and sets *arg to NULL. Hence callers have to pass
+ * the *address* of the pointer variable that points to the memory which should
+ * be freed.
  */
 void freep(void *arg)
 {
-       void **ptr = (void **)arg;
-       free(*ptr);
-       *ptr = NULL;
+       if (arg) {
+               void **ptr = arg;
+               free(*ptr);
+               *ptr = NULL;
+       }
 }
 
 /**
index a71963c9bbda192f047f144e970d92dcfd764a77..904c779353bbd5e08dfab8e449e607dead8a622c 100644 (file)
@@ -22,10 +22,11 @@ check: $(tests)
 test: $(tests)
 
 $(tests): all
-       $(Q) $@ $(test_options)
+       $(call SAY, $(@))
+       $@ $(test_options)
 
 test-help:
-       $(Q) for t in $(tests); do $$t $(test_options) -h; done
+       @for t in $(tests); do $$t $(test_options) -h; done
 
 test-clean:
        $(RM) -r $(results_dir)
index 67846b141926e80baba083edda9177fa8b3b6acf..58d45ab43d6508619d34186b3f4a23f6d455ecc7 100644 (file)
@@ -186,7 +186,6 @@ err:
        return ret;
 }
 
-/** See \ref recv_init(). */
 const struct receiver lsg_recv_cmd_com_udp_user_data = {
        .open = udp_recv_open,
        .close = udp_recv_close,
index e6048a868710e1e1b62213fda895d1dfc90a2bd1..63e49677b0f1b85c13c17160a7b249531c1fbcd4 100644 (file)
--- a/wma_afh.c
+++ b/wma_afh.c
@@ -646,13 +646,13 @@ out:
 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,
+};