From: Andre Noll Date: Wed, 8 May 2024 17:48:44 +0000 (+0200) Subject: Merge topic branch t/btr into next X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=refs%2Fheads%2Fnext;hp=9b6c71b05beb750da78bea312b8b9347d8fda21f Merge topic branch t/btr into next Some helpers such as btr_get_input_queue_size() are very expensive if the buffer tree contains many buffers, which is the case for mp3 and aac streams. This is noticeable in particular with para_play, which spends more time in the btr subsystem than in the mp3 decoder if the file is large enough. This branch contains a few patches to improve that. * refs/heads/t/btr: btr: Streamline the documentation of buffer_tree.h. Constify buffer tree API. btr: Merge buffers on insertion. btr: Speed up btr_node_status(). Speed up mp3dec filter. --- diff --git a/Makefile.in b/Makefile.in index c618561d..396c8de6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -12,21 +12,26 @@ FLEX := @FLEX@ BISON := @BISON@ M4 := @M4@ LOPSUBGEN := @LOPSUBGEN@ +CRYPTOLIB := @CRYPTOLIB@ -executables := @executables@ +NEED_OGG_OBJECTS := @NEED_OGG_OBJECTS@ +NEED_VORBIS_OBJECTS := @NEED_VORBIS_OBJECTS@ +NEED_SPEEX_OBJECTS := @NEED_SPEEX_OBJECTS@ +NEED_OPUS_OBJECTS := @NEED_OPUS_OBJECTS@ +NEED_FLAC_OBJECTS := @NEED_FLAC_OBJECTS@ +NEED_AO_OBJECTS := @NEED_AO_OBJECTS@ -recv_objs := @recv_objs@ -filter_objs := @filter_objs@ -client_objs := @client_objs@ -gui_objs := @gui_objs@ -audiod_objs := @audiod_objs@ -audioc_objs := @audioc_objs@ -mixer_objs := @mixer_objs@ -server_objs := @server_objs@ -upgrade_db_objs := @upgrade_db_objs@ -write_objs := @write_objs@ -afh_objs := @afh_objs@ -play_objs := @play_objs@ +HAVE_OSL := @HAVE_OSL@ +HAVE_FAAD := @HAVE_FAAD@ +HAVE_READLINE := @HAVE_READLINE@ +HAVE_FLAC := @HAVE_FLAC@ +HAVE_MAD := @HAVE_MAD@ +HAVE_SAMPLERATE := @HAVE_SAMPLERATE@ +HAVE_AO := @HAVE_AO@ +HAVE_PTHREAD := @HAVE_PTHREAD@ +HAVE_OSS := @HAVE_OSS@ +HAVE_ALSA := @HAVE_ALSA@ +HAVE_CURSES := @HAVE_CURSES@ speex_cppflags := @speex_cppflags@ opus_cppflags := @opus_cppflags@ diff --git a/Makefile.real b/Makefile.real index bd2bd9d9..92a5724b 100644 --- a/Makefile.real +++ b/Makefile.real @@ -14,7 +14,6 @@ SEVERITIES := \"debug\",\"info\",\"notice\",\"warning\",\"error\",\"crit\",\"eme vardir := /var/paraslash mandir := $(datarootdir)/man/man1 MKDIR_P := mkdir -p -prefixed_executables := $(addprefix para_, $(executables)) build_date := $(shell date) uname_s := $(shell uname -s 2>/dev/null || echo "UNKNOWN_OS") @@ -35,15 +34,263 @@ m4depdir := $(build_dir)/m4deps lls_suite_dir := $(build_dir)/lls lls_m4_dir := m4/lls test_dir := t -yy_src_dir = yy -yy_build_dir = $(build_dir)/yy +yy_src_dir := yy +yy_build_dir := $(build_dir)/yy + +executables := recv filter audioc write afh play +ifneq ($(CRYPTOLIB),) + ifeq ($(HAVE_OSL),yes) + executables += server upgrade_db + server_objs := $(addsuffix .o, \ + server afh_common mp3_afh vss command net string \ + signal time daemon http_send close_on_fork \ + crypt_common base64 ipc dccp_send fd user_list \ + chunk_queue afs aft mood mp score attribute blob \ + playlist sched acl send_common udp_send color fec \ + wma_afh wma_common sideband version lsu \ + ) + ifeq ($(CRYPTOLIB),openssl) + server_objs += openssl.o + else + server_objs += gcrypt.o + endif + ifeq ($(NEED_OGG_OBJECTS),yes) + server_objs += ogg_afh_common.o + endif + ifeq ($(NEED_VORBIS_OBJECTS),yes) + server_objs += ogg_afh.o + endif + ifeq ($(NEED_SPEEX_OBJECTS),yes) + server_objs += spx_afh.o spx_common.o + endif + ifeq ($(NEED_OPUS_OBJECTS),yes) + server_objs += opus_afh.o opus_common.o + endif + ifeq ($(NEED_FLAC_OBJECTS),yes) + server_objs += flac_afh.o + endif + ifeq ($(HAVE_FAAD),yes) + server_objs += aac_afh.o mp4.o + endif + upgrade_db_objs := $(addsuffix .o, crypt_common exec fd string \ + upgrade_db version base64) + endif +endif +ifneq ($(CRYPTOLIB),) + executables += client audiod + client_objs := $(addsuffix .o, \ + client net string fd lsu sched stdin stdout time sideband client_common \ + buffer_tree crypt_common base64 version $(CRYPTOLIB) \ + ) + ifeq ($(HAVE_READLINE),yes) + client_objs += interactive.o + endif + audiod_objs := $(addsuffix .o, \ + audiod signal string daemon stat net crypt_common base64 sideband \ + time grab_client filter_common wav_filter compress_filter amp_filter \ + http_recv dccp_recv recv_common fd sched write_common file_write \ + audiod_command fecdec_filter client_common udp_recv color fec \ + prebuffer_filter version bitstream imdct wma_common wmadec_filter \ + buffer_tree sync_filter lsu $(CRYPTOLIB) \ + ) + audiod_audio_formats := "wma" + ifeq ($(NEED_VORBIS_OBJECTS),yes) + audiod_objs += oggdec_filter.o + audiod_audio_formats += ,"ogg" + endif + ifeq ($(NEED_SPEEX_OBJECTS),yes) + audiod_objs += spxdec_filter.o spx_common.o + audiod_audio_formats += ,"spx" + endif + ifeq ($(NEED_OPUS_OBJECTS),yes) + audiod_objs += opusdec_filter.o opus_common.o + audiod_audio_formats += ,"opus" + endif + ifeq ($(NEED_FLAC_OBJECTS),yes) + audiod_objs += flacdec_filter.o + audiod_audio_formats += ,"flac" + endif + ifeq ($(HAVE_FAAD),yes) + audiod_objs += aacdec_filter.o + audiod_audio_formats += ,"aac" + endif + ifeq ($(HAVE_MAD),yes) + audiod_objs += mp3dec_filter.o + audiod_audio_formats += ,"mp3" + endif + ifeq ($(HAVE_OSS),yes) + audiod_objs += oss_write.o + endif + ifeq ($(HAVE_ALSA),yes) + audiod_objs += alsa_write.o + endif + ifeq ($(NEED_AO_OBJECTS),yes) + audiod_objs += ao_write.o + endif + ifeq ($(HAVE_SAMPLERATE),yes) + audiod_objs += resample_filter.o check_wav.o + endif +endif +ifneq ($(HAVE_OSS)-$(HAVE_ALSA),no-no) + executables += mixer + mixer_objs := $(addsuffix .o, mixer exec string fd time lsu version) + ifeq ($(HAVE_OSS),yes) + mixer_objs += oss_mix.o + endif + ifeq ($(HAVE_ALSA),yes) + mixer_objs += alsa_mix.o + endif +endif +ifeq ($(HAVE_CURSES),yes) + executables += gui + gui_objs := $(addsuffix .o, exec signal string stat ringbuffer fd \ + gui gui_theme lsu time sched version) +endif +filter_objs := $(addsuffix .o, \ + filter_common wav_filter compress_filter filter string stdin stdout \ + sched fd amp_filter fecdec_filter fec lsu version prebuffer_filter \ + time bitstream imdct wma_common wmadec_filter buffer_tree net \ + sync_filter \ +) +ifeq ($(NEED_VORBIS_OBJECTS),yes) + filter_objs += oggdec_filter.o +endif +ifeq ($(NEED_SPEEX_OBJECTS),yes) + filter_objs += spxdec_filter.o spx_common.o +endif +ifeq ($(NEED_OPUS_OBJECTS),yes) + filter_objs += opusdec_filter.o opus_common.o +endif +ifeq ($(NEED_FLAC_OBJECTS),yes) + filter_objs += flacdec_filter.o +endif +ifeq ($(HAVE_FAAD),yes) + filter_objs += aacdec_filter.o +endif +ifeq ($(HAVE_MAD),yes) + filter_objs += mp3dec_filter.o +endif +ifeq ($(HAVE_SAMPLERATE),yes) + filter_objs += resample_filter.o check_wav.o +endif + +recv_objs := $(addsuffix .o, \ + http_recv recv_common recv time string net dccp_recv fd sched stdout \ + udp_recv buffer_tree afh_recv afh_common wma_afh wma_common mp3_afh \ + version \ +) +ifeq ($(NEED_OGG_OBJECTS),yes) + recv_objs += ogg_afh_common.o +endif +ifeq ($(NEED_VORBIS_OBJECTS),yes) + recv_objs += ogg_afh.o +endif +ifeq ($(NEED_SPEEX_OBJECTS),yes) + recv_objs += spx_afh.o spx_common.o +endif +ifeq ($(NEED_OPUS_OBJECTS),yes) + recv_objs += opus_afh.o opus_common.o +endif +ifeq ($(NEED_FLAC_OBJECTS),yes) + recv_objs += flac_afh.o +endif +ifeq ($(HAVE_FAAD),yes) + recv_objs += aac_afh.o mp4.o +endif + +audio_format_handlers := mp3 wma +afh_objs := $(addsuffix .o, afh string fd mp3_afh afh_common time wma_afh \ + wma_common version) +ifeq ($(NEED_OGG_OBJECTS),yes) + afh_objs += ogg_afh_common.o +endif +ifeq ($(NEED_VORBIS_OBJECTS),yes) + afh_objs += ogg_afh.o + audio_format_handlers += ogg +endif +ifeq ($(NEED_SPEEX_OBJECTS),yes) + afh_objs += spx_common.o + audio_format_handlers += spx +endif +ifeq ($(NEED_OPUS_OBJECTS),yes) + afh_objs += opus_afh.o opus_common.o + audio_format_handlers += opus +endif +ifeq ($(NEED_FLAC_OBJECTS),yes) + afh_objs += flac_afh.o + audio_format_handlers += flac +endif +ifeq ($(HAVE_FAAD),yes) + afh_objs += aac_afh.o mp4.o + audio_format_handlers += aac +endif + +play_objs := $(addsuffix .o, \ + play fd sched buffer_tree time string net afh_recv afh_common \ + wma_afh wma_common mp3_afh recv_common udp_recv http_recv dccp_recv \ + filter_common fec bitstream imdct wav_filter compress_filter \ + amp_filter prebuffer_filter fecdec_filter wmadec_filter write_common \ + file_write version sync_filter lsu \ +) +ifeq ($(NEED_OGG_OBJECTS),yes) + play_objs += ogg_afh_common.o +endif +ifeq ($(NEED_VORBIS_OBJECTS),yes) + play_objs += oggdec_filter.o ogg_afh.o +endif +ifeq ($(NEED_SPEEX_OBJECTS),yes) + play_objs += spxdec_filter.o spx_afh.o spx_common.o +endif +ifeq ($(NEED_OPUS_OBJECTS),yes) + play_objs += opusdec_filter.o opus_afh.o opus_common.o +endif +ifeq ($(NEED_FLAC_OBJECTS),yes) + play_objs += flacdec_filter.o flac_afh.o +endif +ifeq ($(HAVE_FAAD),yes) + play_objs += aac_afh.o aacdec_filter.o mp4.o +endif +ifeq ($(HAVE_MAD),yes) + play_objs += mp3dec_filter.o +endif +ifeq ($(HAVE_OSS),yes) + play_objs += oss_write.o +endif +ifeq ($(HAVE_ALSA),yes) + play_objs += alsa_write.o +endif +ifeq ($(NEED_AO_OBJECTS),yes) + play_objs += ao_write.o +endif +ifeq ($(HAVE_READLINE),yes) + play_objs += interactive.o +endif +ifeq ($(HAVE_SAMPLERATE),yes) + play_objs += resample_filter.o check_wav.o +endif + +write_objs := $(addsuffix .o, write write_common file_write time fd \ + string sched stdin buffer_tree check_wav version) +ifeq ($(NEED_AO_OBJECTS),yes) + write_objs += ao_write.o +endif +ifeq ($(HAVE_OSS),yes) + write_objs += oss_write.o +endif +ifeq ($(HAVE_ALSA),yes) + write_objs += alsa_write.o +endif + +audioc_objs := $(addsuffix .o, audioc string lsu net fd time version) +ifeq ($(HAVE_READLINE),yes) + audioc_objs += buffer_tree.o interactive.o sched.o +endif # sort removes duplicate words, which is all we need here -all_objs := $(sort $(recv_objs) $(filter_objs) $(client_objs) $(gui_objs) \ +dep_objs := $(sort $(recv_objs) $(filter_objs) $(client_objs) $(gui_objs) \ $(audiod_objs) $(audioc_objs) $(mixer_objs) $(server_objs) \ - $(write_objs) $(afh_objs) $(play_objs)) -deps := $(addprefix $(dep_dir)/, $(all_objs:.o=.d)) -deps += $(addprefix $(dep_dir)/, mp.bison.d mp.flex.d) + $(write_objs) $(afh_objs) $(play_objs) mp.bison mp.flex) +deps := $(addprefix $(dep_dir)/, $(dep_objs:.o=.d)) afh_objs += afh.lsg.o audioc_objs += audioc.lsg.o @@ -84,6 +331,7 @@ write_objs := $(addprefix $(object_dir)/, $(write_objs)) afh_objs := $(addprefix $(object_dir)/, $(afh_objs)) play_objs := $(addprefix $(object_dir)/, $(play_objs)) +prefixed_executables := $(addprefix para_, $(executables)) man_pages := $(patsubst %, $(man_dir)/%.1, $(prefixed_executables)) autocrap := config.h.in configure @@ -200,6 +448,10 @@ $(object_dir)/%.o: %.c | $(object_dir) OD = $(addsuffix .d, $(addprefix $(dep_dir)/, $(1))) \ $(addsuffix .o, $(addprefix $(object_dir)/, $(1))) +$(call OD, audiod): \ + CPPFLAGS += -DAUDIOD_AUDIO_FORMAT_ARRAY='$(audiod_audio_formats)' +$(call OD, afh command): \ + CPPFLAGS += -DAUDIO_FORMAT_HANDLERS='"$(audio_format_handlers)"' $(call OD, opus%): CPPFLAGS += $(opus_cppflags) $(call OD, gui gui%): CPPFLAGS += $(curses_cppflags) $(call OD, spx%): CPPFLAGS += $(speex_cppflags) diff --git a/NEWS.md b/NEWS.md index 4b718d8a..d5812289 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,9 +1,24 @@ NEWS ==== ----------------------------------------------- -0.7.3 (to be announced) "weighted correctness" ----------------------------------------------- +--------------------------------------------- +0.7.4 (to be announced) "genetic contraction" +--------------------------------------------- + +Downloads: +[tarball](./releases/paraslash-git.tar.xz) + +----------------------------------------- +0.7.3 (2024-03-12) "weighted correctness" +----------------------------------------- + +The highlight of this release is the new "ls --admissible=m/foo" +feature described below. Other user-visible changes include minor +additions to the "ls" and "select" server commands. The release also +includes a fair number of cleanups for the crypto code and the file +descriptor utilities, both without visible effects. Old ssh keys +and outdated openssl library versions are now deprecated and cause +warnings. - Old style PEM keys are now deprecated. They still work but their use results in a run-time warning. The removal of PEM key support is @@ -23,7 +38,8 @@ NEWS - Cleanup of the openssl-specific code. Downloads: -[tarball](./releases/paraslash-git.tar.xz) +[tarball](./releases/paraslash-0.7.3.tar.xz), +[signature](./releases/paraslash-0.7.3.tar.xz.asc) ------------------------------------- 0.7.2 (2023-03-08) "optical friction" diff --git a/aacdec_filter.c b/aacdec_filter.c index 87a7900a..ab07be8f 100644 --- a/aacdec_filter.c +++ b/aacdec_filter.c @@ -41,7 +41,8 @@ struct private_aacdec_data { unsigned int sample_rate; }; -static int aacdec_execute(struct btr_node *btrn, const char *cmd, char **result) +static int aacdec_execute(const struct btr_node *btrn, const char *cmd, + char **result) { struct filter_node *fn = btr_context(btrn); struct private_aacdec_data *padd = fn->private_data; diff --git a/afh_recv.c b/afh_recv.c index 8449e787..687b77d9 100644 --- a/afh_recv.c +++ b/afh_recv.c @@ -30,7 +30,7 @@ struct private_afh_recv_data { void *afh_context; }; -static int afh_execute(struct btr_node *btrn, const char *cmd, char **result) +static int afh_execute(const struct btr_node *btrn, const char *cmd, char **result) { struct receiver_node *rn = btr_context(btrn); struct private_afh_recv_data *pard = rn->private_data; diff --git a/audiod.c b/audiod.c index 7c223995..0fae454c 100644 --- a/audiod.c +++ b/audiod.c @@ -46,8 +46,9 @@ static struct lls_parse_result *lpr; #define OPT_UINT32_VAL(_name) (lls_uint32_val(0, OPT_RESULT(_name))) __printf_2_3 void (*para_log)(int, const char*, ...) = daemon_log; -/** define the array containing all supported audio formats */ -const char *audio_formats[] = {AUDIOD_AUDIO_FORMAT_ARRAY NULL}; +/* Audio formats supported by audiod */ +static const char *audio_formats[] = {AUDIOD_AUDIO_FORMAT_ARRAY}; +#define NUM_AUDIO_FORMATS ARRAY_SIZE(audio_formats) /** Defines how audiod handles one supported audio format. */ struct audio_format_info { diff --git a/audiod.h b/audiod.h index 39beda1b..d5a9da65 100644 --- a/audiod.h +++ b/audiod.h @@ -2,13 +2,6 @@ /** \file audiod.h Symbols exported from audiod.c. */ - -/** enum of audio formats supported by para_audiod */ -enum {AUDIOD_AUDIO_FORMATS_ENUM}; - -/** array of audio format names supported by para_audiod */ -extern const char *audio_formats[]; - extern int audiod_status; /* defined in audiod.c */ diff --git a/buffer_tree.c b/buffer_tree.c index 35353f56..255dc475 100644 --- a/buffer_tree.c +++ b/buffer_tree.c @@ -103,12 +103,12 @@ void btr_pool_free(struct btr_pool *btrp) * \return The same value which was passed during creation time to * btr_pool_new(). */ -size_t btr_pool_size(struct btr_pool *btrp) +size_t btr_pool_size(const struct btr_pool *btrp) { return btrp->area_end - btrp->area_start; } -static size_t btr_pool_filled(struct btr_pool *btrp) +static size_t btr_pool_filled(const struct btr_pool *btrp) { if (!btrp->whead) return btr_pool_size(btrp); @@ -129,7 +129,7 @@ static size_t btr_pool_filled(struct btr_pool *btrp) * the largest contiguous buffer that can currently be allocated from the * buffer pool. */ -size_t btr_pool_unused(struct btr_pool *btrp) +size_t btr_pool_unused(const struct btr_pool *btrp) { return btr_pool_size(btrp) - btr_pool_filled(btrp); } @@ -138,7 +138,7 @@ size_t btr_pool_unused(struct btr_pool *btrp) * Return maximal size available for one read. This is * smaller than the value returned by btr_pool_unused(). */ -static size_t btr_pool_available(struct btr_pool *btrp) +static size_t btr_pool_available(const struct btr_pool *btrp) { if (!btrp->whead) return 0; @@ -156,7 +156,7 @@ static size_t btr_pool_available(struct btr_pool *btrp) * \return The maximal amount of bytes that may be written to the returned * buffer. */ -size_t btr_pool_get_buffer(struct btr_pool *btrp, char **result) +size_t btr_pool_get_buffer(const struct btr_pool *btrp, char **result) { if (result) *result = btrp->whead; @@ -174,7 +174,7 @@ size_t btr_pool_get_buffer(struct btr_pool *btrp, char **result) * consists of two buffers. If this function returns the value n, then n * elements of \a iov are initialized. */ -int btr_pool_get_buffers(struct btr_pool *btrp, struct iovec iov[2]) +int btr_pool_get_buffers(const struct btr_pool *btrp, struct iovec iov[2]) { size_t sz, unused; char *buf; @@ -322,7 +322,7 @@ static void dealloc_buffer(struct btr_buffer *btrb) free(btrb->buf); } -static struct btr_buffer_reference *get_first_input_br(struct btr_node *btrn) +static struct btr_buffer_reference *get_first_input_br(const struct btr_node *btrn) { if (list_empty(&btrn->input_queue)) return NULL; @@ -330,6 +330,14 @@ static struct btr_buffer_reference *get_first_input_br(struct btr_node *btrn) struct btr_buffer_reference, node); } +static struct btr_buffer_reference *get_last_input_br(const struct btr_node *btrn) +{ + if (list_empty(&btrn->input_queue)) + return NULL; + return list_last_entry(&btrn->input_queue, + struct btr_buffer_reference, node); +} + /* * Deallocate the reference, release the resources if refcount drops to zero. */ @@ -346,6 +354,20 @@ static void btr_drop_buffer_reference(struct btr_buffer_reference *br) } } +static bool may_merge_btrb(const struct btr_buffer *btrb, + const struct btr_buffer_reference *br) +{ + if (!br) + return false; + if (br->consumed > 0) + return false; + if (br->btrb->buf + br->btrb->size != btrb->buf) + return false; + if (!br->btrb->pool) + return true; + return br->btrb->size + btrb->size < btr_pool_size(br->btrb->pool) / 3; +} + static void add_btrb_to_children(struct btr_buffer *btrb, struct btr_node *btrn, size_t consumed) { @@ -354,11 +376,17 @@ static void add_btrb_to_children(struct btr_buffer *btrb, if (btrn->start.tv_sec == 0) btrn->start = *now; FOR_EACH_CHILD(ch, btrn) { - struct btr_buffer_reference *br = zalloc(sizeof(*br)); - br->btrb = btrb; - br->consumed = consumed; - list_add_tail(&br->node, &ch->input_queue); - btrb->refcount++; + struct btr_buffer_reference *br = get_last_input_br(ch); + if (may_merge_btrb(btrb, br)) { + br->btrb->size += btrb->size; + free(btrb); + } else { + br = zalloc(sizeof(*br)); + br->btrb = btrb; + br->consumed = consumed; + list_add_tail(&br->node, &ch->input_queue); + btrb->refcount++; + } if (ch->start.tv_sec == 0) ch->start = *now; } @@ -534,7 +562,7 @@ void btr_pushdown_one(struct btr_node *btrn) * * \return True if this node has no children. False otherwise. */ -static bool btr_no_children(struct btr_node *btrn) +static bool btr_no_children(const struct btr_node *btrn) { return list_empty(&btrn->children); } @@ -551,7 +579,7 @@ static bool btr_no_children(struct btr_node *btrn) * After a (non-leaf) node was removed removed from the tree, the function * returns true for all child nodes. */ -bool btr_no_parent(struct btr_node *btrn) +bool btr_no_parent(const struct btr_node *btrn) { return !btrn->parent; } @@ -574,7 +602,7 @@ bool btr_no_parent(struct btr_node *btrn) * * \return True if \a btrn has no siblings. */ -bool btr_inplace_ok(struct btr_node *btrn) +bool btr_inplace_ok(const struct btr_node *btrn) { struct btr_buffer_reference *br; FOR_EACH_BUFFER_REF(br, btrn) { @@ -587,12 +615,13 @@ bool btr_inplace_ok(struct btr_node *btrn) return true; } -static inline size_t br_available_bytes(struct btr_buffer_reference *br) +static inline size_t br_available_bytes(const struct btr_buffer_reference *br) { return br->btrb->size - br->consumed; } -static size_t btr_get_buffer_by_reference(struct btr_buffer_reference *br, char **buf) +static size_t btr_get_buffer_by_reference(const struct btr_buffer_reference *br, + char **buf) { if (buf) *buf = br->btrb->buf + br->consumed; @@ -619,7 +648,8 @@ static size_t btr_get_buffer_by_reference(struct btr_buffer_reference *br, char * to by \a btrn, the function returns zero and the value of \a bufp is * undefined. */ -size_t btr_next_buffer_omit(struct btr_node *btrn, size_t omit, char **bufp) +size_t btr_next_buffer_omit(const struct btr_node *btrn, size_t omit, + char **bufp) { struct btr_buffer_reference *br; size_t wrap_count, sz, rv = 0; @@ -684,7 +714,7 @@ out: * The call of this function is is equivalent to calling \ref * btr_next_buffer_omit() with an \a omit value of zero. */ -size_t btr_next_buffer(struct btr_node *btrn, char **bufp) +size_t btr_next_buffer(const struct btr_node *btrn, char **bufp) { return btr_next_buffer_omit(btrn, 0, bufp); } @@ -816,7 +846,7 @@ out: * This simply iterates over all buffer references in the input queue and * returns the sum of the sizes of all references. */ -size_t btr_get_input_queue_size(struct btr_node *btrn) +size_t btr_get_input_queue_size(const struct btr_node *btrn) { struct btr_buffer_reference *br; size_t size = 0, wrap_consumed = 0; @@ -833,6 +863,22 @@ size_t btr_get_input_queue_size(struct btr_node *btrn) return size; } +static bool min_iqs_available(size_t min_iqs, const struct btr_node *btrn) +{ + struct btr_buffer_reference *br; + size_t have = 0, wrap_consumed = 0; + + FOR_EACH_BUFFER_REF(br, btrn) { + if (br->wrap_count != 0) { + wrap_consumed = br->consumed; + continue; + } + have += br_available_bytes(br); + if (have > wrap_consumed + min_iqs) + return true; + } + return false; +} /** * Remove a node from the buffer tree, reconnecting parent and children. * @@ -875,7 +921,7 @@ void btr_splice_out_node(struct btr_node **btrnp) * \return This function iterates over all children of the given node and * returns the size of the largest input queue. */ -size_t btr_get_output_queue_size(struct btr_node *btrn) +size_t btr_get_output_queue_size(const struct btr_node *btrn) { size_t max_size = 0; struct btr_node *ch; @@ -903,7 +949,7 @@ size_t btr_get_output_queue_size(struct btr_node *btrn) * * \sa \ref receiver::execute, \ref filter::execute, \ref writer::execute. */ -int btr_exec_up(struct btr_node *btrn, const char *command, char **value_result) +int btr_exec_up(const struct btr_node *btrn, const char *command, char **value_result) { int ret; @@ -933,12 +979,12 @@ int btr_exec_up(struct btr_node *btrn, const char *command, char **value_result) * * \sa \ref btr_new_node(), struct \ref btr_node_description. */ -void *btr_context(struct btr_node *btrn) +void *btr_context(const struct btr_node *btrn) { return btrn->context; } -static bool need_buffer_pool_merge(struct btr_node *btrn) +static bool need_buffer_pool_merge(const struct btr_node *btrn) { struct btr_buffer_reference *br = get_first_input_br(btrn); @@ -1113,7 +1159,7 @@ void btr_merge(struct btr_node *btrn, size_t dest_size) } } -static bool btr_eof(struct btr_node *btrn) +static bool btr_eof(const struct btr_node *btrn) { char *buf; size_t len = btr_next_buffer(btrn, &buf); @@ -1121,7 +1167,7 @@ static bool btr_eof(struct btr_node *btrn) return (len == 0 && btr_no_parent(btrn)); } -static void log_tree_recursively(struct btr_node *btrn, int loglevel, int depth) +static void log_tree_recursively(const struct btr_node *btrn, int loglevel, int depth) { struct btr_node *ch; const char spaces[] = " ", *space = spaces + 16 - depth; @@ -1139,7 +1185,7 @@ static void log_tree_recursively(struct btr_node *btrn, int loglevel, int depth) * \param btrn Start logging at this node. * \param loglevel Set severity with which the tree should be logged. */ -void btr_log_tree(struct btr_node *btrn, int loglevel) +void btr_log_tree(const struct btr_node *btrn, int loglevel) { return log_tree_recursively(btrn, loglevel, 0); } @@ -1199,12 +1245,9 @@ struct btr_node *btr_search_node(const char *name, struct btr_node *root) * btrn, the function also returns zero in order to bound the memory usage of * the buffer tree. */ -int btr_node_status(struct btr_node *btrn, size_t min_iqs, +int btr_node_status(const struct btr_node *btrn, size_t min_iqs, enum btr_node_type type) { - size_t iqs; - - assert(btrn); if (type != BTR_NT_LEAF && btr_no_children(btrn)) return -E_BTR_NO_CHILD; if (type != BTR_NT_ROOT && btr_eof(btrn)) @@ -1214,12 +1257,9 @@ int btr_node_status(struct btr_node *btrn, size_t min_iqs, return 0; if (type == BTR_NT_ROOT) return 1; - iqs = btr_get_input_queue_size(btrn); - if (iqs == 0) /* we have a parent, because not eof */ - return 0; - if (iqs < min_iqs && !btr_no_parent(btrn)) - return 0; - return 1; + if (min_iqs_available(min_iqs, btrn)) + return 1; + return btr_no_parent(btrn); } /** @@ -1230,7 +1270,7 @@ int btr_node_status(struct btr_node *btrn, size_t min_iqs, * * Mainly useful for the time display of para_audiod. */ -void btr_get_node_start(struct btr_node *btrn, struct timeval *tv) +void btr_get_node_start(const struct btr_node *btrn, struct timeval *tv) { *tv = btrn->start; } @@ -1245,7 +1285,7 @@ void btr_get_node_start(struct btr_node *btrn, struct timeval *tv) * \return The parent of \a btrn, or \p NULL if \a btrn is the * root node of the buffer tree. */ -struct btr_node *btr_parent(struct btr_node *btrn) +struct btr_node *btr_parent(const struct btr_node *btrn) { return btrn->parent; } diff --git a/buffer_tree.h b/buffer_tree.h index 34535219..70fb3055 100644 --- a/buffer_tree.h +++ b/buffer_tree.h @@ -3,45 +3,43 @@ /** * \file buffer_tree.h Buffer tree management. * - * \par Buffer trees and buffer tree nodes. - * The buffer tree API offers a more powerful method than standard unix pipes - * for managing the data flow from the producer of the data (e.g. the network - * receiver) to its consumer(s) (e.g. a sound card). + * Buffer trees and buffer tree nodes. * - * A buffer tree consists of buffer tree nodes linked via certain parent/child - * relationships. + * The buffer tree API offers an efficient method for managing the data flow + * from a producer (e.g. the network receiver) to the consumer(s) (e.g. a sound + * card). + * + * A buffer tree consists of buffer tree nodes which are linked together via + * parent/child relationships. Data buffers are propagated down without copying. * * Each data buffer starts its way from the root of the buffer tree. At each * node the data is investigated and possibly changed. New data is then fed to - * each child. Everything happens within one single-treaded process. There are - * no file descriptors and no calls to read() or write(). + * each child. There are no file descriptors, no processes/threads and no calls + * to read() or write(). * * Whenever a node in the buffer tree creates output, either by creating a new * buffer or by pushing down buffers received from its parent, references to - * that buffer are created for all children of the node. The buffer tree code - * tries hard to avoid to copy buffer contents, but is forced to do so in case - * there are alignment constraints. + * that buffer are created for all children of the node. The code avoids to + * copy buffer contents when possible. * - * Communication between nodes is possible via the btr_exec_up() function. - * For example, in para_audiod the alsa writer asks all parent nodes - * for for the number of channels and the sample rate of the current - * audio file. + * Communication between nodes is possible via the btr_exec_up() function. For + * example, in para_audiod the alsa writer asks all parent nodes for the number + * of channels and the sample rate of the current audio file. * * Buffer pools - An alternative to malloc/free buffer management. * - * Non-leaf nodes usually create output to be processed by their children. The - * data must be fed through the output channel(s) of the node in order to make - * that data available to each child. + * Non-leaf nodes usually create output to be processed by their child nodes. + * The data must be fed through the output channel(s) of the node in order to + * make that data available to each child. * * The easiest way to do so is to malloc() a buffer, fill it, and then call * btr_add_output(). This adds references to that buffer to all children. The * buffer is automatically freed if no buffer tree node is using it any more. * - * This approach, while being simple, has some drawbacks, especially affecting - * the root nodes of the buffer tree. Often the data source which is - * represented by a root node does not know in advance how much data will be - * available. Therefore the allocated buffer is either larger than what can - * currently be read, or is too small so that multiple buffers have to be used. + * This approach is simple but has some drawbacks. For example the data source + * represented by the root node does not know in advance how much data will be + * available. Therefore the allocated buffer will either be larger than + * necessary or too small so that multiple buffers have to be used. * * While this could be worked around by using a large buffer and calling * realloc() afterwards to shrink the buffer according to how much has been @@ -131,7 +129,7 @@ enum btr_node_type { * know the sample rate of its input known to e.g. the mp3dec node further up * in the buffer tree. */ -typedef int (*btr_command_handler)(struct btr_node *btrn, +typedef int (*btr_command_handler)(const struct btr_node *btrn, const char *command, char **result); /** @@ -166,38 +164,38 @@ struct btr_node_description { void *context; }; -size_t btr_pool_size(struct btr_pool *btrp); +size_t btr_pool_size(const struct btr_pool *btrp); struct btr_pool *btr_pool_new(const char *name, size_t area_size); void btr_pool_free(struct btr_pool *btrp); -size_t btr_pool_get_buffer(struct btr_pool *btrp, char **result); -int btr_pool_get_buffers(struct btr_pool *btrp, struct iovec iov[2]); +size_t btr_pool_get_buffer(const struct btr_pool *btrp, char **result); +int btr_pool_get_buffers(const struct btr_pool *btrp, struct iovec iov[2]); void btr_add_output_pool(struct btr_pool *btrp, size_t size, struct btr_node *btrn); -size_t btr_pool_unused(struct btr_pool *btrp); +size_t btr_pool_unused(const struct btr_pool *btrp); void btr_copy(const void *src, size_t n, struct btr_pool *btrp, struct btr_node *btrn); - struct btr_node *btr_new_node(struct btr_node_description *bnd); void btr_remove_node(struct btr_node **btrnp); void btr_add_output(char *buf, size_t size, struct btr_node *btrn); void btr_add_output_dont_free(const char *buf, size_t size, struct btr_node *btrn); -size_t btr_get_input_queue_size(struct btr_node *btrn); -size_t btr_get_output_queue_size(struct btr_node *btrn); -bool btr_no_parent(struct btr_node *btrn); -size_t btr_next_buffer(struct btr_node *btrn, char **bufp); -size_t btr_next_buffer_omit(struct btr_node *btrn, size_t omit, char **bufp); +size_t btr_get_input_queue_size(const struct btr_node *btrn); +size_t btr_get_output_queue_size(const struct btr_node *btrn); +bool btr_no_parent(const struct btr_node *btrn); +size_t btr_next_buffer(const struct btr_node *btrn, char **bufp); +size_t btr_next_buffer_omit(const struct btr_node *btrn, size_t omit, + char **bufp); void btr_consume(struct btr_node *btrn, size_t numbytes); -int btr_exec_up(struct btr_node *btrn, const char *command, char **value_result); +int btr_exec_up(const struct btr_node *btrn, const char *command, char **value_result); void btr_splice_out_node(struct btr_node **btrnp); void btr_pushdown(struct btr_node *btrn); -void *btr_context(struct btr_node *btrn); +void *btr_context(const struct btr_node *btrn); void btr_merge(struct btr_node *btrn, size_t dest_size); -void btr_log_tree(struct btr_node *btrn, int ll); +void btr_log_tree(const struct btr_node *btrn, int ll); void btr_pushdown_one(struct btr_node *btrn); -bool btr_inplace_ok(struct btr_node *btrn); -int btr_node_status(struct btr_node *btrn, size_t min_iqs, +bool btr_inplace_ok(const struct btr_node *btrn); +int btr_node_status(const struct btr_node *btrn, size_t min_iqs, enum btr_node_type type); -void btr_get_node_start(struct btr_node *btrn, struct timeval *tv); +void btr_get_node_start(const struct btr_node *btrn, struct timeval *tv); struct btr_node *btr_search_node(const char *name, struct btr_node *root); void btr_drain(struct btr_node *btrn); -struct btr_node *btr_parent(struct btr_node *btrn); +struct btr_node *btr_parent(const struct btr_node *btrn); diff --git a/check_wav.c b/check_wav.c index 3789f30a..cb39eb54 100644 --- a/check_wav.c +++ b/check_wav.c @@ -54,7 +54,7 @@ void check_wav_pre_monitor(struct sched *s, struct check_wav_context *cwc) sched_min_delay(s); } -static int check_wav_exec(struct btr_node *btrn, const char *cmd, char **result) +static int check_wav_exec(const struct btr_node *btrn, const char *cmd, char **result) { struct check_wav_context *cwc = btr_context(btrn); int val, header_val, given, arg; diff --git a/client.c b/client.c index 84b7580c..d2d11fd3 100644 --- a/client.c +++ b/client.c @@ -549,6 +549,7 @@ __noreturn static void interactive_session(void) i9e_close(); para_log = stderr_log; out: + free(ici.history_file); if (ret < 0) PARA_ERROR_LOG("%s\n", para_strerror(-ret)); exit(ret < 0? EXIT_FAILURE : EXIT_SUCCESS); diff --git a/configure.ac b/configure.ac index 92560e00..34dcd060 100644 --- a/configure.ac +++ b/configure.ac @@ -5,7 +5,6 @@ AC_INIT([paraslash], [m4_esyscmd_s(./GIT-VERSION-GEN)], AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([Makefile]) -AC_DEFUN([add_dot_o],[$(for i in $@; do printf "$i.o "; done)]) AC_DEFUN([LIB_ARG_WITH], [ AC_ARG_WITH($1-headers, [AS_HELP_STRING(--with-$1-headers=dir, [look for $1 headers in dir])]) @@ -38,6 +37,7 @@ AC_DEFUN([LIB_SUBST_FLAGS], [ if test "$HAVE_[]m4_toupper([$1])" = 'yes'; then AC_DEFINE(HAVE_[]m4_toupper([$1]), 1, define to 1 to turn on $1 support) + AC_SUBST(HAVE_[]m4_toupper([$1])) else $1_cppflags= $1_ldflags= @@ -61,7 +61,6 @@ REQUIRE_EXECUTABLE([bison]) REQUIRE_EXECUTABLE([flex]) REQUIRE_EXECUTABLE([m4]) -executables="recv filter audioc write afh play" ########################################################################### osl STASH_FLAGS LIB_ARG_WITH([osl], [-losl]) @@ -110,15 +109,6 @@ if test $HAVE_OPENSSL = yes; then will be removed in the next major paraslash release. Please upgrade your openssl installation.]) fi - HAVE_CRYPTO_CLEANUP_ALL_EX_DATA=yes - AC_CHECK_DECL([CRYPTO_cleanup_all_ex_data], [], - [HAVE_CRYPTO_CLEANUP_ALL_EX_DATA=no], - [#include ]) - AC_CHECK_LIB([crypto], [CRYPTO_cleanup_all_ex_data], [], - [HAVE_CRYPTO_CLEANUP_ALL_EX_DATA=no]) - test $HAVE_CRYPTO_CLEANUP_ALL_EX_DATA = yes && - AC_DEFINE([HAVE_CRYPTO_CLEANUP_ALL_EX_DATA], [1], - [not available on FreeBSD 12]) HAVE_OPENSSL_THREAD_STOP=yes AC_CHECK_DECL([OPENSSL_thread_stop], [], [HAVE_OPENSSL_THREAD_STOP=no], @@ -172,6 +162,7 @@ case "$enable_cryptolib" in ;; esac AC_SUBST(crypto_ldflags) +AC_SUBST(CRYPTOLIB) ########################################################################## iconv STASH_FLAGS LIBS= @@ -273,27 +264,26 @@ AC_CHECK_LIB([FLAC], [FLAC__stream_decoder_init_file], [], HAVE_FLAC=no) LIB_SUBST_FLAGS(flac) UNSTASH_FLAGS -# some helper functions for codecs which use the ogg container format -AC_DEFUN([NEED_OGG_OBJECTS], [{ - test "$HAVE_OGG" = 'yes' -a \( \ +# some helpers for the ogg container format +AS_IF([test "$HAVE_OGG" = 'yes' -a \( \ "$HAVE_VORBIS" = 'yes' \ -o "$HAVE_SPEEX" = 'yes' \ -o "$HAVE_OPUS" = 'yes' \ -o "$HAVE_FLAC" = 'yes' \ - \) -}]) -AC_DEFUN([NEED_VORBIS_OBJECTS], [{ - test "$HAVE_OGG" = 'yes' -a "$HAVE_VORBIS" = 'yes' -}]) -AC_DEFUN([NEED_SPEEX_OBJECTS], [{ - test "$HAVE_OGG" = 'yes' -a "$HAVE_SPEEX" = 'yes' -}]) -AC_DEFUN([NEED_OPUS_OBJECTS], [{ - test "$HAVE_OGG" = 'yes' -a "$HAVE_OPUS" = 'yes' -}]) -AC_DEFUN([NEED_FLAC_OBJECTS], [{ - test "$HAVE_OGG" = 'yes' -a "$HAVE_FLAC" = 'yes' -}]) +\)], [NEED_OGG_OBJECTS=yes], [NEED_OGG_OBJECTS=no]) +AC_SUBST([NEED_OGG_OBJECTS]) +AS_IF([test "$HAVE_OGG" = 'yes' -a "$HAVE_VORBIS" = 'yes'], + [NEED_VORBIS_OBJECTS=yes], [NEED_VORBIS_OBJECTS=no]) +AC_SUBST([NEED_VORBIS_OBJECTS]) +AS_IF([test "$HAVE_OGG" = 'yes' -a "$HAVE_SPEEX" = 'yes'], + [NEED_SPEEX_OBJECTS=yes], [NEED_SPEEX_OBJECTS=no]) +AC_SUBST([NEED_SPEEX_OBJECTS]) +AS_IF([test "$HAVE_OGG" = 'yes' -a "$HAVE_OPUS" = 'yes'], + [NEED_OPUS_OBJECTS=yes], [NEED_OPUS_OBJECTS=no]) +AC_SUBST([NEED_OPUS_OBJECTS]) +AS_IF([test "$HAVE_OGG" = 'yes' -a "$HAVE_FLAC" = 'yes'], + [NEED_FLAC_OBJECTS=yes], [NEED_FLAC_OBJECTS=no]) +AC_SUBST([NEED_FLAC_OBJECTS]) ########################################################################### faad STASH_FLAGS LIB_ARG_WITH([faad], [-lfaad]) @@ -349,7 +339,9 @@ AC_CHECK_HEADER(ao/ao.h, [], HAVE_AO=no) AC_CHECK_LIB([ao], [ao_initialize], [], HAVE_AO=no) LIB_SUBST_FLAGS(ao) UNSTASH_FLAGS -AC_DEFUN([NEED_AO_OBJECTS], [{ test $HAVE_AO = yes -a $HAVE_PTHREAD = yes; }]) +AS_IF([test $HAVE_AO = yes -a $HAVE_PTHREAD = yes], + [NEED_AO_OBJECTS]=yes, [NEED_AO_OBJECTS=no]) +AC_SUBST([NEED_AO_OBJECTS]) ######################################################################## readline STASH_FLAGS AC_SEARCH_LIBS([tgetent], [tinfo curses terminfo termcap]) @@ -381,502 +373,5 @@ AC_ARG_ENABLE([ubsan], [AS_HELP_STRING(--enable-ubsan, [Detect and report undefined behaviour.])], [ENABLE_UBSAN=yes], [ENABLE_UBSAN=no]) AC_SUBST(ENABLE_UBSAN) -######################################################################### server -if test -n "$CRYPTOLIB" && test $HAVE_OSL = yes && test -n "$BISON" && \ - test -n "$FLEX"; then - build_server="yes" - executables="$executables server upgrade_db" - server_errlist_objs=" - server - afh_common - mp3_afh - vss - command - net - string - signal - time - daemon - http_send - close_on_fork - crypt_common - base64 - ipc - dccp_send - fd - user_list - chunk_queue - afs - aft - mood - mp - score - attribute - blob - playlist - sched - acl - send_common - udp_send - color - fec - wma_afh - wma_common - sideband - version - lsu - " - if test "$CRYPTOLIB" = openssl; then - server_errlist_objs="$server_errlist_objs openssl" - else - server_errlist_objs="$server_errlist_objs gcrypt" - fi - NEED_OGG_OBJECTS() && server_errlist_objs="$server_errlist_objs ogg_afh_common" - NEED_VORBIS_OBJECTS() && server_errlist_objs="$server_errlist_objs ogg_afh" - NEED_SPEEX_OBJECTS() && server_errlist_objs="$server_errlist_objs spx_afh spx_common" - NEED_OPUS_OBJECTS() && server_errlist_objs="$server_errlist_objs opus_afh opus_common" - NEED_FLAC_OBJECTS && server_errlist_objs="$server_errlist_objs flac_afh" - if test $HAVE_FAAD = yes; then - server_errlist_objs="$server_errlist_objs aac_afh mp4" - fi - server_objs="$server_errlist_objs" - AC_SUBST(server_objs, add_dot_o($server_objs)) -else - build_server="no" -fi -############################################################# upgrade_db -upgrade_db_objs=' - crypt_common - exec - fd - string - upgrade_db - version - base64 -' -AC_SUBST(upgrade_db_objs, add_dot_o($upgrade_db_objs)) -############################################################# client -if test -n "$CRYPTOLIB"; then - build_client="yes" - executables="$executables client" - client_errlist_objs=" - client - net - string - fd - lsu - sched - stdin - stdout - time - sideband - client_common - buffer_tree - crypt_common - base64 - version - " - if test "$CRYPTOLIB" = openssl; then - client_errlist_objs="$client_errlist_objs openssl" - else - client_errlist_objs="$client_errlist_objs gcrypt" - fi - if test $HAVE_READLINE = yes; then - client_errlist_objs="$client_errlist_objs interactive" - fi - client_objs="$client_errlist_objs" - AC_SUBST(client_objs, add_dot_o($client_errlist_objs)) -else - build_client="no" -fi -############################################################# audiod -if test -n "$CRYPTOLIB"; then - build_audiod="yes" - executables="$executables audiod" - audiod_audio_formats="wma" - audiod_errlist_objs="$audiod_errlist_objs - audiod - signal - string - daemon - stat - net - crypt_common - base64 - sideband - time - grab_client - filter_common - wav_filter - compress_filter - amp_filter - http_recv - dccp_recv - recv_common - fd - sched - write_common - file_write - audiod_command - fecdec_filter - client_common - udp_recv - color - fec - prebuffer_filter - version - bitstream - imdct - wma_common - wmadec_filter - buffer_tree - sync_filter - lsu - " - if test "$CRYPTOLIB" = openssl; then - audiod_errlist_objs="$audiod_errlist_objs openssl" - else - audiod_errlist_objs="$audiod_errlist_objs gcrypt" - fi - NEED_VORBIS_OBJECTS && { - audiod_errlist_objs="$audiod_errlist_objs oggdec_filter" - audiod_audio_formats="$audiod_audio_formats ogg" - } - NEED_SPEEX_OBJECTS && { - audiod_errlist_objs="$audiod_errlist_objs spxdec_filter spx_common" - audiod_audio_formats="$audiod_audio_formats spx" - } - NEED_OPUS_OBJECTS && { - audiod_errlist_objs="$audiod_errlist_objs opusdec_filter opus_common" - audiod_audio_formats="$audiod_audio_formats opus" - } - NEED_FLAC_OBJECTS && { - audiod_errlist_objs="$audiod_errlist_objs flacdec_filter" - audiod_audio_formats="$audiod_audio_formats flac" - } - if test $HAVE_FAAD = yes; then - audiod_errlist_objs="$audiod_errlist_objs aacdec_filter" - audiod_audio_formats="$audiod_audio_formats aac" - fi - if test $HAVE_MAD = yes; then - audiod_audio_formats="$audiod_audio_formats mp3" - audiod_errlist_objs="$audiod_errlist_objs mp3dec_filter" - fi - if test $HAVE_OSS = yes; then - audiod_errlist_objs="$audiod_errlist_objs oss_write" - fi - if test $HAVE_ALSA = yes; then - audiod_errlist_objs="$audiod_errlist_objs alsa_write" - fi - NEED_AO_OBJECTS && { - audiod_errlist_objs="$audiod_errlist_objs ao_write" - } - if test $HAVE_SAMPLERATE = yes; then - audiod_errlist_objs="$audiod_errlist_objs resample_filter check_wav" - fi - audiod_objs="$audiod_errlist_objs" - AC_SUBST(audiod_objs, add_dot_o($audiod_objs)) - - enum="$(for i in $audiod_audio_formats; do printf "AUDIO_FORMAT_${i}, " | tr '[a-z]' '[A-Z]'; done)" - AC_DEFINE_UNQUOTED(AUDIOD_AUDIO_FORMATS_ENUM, $enum NUM_AUDIO_FORMATS, - enum of audio formats supported by audiod) - names="$(for i in $audiod_audio_formats; do printf \"$i\",' ' ; done)" - AC_DEFINE_UNQUOTED(AUDIOD_AUDIO_FORMAT_ARRAY, $names, array of audio formats supported by audiod) -else - build_audiod="no" -fi -########################################################################### mixer -if test $HAVE_OSS = yes -o $HAVE_ALSA = yes; then - build_mixer="yes" - executables="$executables mixer" - mixer_errlist_objs="mixer exec string fd time lsu version" - if test $HAVE_OSS = yes; then - mixer_errlist_objs="$mixer_errlist_objs oss_mix" - fi - if test $HAVE_ALSA = yes; then - mixer_errlist_objs="$mixer_errlist_objs alsa_mix" - fi - mixer_objs="$mixer_errlist_objs" - AC_SUBST(mixer_objs, add_dot_o($mixer_objs)) -else - build_mixer="no" - AC_MSG_WARN([no mixer support]) -fi -########################################################################### gui -if test $HAVE_CURSES = yes; then - build_gui="yes" - executables="$executables gui" - gui_errlist_objs=" - exec - signal - string - stat - ringbuffer - fd - gui - gui_theme - lsu - time - sched - version - " - gui_objs="$gui_errlist_objs" - AC_SUBST(gui_objs, add_dot_o($gui_objs)) -else - build_gui="no" - AC_MSG_WARN([no curses lib, cannot build para_gui]) -fi -######################################################################## filter -filter_errlist_objs=" - filter_common - wav_filter - compress_filter - filter - string - stdin - stdout - sched - fd - amp_filter - fecdec_filter - fec - lsu - version - prebuffer_filter - time - bitstream - imdct - wma_common - wmadec_filter - buffer_tree - net - sync_filter -" -NEED_VORBIS_OBJECTS && filter_errlist_objs="$filter_errlist_objs oggdec_filter" -NEED_SPEEX_OBJECTS && filter_errlist_objs="$filter_errlist_objs spxdec_filter spx_common" -NEED_OPUS_OBJECTS && filter_errlist_objs="$filter_errlist_objs opusdec_filter opus_common" -NEED_FLAC_OBJECTS && filter_errlist_objs="$filter_errlist_objs flacdec_filter" -if test $HAVE_FAAD = yes; then - filter_errlist_objs="$filter_errlist_objs aacdec_filter" -fi -if test $HAVE_MAD = yes; then - filter_errlist_objs="$filter_errlist_objs mp3dec_filter" -fi -if test $HAVE_SAMPLERATE = yes; then - filter_errlist_objs="$filter_errlist_objs resample_filter check_wav" -fi -filter_objs="$filter_errlist_objs" - -AC_SUBST(filter_objs, add_dot_o($filter_objs)) -########################################################################## recv -recv_errlist_objs=" - http_recv - recv_common - recv - time - string - net - dccp_recv - fd - sched - stdout - udp_recv - buffer_tree - afh_recv - afh_common - wma_afh - wma_common - mp3_afh - version -" -NEED_OGG_OBJECTS && recv_errlist_objs="$recv_errlist_objs ogg_afh_common" -NEED_VORBIS_OBJECTS && recv_errlist_objs="$recv_errlist_objs ogg_afh" -NEED_SPEEX_OBJECTS && recv_errlist_objs="$recv_errlist_objs spx_afh spx_common" -NEED_OPUS_OBJECTS && recv_errlist_objs="$recv_errlist_objs opus_afh opus_common" -NEED_FLAC_OBJECTS && recv_errlist_objs="$recv_errlist_objs flac_afh" - -if test $HAVE_FAAD = yes; then - recv_errlist_objs="$recv_errlist_objs aac_afh mp4" -fi -recv_objs="$recv_errlist_objs" -AC_SUBST(recv_objs, add_dot_o($recv_objs)) -########################################################################### afh -audio_format_handlers="mp3 wma" -afh_errlist_objs=" - afh - string - fd - mp3_afh - afh_common - time - wma_afh - wma_common - version -" -NEED_OGG_OBJECTS && afh_errlist_objs="$afh_errlist_objs ogg_afh_common" -NEED_VORBIS_OBJECTS && { - afh_errlist_objs="$afh_errlist_objs ogg_afh" - audio_format_handlers="$audio_format_handlers ogg" -} -NEED_SPEEX_OBJECTS && { - afh_errlist_objs="$afh_errlist_objs spx_afh spx_common" - audio_format_handlers="$audio_format_handlers spx" -} -NEED_OPUS_OBJECTS && { - afh_errlist_objs="$afh_errlist_objs opus_afh opus_common" - audio_format_handlers="$audio_format_handlers opus" -} -NEED_FLAC_OBJECTS && { - afh_errlist_objs="$afh_errlist_objs flac_afh" - audio_format_handlers="$audio_format_handlers flac" -} -if test $HAVE_FAAD = yes; then - afh_errlist_objs="$afh_errlist_objs aac_afh mp4" - audio_format_handlers="$audio_format_handlers aac" -fi - -afh_objs="$afh_errlist_objs" - -AC_SUBST(afh_objs, add_dot_o($afh_objs)) -########################################################################## play -play_errlist_objs=" - play - fd - sched - buffer_tree - time - string - net - afh_recv - afh_common - wma_afh - wma_common - mp3_afh - recv_common - udp_recv - http_recv - dccp_recv - filter_common - fec - bitstream - imdct - wav_filter - compress_filter - amp_filter - prebuffer_filter - fecdec_filter - wmadec_filter - write_common - file_write - version - sync_filter - lsu -" -NEED_OGG_OBJECTS && play_errlist_objs="$play_errlist_objs ogg_afh_common" -NEED_VORBIS_OBJECTS && { - play_errlist_objs="$play_errlist_objs oggdec_filter ogg_afh" -} -NEED_SPEEX_OBJECTS && { - play_errlist_objs="$play_errlist_objs spxdec_filter spx_afh spx_common" -} -NEED_OPUS_OBJECTS && - play_errlist_objs="$play_errlist_objs - opusdec_filter - opus_afh - opus_common - " -NEED_FLAC_OBJECTS && { - play_errlist_objs="$play_errlist_objs flacdec_filter flac_afh" -} -if test $HAVE_FAAD = yes; then - play_errlist_objs="$play_errlist_objs aac_afh aacdec_filter mp4" -fi -if test $HAVE_MAD = yes; then - play_errlist_objs="$play_errlist_objs mp3dec_filter" -fi -if test $HAVE_OSS = yes; then - play_errlist_objs="$play_errlist_objs oss_write" -fi -if test $HAVE_ALSA = yes; then - play_errlist_objs="$play_errlist_objs alsa_write" -fi -NEED_AO_OBJECTS && { - play_errlist_objs="$play_errlist_objs ao_write" -} -if test $HAVE_READLINE = yes; then - play_errlist_objs="$play_errlist_objs interactive" -fi -if test $HAVE_SAMPLERATE = yes; then - play_errlist_objs="$play_errlist_objs resample_filter check_wav" -fi - -play_objs="$play_errlist_objs" -AC_SUBST(play_objs, add_dot_o($play_objs)) -######################################################################### write -write_errlist_objs=" - write - write_common - file_write - time - fd - string - sched - stdin - buffer_tree - check_wav - version -" - -NEED_AO_OBJECTS && { - write_errlist_objs="$write_errlist_objs ao_write" -} -if test $HAVE_OSS = yes; then - write_errlist_objs="$write_errlist_objs oss_write" -fi -if test $HAVE_ALSA = yes; then - write_errlist_objs="$write_errlist_objs alsa_write" -fi -write_objs="$write_errlist_objs" -AC_SUBST(write_objs, add_dot_o($write_objs)) -######################################################################## audioc -audioc_errlist_objs=" - audioc - string - lsu - net - fd - time - version -" -if test $HAVE_READLINE = yes; then - audioc_errlist_objs="$audioc_errlist_objs - buffer_tree - interactive - sched - " -fi -audioc_objs="$audioc_errlist_objs" -AC_SUBST(audioc_objs, add_dot_o($audioc_objs)) - -AC_DEFINE_UNQUOTED(AUDIO_FORMAT_HANDLERS, "$audio_format_handlers", - [formats supported by para_server and para_afh]) -AC_SUBST(executables) AC_OUTPUT -AC_MSG_NOTICE([ -paraslash configuration: -~~~~~~~~~~~~~~~~~~~~~~~~ -crypto lib: ${CRYPTOLIB:-[none]} -unix socket credentials: $have_ucred -readline (interactive CLIs): $HAVE_READLINE -id3 version 2 support: $HAVE_ID3TAG -faad: $HAVE_FAAD -audio format handlers: $audio_format_handlers - -exe: $executables -para_server: $build_server -para_gui: $build_gui -para_mixer: $build_mixer -para_client: $build_client -para_audiod: $build_audiod -]) diff --git a/flacdec_filter.c b/flacdec_filter.c index fb8ebf15..bc3a678b 100644 --- a/flacdec_filter.c +++ b/flacdec_filter.c @@ -187,7 +187,7 @@ static int flacdec_init(struct filter_node *fn) return -E_FLACDEC_DECODER_INIT; } -static int flacdec_execute(struct btr_node *btrn, const char *cmd, +static int flacdec_execute(const struct btr_node *btrn, const char *cmd, char **result) { struct filter_node *fn = btr_context(btrn); diff --git a/ipc.c b/ipc.c index 8e9dd51a..c245f690 100644 --- a/ipc.c +++ b/ipc.c @@ -218,7 +218,7 @@ size_t shm_get_shmmax(void) { int fd = open("/proc/sys/kernel/shmmax", O_RDONLY); if (fd >= 0) { - char buf[100] = ""; + char buf[100]; int ret = read(fd, buf, sizeof(buf) - 1); if (ret > 0) { buf[ret] = '\0'; diff --git a/list.h b/list.h index 78c302fa..82f5b36d 100644 --- a/list.h +++ b/list.h @@ -161,3 +161,5 @@ static inline int list_is_singular(const struct list_head *head) */ #define list_first_entry(ptr, type, member) \ list_entry((ptr)->next, type, member) +#define list_last_entry(ptr, type, member) \ + list_entry((ptr)->prev, type, member) diff --git a/mp3dec_filter.c b/mp3dec_filter.c index d40df85e..d4d4712f 100644 --- a/mp3dec_filter.c +++ b/mp3dec_filter.c @@ -79,12 +79,11 @@ static int mp3dec_post_monitor(__a_unused struct sched *s, void *context) int i, ret; struct private_mp3dec_data *pmd = fn->private_data; struct btr_node *btrn = fn->btrn; - size_t loaded = 0, len, iqs; + size_t loaded = 0, len; char *inbuffer, *outbuffer; next_buffer: pmd->stream.error = 0; - iqs = btr_get_input_queue_size(btrn); ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL); if (ret < 0) goto err; @@ -104,7 +103,7 @@ next_frame: if (ret < 0) { mp3dec_consume(btrn, &pmd->stream, len); if (pmd->stream.error == MAD_ERROR_BUFLEN) { - if (len == iqs && btr_no_parent(btrn)) { + if (fn->min_iqs > 0 && btr_no_parent(btrn)) { ret = -E_EOF; goto err; } @@ -128,7 +127,7 @@ decode: mad_stream_sync(&pmd->stream); if (pmd->stream.error == MAD_ERROR_BUFLEN) { ret = -E_EOF; - if (len == iqs && btr_no_parent(btrn)) + if (btr_no_parent(btrn)) goto err; fn->min_iqs += 100; ret = -E_MP3DEC_CORRUPT; @@ -176,7 +175,8 @@ static void mp3dec_open(struct filter_node *fn) mad_stream_options(&pmd->stream, MAD_OPTION_IGNORECRC); } -static int mp3dec_execute(struct btr_node *btrn, const char *cmd, char **result) +static int mp3dec_execute(const struct btr_node *btrn, const char *cmd, + char **result) { struct filter_node *fn = btr_context(btrn); struct private_mp3dec_data *pmd = fn->private_data; diff --git a/oggdec_filter.c b/oggdec_filter.c index b1aec4bc..91c18c48 100644 --- a/oggdec_filter.c +++ b/oggdec_filter.c @@ -107,7 +107,8 @@ static void ogg_close(struct filter_node *fn) fn->private_data = NULL; } -static int oggdec_execute(struct btr_node *btrn, const char *cmd, char **result) +static int oggdec_execute(const struct btr_node *btrn, const char *cmd, + char **result) { struct filter_node *fn = btr_context(btrn); struct private_oggdec_data *pod = fn->private_data; diff --git a/openssl.c b/openssl.c index f696cd9e..13550e7a 100644 --- a/openssl.c +++ b/openssl.c @@ -54,9 +54,6 @@ void crypt_init(void) void crypt_shutdown(void) { -#ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA - CRYPTO_cleanup_all_ex_data(); -#endif #ifdef HAVE_OPENSSL_THREAD_STOP /* openssl-1.1 or later */ OPENSSL_thread_stop(); #else /* openssl-1.0 */ diff --git a/opusdec_filter.c b/opusdec_filter.c index f36990fa..504ba0e8 100644 --- a/opusdec_filter.c +++ b/opusdec_filter.c @@ -75,7 +75,7 @@ struct opusdec_context { ogg_int32_t opus_serialno; }; -static int opusdec_execute(struct btr_node *btrn, const char *cmd, +static int opusdec_execute(const struct btr_node *btrn, const char *cmd, char **result) { struct filter_node *fn = btr_context(btrn); diff --git a/resample_filter.c b/resample_filter.c index 72cb3f62..6d4599a8 100644 --- a/resample_filter.c +++ b/resample_filter.c @@ -28,7 +28,8 @@ struct resample_context { struct check_wav_context *cwc; }; -static int resample_execute(struct btr_node *btrn, const char *cmd, char **result) +static int resample_execute(const struct btr_node *btrn, const char *cmd, + char **result) { struct filter_node *fn = btr_context(btrn); struct resample_context *ctx = fn->private_data; diff --git a/spxdec_filter.c b/spxdec_filter.c index 08eac02a..ce72125e 100644 --- a/spxdec_filter.c +++ b/spxdec_filter.c @@ -102,7 +102,7 @@ static void speexdec_close(struct filter_node *fn) fn->private_data = NULL; } -static int speexdec_execute(struct btr_node *btrn, const char *cmd, +static int speexdec_execute(const struct btr_node *btrn, const char *cmd, char **result) { struct filter_node *fn = btr_context(btrn); diff --git a/t/makefile.test b/t/makefile.test index 904c7793..1ef3ac69 100644 --- a/t/makefile.test +++ b/t/makefile.test @@ -7,7 +7,7 @@ test_options := --executables-dir $(shell pwd) test_options += --results-dir $(results_dir) test_options += --trash-dir $(trash_dir) test_options += --executables "$(prefixed_executables)" -test_options += --objects "$(basename $(all_objs))" +test_options += --objects "$(basename $(dep_objs))" test_options += --man-dir $(man_dir) ifdef V diff --git a/wmadec_filter.c b/wmadec_filter.c index f2ca273c..5b3d9874 100644 --- a/wmadec_filter.c +++ b/wmadec_filter.c @@ -1147,7 +1147,8 @@ static void wmadec_close(struct filter_node *fn) fn->private_data = NULL; } -static int wmadec_execute(struct btr_node *btrn, const char *cmd, char **result) +static int wmadec_execute(const struct btr_node *btrn, const char *cmd, + char **result) { struct filter_node *fn = btr_context(btrn); struct private_wmadec_data *pwd = fn->private_data;