Cooking in next since 2015-04-26.
* refs/heads/t/taggers:
aac: Fix compilation without libmp4v2.
The mp4 tagger.
The mp3 tagger.
The flac tagger.
The ogg/speex tagger.
The ogg/vorbis tagger.
The ogg/opus tagger.
The wma tagger.
exec_prefix := @exec_prefix@
# These two use prefix and exec_prefix
-BINDIR := @bindir@
+bindir := @bindir@
datarootdir := @datarootdir@
PACKAGE_TARNAME := @PACKAGE_TARNAME@
PACKAGE_VERSION := @PACKAGE_VERSION@
-INSTALL := @install@
-GENGETOPT := @gengetopt@
-HELP2MAN := @help2man@
+INSTALL := @INSTALL@
+GENGETOPT := @GENGETOPT@
+HELP2MAN := @HELP2MAN@
ggo_descriptions_declared := @ggo_descriptions_declared@
object_executable_matrix := @object_executable_matrix@
readline_cppflags := @readline_cppflags@
alsa_cppflags := @alsa_cppflags@
oss_cppflags := @oss_cppflags@
+ mp4v2_cppflags := @mp4v2_cppflags@
clock_gettime_ldflags := @clock_gettime_ldflags@
id3tag_ldflags := @id3tag_ldflags@
curses_ldflags := @curses_ldflags@
core_audio_ldflags := @core_audio_ldflags@
crypto_ldflags := @crypto_ldflags@
+ iconv_ldflags := @iconv_ldflags@
+ mp4v2_ldflags := @mp4v2_ldflags@
include Makefile.real
-VARDIR := /var/paraslash
-MANDIR := $(datarootdir)/man/man1
+vardir := /var/paraslash
+mandir := $(datarootdir)/man/man1
STRIP := $(CROSS_COMPILE)strip
HOSTCC ?= cc
MKDIR_P := mkdir -p
$(subst u,U,$(subst v,V,$(subst w,W,$(subst x,X,$(subst y,Y,\
$(subst z,Z,$1))))))))))))))))))))))))))
-CPPFLAGS += -DBINDIR='"$(BINDIR)"'
-CPPFLAGS += -DBUILD_DATE='"$(build_date)"'
-CPPFLAGS += -DUNAME_RS='"$(uname_rs)"'
-CPPFLAGS += -DCC_VERSION='"$(cc_version)"'
+CPPFLAGS += -DBINDIR='"$(bindir)"'
+CPPFLAGS += -DBUILD_DATE='"$(shell date)"'
+CPPFLAGS += -DUNAME_RS='"$(shell uname -rs)"'
+CPPFLAGS += -DCC_VERSION='"$(shell $(CC) --version | head -n 1)"'
CPPFLAGS += -DMAIN_INPUT_FILE_IS_$(*F)
CPPFLAGS += $(arch_cppflags)
CPPFLAGS += -I/usr/local/include
ifeq ($(uname_s),Linux)
# these cause warnings on *BSD
+ CPPFLAGS += -Wunused-macros
STRICT_CFLAGS += -fdata-sections -ffunction-sections
STRICT_CFLAGS += -Wstrict-prototypes
STRICT_CFLAGS += -Wshadow
$(cmdlist_dir)/%.command_list.man: %.cmd %.c | $(cmdlist_dir)
@[ -z "$(Q)" ] || echo 'GEN $@'
$(Q) ./command_util.bash man < $< > $@
-$(cmdlist_dir)/%.completion.h: %.cmd %.c | $(cmdlist_dir)
+$(cmdlist_dir)/%.completion.h: %.cmd | $(cmdlist_dir)
@[ -z "$(Q)" ] || echo 'GEN $@'
$(Q) ./command_util.bash compl $(strip $(call TOUPPER,$(*F)))_COMPLETERS \
$(strip $(call TOUPPER,$(*F)))_COMMANDS < $< > $@
$(object_dir)/mp3_afh.o $(dep_dir)/mp3_afh.d: CPPFLAGS += $(id3tag_cppflags)
$(object_dir)/crypt.o $(dep_dir)/crypt.d: CPPFLAGS += $(openssl_cppflags)
$(object_dir)/gcrypt.o $(dep_dir)/gcrypt.d: CPPFLAGS += $(gcrypt_cppflags)
+ $(object_dir)/ao_write.o $(dep_dir)/ao_write.d: CPPFLAGS += $(ao_cppflags)
+ $(object_dir)/aac_afh.o $(dep_dir)/aac_afh.d: CPPFLAGS += $(mp4v2_cppflags)
$(object_dir)/alsa%.o $(dep_dir)/alsa%.d: CPPFLAGS += $(alsa_cppflags)
$(object_dir)/interactive.o $(dep_dir)/interactive.d \
para_play \
: LDFLAGS += \
$(mad_ldflags) \
+ $(faad_ldflags) \
$(samplerate_ldflags) \
-lm
$(faad_ldflags) \
$(flac_ldflags)
+ para_server \
+ para_play \
+ para_afh \
+ para_recv \
+ : LDFLAGS += \
+ $(mp4v2_ldflags)
+
para_server \
para_client \
para_audioc \
: LDFLAGS += \
$(socket_ldflags) $(nsl_ldflags)
+ 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 $@'
maintainer-clean: distclean
@[ -z "$(Q)" ] || echo 'MAINTAINER-CLEAN'
$(Q) rm -f *.tar.bz2 config.h configure config.h.in
- $(Q) rm -rf web_sync
install: all man
- $(MKDIR_P) $(BINDIR) $(MANDIR)
+ $(MKDIR_P) $(bindir) $(mandir)
$(INSTALL) -s --strip-program $(STRIP) -m 755 \
- $(prefixed_executables) $(BINDIR)
- $(INSTALL) -m 644 $(man_pages) $(MANDIR)
- $(MKDIR_P) $(VARDIR) >/dev/null 2>&1 || true # not fatal, so don't complain
+ $(prefixed_executables) $(bindir)
+ $(INSTALL) -m 644 $(man_pages) $(mandir)
+ $(MKDIR_P) $(vardir) >/dev/null 2>&1 || true # not fatal, so don't complain
$(tarball):
$(Q) rm -rf $(tarball) $(tarball_pfx)
NEWS
====
------------------------------------------
-current master branch "magnetic momentum"
------------------------------------------
++------------------------------------------
++current master branch "cascading gradient"
++------------------------------------------
++
++ - para_afh learned to modify meta tags of mp3 wma ogg spx
++ opus flac aac files.
++
+--------------------------------------
+0.5.5 (2015-09-20) "magnetic momentum"
+--------------------------------------
+
+Many new features and a lot of other improvements.
+
- On Linux systems, local sockets are now created in the
abstract name space by default. This allows to get rid of
the socket specials in /var/paraslash.
+ - The --user-allow option of para_audiod now accepts also
+ usernames rather than only user IDs.
- New autoconf macros to avoid duplication in configure.ac.
- Status items (as shown by para_gui) are updated correctly
when the meta information of the current audio changes.
+ - para_server and para_audiod no longer refuse to start in
+ the background if no log file is given. Instead, all log
+ messages go to /dev/null in this case.
+ - Web page cleanup.
+ - New syntax for the -l and -s options of the ls command.
+ These options should now be specified as -l=v rather than
+ -lv, for example. The old syntax still works, but support
+ will be dropped in v0.6.0.
-Download: ./releases/paraslash-git.tar.bz2 (tarball)
+Download: ./releases/paraslash-0.5.5.tar.bz2 (tarball)
+./releases/paraslash-0.5.5.tar.bz2.asc (signature)
------------------------------------------
0.5.4 (2015-01-23) "exponential alignment"
},
{
.name = "aac",
- #ifdef HAVE_FAAD
+ #if defined(HAVE_MP4V2)
.init = aac_afh_init,
#endif
},
},
{
.name = "flac",
-#ifdef HAVE_FLAC
+#if defined(HAVE_OGG) && defined(HAVE_FLAC)
.init = flac_afh_init,
#endif
},
status_item_list[SI_COMMENT], afhi->tags.comment? afhi->tags.comment : ""
);
}
+
+ /**
+ * Create a copy of the given file with altered meta tags.
+ *
+ * \param audio_format_id Specifies the audio format.
+ * \param map The (read-only) memory map of the input file.
+ * \param mapsize The size of the input file in bytes.
+ * \param tags The new tags.
+ * \param output_fd Altered file is created using this file descriptor.
+ * \param filename The name of the temporary output file.
+ *
+ * This calls the ->rewrite_tags method of the audio format handler associated
+ * with \a audio_format_id to create a copy of the memory-mapped file given
+ * by \a map and \a mapsize, but with altered tags according to \a tags. If
+ * the audio format handler for \a audio_format_id lacks this optional method,
+ * the function returns (the paraslash error code of) \p ENOTSUP.
+ *
+ * \return Standard.
+ */
+ 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;
+
+ if (!afh->rewrite_tags)
+ return -ERRNO_TO_PARA_ERROR(ENOTSUP);
+ return afh->rewrite_tags(map, mapsize, tags, output_fd, filename);
+ }
LIBS="$OLD_LIBS"
])
AC_DEFUN([LIB_SUBST_FLAGS], [
- if test "$HAVE_[]m4_toupper([$1])" == 'yes'; then
+ if test "$HAVE_[]m4_toupper([$1])" = 'yes'; then
AC_DEFINE(HAVE_[]m4_toupper([$1]), 1,
define to 1 to turn on $1 support)
else
AC_C_BIGENDIAN()
-AC_PATH_PROG([gengetopt], [gengetopt])
-test -z "$gengetopt" && AC_MSG_ERROR(
+AC_PATH_PROG([GENGETOPT], [gengetopt])
+test -z "$GENGETOPT" && AC_MSG_ERROR(
[gengetopt is required to build this package])
-AC_PATH_PROG([help2man], [help2man])
-test -z "$help2man" && AC_MSG_ERROR(
+AC_PATH_PROG([HELP2MAN], [help2man])
+test -z "$HELP2MAN" && AC_MSG_ERROR(
[help2man is required to build this package])
-AC_PATH_PROG([install], [install])
-test -z "$install" && AC_MSG_ERROR(
+AC_PATH_PROG([INSTALL], [install])
+test -z "$INSTALL" && AC_MSG_ERROR(
[The install program is required to build this package])
AC_PROG_CC
[socket_ldflags="-lsocket"]
)
AC_SUBST(socket_ldflags)
+ ########################################################################## iconv
+ STASH_FLAGS
+ LIBS=
+ AC_SEARCH_LIBS([libiconv_open], [iconv],
+ [iconv_ldflags="$LIBS"],
+ []
+ )
+ AC_SUBST(iconv_ldflags)
+ AC_MSG_CHECKING([whether iconv needs const char ** cast])
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([
+ #include <iconv.h>
+ ],[
+ size_t iconv(iconv_t cd, const char **inbuf,
+ size_t *inbytesleft, char **outbuf,
+ size_t *outbytesleft);
+ ])
+ ],
+ [cast='(const char **)'; msg=yes],
+ [cast=; msg=no]
+ )
+ AC_DEFINE_UNQUOTED(ICONV_CAST, $cast, [cast for second arg to iconv()])
+ AC_MSG_RESULT($msg)
+ UNSTASH_FLAGS
########################################################################### libnsl
AC_CHECK_LIB([c], [gethostbyname],
[nsl_ldflags=],
AC_DEFINE(HAVE_UCRED, 1, define to 1 you have struct ucred)
fi
########################################################################### gengetopt
-echo 'option "z" z "" flag off' | $gengetopt --file-name conftest-ggo &&
+echo 'option "z" z "" flag off' | $GENGETOPT --file-name conftest-ggo &&
AC_CHECK_DECL(
[gengetopt_args_info_description],
[ggo_descriptions_declared=yes],
HAVE_OGG=yes
AC_CHECK_HEADERS([ogg/ogg.h], [], [HAVE_OGG=no])
AC_CHECK_LIB([ogg], [ogg_stream_init], [], [HAVE_OGG=no])
+ AC_CHECK_LIB([ogg], [ogg_stream_flush_fill], [
+ AC_DEFINE(HAVE_OGG_STREAM_FLUSH_FILL, 1, [libogg >= 1.3.0])])
LIB_SUBST_FLAGS(ogg)
UNSTASH_FLAGS
######################################################################### vorbis
AC_CHECK_LIB([samplerate], [src_process], [], HAVE_SAMPLERATE=no)
LIB_SUBST_FLAGS(samplerate)
UNSTASH_FLAGS
+ ########################################################################## mp4v2
+ STASH_FLAGS
+ LIB_ARG_WITH([mp4v2], [-lmp4v2])
+ HAVE_MP4V2=yes
+ AC_CHECK_HEADER([mp4v2/mp4v2.h], [], [HAVE_MP4V2=no])
+ AC_CHECK_LIB([mp4v2], [MP4Read], [], [HAVE_MP4V2=no])
+ LIB_SUBST_FLAGS(mp4v2)
+ UNSTASH_FLAGS
######################################################################### server
if test -n "$CRYPTOLIB" && test $HAVE_OSL = yes; then
build_server="yes"
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"
- test $HAVE_FAAD = yes && server_errlist_objs="$server_errlist_objs aac_afh aac_common"
+ if test $HAVE_FAAD = yes && test $HAVE_MP4V2 = yes; then
+ server_errlist_objs="$server_errlist_objs aac_afh aac_common"
+ fi
server_objs="add_cmdline($server_cmdline_objs) $server_errlist_objs"
AC_SUBST(server_objs, add_dot_o($server_objs))
AC_DEFINE_UNQUOTED(INIT_SERVER_ERRLISTS,
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
+ if test $HAVE_FAAD = yes -a $HAVE_MP4V2 = yes; then
recv_errlist_objs="$recv_errlist_objs aac_afh aac_common"
fi
recv_objs="add_cmdline($recv_cmdline_objs) $recv_errlist_objs"
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_common aac_afh"
+ if test $HAVE_FAAD = yes -a $HAVE_MP4V2 = yes; then
+ afh_errlist_objs="$afh_errlist_objs aac_afh aac_common"
audio_format_handlers="$audio_format_handlers aac"
fi
play_errlist_objs="$play_errlist_objs flacdec_filter flac_afh"
}
if test $HAVE_FAAD = yes; then
- play_errlist_objs="$play_errlist_objs aacdec_filter aac_afh aac_common"
+ play_errlist_objs="$play_errlist_objs aacdec_filter"
+ fi
+ if test $HAVE_MP4V2 = yes; then
+ play_errlist_objs="$play_errlist_objs aac_afh"
+ fi
+ if test $HAVE_MP4V2 = yes || test $HAVE_FAAD = yes; then
+ play_errlist_objs="$play_errlist_objs aac_common"
fi
if test $HAVE_MAD = yes; then
play_cmdline_objs="$play_cmdline_objs mp3dec_filter"
crypto lib: ${CRYPTOLIB:-[none]}
unix socket credentials: $have_ucred
readline (interactive CLIs): $HAVE_READLINE
- audio formats handlers: $audio_format_handlers
id3 version 2 support: $HAVE_ID3TAG
- filters: $filters
+ faad: $HAVE_FAAD
+ mp4v2: $HAVE_MP4V2
+
+ audio format handlers: $audio_format_handlers
+ filters: $(echo $filters)
writers: $writers
para_fade: $build_fade
PARA_ERROR(FLAC_SKIP_META, "could not skip metadata"), \
PARA_ERROR(FLAC_DECODE_POS, "could not get decode position"), \
PARA_ERROR(FLAC_STREAMINFO, "could not read stream info meta block"), \
+ PARA_ERROR(FLAC_REPLACE_COMMENT, "could not replace vorbis comment"), \
+ PARA_ERROR(FLAC_WRITE_CHAIN, "failed to write metadata chain"), \
#define AFH_RECV_ERRORS \
#define OGG_AFH_COMMON_ERRORS \
- PARA_ERROR(STREAM_PACKETOUT, "ogg stream packet-out error (first packet)"), \
+ PARA_ERROR(STREAM_PACKETOUT, "ogg stream packet-out error"), \
+ PARA_ERROR(STREAM_PACKETIN, "ogg stream packet-in error"), \
PARA_ERROR(SYNC_PAGEOUT, "ogg sync page-out error (no ogg file?)"), \
- PARA_ERROR(STREAM_PAGEIN, "ogg stream page-in error (first page)"), \
+ PARA_ERROR(STREAM_PAGEIN, "ogg stream page-in error"), \
+ PARA_ERROR(STREAM_PAGEOUT, "ogg stream page-out error"), \
PARA_ERROR(OGG_SYNC, "internal ogg storage overflow"), \
PARA_ERROR(OGG_EMPTY, "no ogg pages found"), \
#define AFT_ERRORS \
- PARA_ERROR(BAD_AFSI, "invaiid afs info"), \
+ PARA_ERROR(BAD_AFSI, "invalid afs info"), \
PARA_ERROR(LOCALTIME, "localtime() failed"), \
PARA_ERROR(STRFTIME, "strftime() failed"), \
PARA_ERROR(BAD_PATH, "invalid path"), \
#define STRING_ERRORS \
PARA_ERROR(ATOI_OVERFLOW, "value too large"), \
- PARA_ERROR(STRTOLL, "unknown strtoll error"), \
PARA_ERROR(ATOI_NO_DIGITS, "no digits found in string"), \
PARA_ERROR(ATOI_JUNK_AT_END, "further characters after number"), \
PARA_ERROR(SIZE_PREFIX, "bad size prefix"), \
PARA_ERROR(MP3_INFO, "could not read mp3 info"), \
PARA_ERROR(HEADER_FREQ, "invalid header frequency"), \
PARA_ERROR(HEADER_BITRATE, "invalid header bitrate"), \
-
+ PARA_ERROR(ID3_DETACH, "could not detach id3 frame"), \
+ PARA_ERROR(ID3_ATTACH, "could not atttach id3 frame"), \
+ PARA_ERROR(ID3_SETENCODING, "could not set id3 text encoding field"), \
+ PARA_ERROR(ID3_SETSTRING, "could not set id3 string field"), \
#define AAC_AFH_ERRORS \
PARA_ERROR(STSZ, "did not find stcz atom"), \
PARA_ERROR(MP4ASC, "audio spec config error"), \
PARA_ERROR(AAC_AFH_INIT, "failed to init aac decoder"), \
-
+ PARA_ERROR(MP4V2, "mp4v2 library error"), \
+ PARA_ERROR(NO_AUDIO_TRACK, "file contains no valid audio track"), \
#define AAC_COMMON_ERRORS \
PARA_ERROR(ESDS, "did not find esds atom"), \
#define OGG_AFH_ERRORS \
PARA_ERROR(VORBIS, "vorbis synthesis header-in error (not vorbis?)"), \
+ PARA_ERROR(VORBIS_COMMENTHEADER, "could not create vorbis comment header"), \
PARA_ERROR(OGG_PACKET_IN, "ogg_stream_packetin() failed"), \
PARA_ERROR(OGG_STREAM_FLUSH, "ogg_stream_flush() failed"), \
PARA_ERROR(AACDEC_INIT, "failed to init aac decoder"), \
PARA_ERROR(AAC_DECODE, "aac decode error"), \
-
#define CHUNK_QUEUE_ERRORS \
PARA_ERROR(QUEUE, "packet queue overrun"), \
--- /dev/null
- <li> Stand-alone decoder/player </li>
+<h1>About</h1>
+<hr>
+
+Paraslash is a collection of network audio streaming tools for Unix
+systems. It is written in C and released under the GPLv2.
+
+<ul>
+ <li> Runs on Linux, Mac OS, FreeBSD, NetBSD </li>
+ <li> Mp3, ogg/vorbis, ogg/speex, aac (m4a), wma, flac and ogg/opus support </li>
+ <li> http, dccp and udp network streaming </li>
++ <li> Stand-alone decoder, player, tagger </li>
+ <li> Curses-based gui (<a href="gui.png">screenshot</a>) </li>
+ <li> Integrated volume normalizer, fader, alarm clock </li>
+ <li> Sophisticated audio file selector </li>
+ <li> Command line interface with tab-completion </li>
+ <li> Open source and well documented </li>
+</ul>
+
+<b> Author: </b> André Noll,
+<a href="mailto:maan@tuebingen.mpg.de">maan@tuebingen.mpg.de</a>
+<br>
+Comments and bug reports are welcome. Please provide the version of
+paraslash you are using and relevant parts of the logs.
- XREFERENCE(http://www.underbit.com/products/mad/,
libid3tag). For version-2 ID3 tag support, you'll need
the libid3tag development package libid3tag0-dev. Without
- libid3tag, only version one tags are recognized.
+ libid3tag, only version-1 tags are recognized. The mp3 tagger
+ also needs this library for modifying (id3v1 and id3v2) tags.
- XREFERENCE(http://www.xiph.org/downloads/, ogg vorbis).
For ogg vorbis streams you'll need libogg, libvorbis,
The command
- para_client -- ls -lv
+ para_client -- ls -l=v
gives you a verbose listing of your audio files also showing which
attributes are set.
from the client to the server.
There is no knowledge about the server commands built into para_client,
-so it does not know about addblob commands. Instead, it inspects the
-first data package sent by the server for a magic string. If this
-string was found, it sends STDIN to the server, otherwise it dumps
-data from the server to STDOUT.
+so it does not know about addblob commands. Instead, the server sends
+a special "awaiting data" packet for these commands. If the client
+receives this packet, it sends STDIN to the server, otherwise it
+dumps data from the server to STDOUT.
Streaming protocols
~~~~~~~~~~~~~~~~~~~
operates on undecoded PCM data (visualizers, equalizers etc.). Such
filters are called _decoders_ in general, and xxxdec is the name of
the paraslash decoder for the audio format xxx. For example, the mp3
-decoder filter is called mp3dec.
+decoder is called mp3dec.
Note that the output of the decoder is about 10 times larger than
its input. This means that filters that operate on the decoded audio
Paraslash relies on external libraries for most decoders, so these
libraries must be installed for the decoder to be included in the
-para_filter and para_audiod executables. The oggdec filter depends
-on the libogg and libvorbis libraries for example.
+executables. For example, the mp3dec filter depends on the mad library.
Forward error correction
~~~~~~~~~~~~~~~~~~~~~~~~