]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
Merge commit 'athcx/master'
authorAndre Noll <maan@systemlinux.org>
Sun, 18 Jan 2009 23:29:44 +0000 (00:29 +0100)
committerAndre Noll <maan@systemlinux.org>
Sun, 18 Jan 2009 23:29:44 +0000 (00:29 +0100)
170 files changed:
.gitignore
Doxyfile
FEATURES
INSTALL
Makefile.in
NEWS
README
README.afs
REQUIREMENTS
aac.h
aac_common.c
aacdec_filter.c
acl.c
acl.h
afh.c
afh.ggo [deleted file]
afh.h
afh_common.c
afs.c
afs.h
aft.c
alsa_write.ggo [deleted file]
amp_filter.c
amp_filter.ggo [deleted file]
attribute.c
audioc.c
audioc.ggo [deleted file]
audiod.c
audiod.ggo [deleted file]
audiod.h
audiod_command.c
bash_completion
blob.c
chunk_queue.c
chunk_queue.h
client.c
client.ggo [deleted file]
client.h
client_common.c
close_on_fork.c
color.c [new file with mode: 0644]
color.h [new file with mode: 0644]
command.c
compress_filter.c
compress_filter.ggo [deleted file]
configure.ac
crypt.c
crypt.h
daemon.c
daemon.h
dccp_recv.c
dccp_recv.ggo [deleted file]
dccp_send.c
error.h
exec.c
fade.c
fade.ggo [deleted file]
fd.c
fd.h
file_write.c
file_write.ggo [deleted file]
filter.c
filter.ggo [deleted file]
filter.h
filter_common.c
fsck.c
fsck.ggo [deleted file]
ggo.c
ggo.h
ggo/afh.m4 [new file with mode: 0644]
ggo/alsa_write.ggo [new file with mode: 0644]
ggo/amp_filter.ggo [new file with mode: 0644]
ggo/audioc.m4 [new file with mode: 0644]
ggo/audiod.m4 [new file with mode: 0644]
ggo/client.m4 [new file with mode: 0644]
ggo/color.m4 [new file with mode: 0644]
ggo/compress_filter.ggo [new file with mode: 0644]
ggo/config_file.m4 [new file with mode: 0644]
ggo/daemon.m4 [new file with mode: 0644]
ggo/dccp_recv.ggo [new file with mode: 0644]
ggo/fade.ggo [new file with mode: 0644]
ggo/file_write.ggo [new file with mode: 0644]
ggo/filter.m4 [new file with mode: 0644]
ggo/fsck.m4 [new file with mode: 0644]
ggo/grab_client.ggo [new file with mode: 0644]
ggo/group.m4 [new file with mode: 0644]
ggo/gui.m4 [new file with mode: 0644]
ggo/header.m4 [new file with mode: 0644]
ggo/http_recv.ggo [new file with mode: 0644]
ggo/logfile.m4 [new file with mode: 0644]
ggo/loglevel.m4 [new file with mode: 0644]
ggo/makefile [new file with mode: 0644]
ggo/mp3dec_filter.ggo [new file with mode: 0644]
ggo/oggdec_filter.ggo [new file with mode: 0644]
ggo/osx_write.ggo [new file with mode: 0644]
ggo/recv.m4 [new file with mode: 0644]
ggo/server.m4 [new file with mode: 0644]
ggo/udp_recv.ggo [new file with mode: 0644]
ggo/user.m4 [new file with mode: 0644]
ggo/write.m4 [new file with mode: 0644]
grab_client.c
grab_client.ggo [deleted file]
gui.c
gui.ggo [deleted file]
gui.h
gui_theme.c
hash.h
http_recv.c
http_recv.ggo [deleted file]
http_send.c
ipc.c
mood.c
mp3_afh.c
mp3dec_filter.c
mp3dec_filter.ggo [deleted file]
net.c
net.h
ogg_afh.c
oggdec_filter.c
oggdec_filter.ggo [deleted file]
ortp.h [deleted file]
ortp_recv.c [deleted file]
ortp_recv.ggo [deleted file]
ortp_send.c [deleted file]
osl.c
osl.h
osl_core.h
osx_write.c
osx_write.ggo [deleted file]
para.h
playlist.c
portable_io.h
recv.c
recv.ggo [deleted file]
recv.h
recv_common.c
ringbuffer.c
ringbuffer.h
sched.c
sched.h
score.c
send.h
send_common.c
server.c
server.ggo [deleted file]
server.h
sha1.c
signal.c
signal.h
stat.c
stdin.c
stdin.h
stdout.c
stdout.h
string.c
string.h
time.c
udp_header.h [new file with mode: 0644]
udp_recv.c [new file with mode: 0644]
udp_send.c [new file with mode: 0644]
user_list.c
user_list.h
vss.c
vss.h
wav_filter.c
write.c
write.ggo [deleted file]
write.h
write_common.c
write_common.h

index 18c71cf9ca50130ee76cc7ea17bfae439303497d..a23f234f978061dc07fba413a178549f68cc164d 100644 (file)
@@ -26,3 +26,7 @@ web/sync
 *.swp
 error2.h
 web_sync
+confdefs.h
+conftest
+conftest.c
+
index 45acb18864af63ed040e867ffd8f0b874743d75c..43209a529eb88c7930170ca26c15b03aa9f9b588 100644 (file)
--- a/Doxyfile
+++ b/Doxyfile
@@ -1060,7 +1060,6 @@ INCLUDE_FILE_PATTERNS  =
 # instead of the = operator.
 
 PREDEFINED             = HAVE_MAD \
-                         HAVE_ORTP \
                         HAVE_FAAD \
                          HAVE_OGGVORBIS \
                          __GNUC__=4 \
index 100a49c5c58fa7873373590832312fde8c5f7dd9..8e540a8eb7182ab1017270556e8f702c5d7f0104 100644 (file)
--- a/FEATURES
+++ b/FEATURES
@@ -6,7 +6,7 @@ Features
        * Runs on Linux, Mac OS, FreeBSD, NetBSD, Solaris and probably other
          Unixes
        * Mp3, ogg vorbis, aac(m4a) support
-       * Local or remote http, dccp, and ortp network audio streaming
+       * Local or remote http, dccp, and udp network audio streaming
        * IPv6 support
        * Volume normalizer
        * Stream grabbing at any point in the filter chain
diff --git a/INSTALL b/INSTALL
index 9cc36f41aca382ddcfde6dc45566cf33aa4cba92..b0bbbadbfdde6ade5b2555365dc87f90ca52d5a1 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -11,11 +11,10 @@ See
 <<
 <a href="REQUIREMENTS.html"> REQUIREMENTS </a>
 >>
-for a list of required software. You don't need everything listed
-there. In particular, mp3, ogg vorbis and aac, ortp support is
-optional. Autoconf will detect what is installed on your system
-and will only try to build those executables that can be built with
-your setup.
+for a list of required software. You don't need everything listed there. In
+particular, mp3, ogg vorbis and aac support are all optional. Autoconf will
+detect what is installed on your system and will only try to build those
+executables that can be built with your setup.
 
 Note that no special library (not even the mp3 decoding library libmad)
 is needed for para_server if you only want to stream mp3 files.
@@ -100,10 +99,10 @@ the directory /var/paraslash.
 Alternatively, use the --afs_socket Option to specify a different
 location for the afs command socket.
 
-For this first try, we'll use a debug level of two to make the
-output of para_server more verbose.
+For this first try, we'll use the info loglevel to make the output
+of para_server more verbose.
 
-       para_server -l 2
+       para_server -l info
 
 Now you can use para_client to connect to the server and issue
 commands. Open a new shell (as "bar" on "client_host" in the above
@@ -165,7 +164,7 @@ Paraslash comes with its own receiving and playing software, which
 will be described next. Try the following on client_host (assuming
 Linux/ALSA and an mp3 stream):
 
-       para_recv -l 2 -r 'http -i server_host' > file.mp3
+       para_recv -l info -r 'http -i server_host' > file.mp3
        # (interrupt with CTRL+C after a few seconds)
        ls -l file.mp3 # should not be empty
        para_filter -f mp3dec -f wav < file.mp3 > file.wav
@@ -197,7 +196,7 @@ supposed to play the audio stream. Try
 for help. Usually you have to specify only server_host as the receiver
 specifier for each supported audio format, like this:
 
-       para_audiod -l 2 -r 'mp3:http -i server_host'
+       para_audiod -l info -r 'mp3:http -i server_host'
 
 The preferred way to use para_audiod is to run it once at system start
 as an unprivileged user. para_audiod needs to create a "well-known"
index 4e6ef96258b4f7c2fcf4ee324d0a6ac4b4ae7b01..670be971b5f10a9d9510667ff2af7989648f18b3 100644 (file)
@@ -5,7 +5,8 @@ BINDIR := @bindir@
 VARDIR := /var/paraslash
 PKGDATADIR := @datarootdir@/@PACKAGE_NAME@
 MANDIR := @datarootdir@/man/man1
-
+PACKAGE_VERSION := @PACKAGE_VERSION@
+PACKAGE_STRING := @PACKAGE_STRING@
 install_sh := @install_sh@
 
 build_date := $(shell date)
@@ -59,15 +60,22 @@ BINARIES = para_server para_client para_audioc para_recv \
 man_binaries := $(BINARIES)
 man_pages := $(patsubst %, man/man1/%.1, $(man_binaries))
 man_pages_in := $(patsubst %, web/%.man.in.html, $(man_binaries))
-gengetopts := $(wildcard *.ggo)
-gengetopts_c := $(gengetopts:.ggo=.cmdline.c)
-gengetopts_h := $(gengetopts:.ggo=.cmdline.h)
+
+ggo_dir := ggo
+
+m4_ggos := afh audioc audiod client filter fsck gui recv server write
+all_ggos := $(m4_ggos) dccp_recv oggdec_filter alsa_write fade http_recv \
+       osx_write udp_recv amp_filter compress_filter file_write \
+       grab_client mp3dec_filter
+ggo_generated := $(addsuffix .cmdline.c, $(all_ggos)) $(addsuffix .cmdline.h, $(all_ggos)) \
+       $(addsuffix .ggo, $(addprefix $(ggo_dir)/,$(m4_ggos)))
+
 autocrap := config.h.in configure
-tarball_pfx := @PACKAGE_TARNAME@-@PACKAGE_VERSION@
+tarball_pfx := @PACKAGE_TARNAME@-$(PACKAGE_VERSION)
 tarball_delete = web versions pics .changelog_before_cvs .changelog_cvs .gitignore
 tarball_delete := $(patsubst %,$(tarball_pfx)/%,$(tarball_delete))
-tarball_add := $(gengetopts_c) $(gengetopts_h) $(autocrap)
-tarball := @PACKAGE_TARNAME@-@PACKAGE_VERSION@.tar.bz2
+tarball_add := $(ggo_generated) $(autocrap)
+tarball := @PACKAGE_TARNAME@-$(PACKAGE_VERSION).tar.bz2
 
 .PHONY: clean distclean maintainer-clean install man tarball
 all: $(BINARIES) $(man_pages)
@@ -77,58 +85,7 @@ tarball: $(tarball)
 *.o: para.h config.h gcc-compat.h
 
 include Makefile.deps
-
-module_ggo_opts := --set-version="(@PACKAGE_STRING@, $(codename))"
-
-grab_client.cmdline.h grab_client.cmdline.c: grab_client.ggo
-       gengetopt $(module_ggo_opts) \
-               -S \
-               --set-package=grab \
-               --no-handle-help \
-               --no-handle-error \
-               --no-handle-version \
-               --arg-struct-name=grab_client_args_info \
-               --file-name=$(subst .ggo,,$<).cmdline \
-               --func-name $(subst .ggo,,$<)_cmdline_parser < $<
-
-%_recv.cmdline.h %_recv.cmdline.c: %_recv.ggo
-       gengetopt $(module_ggo_opts) \
-               --set-package=$(subst .ggo,,$<) \
-               --arg-struct-name=$(subst .ggo,,$<)_args_info \
-               --file-name=$(subst .ggo,,$<).cmdline \
-               --func-name $(subst .ggo,,$<)_cmdline_parser < $<
-
-%_filter.cmdline.h %_filter.cmdline.c: %_filter.ggo
-       gengetopt $(module_ggo_opts) \
-               --set-package=$(subst .ggo,,$<) \
-               --arg-struct-name=$(subst .ggo,,$<)_args_info \
-               --file-name=$(subst .ggo,,$<).cmdline \
-               --func-name $(subst _filter.ggo,,$<)_cmdline_parser < $<
-%_write.cmdline.h %_write.cmdline.c: %_write.ggo
-       gengetopt -S $(module_ggo_opts) \
-               --set-package=$(subst .ggo,,$<) \
-               --arg-struct-name=$(subst .ggo,,$<)_args_info \
-               --file-name=$(subst .ggo,,$<).cmdline \
-               --func-name $(subst _write.ggo,,$<)_cmdline_parser < $<
-
-%.cmdline.h %.cmdline.c: %.ggo
-       case $< in client.ggo) O="--unamed-opts=command";; \
-               audioc.ggo) O="--unamed-opts=command";; \
-               fsck.ggo) O="--unamed-opts=table";; \
-               afh.ggo) O="--unamed-opts=audio_file";; \
-               recv.ggo) O="--no-handle-help";; \
-               filter.ggo) O="--no-handle-help";; \
-               write.ggo) O="--no-handle-help";; \
-               audiod.ggo) O="--no-handle-help";; \
-       esac; \
-       if test $< != fsck.ggo; then O="$$O --conf-parser "; fi; \
-       gengetopt $$O \
-               --no-handle-version \
-               --file-name=$(*F).cmdline \
-               --func-name $(*F)_cmdline_parser \
-               --arg-struct-name=$(*F)_args_info \
-               --set-package="para_$(subst .cmdline,,$(*F))" \
-               --set-version="@PACKAGE_VERSION@"  < $<
+include $(ggo_dir)/makefile
 
 %_command_list.c %_command_list.h: %.cmd
        ./command_util.sh c < $< >$@
@@ -147,21 +104,9 @@ man/man1/para_audiod.1: para_audiod audiod_command_list.man
        mkdir -p man/man1
        help2man -h --detailed-help -N -i audiod_command_list.man ./para_audiod > $@
 
-man/man1/para_filter.1: para_filter
-       mkdir -p man/man1
-       help2man -h --detailed-help -N ./$< > $@
-
-man/man1/para_write.1: para_write
-       mkdir -p man/man1
-       help2man -h --detailed-help -N ./$< > $@
-
-man/man1/para_recv.1: para_recv
-       mkdir -p man/man1
-       help2man -h --detailed-help -N ./$< > $@
-
 man/man1/%.1: %
        mkdir -p man/man1
-       help2man -N ./$< > $@
+       help2man -h --detailed-help -N ./$< > $@
 
 man/html/%.html: man/man1/%.1
        mkdir -p man/html
@@ -171,12 +116,6 @@ web/%.man.in.html: man/man1/%.1
        man2html $< | sed -e '/^<\/BODY>/,$$d' -e '1,/<\/HEAD><BODY>/d' > $@
 
 
-ortp_recv.o: ortp_recv.c
-       $(CC) -c $(CPPFLAGS) $(DEBUG_CPPFLAGS) @ortp_cppflags@ $<
-
-ortp_send.o: ortp_send.c
-       $(CC) -c $(CPPFLAGS) $(DEBUG_CPPFLAGS) @ortp_cppflags@ $<
-
 oggdec_filter.o: oggdec_filter.c
        $(CC) -c $(CPPFLAGS) $(DEBUG_CPPFLAGS) @oggvorbis_cppflags@ $<
 ogg_afh.o: ogg_afh.c
@@ -242,7 +181,7 @@ distclean: clean
        rm -f GPATH GRTAGS GSYMS GTAGS
 
 maintainer-clean: distclean
-       rm -f $(gengetopts_c) $(gengetopts_h) *.tar.bz2 \
+       rm -f $(ggo_generated) *.tar.bz2 \
                config.h configure \
                config.h.in skencil/*.pdf skencil/*.ps
        rm -f *_command_list.* *.man man/man1/*
@@ -254,7 +193,7 @@ install: all man
        $(install_sh) -m 644 $(man_pages) $(MANDIR)
        mkdir -p $(VARDIR) >/dev/null 2>&1 || true # not fatal, so don't complain
 
-@PACKAGE_TARNAME@-@PACKAGE_VERSION@.tar.bz2: $(tarball_add)
+@PACKAGE_TARNAME@-$(PACKAGE_VERSION).tar.bz2: $(tarball_add)
        rm -rf $(tarball_pfx).tar.bz2 $(tarball_pfx)
        git archive --format=tar --prefix=$(tarball_pfx)/ HEAD \
                | tar --delete $(tarball_delete) > $(tarball_pfx).tar
diff --git a/NEWS b/NEWS
index 8418cd8a13ea75e6eec656c0beafd15f7f702a20..5464bd7a92c2d153902afc6ab0c838edfe24c3d8 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,11 +4,28 @@ NEWS
 ----------------------------------------------
 0.3.4 (to be announced) "elliptic inheritance"
 ----------------------------------------------
+
+The new udp sender, colored logs and various other improvements.
+
+       - The udp sender replaces the ortp sender. The new code is
+         both smaller and cleaner than the old ortp sender/receiver
+         code. As the udp sender does not depend on any special
+         libraries, it is built unconditionally. The default port
+         for udp streaming now defaults to 8000, like for the http
+         and the dccp senders/receivers.
+       - Loglevels are now specified as symbolic names, e.g.
+         "--loglevel info".
+       - para_server/para_audiod: Color support for log messages.
        - new options for mp3dec: --ignore-crc, --bufsize
+       - new audiod option: --config-file.
+       - gengetopt cleanups.
        - Improved help/man pages: The documentation of para_audiod,
          para_recv, para_filter and para_write now also contains
-         all options of the available receivers/filters/writers.
-       - new audiod option: --config-file.
+         all options of the available receivers/filters/writers. The
+         man page of para_fade contains a description of the different
+         modes of operation.
+       - More source code documentation.
+       - vss timing fixes.
 
 --------------------------------------------
 0.3.3 (2008-12-01) "axiomatic perspectivity"
diff --git a/README b/README
index 3308d0b3f3f0cc45c83af7ca218688c39e3b34d0..dd0dc76a0be00a395ad91ab19834bf2c0974f65d 100644 (file)
--- a/README
+++ b/README
@@ -18,7 +18,7 @@ accepts commands such as play, stop, pause, next from authenticated
 clients. However, there are many more commands.
 
 It supports three built-in network streaming methods (senders): http, dccp,
-or rtp.
+or udp.
 
        * The http sender is recommended for public streams that can be played
          by any player like mpg123, xmms, itunes, winamp...
@@ -26,7 +26,7 @@ or rtp.
        * The dccp sender requires kernel support for the datagram congestion
          control protocol.
 
-       * The ortp sender is recommended for multicast LAN streaming.
+       * The udp sender is recommended for multicast LAN streaming.
 
 It is possible to activate more than one sender simultaneously.
 
@@ -58,7 +58,7 @@ Its features include
 
 Despite of all these features, paraslash is lightweight. The
 stripped binary of para_server with all its features compiled in
-mp3/ogg/aac support, http/dccp/ortp support) is about 160K on i386
+mp3/ogg/aac support, http/dccp/udp support) is about 160K on i386
 under Linux. para_audiod (see below) is even smaller.
 
 -----------
@@ -79,7 +79,7 @@ encrypted with a symmetric rc4 session key.
 para_recv
 ---------
 
-A command line http/dccp/ortp stream grabber. The http mode of this
+A command line http/dccp/udp stream grabber. The http mode of this
 tool can be used to receive data from any http streaming source.
 
 -----------
index 9e588a6a6c7a888168bf61af239823e81c98f560..ca01df6ac678a7cb3b1be14ac5957a1ddb1a4137 100644 (file)
@@ -225,10 +225,10 @@ songs is
 Troubles?
 ---------
 
-Use loglevel one (option -l 1 for most commands) to show debugging
-info. Almost all paraslash executables have a brief online help which
-is displayed by using the -h switch. The --detailed-help option prints
-the full help text.
+Use the debug loglevel (option -l debug for most commands) to show
+debugging info. Almost all paraslash executables have a brief online
+help which is displayed by using the -h switch. The --detailed-help
+option prints the full help text.
 
 para_fsck tries to fix your database. Use --force (even if your name
 isn't Luke) to clean up after a crash. However, first make sure
index b03c4c3f98a2fcef432389daa329893cfb7ca490..c1743fd2fb55f810f95949d7586ff7c3376b2801 100644 (file)
@@ -42,11 +42,6 @@ Optional features:
          http://www.audiocoding.com/.
          Debian package: libfaad-dev.
 
-       - *ortp*:
-         If you intend to use the optional ortp streamer, you'll
-         need libortp which is contained in the linphone source code:
-         http://www.linphone.org/index.php/eng
-
        - On Linux, you'll need to have ALSA's development package
          installed. The Debian package is called libasound2-dev.
 
@@ -58,3 +53,4 @@ Hacking the source:
        - grutatxt http://www.triptico.com/software/grutatxt.html
        - doxygen http://www.stack.nl/~dimitri/doxygen/
        - global ftp://ftp.gnu.org/pub/gnu/global
+       - m4: ftp://ftp.gnu.org/pub/gnu/m4/
diff --git a/aac.h b/aac.h
index ddb26e5e2d68294448dbfa890e78f148e0e1598b..1efe75aceeb3a3935acfc21b50fd548344c09306 100644 (file)
--- a/aac.h
+++ b/aac.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 290622edb27cf3a0949395881d4b3e01ba5266d9..fda6346011c5aae30c6ede3fc0f8347ef838e161 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 8eddc0e71566d7c9cb816a5d52d70e5d35bb5b84..d9226b0d8d37e221ef6ac2f15e383a1063389241 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/acl.c b/acl.c
index a3e161db3278c3db1e7b82d1836cbaa16e8897ec..72869ee8c79f71756dad66ebac0763592c07be39 100644 (file)
--- a/acl.c
+++ b/acl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/acl.h b/acl.h
index 0e53ce0520b4687076c66e8addab95ffd2e70c90..60185937dc7ce20b342f6c8558a92db4f8985cbb 100644 (file)
--- a/acl.h
+++ b/acl.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2008-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/afh.c b/afh.c
index 24c2bc67dcd81addb013f2f00a87a64494f5933a..fad93c49cdca17f54558c2c6cdc25646773bea11 100644 (file)
--- a/afh.c
+++ b/afh.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2008-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -21,7 +21,9 @@ static struct afh_args_info conf;
 const char *status_item_list[] = {STATUS_ITEM_ARRAY};
 
 INIT_AFH_ERRLISTS;
-INIT_STDERR_LOGGING(conf.loglevel_arg)
+
+static int loglevel;
+INIT_STDERR_LOGGING(loglevel)
 
 static void print_info(int audio_format_num, struct afh_info *afhi)
 {
@@ -139,6 +141,7 @@ int main(int argc, char **argv)
 
        afh_cmdline_parser(argc, argv, &conf);
        HANDLE_VERSION_FLAG("afh", conf);
+       loglevel = get_loglevel_by_name(conf.loglevel_arg);
        ret = -E_AFH_SYNTAX;
        if (conf.inputs_num == 0)
                goto out;
diff --git a/afh.ggo b/afh.ggo
deleted file mode 100644 (file)
index 056a34d..0000000
--- a/afh.ggo
+++ /dev/null
@@ -1,122 +0,0 @@
-text "
-para_afh, the audio format handler tool, is a stand-alone program
-contained in the paraslash package for analyzing and streaming audio
-files. It can be used to
-
-       - print tech info about the given audio file to stdout.
-       In particular, the 'chunk table' of the audio file, an array
-       of offsets within the audio file, may be printed. This table
-       can be used by other programs unaware of the particular audio
-       format to stream the audio file.
-
-       - write selected parts of the given audio file in complete
-       chunks without decoding. Thus para_afh can be used to 'cut'
-       an audio file.
-
-       - write selected parts of the given audio files 'just in time'
-       to sdout.  This may be useful for third-party software that
-       is capable of reading from stdin.
-"
-
-option "loglevel" l
-#~~~~~~~~~~~~~~~~~~
-"set loglevel (0-6)"
-int typestr="level"
-default="4"
-optional
-
-defgroup "mode"
-#--------------
-groupdesc="
-       There are two modes of operation: Info mode and stream mode,
-       one of which must be selected by the corresponding option.
-       See below.
-"
-required
-
-groupoption "info" i
-#~~~~~~~~~~~~~~~~~~~
-"select info mode"
-group="mode"
-details="
-       In this mode, the program prints technical information about
-       the given audio file to stdout.
-"
-
-groupoption "stream" s
-#~~~~~~~~~~~~~~~~~~~~~
-"select stream mode"
-group="mode"
-details="
-       If this mode is selected, the selected parts of the content
-       of the audio file are written to stdout. Only complete chunks
-       with respect of the underlying audio format are written.
-       For example, only complete frames in case of mp3 files.
-"
-
-section "Options for info mode"
-#==============================
-
-option "chunk_table" c
-#~~~~~~~~~~~~~~~~~~~~~
-"print also the chunk table"
-flag off
-dependon="info"
-
-section "Options for stream mode"
-#================================
-
-
-option "begin_chunk" b
-#~~~~~~~~~~~~~~~~~~~~~
-"skip a number of chunks"
-int typestr="chunk_num"
-default="0"
-dependon="stream"
-optional
-details="
-       The chunk_num argument must be between -num_chunks and
-       num_chunks - 1 inclusively where num_chunks is the total number
-       of chunks which is printed when using the --info option. If
-       chunk_num is negative, the given number of chunks are counted
-       backwards from the end of the file. For example --begin_chunk
-       -100 instructs para_afh to start output at chunk num_chunks
-       - 100. This is mainly useful for cutting off the end of an
-       audio file.
-"
-
-option "end_chunk" e
-#~~~~~~~~~~~~~~~~~~~
-"only write up to chunk chunk_num"
-int typestr="chunk_num"
-dependon="stream"
-optional
-details="
-       For the chunk_num argument the same rules as for --begin_chunk
-       apply.  The default is to write up to the last chunk.
-"
-
-option "just_in_time" j
-#~~~~~~~~~~~~~~~~~~~~~~
-"use timed writes"
-flag off
-dependon="stream"
-details="
-       Write the specified chunks of data 'just in time', i.e. the
-       write of each chunk is delayed until the time it is needed
-       by the decoder/player in order to guarantee an uninterupted
-       audio stream.
-"
-
-option "no_header" H
-#~~~~~~~~~~~~~~~~~~~
-"do not write an audio file header"
-flag off
-dependon="stream"
-details="
-       If an audio format needs information about the audio file
-       in a format-specific header in order to be understood by
-       the decoding software, a suitable header is automatically
-       send. This option changes the default behaviour, i.e. no
-       header is written.
-"
diff --git a/afh.h b/afh.h
index e315f7870240b5796098e5cf9994acdfceea6cf5..4e2020bb914411e376d8f274f09df8f07830c010 100644 (file)
--- a/afh.h
+++ b/afh.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index bec99bf4d29b6fb8b75d66e29a627eb4f5a002a3..f7066cfc23e9246b707ad51fe4aa42681fe497d1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/afs.c b/afs.c
index 5f47941e13cae9b43c454e5573fb26de6588f4e8..b8acb53a9ffa2782e8fc0421a9a01f5642347eed 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -766,6 +766,7 @@ static void signal_post_select(struct sched *s, struct task *t)
        st->signum = para_next_signal();
        if (st->signum == SIGHUP) {
                close_afs_tables();
+               parse_config_or_die(1);
                t->error = open_afs_tables();
                if (t->error < 0)
                        return;
@@ -1174,6 +1175,16 @@ int com_check(int fd, int argc, char * const * const argv)
        return 1;
 }
 
+/**
+ * The afs event dispatcher.
+ *
+ * \param event Type of the event.
+ * \param pb May be \p NULL.
+ * \param data Type depends on \a event.
+ *
+ * This function calls the table handlers of all tables and passes \a pb and \a
+ * data verbatim. It's up to the handlers to interpret the \a data pointer.
+ */
 void afs_event(enum afs_events event, struct para_buffer *pb,
                void *data)
 {
diff --git a/afs.h b/afs.h
index a596317f957f2dabb8a7287d689810883f4270b6..267cc8d35a0032e2b221162857507df9a4358b6c 100644 (file)
--- a/afs.h
+++ b/afs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -61,14 +61,23 @@ enum afs_events {
        BLOB_REMOVE,
 };
 
+/**
+ * Used as data for \ref afs_event() for events of type \p ATTRIBUTE_ADD.
+ */
 struct rmatt_event_data {
+       /** The name of the attribute being added. */
        const char *name;
+       /** Its bit number. */
        unsigned char bitnum;
 };
 
-
+/**
+ * Used as data for \ref afs_event() for events of type \p ATTRIBUTE_AFSI_CHANGE.
+ */
 struct afsi_change_event_data {
+       /** Pointer to the row that has changed. */
        struct osl_row *aft_row;
+       /** Afs info before the change. */
        struct afs_info *old_afsi;
 };
 
@@ -87,7 +96,6 @@ struct afs_table {
        /** Handles afs events. */
        int (*event_handler)(enum afs_events event, struct para_buffer *pb,
                void *data);
-       /* int *(check)() */
 };
 
 enum play_mode {PLAY_MODE_MOOD, PLAY_MODE_PLAYLIST};
diff --git a/aft.c b/aft.c
index d5a355566e387df5bc6e8b1ec06fad03bb660c3e..7bfad504f04b8626ea8fbd436ece8dcef34124ff 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -1008,6 +1008,13 @@ out:
        return ret;
 }
 
+/**
+ * Write a list of audio-file related status items with empty values.
+ *
+ * \param buf Result pointer.
+ *
+ * This is used by vss when currently no audio file is open.
+ */
 void make_empty_status_items(char *buf)
 {
        sprintf(buf,
diff --git a/alsa_write.ggo b/alsa_write.ggo
deleted file mode 100644 (file)
index 84f49d5..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-option "device" d
-#~~~~~~~~~~~~~~~~
-"set PCM device"
-string typestr="device"
-default="default"
-optional
-details="
-       On systems with dmix, a better choice than the default
-       value might be to use \"plug:swmix\".
-"
-
-option "channels" c
-#~~~~~~~~~~~~~~~~~~
-"specify number of channels"
-int typestr="num"
-default="2"
-optional
-details="
-       This option is only necessary for playing raw audio with
-       para_write.  In all other cases (plaing wav files with
-       para_write or using this writer with para_audiod), the number
-       of channels will be obtained from other resources.
-"
-
-option "samplerate" s
-#~~~~~~~~~~~~~~~~~~~~~
-"force given sample rate"
-int typestr="num"
-default="44100"
-optional
-details="
-       Again, it is only necessary to specify this when playing raw
-       audio with para_write.
-"
index a88719e33544b4a08e3d74862ee54cf13cae3d19..a011c411ef376c61f89fa6cc6baf574f04caeb0f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/amp_filter.ggo b/amp_filter.ggo
deleted file mode 100644 (file)
index 865df3a..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-option "amp" a
-#~~~~~~~~~~~~~
-"amplification value"
-int typestr="number"
-default="32"
-optional
-details="
-       The amplification value determines the scaling factor by
-       which the amplitude of the audio stream is multiplied. The
-       formula for the scaling factor is
-
-               factor = 1 + amp / 64.
-
-       For example, an amplifiction value of zero results in a
-       scaling factor of one while an amplification value of 64
-       means to double the volume.
-"
index 655c286697a6ca68c94da410ec5841276dd97ef5..d22511de76f92f19835b6c5c57faa54ba9360eab 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -598,7 +598,11 @@ static int attribute_create(const char *dir)
        return osl_create_table(&attribute_table_desc);
 }
 
-
+/**
+ * Initialize the attribute table structure.
+ *
+ * \param t The table structure to initialize.
+ */
 void attribute_init(struct afs_table *t)
 {
        t->name = attribute_table_desc.name;
index a8f88e315403955fbc04539595ad19236e13c9f2..666990dba411e65b4dfff4d4d227332e7401ac92 100644 (file)
--- a/audioc.c
+++ b/audioc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -21,7 +21,8 @@ INIT_AUDIOC_ERRLISTS;
 /** the gengetopt structure containing command line args */
 struct audioc_args_info conf;
 
-INIT_STDERR_LOGGING(conf.loglevel_arg);
+static int loglevel;
+INIT_STDERR_LOGGING(loglevel);
 
 static char *concat_args(unsigned argc, char * const *argv)
 {
@@ -87,6 +88,7 @@ int main(int argc, char *argv[])
                        exit(EXIT_FAILURE);
                }
        }
+       loglevel = get_loglevel_by_name(conf.loglevel_arg);
        args = conf.inputs_num?
                concat_args(conf.inputs_num, conf.inputs) :
                para_strdup("stat");
diff --git a/audioc.ggo b/audioc.ggo
deleted file mode 100644 (file)
index 87ef71e..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-option "loglevel" l
-#~~~~~~~~~~~~~~~~~~
-"set loglevel (0-6)"
-       int typestr="level"
-       default="4"
-       optional
-
-
-option "socket" s
-#~~~~~~~~~~~~~~~~
-"well-known socket (default=/var/paraslash/audiod.socket.$HOSTNAME)"
-       string typestr="filename"
-       optional
-
-
-option "bufsize" b
-#~~~~~~~~~~~~~~~~~
-"size of internal buffer"
-       int typestr="bytes"
-       default="8192"
-       optional
index 63d42cacb5218b92a8cea76c8a0626349437b8e6..a92c4e3b1ebca665a3804bc168472673fd733037 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -83,7 +83,6 @@ int audiod_status = AUDIOD_ON;
 struct audiod_args_info conf;
 
 static char *socket_name;
-static FILE *logfile;
 static struct audio_format_info afi[NUM_AUDIO_FORMATS];
 
 static struct signal_task signal_task_struct, *sig_task = &signal_task_struct;
@@ -181,42 +180,27 @@ out:
        );
 }
 
-/**
- * the log function of para_audiod
- *
- * \param ll loglevel
- * \param fmt the format string
- */
-__printf_2_3 void para_log(int ll, const char* fmt,...)
+static int want_colors(void)
 {
-       va_list argp;
-       FILE *outfd;
-       struct tm *tm;
-       time_t t1;
-       char str[MAXLINE] = "";
-       static char *hostname;
-
-       if (ll < conf.loglevel_arg)
-               return;
-       if (!logfile && conf.daemon_given)
-               return;
-       if (!hostname)
-               hostname = para_hostname();
-       outfd = logfile? logfile : stderr;
-       time(&t1);
-       tm = localtime(&t1);
-       strftime(str, MAXLINE, "%b %d %H:%M:%S", tm);
-       fprintf(outfd, "%s %s ", str, hostname);
-       if (conf.loglevel_arg <= INFO)
-               fprintf(outfd, "%i ", ll);
-       va_start(argp, fmt);
-       vfprintf(outfd, fmt, argp);
-       va_end(argp);
+       if (conf.color_arg == color_arg_no)
+               return 0;
+       if (conf.color_arg == color_arg_yes)
+               return 1;
+       if (conf.logfile_given)
+               return 0;
+       return isatty(STDERR_FILENO);
 }
 
 static void parse_config_or_die(void)
 {
        char *config_file;
+       struct audiod_cmdline_parser_params params = {
+               .override = 0,
+               .initialize = 0,
+               .check_required = 1,
+               .check_ambiguity = 0,
+               .print_errors = 1
+       };
 
        if (conf.config_file_given)
                config_file = para_strdup(conf.config_file_arg);
@@ -229,20 +213,12 @@ static void parse_config_or_die(void)
                PARA_EMERG_LOG("can not read config file %s\n", config_file);
                goto err;
        }
-       if (config_file) {
-               struct audiod_cmdline_parser_params params = {
-                       .override = 0,
-                       .initialize = 0,
-                       .check_required = 1,
-                       .check_ambiguity = 0,
-                       .print_errors = 1
-               };
-               if (audiod_cmdline_parser_config_file(config_file, &conf, &params)) {
-                       PARA_EMERG_LOG("parse error in config file\n");
-                       goto err;
-               }
+       if (audiod_cmdline_parser_config_file(config_file, &conf, &params)) {
+               PARA_EMERG_LOG("parse error in config file\n");
+               goto err;
        }
        free(config_file);
+       daemon_set_loglevel(conf.loglevel_arg);
        return;
 err:
        free(config_file);
@@ -1109,6 +1085,20 @@ __noreturn static void print_help_and_die(void)
        exit(0);
 }
 
+static void init_colors_or_die(void)
+{
+       int ret, i;
+
+       if (!want_colors())
+               return;
+       daemon_set_default_log_colors();
+       daemon_set_flag(DF_COLOR_LOG);
+       for (i = 0; i < conf.log_color_given; i++) {
+               ret = daemon_set_log_color(conf.log_color_arg[i]);
+               if (ret < 0)
+                       exit(EXIT_FAILURE);
+       }
+}
 
 /**
  * the main function of para_audiod
@@ -1136,18 +1126,24 @@ int main(int argc, char *argv[])
        valid_fd_012();
        audiod_cmdline_parser_ext(argc, argv, &conf, &params);
        HANDLE_VERSION_FLAG("audiod", conf);
-       para_drop_privileges(conf.user_arg, conf.group_arg);
+       drop_privileges_or_die(conf.user_arg, conf.group_arg);
        parse_config_or_die();
-       if (conf.logfile_given)
-               logfile = open_log(conf.logfile_arg);
-       i = init_stream_io();
        if (conf.help_given || conf.detailed_help_given)
                print_help_and_die();
+       daemon_set_flag(DF_LOG_TIME);
+       daemon_set_flag(DF_LOG_HOSTNAME);
+       daemon_set_flag(DF_LOG_LL);
+       if (conf.logfile_given) {
+               daemon_set_logfile(conf.logfile_arg);
+               daemon_open_log_or_die();
+       }
+       init_colors_or_die();
+       i = init_stream_io();
        if (i < 0) {
                PARA_EMERG_LOG("init stream io error: %s\n", para_strerror(-i));
                exit(EXIT_FAILURE);
        }
-       log_welcome("para_audiod", conf.loglevel_arg);
+       log_welcome("para_audiod");
        server_uptime(UPTIME_SET);
        set_initial_status();
        FOR_EACH_SLOT(i)
@@ -1160,7 +1156,7 @@ int main(int argc, char *argv[])
        init_command_task(cmd_task);
 
        if (conf.daemon_given)
-               daemon_init();
+               daemonize();
 
        register_task(&sig_task->task);
        register_task(&cmd_task->task);
diff --git a/audiod.ggo b/audiod.ggo
deleted file mode 100644 (file)
index 8f960c6..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-#########################
-section "General options"
-#########################
-
-text "
-       These options are identical to their counterparts in para_server
-       and are discussed in detail there.
-"
-
-option "loglevel" l
-#~~~~~~~~~~~~~~~~~~
-"set loglevel (1-6)"
-int typestr="level"
-default="4"
-optional
-
-option "config_file" c
-#~~~~~~~~~~~~~~~~~~~~~
-"(default='~/.paraslash/audiod.conf'"
-string typestr="filename"
-optional
-
-option "logfile" L
-#~~~~~~~~~~~~~~~~~
-"where to write log output"
-string typestr="filename"
-optional
-
-option "daemon" d
-#~~~~~~~~~~~~~~~~
-"run as background daemon"
-flag off
-dependon="logfile"
-
-option "user" u
-#~~~~~~~~~~~~~~
-"run as the given user"
-string typestr="name"
-optional
-
-option "group" g
-#~~~~~~~~~~~~~~~
-"set group id"
-string typestr="group"
-optional
-
-########################
-section "Audiod options"
-########################
-
-option "force" F
-#~~~~~~~~~~~~~~~
-"force startup"
-flag off
-details="
-       If this flag is not given, para_audiod refuses to start if the
-       well-known socket file (see the --socket option) already exists
-       because this usually means that para_audiod is already running
-       and listening on that socket. After a crash or if para_audiod
-       received a SIGKILL signal, a stale socket file might remain and
-       you have to use --force once to force startup of para_audiod.
-"
-
-option "mode" m
-#~~~~~~~~~~~~~~
-"startup mode"
-string typestr="mode"
-default="on"
-optional
-details="
-       Para_audiod supports three modes of operation: On, off and
-       standby (sb).  This option selects the mode that should be
-       used on startup. If para_audiod operates in \"on\" mode, it
-       will connect to para_server in order to receive its status
-       information. If para_server announces the availability of an
-       audio stream, para_audiod will automatically download, decode
-       and play the audio stream according to the given stream I/O
-       options, see below.
-
-       In \"standby\" mode, para_audiod will only receive the
-       status information from para_server but will not download
-       the audio stream.
-
-       In \"off\" mode, para_audiod does not connect para_server at
-       all, but still listens on the local socket for connections.
-"
-
-option "socket" s
-#~~~~~~~~~~~~~~~~
-"well-known socket"
-string typestr="filename"
-optional
-details="
-       Para_audiod uses a \"well-known\" socket to listen
-       on for connections from para_audioc. This socket is a
-       special file in the file system; its location defaults to
-       /var/paraslash/audiod_sock.<host_name>.
-
-       para_audioc, the client program used to connect to para_audiod,
-       opens this socket in order to talk to para_audiod.  If the
-       default value for para_audiod is changed, para_audioc must be
-       instructed to use also \"filename\" for connecting para_audiod.
-"
-
-option "user_allow" -
-#~~~~~~~~~~~~~~~~~~~~
-"allow this uid"
-int typestr="uid"
-default="-1"
-optional
-multiple
-details="
-       Allow the user identified by \"uid\" to connect to para_audiod.
-       May be specified multiple times. If not specified at all,
-       all users are allowed to connect.
-
-       This feature requires unix socket credentials and is currently
-       only supported on Linux systems. On other operating systems,
-       the option is silently ignored and all local users are allowed
-       to connect to para_audiod.
-"
-
-option "clock_diff_count" -
-#~~~~~~~~~~~~~~~~~~~~~~~~~~
-"sync clock on startup"
-int typestr="count"
-default="0"
-optional
-details="
-       Check the clock difference between the host running para_server
-       and the local host running para_audiod that many times before
-       starting any stream I/0. Set this to non-zero for non-local
-       setups if the clocks of these two hosts are not syncronized
-       by ntp or similar.
-"
-
-#############################
-section "Stream I/O options"
-#############################
-
-option "receiver" r
-#~~~~~~~~~~~~~~~~~~
-"select receiver"
-string typestr="receiver_spec"
-default="http"
-optional
-multiple
-details="
-       This option may be given multiple times, once for each
-       supported audio format. The \"receiver_spec\" consists of
-       an audio format and the receiver name, separated by a colon,
-       and any options for that receiver, seperated by whitespace.
-       If any receiver options are present, the whole receiver
-       argument must be quoted.
-
-       Example:
-
-               -r 'mp3:http -i my.host.org -p 8009'
-"
-
-
-option "no_default_filters" D
-#~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"Configure filters manually"
-flag off
-details="
-       If (and only if) this option is set, the --filter options
-       (see below) take effect.  Otherwise, the compiled-in default
-       filters mp3dec, oggdec and aacdec are activated for mp3, ogg,
-       aac streams respectively.
-"
-
-option "filter" f
-#~~~~~~~~~~~~~~~~
-"Use non-default filters"
-string typestr="filter_spec"
-optional
-multiple
-dependon="no_default_filters"
-details="
-       This option may be given multiple times. The \"filter_spec\"
-       consists of an audio format, the name of the filter, and any
-       options for that filter. Mote that order matters.
-
-       Examples:
-
-               --filter 'mp3:mp3dec'
-
-               --filter 'mp3:compress --inertia 5 --damp 2'
-
-"
-
-option "writer" w
-#~~~~~~~~~~~~~~~~
-"Specify stream writer."
-string typestr="writer_spec"
-optional
-multiple
-details="
-       May be given multiple times, even multiple times for the same
-       audio format.  Default value is \"alsa\" for all supported
-       audio formats. Example:
-
-               --writer 'aac:osx'
-
-"
-
-option "stream_delay" -
-#~~~~~~~~~~~~~~~~~~~~~~
-"time for client sync"
-int typestr="milliseconds"
-default="200"
-optional
-details="
-       Add the given amount of milliseconds to the stream start time
-       announced by para_server and do not send data to the writer
-       before that time (modulo clock difference).
-
-       This is useful mainly for syncronizing the audio output of
-       different clients.
-"
index 60de4caf8131368b8684f479f5f24db60fed156e..5bd41c4fa00f52f3b6b24d4508967ecd707d418d 100644 (file)
--- a/audiod.h
+++ b/audiod.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 27ef63caea22f9af45d9a951a5df39d1cb078210..a6f6776267b1183ec947cf4bbfdf268fe3e8077d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index aeee64c17713f7d1d16cb1b226958fcf7d304124..cd647e2096b61ce583a4bd48318484cb814762e9 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Licensed under the GPL v2. For licencing details see COPYING.
 
-PC="para_client -l 5 -- "
+PC="para_client -l error -- "
 
 __para_commandlist=
 __para_sender_list=
diff --git a/blob.c b/blob.c
index fd8ddc801ccce343914a2845c1b0c0c96c5b7d6c..1742ac427c85e6e7cc35becc9cfbe508e45bf750 100644 (file)
--- a/blob.c
+++ b/blob.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 571f8d18689c908130bf3d37aaab75a968183a4d..fa31718590dd73fad6f034d69ce2a8d7fc299e86 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 9959b74cdf8a33f3bddc4bdad04bb49b2f6001b2..2bed999cec5ecadc17b791db4a6ae85da78158ce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 4208579b5e756bbbee9ec03cd10613e13c9a596e..fdd07b247e617c86d3f38ff059d8bb8672356a9c 100644 (file)
--- a/client.c
+++ b/client.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -54,7 +54,8 @@ static struct task svt = {
        .status = "supervisor task"
 };
 
-INIT_STDERR_LOGGING(ct->conf.loglevel_arg);
+static int client_loglevel; /* loglevel */
+INIT_STDERR_LOGGING(client_loglevel);
 
 
 /**
@@ -82,6 +83,7 @@ int main(int argc, char *argv[])
        ret = client_open(argc, argv, &ct);
        if (ret < 0) /* can not use PARA_LOG here because ct is NULL */
                exit(EXIT_FAILURE);
+       client_loglevel = get_loglevel_by_name(ct->conf.loglevel_arg);
        register_task(&svt);
        ret = schedule(&s);
        if (ret < 0)
diff --git a/client.ggo b/client.ggo
deleted file mode 100644 (file)
index 1d6b410..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# file client.conf
-args "--no-handle-error"
-option "hostname" i "ip or host to connect" string typestr="host" default="localhost" optional
-option "user" u "paraslash username" string typestr="username" default="<current user>" optional
-option "server_port" p "port to connect" int typestr="port" default="2990" optional
-option "key_file" k "(default='~/.paraslash/key.<user>')" string typestr="filename" optional
-option "loglevel" l "set loglevel (0-6)" int typestr="number" default="5" optional
-option "config_file" c "(default='~/.paraslash/client.conf')" string typestr="filename" optional
-option "plain" - "request an uncrypted session" flag off
index dcec361129b3cbe0223bbe80dfbdfbc2e3f17eac..b813f186590b3d505ee20187ba050cee38c02c0c 100644 (file)
--- a/client.h
+++ b/client.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 9886cfe5f93ef187f0f61fc0642a68b41f0b0619..e757a3a7a954bb6885a61613ce19c7158f96330f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -364,7 +364,7 @@ int client_open(int argc, char *argv[], struct client_task **ct_ptr)
                        goto out;
        }
        ret = 1;
-       PARA_INFO_LOG("loglevel: %d\n", ct->conf.loglevel_arg);
+       PARA_INFO_LOG("loglevel: %s\n", ct->conf.loglevel_arg);
        PARA_INFO_LOG("config_file: %s\n", ct->config_file);
        PARA_INFO_LOG("key_file: %s\n", ct->key_file);
        PARA_NOTICE_LOG("connecting %s:%d\n", ct->conf.hostname_arg,
index 4f7c2b955a4d9f1404386f57b8246b803115a2bf..299aab0b0f613750481657951837da1626ed9aff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/color.c b/color.c
new file mode 100644 (file)
index 0000000..bd09446
--- /dev/null
+++ b/color.c
@@ -0,0 +1,132 @@
+/** \file color.c Functions for printing colored messages. */
+
+/*
+ * Mostly taken from the git source tree, version 1.6.1.76, January 2008.
+ */
+
+#include "para.h"
+#include "color.h"
+
+static int parse_color(const char *name, int len)
+{
+       static const char * const color_names[] = {
+               "normal", "black", "red", "green", "yellow",
+               "blue", "magenta", "cyan", "white"
+       };
+       char *end;
+       int i;
+       for (i = 0; i < ARRAY_SIZE(color_names); i++) {
+               const char *str = color_names[i];
+               if (!strncasecmp(name, str, len) && !str[len])
+                       return i - 1;
+       }
+       i = strtol(name, &end, 10);
+       if (end - name == len && i >= -1 && i <= 255)
+               return i;
+       return -2;
+}
+
+static int parse_attr(const char *name, int len)
+{
+       static const int attr_values[] = { 1, 2, 4, 5, 7 };
+       static const char * const attr_names[] = {
+               "bold", "dim", "ul", "blink", "reverse"
+       };
+       int i;
+       for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
+               const char *str = attr_names[i];
+               if (!strncasecmp(name, str, len) && !str[len])
+                       return attr_values[i];
+       }
+       return -1;
+}
+
+/**
+ * Create an escape sequence for colored output.
+ *
+ * \param value Human-readable color spec.
+ * \param dst Result pointer for the escape sequence.
+ *
+ * \return -1 on errors, 1 on success.
+ *
+ * Format of \a value: [fg [bg]] [attr].
+ */
+int color_parse(const char *value, char *dst)
+{
+       const char *ptr = value;
+       int attr = -1;
+       int fg = -2;
+       int bg = -2;
+
+       if (!strcasecmp(value, "reset")) {
+               strcpy(dst, COLOR_RESET);
+               return 1;
+       }
+
+       /* [fg [bg]] [attr] */
+       while (*ptr) {
+               const char *word = ptr;
+               int val, len = 0;
+
+               while (word[len] && !isspace(word[len]))
+                       len++;
+
+               ptr = word + len;
+               while (*ptr && isspace(*ptr))
+                       ptr++;
+
+               val = parse_color(word, len);
+               if (val >= -1) {
+                       if (fg == -2) {
+                               fg = val;
+                               continue;
+                       }
+                       if (bg == -2) {
+                               bg = val;
+                               continue;
+                       }
+                       goto bad;
+               }
+               val = parse_attr(word, len);
+               if (val < 0 || attr != -1)
+                       goto bad;
+               attr = val;
+       }
+
+       if (attr >= 0 || fg >= 0 || bg >= 0) {
+               int sep = 0;
+
+               *dst++ = '\033';
+               *dst++ = '[';
+               if (attr >= 0) {
+                       *dst++ = '0' + attr;
+                       sep++;
+               }
+               if (fg >= 0) {
+                       if (sep++)
+                               *dst++ = ';';
+                       if (fg < 8) {
+                               *dst++ = '3';
+                               *dst++ = '0' + fg;
+                       } else {
+                               dst += sprintf(dst, "38;5;%d", fg);
+                       }
+               }
+               if (bg >= 0) {
+                       if (sep++)
+                               *dst++ = ';';
+                       if (bg < 8) {
+                               *dst++ = '4';
+                               *dst++ = '0' + bg;
+                       } else {
+                               dst += sprintf(dst, "48;5;%d", bg);
+                       }
+               }
+               *dst++ = 'm';
+       }
+       *dst = 0;
+       return 1;
+bad:
+       PARA_ERROR_LOG("bad color value '%s'\n", value);
+       return -1;
+}
diff --git a/color.h b/color.h
new file mode 100644 (file)
index 0000000..12972b3
--- /dev/null
+++ b/color.h
@@ -0,0 +1,10 @@
+/** \file color.h Exported functions from color.c. */
+
+
+/** "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
+#define COLOR_MAXLEN 24
+
+/** Switch back to normal colors. */
+#define COLOR_RESET "\033[m"
+
+int color_parse(const char *value, char *dst);
index 3932ed2215691ea12fbbf04b7c7de9884c4cce4b..9abe04a341f94520a3720167e6610f1940e9fb24 100644 (file)
--- a/command.c
+++ b/command.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -283,7 +283,7 @@ int com_si(int fd, int argc, __a_unused char * const * argv)
                "server_pid: %d\n"
                "afs_pid: %d\n"
                "connections (active/accepted/total): %u/%u/%u\n"
-               "current loglevel: %i\n"
+               "current loglevel: %s\n"
                "supported audio formats: %s\n"
                "supported senders: %s\n"
                "%s",
index c7af325385ae7013dc44d64fa061266903aee040..f853b6335d5a9fd9744f86343dd22df6184e6ca1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/compress_filter.ggo b/compress_filter.ggo
deleted file mode 100644 (file)
index 74dcbc0..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-option "blocksize" b
-#~~~~~~~~~~~~~~~~~~~
-"adjust block size"
-int typestr="number"
-default="15"
-optional
-details = "
-       Larger blocksize means fewer volume adjustments per time unit.
-"
-
-option "aggressiveness" a
-#~~~~~~~~~~~~~~~~~~~~~~~~
- "controls the maximum amount to amplify by"
-int typestr="number"
-default="4"
-optional
-
-option "inertia" i
-#~~~~~~~~~~~~~~~~~
- "how much inertia ramping has"
- int typestr="number"
-default="6"
-optional
-
-option "target_level" t
-#~~~~~~~~~~~~~~~~~~~~~~
-"target signal level (0-32768)"
-int typestr="number"
-default="20000"
-optional
-
-option "damp" d
-#~~~~~~~~~~~~~~
-"if non-zero, scale down after normalizing"
-int typestr="number"
-default="0"
-optional
index 664280ac9a4835e8e5fe1209584fb25217e2554a..afb993af265065e7082adcf9ebbececa99f11b57 100644 (file)
@@ -83,17 +83,18 @@ daemon stat crypt http_send close_on_fork ipc acl afh fade amp_filter
 dccp_send fd user_list chunk_queue afs osl aft mood score attribute blob ringbuffer
 playlist sha1 rbtree sched audiod grab_client filter_common wav_filter compress_filter
 http_recv dccp_recv recv_common write_common file_write audiod_command
-client_common recv stdout filter stdin audioc write client fsck exec send_common ggo"
+client_common recv stdout filter stdin audioc write client fsck exec send_common ggo
+udp_recv udp_send color"
 
 all_executables="server recv filter audioc write client fsck afh"
 
-recv_cmdline_objs="recv.cmdline http_recv.cmdline dccp_recv.cmdline"
+recv_cmdline_objs="recv.cmdline http_recv.cmdline dccp_recv.cmdline udp_recv.cmdline"
 recv_errlist_objs="http_recv recv_common recv time string net dccp_recv
-       fd sched stdout ggo"
+       fd sched stdout ggo udp_recv"
 recv_ldflags=""
 
-receivers=" http dccp"
-senders=" http dccp"
+receivers=" http dccp udp"
+senders=" http dccp udp"
 
 filter_cmdline_objs="filter.cmdline compress_filter.cmdline amp_filter.cmdline"
 filter_errlist_objs="filter_common wav_filter compress_filter filter string stdin stdout sched fd amp_filter ggo"
@@ -106,11 +107,11 @@ audioc_ldflags=""
 
 audiod_cmdline_objs="audiod.cmdline grab_client.cmdline compress_filter.cmdline
        http_recv.cmdline dccp_recv.cmdline file_write.cmdline client.cmdline
-       audiod_command_list amp_filter.cmdline"
+       audiod_command_list amp_filter.cmdline udp_recv.cmdline"
 audiod_errlist_objs="audiod signal string daemon stat net
        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 crypt
-       client_common ggo"
+       client_common ggo udp_recv color"
 audiod_ldflags=""
 audiod_audio_formats=""
 
@@ -122,7 +123,7 @@ server_cmdline_objs="server.cmdline server_command_list afs_command_list"
 server_errlist_objs="server afh_common mp3_afh vss command net string signal
        time daemon stat crypt http_send close_on_fork
        ipc dccp_send fd user_list chunk_queue afs osl aft mood score attribute
-       blob playlist sha1 rbtree sched acl send_common"
+       blob playlist sha1 rbtree sched acl send_common udp_send color"
 server_ldflags=""
 server_audio_formats=" mp3"
 
@@ -500,52 +501,6 @@ fi
 CPPFLAGS="$OLD_CPPFLAGS"
 LDFLAGS="$OLD_LDFLAGS"
 LIBS="$OLD_LIBS"
-########################################################################### ortp
-have_ortp="yes"
-OLD_CPPFLAGS="$CPPFLAGS"
-OLD_LD_FLAGS="$LDFLAGS"
-OLD_LIBS="$LIBS"
-AC_ARG_WITH(ortp_headers, [AC_HELP_STRING(--with-ortp-headers=dir,
-       [look for ortp/ortp.h also in dir])])
-if test -n "$with_ortp_headers"; then
-       ortp_cppflags="-I$with_ortp_headers"
-       CPPFLAGS="$CPPFLAGS $ortp_cppflags"
-fi
-AC_ARG_WITH(ortp_libs, [AC_HELP_STRING(--with-ortp-libs=dir,
-       [look for libortp also in dir])])
-if test -n "$with_ortp_libs"; then
-       ortp_libs="-L$with_ortp_libs"
-       LDFLAGS="$LDFLAGS $ortp_libs"
-fi
-AC_CHECK_HEADERS([ortp/ortp.h], [], [have_ortp="no"])
-AC_CHECK_LIB([ortp], [ortp_init], [], [have_ortp="no"])
-if test "$have_ortp" = "yes"; then
-       all_errlist_objs="$all_errlist_objs ortp_recv ortp_send"
-
-       recv_cmdline_objs="$recv_cmdline_objs ortp_recv.cmdline"
-       recv_errlist_objs="$recv_errlist_objs ortp_recv"
-
-       audiod_cmdline_objs="$audiod_cmdline_objs ortp_recv.cmdline"
-       audiod_errlist_objs="$audiod_errlist_objs ortp_recv"
-
-       server_errlist_objs="$server_errlist_objs ortp_send"
-
-       recv_ldflags="$recv_ldflags $ortp_libs -lortp"
-       server_ldflags="$server_ldflags $ortp_libs -lortp"
-       audiod_ldflags="$audiod_ldflags $ortp_libs -lortp"
-
-       receivers="$receivers ortp"
-       senders="$senders ortp"
-       AC_DEFINE(HAVE_ORTP, 1, [define to 1 to turn on ortp support])
-       AC_SUBST(ortp_cppflags)
-       AC_SUBST(ortp_libs)
-else
-       AC_MSG_NOTICE([deactivating ortp sender/receiver])
-fi
-CPPFLAGS="$OLD_CPPFLAGS"
-LDFLAGS="$OLD_LDFLAGS"
-LIBS="$OLD_LIBS"
-
 
 AC_SUBST(extra_binaries, [$extras])
 AC_SUBST(extra_filter_objs, [$extra_filter_objs])
@@ -735,7 +690,7 @@ AC_DEFINE_UNQUOTED(AUDIOD_AUDIO_FORMAT_ARRAY, $names, array of audio formats sup
 
 AC_OUTPUT
 AC_MSG_NOTICE([creating Makefile.deps])
-gcc -MM -MG $faad_cppflags $mad_cppflags $ortp_cppflags $oggvorbis_cppflags *.c > Makefile.deps
+gcc -MM -MG $faad_cppflags $mad_cppflags $oggvorbis_cppflags *.c > Makefile.deps
 AC_MSG_NOTICE([
 paraslash configuration:
 ~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/crypt.c b/crypt.c
index a19b5ac31f98331ea136c9a8d8bebcadcd006ee4..73eebe180dbe2c32718b5dc7fd271f7ca4b329b1 100644 (file)
--- a/crypt.c
+++ b/crypt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/crypt.h b/crypt.h
index 7ac90677768eedb664ee2488ab44bcf0f7bccec7..88af9e89c10e6cfe468e7c6787bfdde32bbb536c 100644 (file)
--- a/crypt.h
+++ b/crypt.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index bb75478adae6f639b314fa7aa98a7ad2c3501e72..cae63ea7f48488124085d79360458ee44b5620a8 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 #include "para.h"
 #include "daemon.h"
 #include <pwd.h>
-
-/* getgrnam() */
-#include <sys/types.h>
+#include <sys/types.h> /* getgrnam() */
 #include <grp.h>
 
 #include "string.h"
+#include "color.h"
+
+/** The internal state of the daemon. */
+struct daemon {
+       /** See \ref daemon_flags. */
+       unsigned flags;
+       /** Set by \ref daemon_set_logfile(). */
+       char *logfile_name;
+       /** Current loglevel, see \ref daemon_set_loglevel(). */
+       int loglevel;
+
+       /** Used by \ref server_uptime() and \ref uptime_str(). */
+       time_t startuptime;
+       /** The file pointer if the logfile is open. */
+       FILE *logfile;
+       /** Used by para_log() if \p DF_LOG_HOSTNAME is set. */
+       char *hostname;
+       /** Used for colored log messages. */
+       char log_colors[NUM_LOGLEVELS][COLOR_MAXLEN];
+};
+
+static struct daemon the_daemon, *me = &the_daemon;
+
+/**
+ * Activate default log colors.
+ *
+ * This should be called early if color support is wanted.
+ */
+void daemon_set_default_log_colors(void)
+{
+       int i;
+       static const char *default_log_colors[NUM_LOGLEVELS] = {
+               [LL_DEBUG] = "normal",
+               [LL_INFO] = "normal",
+               [LL_NOTICE] = "normal",
+               [LL_WARNING] = "yellow",
+               [LL_ERROR] = "red",
+               [LL_CRIT] = "magenta bold",
+               [LL_EMERG] = "red bold",
+       };
+       for (i = 0; i < NUM_LOGLEVELS; i++) {
+               int ret = color_parse(default_log_colors[i], me->log_colors[i]);
+               assert(ret >= 0);
+       }
+}
+
+/**
+ * Set the color for one loglevel.
+ *
+ * \param arg The loglevel/color specifier.
+ *
+ * \a arg must be of the form "ll:[fg [bg]] [attr]".
+ *
+ * \return 1 On success, -1 on errors.
+ */
+int daemon_set_log_color(char const *arg)
+{
+       char *p = strchr(arg, ':');
+       int ret, ll;
+
+       if (!p)
+               goto err;
+       ret = get_loglevel_by_name(arg);
+       if (ret < 0)
+               goto err;
+       ll = ret;
+       p++;
+       ret = color_parse(p, me->log_colors[ll]);
+       if (ret < 0)
+               goto err;
+       return 1;
+err:
+       PARA_ERROR_LOG("%s: color syntax error\n", arg);
+       return -1;
+
+}
+
+/**
+ * Init or change the name of the log file.
+ *
+ * \param logfile_name The full path of the logfile.
+ */
+void daemon_set_logfile(char *logfile_name)
+{
+       free(me->logfile_name);
+       me->logfile_name = NULL;
+       if (logfile_name)
+               me->logfile_name = para_strdup(logfile_name);
+}
+
+/**
+ * Supress log messages with severity lower than the given loglevel.
+ *
+ * \param loglevel The smallest level that should be logged.
+ */
+void daemon_set_loglevel(char *loglevel)
+{
+       int ret = get_loglevel_by_name(loglevel);
+
+       assert(ret >= 0);
+       me->loglevel = ret;
+}
+
+/**
+ * Set one of the daemon config flags.
+ *
+ * \param flag The flag to set.
+ *
+ * \sa \ref daemon_flags.
+ */
+void daemon_set_flag(unsigned flag)
+{
+       me->flags |= flag;
+}
+
+/**
+ * Clear one of the daemon config flags.
+ *
+ * \param flag The flag to clear.
+ *
+ * \sa \ref daemon_flags.
+ */
+void daemon_clear_flag(unsigned flag)
+{
+       me->flags &= ~flag;
+}
+
+static unsigned daemon_test_flag(unsigned flag)
+{
+       return me->flags & flag;
+}
 
 /**
  * Do the usual stuff to become a daemon.
  *
  * \sa fork(2), setsid(2), dup(2).
  */
-void daemon_init(void)
+void daemonize(void)
 {
        pid_t pid;
        int null;
@@ -56,50 +185,43 @@ err:
 }
 
 /**
- * fopen() the given file in append mode.
- *
- * \param logfile_name The name of the file to open.
- *
- * \return Either calls exit() or returns a valid file handle.
+ * Close the log file of the daemon.
  */
-FILE *open_log(const char *logfile_name)
+void daemon_close_log(void)
 {
-       FILE *logfile;
-
-       assert(logfile_name);
-       logfile = fopen(logfile_name, "a");
-       if (!logfile) {
-               PARA_EMERG_LOG("can not open %s: %s\n", logfile_name,
-                       strerror(errno));
-               exit(EXIT_FAILURE);
-       }
-       setlinebuf(logfile);
-       return logfile;
+       if (!me->logfile)
+               return;
+       PARA_INFO_LOG("closing logfile\n");
+       fclose(me->logfile);
+       me->logfile = NULL;
 }
 
 /**
- * Close the log file of the daemon.
- *
- * \param logfile The log file handle.
+ * fopen() the logfile in append mode.
  *
- * It's OK to call this with logfile == \p NULL.
+ * \return Either succeeds or exits.
  */
-void close_log(FILE* logfile)
+void daemon_open_log_or_die(void)
 {
-       if (!logfile)
+       daemon_close_log();
+       if (!me->logfile_name)
                return;
-       PARA_INFO_LOG("closing logfile\n");
-       fclose(logfile);
+       me->logfile = fopen(me->logfile_name, "a");
+       if (!me->logfile) {
+               PARA_EMERG_LOG("can not open %s: %s\n", me->logfile_name,
+                       strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       setlinebuf(me->logfile);
 }
 
 /**
  * Log the startup message containing the paraslash version.
  */
-void log_welcome(const char *whoami, int loglevel)
+void log_welcome(const char *whoami)
 {
        PARA_INFO_LOG("welcome to %s " PACKAGE_VERSION " ("BUILD_DATE")\n",
                whoami);
-       PARA_DEBUG_LOG("using loglevel %d\n", loglevel);
 }
 
 /**
@@ -116,7 +238,7 @@ void log_welcome(const char *whoami, int loglevel)
  *
  * \sa getpwnam(3), getuid(2), setuid(2), getgrnam(2), setgid(2)
  */
-void para_drop_privileges(const char *username, const char *groupname)
+void drop_privileges_or_die(const char *username, const char *groupname)
 {
        struct passwd *p;
        char *tmp;
@@ -168,16 +290,15 @@ void para_drop_privileges(const char *username, const char *groupname)
  */
 time_t server_uptime(enum uptime set_or_get)
 {
-       static time_t startuptime;
        time_t now;
        double diff;
 
        if (set_or_get == UPTIME_SET) {
-               time(&startuptime);
+               time(&me->startuptime);
                return 0;
        }
        time(&now);
-       diff = difftime(now, startuptime);
+       diff = difftime(now, me->startuptime);
        return (time_t) diff;
 }
 
@@ -194,3 +315,51 @@ __malloc char *uptime_str(void)
        return make_message("%li:%02li:%02li", t / 86400,
                (t / 3600) % 24, (t / 60) % 60);
 }
+
+/**
+ * The log function for para_server and para_audiod.
+ *
+ * \param ll The log level.
+ * \param fmt The format string describing the log message.
+ */
+__printf_2_3 void para_log(int ll, const char* fmt,...)
+{
+       va_list argp;
+       FILE *fp;
+       struct tm *tm;
+       time_t t1;
+       char *color, str[MAXLINE] = "";
+
+       ll = PARA_MIN(ll, NUM_LOGLEVELS - 1);
+       ll = PARA_MAX(ll, LL_DEBUG);
+       if (ll < me->loglevel)
+               return;
+
+       fp = me->logfile? me->logfile : stderr;
+       color = daemon_test_flag(DF_COLOR_LOG)? me->log_colors[ll] : NULL;
+       if (color)
+               fprintf(fp, "%s", color);
+       if (daemon_test_flag(DF_LOG_TIME)) {
+               /* date and time */
+               time(&t1);
+               tm = localtime(&t1);
+               strftime(str, MAXLINE, "%b %d %H:%M:%S", tm);
+               fprintf(fp, "%s ", str);
+       }
+       if (daemon_test_flag(DF_LOG_HOSTNAME)) {
+               if (!me->hostname)
+                       me->hostname = para_hostname();
+               fprintf(fp, "%s ", me->hostname);
+       }
+       if (daemon_test_flag(DF_LOG_LL)) /* log loglevel */
+               fprintf(fp, "(%d) ", ll);
+       if (daemon_test_flag(DF_LOG_PID)) { /* log pid */
+               pid_t mypid = getpid();
+               fprintf(fp, "(%d) ", (int)mypid);
+       }
+       va_start(argp, fmt);
+       vfprintf(fp, fmt, argp);
+       va_end(argp);
+       if (color)
+               fprintf(fp, "%s", COLOR_RESET);
+}
index e1b8149aaba8b83af3476a6ba988bcd4722a42d5..c8dd997f97706321f98b3b6808d5e3f29e24fcf9 100644 (file)
--- a/daemon.h
+++ b/daemon.h
@@ -1,12 +1,32 @@
 /** \file daemon.h exported symbols from daemon.c */
 
 
-void daemon_init(void);
-FILE *open_log(const char *logfile_name);
-void close_log(FILE* logfile);
-void log_welcome(const char *whoami, int loglevel);
-void para_drop_privileges(const char *username, const char *groupname);
+void daemonize(void);
+void daemon_open_log_or_die(void);
+void daemon_close_log(void);
+void log_welcome(const char *whoami);
+void drop_privileges_or_die(const char *username, const char *groupname);
 /** used for server_uptime() */
 enum uptime {UPTIME_SET, UPTIME_GET};
 time_t server_uptime(enum uptime set_or_get);
 __malloc char *uptime_str(void);
+void daemon_set_logfile(char *logfile_name);
+void daemon_set_flag(unsigned flag);
+void daemon_clear_flag(unsigned flag);
+void daemon_set_loglevel(char *loglevel);
+void daemon_set_default_log_colors(void);
+int daemon_set_log_color(char const *arg);
+
+/** Daemon log configuration flags. */
+enum daemon_flags {
+       /** Whether the hostname should be logged. */
+       DF_LOG_HOSTNAME = 1,
+       /** Whether the PID should be logged. */
+       DF_LOG_PID = 2,
+       /** Prepend log message with date and time. */
+       DF_LOG_TIME = 4,
+       /** Also print the loglevel for each message. */
+       DF_LOG_LL = 8,
+       /** Use colored output. */
+       DF_COLOR_LOG = 16,
+};
index c73088f83939e153d94e3eb4dcead35d04a1ff05..93dea809d88009b717e1338c4d32cfddd06bea05 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/dccp_recv.ggo b/dccp_recv.ggo
deleted file mode 100644 (file)
index 9717329..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-option "host" i
-"ip or host"
-string default="localhost"
-optional
-details="
-       Both IPv4 and IPv6 addresses are supported.
-"
-
-option "port" p
-"port to connect to"
-int
-default="8000"
-optional
index bbef02e9728a8a587eafd132f92c87f4466eee89..9b72b7c90e089f6b09f711094634f69f826df3ab 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/error.h b/error.h
index 37ff48a9463780220cd7e02b431d622080a432a4..0a5fb21775c58b9437fa0bfe2ec70c86ac602ff3 100644 (file)
--- a/error.h
+++ b/error.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -17,7 +17,7 @@ DEFINE_ERRLIST_OBJECT_ENUM;
 #define TIME_ERRORS
 #define CLOSE_ON_FORK_ERRORS
 #define DAEMON_ERRORS
-#define ORTP_SEND_ERRORS
+#define UDP_SEND_ERRORS
 #define GUI_ERRORS
 #define RINGBUFFER_ERRORS
 #define SCORE_ERRORS
@@ -29,6 +29,7 @@ DEFINE_ERRLIST_OBJECT_ENUM;
 #define DCCP_SEND_ERRORS
 #define HTTP_SEND_ERRORS
 #define GGO_ERRORS
+#define COLOR_ERRORS
 
 
 extern const char **para_errlist[];
@@ -207,13 +208,11 @@ extern const char **para_errlist[];
        PARA_ERROR(RECV_PATTERN, "did not receive expected pattern"), \
 
 
-#define ORTP_RECV_ERRORS \
-       PARA_ERROR(MSG_TO_BUF, "failed to extract rtp packet"), \
-       PARA_ERROR(ORTP_SYNTAX, "ortp syntax error"), \
-       PARA_ERROR(TOO_MANY_BAD_CHUNKS, "too many consecutive bad chunks"), \
-       PARA_ERROR(INVALID_HEADER, "invalid header packet"), \
-       PARA_ERROR(OVERRUN, "output buffer overrun"), \
-       PARA_ERROR(ORTP_RECV_EOF, "ortp_recv: end of file"), \
+#define UDP_RECV_ERRORS \
+       PARA_ERROR(UDP_SYNTAX, "udp_recv syntax error"), \
+       PARA_ERROR(UDP_BAD_HEADER, "invalid udp audio header"), \
+       PARA_ERROR(UDP_OVERRUN, "output buffer overrun"), \
+       PARA_ERROR(UDP_BAD_STREAM_TYPE, "invalid stream type"), \
 
 
 #define HTTP_RECV_ERRORS \
@@ -360,8 +359,6 @@ extern const char **para_errlist[];
 
 #define FD_ERRORS \
        PARA_ERROR(FGETS, "fgets error"), \
-       PARA_ERROR(EMPTY, "file empty"), \
-       PARA_ERROR(MMAP, "mmap error"), \
 
 
 #define WRITE_ERRORS \
diff --git a/exec.c b/exec.c
index bafae240260ef386a1adfc77937fad458a27e40b..3c810a3e4cb5c54ed37fec694084574157d8a784 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2003-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/fade.c b/fade.c
index 33f1ccbeda51ae52cc1dd6a627b545aee84b0923..40b4623cf2219321ed21970a846f016dce4e1b39 100644 (file)
--- a/fade.c
+++ b/fade.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1998-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1998-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/fade.ggo b/fade.ggo
deleted file mode 100644 (file)
index 5965cba..0000000
--- a/fade.ggo
+++ /dev/null
@@ -1,155 +0,0 @@
-section "general options"
-#########################
-
-option "mode" o
-#~~~~~~~~~~~~~~
-
-"{sleep|fade|snooze}"
-       string default="sleep"
-       optional
-
-option "config_file" c
-#~~~~~~~~~~~~~~~~~~~~~
- "(default='~/.paraslash/fade.conf')"
-       string typestr="filename"
-       optional
-
-option "mixer_device" m
-#~~~~~~~~~~~~~~~~~~~~~~
- "mixer device file"
-       string typestr="device"
-       default="/dev/mixer"
-       optional
-
-section "sleep options (only relevant in sleep mode)"
-#####################################################
-
-option "sleep_ivol" -
-#~~~~~~~~~~~~~~~~~~~~
- "set initial volume before doing anything else"
-       int typestr="volume"
-       default="60"
-       optional
-
-option "fa_mode" -
-#~~~~~~~~~~~~~~~~~~~
- "fall asleep afs mode. Select this mode
-right after setting the volume. Example:
-       --fa_mode m/sleep
-"
-
-       string typestr="afs_mode"
-       default="m/fade"
-       optional
-
-option "fa_fade" -
-#~~~~~~~~~~~~~~~~~
- "fall asleep fading time, no fading if set
-to 0"
-       int typestr="seconds"
-       default="1800"
-       optional
-
-option "fa_vol" -
-#~~~~~~~~~~~~~~~~
- "volume to fade to"
-       int typestr="volume"
-       default="20"
-       optional
-
-option "sleep_mode" -
-#~~~~~~~~~~~~~~~~~~~~~~
- "change to this afs mode after fading, stop
-playing if unset."
-       string typestr="afs_mode"
-       default="m/sleep"
-       optional
-
-option "wake_hour" H
-#~~~~~~~~~~~~~~~~~~~
- "(0-23) (default: now + 9 hours)"
-       int typestr="hour"
-       optional
-
-option "wake_min" M
-#~~~~~~~~~~~~~~~~~~
-"(0-59)"
-       int typestr="minutes"
-       default="0"
-       optional
-
-option "wake_mode" -
-#~~~~~~~~~~~~~~~~~~~~~
- "change to this afs mode on waketime"
-       string typestr="afs_mode"
-       default="m/wake"
-       optional
-
-option "wake_fade" -
-#~~~~~~~~~~~~~~~~~~~
- "no fading in if set to 0"
-       int typestr="seconds"
-       default="1200"
-       optional
-
-option "wake_vol" -
-#~~~~~~~~~~~~~~~~~~
- "vol to fade to at waketime"
-       int typestr="volume"
-       default="80"
-       optional
-
-section "snooze options"
-########################
-
-option "snooze_out_fade" -
-#~~~~~~~~~~~~~~~~~~~~~~~~~
- "fade out time"
-       int typestr="seconds"
-       default="30"
-       optional
-
-option "snooze_out_vol" -
-#~~~~~~~~~~~~~~~~~~~~~~~~
- "vol to fade to before snooze"
-       int typestr="volume"
-       default="20"
-       optional
-
-option "snooze_time" -
-#~~~~~~~~~~~~~~~~~~~~~
- "delay"
-       int typestr="seconds"
-       default="600"
-       optional
-
-option "snooze_in_fade" -
-#~~~~~~~~~~~~~~~~~~~~~~~~
- "fade in time"
-       int typestr="seconds"
-       default="180"
-       optional
-
-option "snooze_in_vol" -
-#~~~~~~~~~~~~~~~~~~~~~~~
- "vol to fade to after snooze"
-       int typestr="volume"
-       default="80"
-       optional
-
-section "fade options"
-######################
-
-option "fade_vol" f
-#~~~~~~~~~~~~~~~~~~
- "volume to fade to"
-       int typestr="volume"
-       default="50"
-       optional
-
-option "fade_time" t
-#~~~~~~~~~~~~~~~~~~~
- "time to fade in"
-       int typestr="seconds"
-       default="5"
-       optional
diff --git a/fd.c b/fd.c
index d0b5c895a5f25d02b9f566fbe693a38898057203..8759d5099200c4f6c1b6c31e84b66da3372b5540 100644 (file)
--- a/fd.c
+++ b/fd.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -40,6 +40,45 @@ int write_all(int fd, const char *buf, size_t *len)
        return 1;
 }
 
+/**
+ * Write a buffer to a non-blocking file descriptor.
+ *
+ * \param fd The file descriptor.
+ * \param buf the buffer to write.
+ * \param len the number of bytes of \a buf.
+ * \param max_bytes_per_write Do not write more than that many bytes at once.
+ *
+ * If \a max_bytes_per_write is non-zero, do not send more than that many bytes
+ * per write().
+ *
+ * EAGAIN is not considered an error condition.  For example CCID3 has a
+ * sending wait queue which fills up and is emptied asynchronously. The EAGAIN
+ * case means that there is currently no space in the wait queue, but this can
+ * change at any moment.
+ *
+ * \return Negative on errors, number of bytes written else.
+ */
+int write_nonblock(int fd, const char *buf, size_t len,
+               size_t max_bytes_per_write)
+{
+       size_t written = 0;
+       int ret = 0;
+
+       while (written < len) {
+               size_t num = len - written;
+
+               if (max_bytes_per_write && max_bytes_per_write < num)
+                       num = max_bytes_per_write;
+               ret = write(fd, buf + written, num);
+               if (ret < 0 && errno == EAGAIN)
+                       return written;
+               if (ret < 0)
+                       return -ERRNO_TO_PARA_ERROR(errno);
+               written += ret;
+       }
+       return written;
+}
+
 /**
  * Check whether a file exists.
  *
@@ -135,11 +174,7 @@ __must_check int mark_fd_nonblocking(int fd)
 */
 void para_fd_set(int fd, fd_set *fds, int *max_fileno)
 {
-
-       if (fd < 0 || fd >= FD_SETSIZE) {
-               PARA_EMERG_LOG("fatal: tried to add invalid fd %d\n", fd);
-               exit(EXIT_FAILURE);
-       }
+       assert(fd >= 0 && fd < FD_SETSIZE);
 #if 0
        {
                int flags = fcntl(fd, F_GETFL);
@@ -190,19 +225,26 @@ again:
  * \param flags Exactly one of MAP_SHARED and MAP_PRIVATE.
  * \param fd The file to mmap from.
  * \param offset Mmap start.
+ * \param map Result pointer.
+ *
+ * \return Standard.
  *
- * \return This function either returns a valid pointer to the mapped area
- * or calls exit() on errors.
+ * \sa mmap(2).
  */
-void *para_mmap(size_t length, int prot, int flags, int fd, off_t offset)
+int para_mmap(size_t length, int prot, int flags, int fd, off_t offset,
+               void *map)
 {
-       void *ret = mmap(NULL, length, prot, flags, fd, offset);
-       if (ret != MAP_FAILED)
-               return ret;
-       PARA_EMERG_LOG("mmap failed: %s\n", strerror(errno));
-       PARA_EMERG_LOG("length: %zu, flags: %d, fd: %d, offset: %zu\n",
-               length, flags, fd, (size_t)offset);
-       exit(EXIT_FAILURE);
+       void **m = map;
+
+       errno = EINVAL;
+       if (!length)
+               goto err;
+       *m = mmap(NULL, length, prot, flags, fd, offset);
+       if (*m != MAP_FAILED)
+               return 1;
+err:
+       *m = NULL;
+       return -ERRNO_TO_PARA_ERROR(errno);
 }
 
 /**
@@ -363,17 +405,7 @@ int mmap_full_file(const char *path, int open_mode, void **map,
                goto out;
        }
        *size = file_status.st_size;
-       ret = -E_EMPTY;
-       PARA_DEBUG_LOG("%s: size %zu\n", path, *size);
-       if (!*size)
-               goto out;
-       *map = mmap(NULL, *size, mmap_prot, mmap_flags, fd, 0);
-       if (*map == MAP_FAILED) {
-               *map = NULL;
-               ret = -E_MMAP;
-               goto out;
-       }
-       ret = 1;
+       ret = para_mmap(*size, mmap_prot, mmap_flags, fd, 0, map);
 out:
        if (ret < 0 || !fd_ptr)
                close(fd);
@@ -427,3 +459,24 @@ again:
                goto again;
        return ret;
 }
+
+/**
+ * Ensure that file descriptors 0, 1, and 2 are valid.
+ *
+ * Common approach that opens /dev/null until it gets a file descriptor greater
+ * than two.
+ *
+ * \sa okir's Black Hats Manual.
+ */
+void valid_fd_012(void)
+{
+       while (1) {
+               int fd = open("/dev/null", O_RDWR);
+               if (fd < 0)
+                       exit(EXIT_FAILURE);
+               if (fd > 2) {
+                       close(fd);
+                       break;
+               }
+       }
+}
diff --git a/fd.h b/fd.h
index 22141be2d79a7451188f0d6986b772368248ff71..7c364120a7d3a052c8b67b6867f7da8589aebee2 100644 (file)
--- a/fd.h
+++ b/fd.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -14,7 +14,8 @@ __must_check int mark_fd_nonblocking(int fd);
 __must_check int mark_fd_blocking(int fd);
 void para_fd_set(int fd, fd_set *fds, int *max_fileno);
 __must_check int para_fgets(char *line, int size, FILE *f);
-void *para_mmap(size_t length, int prot, int flags, int fd, off_t offset);
+int para_mmap(size_t length, int prot, int flags, int fd, off_t offset,
+               void *map);
 int para_open(const char *path, int flags, mode_t mode);
 int para_opendir(const char *dirname, DIR **dir, int *cwd);
 int para_mkdir(const char *path, mode_t mode);
@@ -24,3 +25,6 @@ int mmap_full_file(const char *filename, int open_mode, void **map,
        size_t *size, int *fd_ptr);
 int para_munmap(void *start, size_t length);
 int write_ok(int fd);
+void valid_fd_012(void);
+int write_nonblock(int fd, const char *buf, size_t len,
+               size_t max_bytes_per_write);
index 533d33313136133f675a80ca7db98a2aba6f8346..016732ae3fd9379f8ed405cd52e7e3cee281d513 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/file_write.ggo b/file_write.ggo
deleted file mode 100644 (file)
index 56c44f7..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-option "filename" f
-#~~~~~~~~~~~~~~~~~~
-"specify output file name"
-string typestr="filename"
-optional
-details="
-       Defaults to a random filename in ~/.paraslash.
-"
-
index d67aeae44a8d226866c6fcf1a46c192ea4a15cc7..96880b7d31922221b9eb90e25a52a258a60d3245 100644 (file)
--- a/filter.c
+++ b/filter.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -44,7 +44,8 @@ static struct stdout_task *sot = &stdout_task_struct;
 /** Gengetopt struct that holds the command line args. */
 static struct filter_args_info conf;
 
-INIT_STDERR_LOGGING(conf.loglevel_arg);
+static int loglevel;
+INIT_STDERR_LOGGING(loglevel);
 
 static void open_filters(void)
 {
@@ -162,6 +163,7 @@ int main(int argc, char *argv[])
        ret = parse_config(argc, argv);
        if (ret < 0)
                goto out;
+       loglevel = get_loglevel_by_name(conf.loglevel_arg);
        ret = init_filter_chain();
        if (ret < 0)
                goto out;
diff --git a/filter.ggo b/filter.ggo
deleted file mode 100644 (file)
index 5376a6f..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-option "loglevel" l
-#~~~~~~~~~~~~~~~~~~
- "set loglevel (0-6)"
-int typestr="level"
-default="4"
-optional
-
-option "filter" f
-#~~~~~~~~~~~~~~~~
-"Specify filter."
-string typestr="filter_spec"
-optional
-multiple
-details="
-       May be given multiple times to 'pipe' the stream through
-       arbitrary many filters in an efficient way.  The same filter
-       may appear more than once, order matters.
-
-       Filter options may be specified for each '-f' option
-       separately. Note that you will have to quote these options
-       like this:
-
-               -f 'compress --inertia 5 --damp 2'
-"
index c2a6310b5fa12903f7e15ca5453dd312bb3e02c8..2c546c1d21f281529fcda364987e8802b4b52036 100644 (file)
--- a/filter.h
+++ b/filter.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -197,6 +197,7 @@ struct filter {
         */
        int (*parse_config)(int argc, char **argv, void **config);
 
+       /** The help texts for this filter. */
        struct ggo_help help;
 };
 
index a39eefd683ad4092951dd73272ab9968109ed351..d83629bd4bf9d2b3f609ba71d36b5c7afcfc04a8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -155,7 +155,7 @@ again:
 //             fc->eof, *fc->out_loaded, conv, conv_total);
        if (conv)
                goto again;
-       if (!*fc->input_error)
+       if (*fc->input_error >= 0)
                return;
        if (*fc->out_loaded)
                return;
diff --git a/fsck.c b/fsck.c
index ee7f4ee260df9ada41fb06f072d41d8adca200cc..3b605c2d0a65d6260094ba99494009ee8bbfbef8 100644 (file)
--- a/fsck.c
+++ b/fsck.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -19,7 +19,9 @@
 static struct fsck_args_info conf;
 
 INIT_FSCK_ERRLISTS;
-INIT_STDERR_LOGGING(conf.loglevel_arg);
+
+static int loglevel;
+INIT_STDERR_LOGGING(loglevel);
 
 /* taken from git */
 signed char hexval_table[256] = {
@@ -936,6 +938,14 @@ static int check_all_tables(char *base_dir)
        return ret;
 }
 
+/**
+ * The praslash database check program.
+ *
+ * \param argc Usual arg count.
+ * \param argv Usual arg vector.
+ *
+ * \return \p EXIT_SUCCESS or \p EXIT_FAILURE.
+ */
 int main(int argc, char **argv)
 {
        int i, ret;
@@ -947,6 +957,7 @@ int main(int argc, char **argv)
                goto out;
        }
        HANDLE_VERSION_FLAG("fsck", conf);
+       loglevel = get_loglevel_by_name(conf.loglevel_arg);
        if (conf.base_dir_given)
                base_dir = para_strdup(conf.base_dir_arg);
        else {
@@ -970,9 +981,6 @@ out:
                        base_dir? base_dir : "",
                        para_strerror(-ret)
                );
-               if (conf.loglevel_arg > 1)
-                       PARA_EMERG_LOG("re-run with \"--loglevel %d\" to increase verbosity\n",
-                               conf.loglevel_arg - 1);
        } else
                PARA_NOTICE_LOG("success\n");
        if (base_dir)
diff --git a/fsck.ggo b/fsck.ggo
deleted file mode 100644 (file)
index b893705..0000000
--- a/fsck.ggo
+++ /dev/null
@@ -1,47 +0,0 @@
-option "loglevel" l
-#~~~~~~~~~~~~~~~~~~
-
-"set loglevel (0-6)"
-
-       int typestr="level"
-       default="3"
-       optional
-
-option "base_dir" b
-#~~~~~~~~~~~~~~~~~~
-"Full path to the database directory
-containing the table(s) to be checked.
-(default='~/.paraslash/afs_database'"
-
-       string typestr="path"
-       optional
-
-option "dump_dir" d
-#~~~~~~~~~~~~~~~~~~
-"If path is non-empty, para_fsck will write a
-dump of all given tables to the specified
-path."
-
-       string typestr="path"
-       optional
-       default=""
-
-option "no_fsck" n
-#~~~~~~~~~~~~~~~~~
-"Disable fsck mode."
-
-       flag off
-
-option "force" f
-#~~~~~~~~~~~~~~~
-"Force fsck even if the table is dirty.
-Ignored if -n is given."
-
-       flag off
-
-option "dry_run" -
-#~~~~~~~~~~~~~~~~~
-"Only report problems, don't try to fix them."
-
-       flag off
-
diff --git a/ggo.c b/ggo.c
index 55f1043082e5c511231616ad6bc5bd6a43e1f6af..b9852b991530f5b7bcdbd3e3a218f7d7d0222dfd 100644 (file)
--- a/ggo.c
+++ b/ggo.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2008-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 #include "para.h"
 #include "ggo.h"
 
+/**
+ * Wrapper for printf() that exits on errors.
+ *
+ * \param fmt Usual format string.
+ */
 __printf_1_2 void printf_or_die(const char *fmt, ...)
 {
        va_list argp;
@@ -20,9 +25,15 @@ __printf_1_2 void printf_or_die(const char *fmt, ...)
        va_end(argp);
        if (ret >= 0)
                return;
-       fprintf(stderr, "%s: %s\n", __FUNCTION__, strerror(errno));
+       exit(EXIT_FAILURE);
 }
 
+/**
+ * Print one of the two given help texts.
+ *
+ * \param help contains the help texts.
+ * \param detailed_help Whether to print the detailed help text.
+ */
 void ggo_print_help(struct ggo_help *help, int detailed_help)
 {
        const char **p;
diff --git a/ggo.h b/ggo.h
index c9111b16503602f7fe4dc387e0d98023bfd7bdc5..4d452b1d294790ae8e426c0fdcee4a3d24c90813 100644 (file)
--- a/ggo.h
+++ b/ggo.h
@@ -1,7 +1,20 @@
+/*
+ * Copyright (C) 2008-2009 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file ggo.h Functions and structures for help text handling. */
+
+/**
+ * Used by exexutables that can not use gengetopt's generated help function.
+ */
 struct ggo_help {
+       /** The lines of the short help text. */
        const char **short_help;
+       /** The lines of the detailed help text. */
        const char **detailed_help;
 };
 
 void ggo_print_help(struct ggo_help *help, int detailed_help);
-void printf_or_die(const char *fmt, ...);
+__printf_1_2 void printf_or_die(const char *fmt, ...);
diff --git a/ggo/afh.m4 b/ggo/afh.m4
new file mode 100644 (file)
index 0000000..97b8f28
--- /dev/null
@@ -0,0 +1,122 @@
+include(header.m4)
+<qu>
+text "
+para_afh, the audio format handler tool, is a stand-alone program
+contained in the paraslash package for analyzing and streaming audio
+files. It can be used to
+
+       - print tech info about the given audio file to stdout.
+       In particular, the 'chunk table' of the audio file, an array
+       of offsets within the audio file, may be printed. This table
+       can be used by other programs unaware of the particular audio
+       format to stream the audio file.
+
+       - write selected parts of the given audio file in complete
+       chunks without decoding. Thus para_afh can be used to 'cut'
+       an audio file.
+
+       - write selected parts of the given audio files 'just in time'
+       to sdout.  This may be useful for third-party software that
+       is capable of reading from stdin.
+"
+</qu>
+
+include(loglevel.m4)
+
+<qu>
+defgroup "mode"
+#--------------
+groupdesc="
+       There are two modes of operation: Info mode and stream mode,
+       one of which must be selected by the corresponding option.
+       See below.
+"
+required
+
+groupoption "info" i
+#~~~~~~~~~~~~~~~~~~~
+"select info mode"
+group="mode"
+details="
+       In this mode, the program prints technical information about
+       the given audio file to stdout.
+"
+
+groupoption "stream" s
+#~~~~~~~~~~~~~~~~~~~~~
+"select stream mode"
+group="mode"
+details="
+       If this mode is selected, the selected parts of the content
+       of the audio file are written to stdout. Only complete chunks
+       with respect of the underlying audio format are written.
+       For example, only complete frames in case of mp3 files.
+"
+
+section "Options for info mode"
+#==============================
+
+option "chunk_table" c
+#~~~~~~~~~~~~~~~~~~~~~
+"print also the chunk table"
+flag off
+dependon="info"
+
+section "Options for stream mode"
+#================================
+
+
+option "begin_chunk" b
+#~~~~~~~~~~~~~~~~~~~~~
+"skip a number of chunks"
+int typestr="chunk_num"
+default="0"
+dependon="stream"
+optional
+details="
+       The chunk_num argument must be between -num_chunks and
+       num_chunks - 1 inclusively where num_chunks is the total number
+       of chunks which is printed when using the --info option. If
+       chunk_num is negative, the given number of chunks are counted
+       backwards from the end of the file. For example --begin_chunk
+       -100 instructs para_afh to start output at chunk num_chunks
+       - 100. This is mainly useful for cutting off the end of an
+       audio file.
+"
+
+option "end_chunk" e
+#~~~~~~~~~~~~~~~~~~~
+"only write up to chunk chunk_num"
+int typestr="chunk_num"
+dependon="stream"
+optional
+details="
+       For the chunk_num argument the same rules as for --begin_chunk
+       apply.  The default is to write up to the last chunk.
+"
+
+option "just_in_time" j
+#~~~~~~~~~~~~~~~~~~~~~~
+"use timed writes"
+flag off
+dependon="stream"
+details="
+       Write the specified chunks of data 'just in time', i.e. the
+       write of each chunk is delayed until the time it is needed
+       by the decoder/player in order to guarantee an uninterupted
+       audio stream.
+"
+
+option "no_header" H
+#~~~~~~~~~~~~~~~~~~~
+"do not write an audio file header"
+flag off
+dependon="stream"
+details="
+       If an audio format needs information about the audio file
+       in a format-specific header in order to be understood by
+       the decoding software, a suitable header is automatically
+       send. This option changes the default behaviour, i.e. no
+       header is written.
+"
+</qu>
diff --git a/ggo/alsa_write.ggo b/ggo/alsa_write.ggo
new file mode 100644 (file)
index 0000000..84f49d5
--- /dev/null
@@ -0,0 +1,34 @@
+option "device" d
+#~~~~~~~~~~~~~~~~
+"set PCM device"
+string typestr="device"
+default="default"
+optional
+details="
+       On systems with dmix, a better choice than the default
+       value might be to use \"plug:swmix\".
+"
+
+option "channels" c
+#~~~~~~~~~~~~~~~~~~
+"specify number of channels"
+int typestr="num"
+default="2"
+optional
+details="
+       This option is only necessary for playing raw audio with
+       para_write.  In all other cases (plaing wav files with
+       para_write or using this writer with para_audiod), the number
+       of channels will be obtained from other resources.
+"
+
+option "samplerate" s
+#~~~~~~~~~~~~~~~~~~~~~
+"force given sample rate"
+int typestr="num"
+default="44100"
+optional
+details="
+       Again, it is only necessary to specify this when playing raw
+       audio with para_write.
+"
diff --git a/ggo/amp_filter.ggo b/ggo/amp_filter.ggo
new file mode 100644 (file)
index 0000000..865df3a
--- /dev/null
@@ -0,0 +1,17 @@
+option "amp" a
+#~~~~~~~~~~~~~
+"amplification value"
+int typestr="number"
+default="32"
+optional
+details="
+       The amplification value determines the scaling factor by
+       which the amplitude of the audio stream is multiplied. The
+       formula for the scaling factor is
+
+               factor = 1 + amp / 64.
+
+       For example, an amplifiction value of zero results in a
+       scaling factor of one while an amplification value of 64
+       means to double the volume.
+"
diff --git a/ggo/audioc.m4 b/ggo/audioc.m4
new file mode 100644 (file)
index 0000000..ad112e2
--- /dev/null
@@ -0,0 +1,15 @@
+include(header.m4)
+include(loglevel.m4)
+option "socket" s
+#~~~~~~~~~~~~~~~~
+"well-known socket (default=/var/paraslash/audiod.socket.$HOSTNAME)"
+       string typestr="filename"
+       optional
+
+
+option "bufsize" b
+#~~~~~~~~~~~~~~~~~
+"size of internal buffer"
+       int typestr="bytes"
+       default="8192"
+       optional
diff --git a/ggo/audiod.m4 b/ggo/audiod.m4
new file mode 100644 (file)
index 0000000..5390d1b
--- /dev/null
@@ -0,0 +1,195 @@
+include(header.m4)
+define(CURRENT_PROGRAM,para_audiod)
+define(DEFAULT_CONFIG_FILE,~/.paraslash/audiod.conf)
+
+<qu>
+#########################
+section "General options"
+#########################
+</qu>
+
+include(loglevel.m4)
+include(color.m4)
+include(config_file.m4)
+include(logfile.m4)
+include(daemon.m4)
+include(user.m4)
+include(group.m4)
+
+<qu>
+########################
+section "Audiod options"
+########################
+
+option "force" F
+#~~~~~~~~~~~~~~~
+"force startup"
+flag off
+details="
+       If this flag is not given, para_audiod refuses to start if the
+       well-known socket file (see the --socket option) already exists
+       because this usually means that para_audiod is already running
+       and listening on that socket. After a crash or if para_audiod
+       received a SIGKILL signal, a stale socket file might remain and
+       you have to use --force once to force startup of para_audiod.
+"
+
+option "mode" m
+#~~~~~~~~~~~~~~
+"startup mode"
+string typestr="mode"
+default="on"
+optional
+details="
+       Para_audiod supports three modes of operation: On, off and
+       standby (sb).  This option selects the mode that should be
+       used on startup. If para_audiod operates in \"on\" mode, it
+       will connect to para_server in order to receive its status
+       information. If para_server announces the availability of an
+       audio stream, para_audiod will automatically download, decode
+       and play the audio stream according to the given stream I/O
+       options, see below.
+
+       In \"standby\" mode, para_audiod will only receive the
+       status information from para_server but will not download
+       the audio stream.
+
+       In \"off\" mode, para_audiod does not connect para_server at
+       all, but still listens on the local socket for connections.
+"
+
+option "socket" s
+#~~~~~~~~~~~~~~~~
+"well-known socket"
+string typestr="filename"
+optional
+details="
+       Para_audiod uses a \"well-known\" socket to listen
+       on for connections from para_audioc. This socket is a
+       special file in the file system; its location defaults to
+       /var/paraslash/audiod_sock.<host_name>.
+
+       para_audioc, the client program used to connect to para_audiod,
+       opens this socket in order to talk to para_audiod.  If the
+       default value for para_audiod is changed, para_audioc must be
+       instructed to use also \"filename\" for connecting para_audiod.
+"
+
+option "user_allow" -
+#~~~~~~~~~~~~~~~~~~~~
+"allow this uid"
+int typestr="uid"
+default="-1"
+optional
+multiple
+details="
+       Allow the user identified by \"uid\" to connect to para_audiod.
+       May be specified multiple times. If not specified at all,
+       all users are allowed to connect.
+
+       This feature requires unix socket credentials and is currently
+       only supported on Linux systems. On other operating systems,
+       the option is silently ignored and all local users are allowed
+       to connect to para_audiod.
+"
+
+option "clock_diff_count" -
+#~~~~~~~~~~~~~~~~~~~~~~~~~~
+"sync clock on startup"
+int typestr="count"
+default="0"
+optional
+details="
+       Check the clock difference between the host running para_server
+       and the local host running para_audiod that many times before
+       starting any stream I/0. Set this to non-zero for non-local
+       setups if the clocks of these two hosts are not syncronized
+       by ntp or similar.
+"
+
+#############################
+section "Stream I/O options"
+#############################
+
+option "receiver" r
+#~~~~~~~~~~~~~~~~~~
+"select receiver"
+string typestr="receiver_spec"
+default="http"
+optional
+multiple
+details="
+       This option may be given multiple times, once for each
+       supported audio format. The \"receiver_spec\" consists of
+       an audio format and the receiver name, separated by a colon,
+       and any options for that receiver, seperated by whitespace.
+       If any receiver options are present, the whole receiver
+       argument must be quoted.
+
+       Example:
+
+               -r 'mp3:http -i my.host.org -p 8009'
+"
+
+
+option "no_default_filters" D
+#~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+"Configure filters manually"
+flag off
+details="
+       If (and only if) this option is set, the --filter options
+       (see below) take effect.  Otherwise, the compiled-in default
+       filters mp3dec, oggdec and aacdec are activated for mp3, ogg,
+       aac streams respectively.
+"
+
+option "filter" f
+#~~~~~~~~~~~~~~~~
+"Use non-default filters"
+string typestr="filter_spec"
+optional
+multiple
+dependon="no_default_filters"
+details="
+       This option may be given multiple times. The \"filter_spec\"
+       consists of an audio format, the name of the filter, and any
+       options for that filter. Mote that order matters.
+
+       Examples:
+
+               --filter 'mp3:mp3dec'
+
+               --filter 'mp3:compress --inertia 5 --damp 2'
+
+"
+
+option "writer" w
+#~~~~~~~~~~~~~~~~
+"Specify stream writer."
+string typestr="writer_spec"
+optional
+multiple
+details="
+       May be given multiple times, even multiple times for the same
+       audio format.  Default value is \"alsa\" for all supported
+       audio formats. Example:
+
+               --writer 'aac:osx'
+
+"
+
+option "stream_delay" -
+#~~~~~~~~~~~~~~~~~~~~~~
+"time for client sync"
+int typestr="milliseconds"
+default="200"
+optional
+details="
+       Add the given amount of milliseconds to the stream start time
+       announced by para_server and do not send data to the writer
+       before that time (modulo clock difference).
+
+       This is useful mainly for syncronizing the audio output of
+       different clients.
+"
+</qu>
diff --git a/ggo/client.m4 b/ggo/client.m4
new file mode 100644 (file)
index 0000000..1ae5a38
--- /dev/null
@@ -0,0 +1,17 @@
+include(header.m4)
+define(CURRENT_PROGRAM,para_client)
+define(DEFAULT_CONFIG_FILE,~/.paraslash/client.conf)
+<qu>
+args "--no-handle-error"
+option "hostname" i "ip or host to connect" string typestr="host" default="localhost" optional
+option "user" u "paraslash username" string typestr="username" default="<current user>" optional
+option "server_port" p "port to connect" int typestr="port" default="2990" optional
+option "key_file" k "(default='~/.paraslash/key.<user>')" string typestr="filename" optional
+</qu>
+
+include(loglevel.m4)
+include(config_file.m4)
+
+<qu>
+option "plain" - "request an uncrypted session" flag off
+</qu>
diff --git a/ggo/color.m4 b/ggo/color.m4
new file mode 100644 (file)
index 0000000..63e996f
--- /dev/null
@@ -0,0 +1,34 @@
+<qu>
+
+option "color" C
+#~~~~~~~~~~~~~~~
+"activate color output"
+enum typestr="when"
+values = "yes","no","auto"
+default = "auto"
+optional
+
+option "log_color" -
+#~~~~~~~~~~~~~~~~~~~
+"select a color for one type of log message"
+string typestr="color_spec"
+multiple
+optional
+details="
+       The format of \"color_spec\" is [fg [bg]] [attr].
+
+       Valid colors for \"fg\" and \"bg\" are \"normal\", \"black\",
+       \"red\", \"green\", \"yellow\", \"blue\", \"magenta\",
+       \"cyan\", and \"white\".
+
+       The \"attr\" value must be one of \"bold\", \"dim\", \"ul\",
+       \"blink\", \"reverse\".
+
+       Examples:
+
+               --log_color \"debug:green\"
+               --log_color \"info:yellow bold\"
+               --log_color \"notice:white red bold\"
+"
+
+</qu>
diff --git a/ggo/compress_filter.ggo b/ggo/compress_filter.ggo
new file mode 100644 (file)
index 0000000..74dcbc0
--- /dev/null
@@ -0,0 +1,37 @@
+option "blocksize" b
+#~~~~~~~~~~~~~~~~~~~
+"adjust block size"
+int typestr="number"
+default="15"
+optional
+details = "
+       Larger blocksize means fewer volume adjustments per time unit.
+"
+
+option "aggressiveness" a
+#~~~~~~~~~~~~~~~~~~~~~~~~
+ "controls the maximum amount to amplify by"
+int typestr="number"
+default="4"
+optional
+
+option "inertia" i
+#~~~~~~~~~~~~~~~~~
+ "how much inertia ramping has"
+ int typestr="number"
+default="6"
+optional
+
+option "target_level" t
+#~~~~~~~~~~~~~~~~~~~~~~
+"target signal level (0-32768)"
+int typestr="number"
+default="20000"
+optional
+
+option "damp" d
+#~~~~~~~~~~~~~~
+"if non-zero, scale down after normalizing"
+int typestr="number"
+default="0"
+optional
diff --git a/ggo/config_file.m4 b/ggo/config_file.m4
new file mode 100644 (file)
index 0000000..9e2ca40
--- /dev/null
@@ -0,0 +1,14 @@
+<qu>
+option "config_file" c
+#~~~~~~~~~~~~~~~~~~~~~
+"(default='</qu>DEFAULT_CONFIG_FILE<qu>'"
+string typestr="filename"
+optional
+details="
+       </qu>CURRENT_PROGRAM<qu> reads its config file right after parsing
+       the options that were given at the command line. If an
+       option is given both at the command line and in the
+       config file, the value that was specified at the command line
+       takes precedence.
+"
+</qu>
diff --git a/ggo/daemon.m4 b/ggo/daemon.m4
new file mode 100644 (file)
index 0000000..b4e842a
--- /dev/null
@@ -0,0 +1,11 @@
+<qu>
+option "daemon" d
+#~~~~~~~~~~~~~~~~
+"run as background daemon"
+flag off
+dependon="logfile"
+details="
+       Note that </qu>CURRENT_PROGRAM<qu> refuses to start in daemon mode if no
+       logfile was specified.
+"
+</qu>
diff --git a/ggo/dccp_recv.ggo b/ggo/dccp_recv.ggo
new file mode 100644 (file)
index 0000000..9717329
--- /dev/null
@@ -0,0 +1,13 @@
+option "host" i
+"ip or host"
+string default="localhost"
+optional
+details="
+       Both IPv4 and IPv6 addresses are supported.
+"
+
+option "port" p
+"port to connect to"
+int
+default="8000"
+optional
diff --git a/ggo/fade.ggo b/ggo/fade.ggo
new file mode 100644 (file)
index 0000000..388642e
--- /dev/null
@@ -0,0 +1,178 @@
+section "general options"
+#########################
+
+option "mode" o
+#~~~~~~~~~~~~~~
+"{sleep|fade|snooze}"
+string default="sleep"
+optional
+details="
+       para_fade knows these three different modes.
+
+       sleep mode: Change to the initial volume and an initial afs
+       mode, then fade the volume down until the fade out volume is
+       reached. Switch to the afs sleep mode until the wake time is
+       reached. Then switch to the afs wake mode and and fade in to
+       the wake volume.
+
+       fade: Fade the volume to the given value in the given time.
+
+       snooze: Fade out, sleep a bit and fade in.
+"
+
+option "config_file" c
+#~~~~~~~~~~~~~~~~~~~~~
+ "(default='~/.paraslash/fade.conf')"
+       string typestr="filename"
+       optional
+
+option "mixer_device" m
+#~~~~~~~~~~~~~~~~~~~~~~
+ "mixer device file"
+       string typestr="device"
+       default="/dev/mixer"
+       optional
+
+section "sleep options (only relevant in sleep mode)"
+#####################################################
+
+option "sleep_ivol" -
+#~~~~~~~~~~~~~~~~~~~~
+"set initial volume"
+int typestr="volume"
+default="60"
+optional
+details="
+       Used as the start volume, before fading out to the fade out volume.
+"
+
+option "fa_mode" -
+#~~~~~~~~~~~~~~~~~
+"fall asleep afs mode."
+string typestr="afs_mode"
+default="m/fade"
+optional
+details="
+       Select this mode right after setting the volume. Example:
+       --fa_mode m/sleep
+"
+
+option "fa_fade" -
+#~~~~~~~~~~~~~~~~~
+ "fall asleep fading time"
+int typestr="seconds"
+default="1800"
+optional
+details="
+       No fading if set to 0.
+"
+
+option "fa_vol" -
+#~~~~~~~~~~~~~~~~
+ "volume to fade to"
+       int typestr="volume"
+       default="20"
+       optional
+
+option "sleep_mode" -
+#~~~~~~~~~~~~~~~~~~~~~~
+"sleep time afs mode"
+details = "
+       Select the given afs mode after the fade out is complete. If
+       unset, the \"stop\" command is sent to para_server.
+"
+string typestr="afs_mode"
+default="m/sleep"
+optional
+
+option "wake_hour" H
+#~~~~~~~~~~~~~~~~~~~
+ "(0-23) (default: now + 9 hours)"
+       int typestr="hour"
+       optional
+
+option "wake_min" M
+#~~~~~~~~~~~~~~~~~~
+"(0-59)"
+       int typestr="minutes"
+       default="0"
+       optional
+
+option "wake_mode" -
+#~~~~~~~~~~~~~~~~~~~
+"wake time afs mode"
+string typestr="afs_mode"
+default="m/wake"
+optional
+details="
+       Change to this afs mode on waketime.
+"
+
+option "wake_fade" -
+#~~~~~~~~~~~~~~~~~~~
+ "no fading in if set to 0"
+       int typestr="seconds"
+       default="1200"
+       optional
+
+option "wake_vol" -
+#~~~~~~~~~~~~~~~~~~
+ "vol to fade to at waketime"
+       int typestr="volume"
+       default="80"
+       optional
+
+section "snooze options"
+########################
+
+option "snooze_out_fade" -
+#~~~~~~~~~~~~~~~~~~~~~~~~~
+ "fade out time"
+       int typestr="seconds"
+       default="30"
+       optional
+
+option "snooze_out_vol" -
+#~~~~~~~~~~~~~~~~~~~~~~~~
+ "vol to fade to before snooze"
+       int typestr="volume"
+       default="20"
+       optional
+
+option "snooze_time" -
+#~~~~~~~~~~~~~~~~~~~~~
+ "delay"
+       int typestr="seconds"
+       default="600"
+       optional
+
+option "snooze_in_fade" -
+#~~~~~~~~~~~~~~~~~~~~~~~~
+ "fade in time"
+       int typestr="seconds"
+       default="180"
+       optional
+
+option "snooze_in_vol" -
+#~~~~~~~~~~~~~~~~~~~~~~~
+ "vol to fade to after snooze"
+       int typestr="volume"
+       default="80"
+       optional
+
+section "fade options"
+######################
+
+option "fade_vol" f
+#~~~~~~~~~~~~~~~~~~
+ "volume to fade to"
+       int typestr="volume"
+       default="50"
+       optional
+
+option "fade_time" t
+#~~~~~~~~~~~~~~~~~~~
+ "time to fade in"
+       int typestr="seconds"
+       default="5"
+       optional
diff --git a/ggo/file_write.ggo b/ggo/file_write.ggo
new file mode 100644 (file)
index 0000000..56c44f7
--- /dev/null
@@ -0,0 +1,9 @@
+option "filename" f
+#~~~~~~~~~~~~~~~~~~
+"specify output file name"
+string typestr="filename"
+optional
+details="
+       Defaults to a random filename in ~/.paraslash.
+"
+
diff --git a/ggo/filter.m4 b/ggo/filter.m4
new file mode 100644 (file)
index 0000000..4e99176
--- /dev/null
@@ -0,0 +1,21 @@
+include(header.m4)
+include(loglevel.m4)
+<qu>
+option "filter" f
+#~~~~~~~~~~~~~~~~
+"Specify filter."
+string typestr="filter_spec"
+optional
+multiple
+details="
+       May be given multiple times to 'pipe' the stream through
+       arbitrary many filters in an efficient way.  The same filter
+       may appear more than once, order matters.
+
+       Filter options may be specified for each '-f' option
+       separately. Note that you will have to quote these options
+       like this:
+
+               -f 'compress --inertia 5 --damp 2'
+"
+</qu>
diff --git a/ggo/fsck.m4 b/ggo/fsck.m4
new file mode 100644 (file)
index 0000000..d593058
--- /dev/null
@@ -0,0 +1,43 @@
+include(header.m4)
+include(loglevel.m4)
+
+<qu>
+option "base_dir" b
+#~~~~~~~~~~~~~~~~~~
+"Full path to the database directory
+containing the table(s) to be checked.
+(default='~/.paraslash/afs_database'"
+
+       string typestr="path"
+       optional
+
+option "dump_dir" d
+#~~~~~~~~~~~~~~~~~~
+"If path is non-empty, para_fsck will write a
+dump of all given tables to the specified
+path."
+
+       string typestr="path"
+       optional
+       default=""
+
+option "no_fsck" n
+#~~~~~~~~~~~~~~~~~
+"Disable fsck mode."
+
+       flag off
+
+option "force" f
+#~~~~~~~~~~~~~~~
+"Force fsck even if the table is dirty.
+Ignored if -n is given."
+
+       flag off
+
+option "dry_run" -
+#~~~~~~~~~~~~~~~~~
+"Only report problems, don't try to fix them."
+
+       flag off
+
+</qu>
diff --git a/ggo/grab_client.ggo b/ggo/grab_client.ggo
new file mode 100644 (file)
index 0000000..5527143
--- /dev/null
@@ -0,0 +1,33 @@
+option "filter_num" f
+       "point of filter chain to grab"
+       int typestr="num"
+       default="0"
+       optional
+
+option "slot" s
+       "only grab this slot; grab any slot if negative"
+       int typestr="num"
+       default="-1"
+       optional
+
+option "audio_format" a
+       "only grab this type of input stream;
+       grab any if empty"
+       string typestr="name"
+       default=""
+       optional
+
+option "input_grab" i
+       "grab the filter input instead of its output"
+       flag off
+
+option "one_shot" o
+       "stop grabbing if audio file changes"
+       flag off
+
+option "mode" m
+       "select grab mode"
+       typestr="grab_mode"
+       values="sloppy","aggressive","pedantic"
+       default="sloppy"
+       optional
diff --git a/ggo/group.m4 b/ggo/group.m4
new file mode 100644 (file)
index 0000000..2a59ad9
--- /dev/null
@@ -0,0 +1,12 @@
+option "group" g
+#~~~~~~~~~~~~~~~
+"set group id"
+string typestr="group"
+optional
+details="
+       This option sets the group id according to 'group'. This option
+       is silently ignored if EUID != 0. Otherwise, real/effective
+       GID and the saved set-group ID are all set to the GID given by
+       'group'. Must not be given in the config file.
+"
+
diff --git a/ggo/gui.m4 b/ggo/gui.m4
new file mode 100644 (file)
index 0000000..dd1e249
--- /dev/null
@@ -0,0 +1,47 @@
+include(header.m4)
+define(CURRENT_PROGRAM,para_gui)
+
+<qu>
+#########################
+section "general options"
+#########################
+</qu>
+
+include(config_file.m4)
+include(loglevel.m4)
+
+<qu>
+option "timeout" t
+#~~~~~~~~~~~~~~~~~
+"set timeout"
+
+       int typestr="milliseconds"
+       default="30"
+       optional
+
+option "stat_cmd" s
+#~~~~~~~~~~~~~~~~~~
+"command to read server and audiod status
+data from"
+
+       string typestr="command"
+       default="para_audioc stat"
+       optional
+
+#---------------------------------
+section "mapping keys to commands"
+#---------------------------------
+
+option "key_map" k
+#~~~~~~~~~~~~~~~~~
+
+"Map key k to command c using mode m. Mode
+may be d, x or p for display, external and
+paraslash commands, respectively. Of course,
+this option may be given multiple times, one
+for each key mapping."
+
+       string typestr="k:m:c"
+       optional
+       multiple
+</qu>
diff --git a/ggo/header.m4 b/ggo/header.m4
new file mode 100644 (file)
index 0000000..c423187
--- /dev/null
@@ -0,0 +1 @@
+changequote(<qu>,</qu>)
diff --git a/ggo/http_recv.ggo b/ggo/http_recv.ggo
new file mode 100644 (file)
index 0000000..2f1b4d6
--- /dev/null
@@ -0,0 +1,15 @@
+option "host" i
+#~~~~~~~~~~~~~~
+"ip or host"
+string
+default="localhost"
+optional
+details="
+       Both IPv4 and IPv6 addresses are supported.
+"
+
+option "port" p
+#~~~~~~~~~~~~~~
+"tcp port to connect to"
+int default="8000"
+optional
diff --git a/ggo/logfile.m4 b/ggo/logfile.m4
new file mode 100644 (file)
index 0000000..bb10293
--- /dev/null
@@ -0,0 +1,11 @@
+<qu>
+option "logfile" L
+#~~~~~~~~~~~~~~~~~
+"where to write log output"
+string typestr="filename"
+optional
+details="
+       If this option is not given, </qu>CURRENT_PROGRAM<qu> writes the log
+       messages to to stderr
+"
+</qu>
diff --git a/ggo/loglevel.m4 b/ggo/loglevel.m4
new file mode 100644 (file)
index 0000000..0badbf4
--- /dev/null
@@ -0,0 +1,22 @@
+<qu>
+option "loglevel" l
+#~~~~~~~~~~~~~~~~~~
+"set loglevel"
+string typestr="level"
+values = "debug","info","notice","warning","error","crit","emerg"
+default="warning"
+optional
+details="
+       Log only messages with severity greater or equal the given
+       value.
+
+       debug: Produces really noisy output.
+       info: Still noisy, but won't fill up the disk quicky.
+       notice: Indicates normal, but significant event.
+       warning: Unexpected events that can be handled.
+       error: Unhandled error condition.
+       crit: System might be unreliable.
+       emerg: Last message before exit.
+"
+
+</qu>
diff --git a/ggo/makefile b/ggo/makefile
new file mode 100644 (file)
index 0000000..4988d6f
--- /dev/null
@@ -0,0 +1,69 @@
+module_ggo_opts := --set-version="($(PACKAGE_STRING), $(codename))"
+
+grab_client.cmdline.h grab_client.cmdline.c: $(ggo_dir)/grab_client.ggo
+       gengetopt $(module_ggo_opts) \
+               -S \
+               --set-package=grab \
+               --no-handle-help \
+               --no-handle-error \
+               --no-handle-version \
+               --arg-struct-name=grab_client_args_info \
+               --file-name=$(subst .ggo,,$(<F)).cmdline \
+               --func-name $(subst .ggo,,$(<F))_cmdline_parser < $<
+
+%_recv.cmdline.h %_recv.cmdline.c: $(ggo_dir)/%_recv.ggo
+       gengetopt $(module_ggo_opts) \
+               --set-package=$(subst .ggo,,$(<F)) \
+               --arg-struct-name=$(subst .ggo,,$(<F))_args_info \
+               --file-name=$(subst .ggo,,$(<F)).cmdline \
+               --func-name $(subst .ggo,,$(<F))_cmdline_parser < $<
+
+%_filter.cmdline.h %_filter.cmdline.c: $(ggo_dir)/%_filter.ggo
+       gengetopt $(module_ggo_opts) \
+               --set-package=$(subst .ggo,,$(<F)) \
+               --arg-struct-name=$(subst .ggo,,$(<F))_args_info \
+               --file-name=$(subst .ggo,,$(<F)).cmdline \
+               --func-name $(subst _filter.ggo,,$(<F))_cmdline_parser < $<
+%_write.cmdline.h %_write.cmdline.c: $(ggo_dir)/%_write.ggo
+       gengetopt -S $(module_ggo_opts) \
+               --set-package=$(subst .ggo,,$(<F)) \
+               --arg-struct-name=$(subst .ggo,,$(<F))_args_info \
+               --file-name=$(subst .ggo,,$(<F)).cmdline \
+               --func-name $(subst _write.ggo,,$(<F))_cmdline_parser < $<
+
+%.cmdline.h %.cmdline.c: $(ggo_dir)/%.ggo
+       case $(<F) in client.ggo) O="--unamed-opts=command";; \
+               audioc.ggo) O="--unamed-opts=command";; \
+               fsck.ggo) O="--unamed-opts=table";; \
+               afh.ggo) O="--unamed-opts=audio_file";; \
+               recv.ggo) O="--no-handle-help";; \
+               filter.ggo) O="--no-handle-help";; \
+               write.ggo) O="--no-handle-help";; \
+               audiod.ggo) O="--no-handle-help";; \
+       esac; \
+       if test $(<F) != fsck.ggo; then O="$$O --conf-parser "; fi; \
+       gengetopt $$O \
+               --no-handle-version \
+               --file-name=$(*F).cmdline \
+               --func-name $(*F)_cmdline_parser \
+               --arg-struct-name=$(*F)_args_info \
+               --set-package="para_$(subst .cmdline,,$(*F))" \
+               --set-version="$(PACKAGE_VERSION)"  < $<
+
+$(ggo_dir)/server.ggo $(ggo_dir)/audiod.ggo: \
+       $(ggo_dir)/loglevel.m4 $(ggo_dir)/color.m4 \
+       $(ggo_dir)/config_file.m4 $(ggo_dir)/logfile.m4 \
+       $(ggo_dir)/daemon.m4 $(ggo_dir)/user.m4 \
+       $(ggo_dir)/group.m4
+
+$(ggo_dir)/afh.ggo: $(ggo_dir)/loglevel.m4
+$(ggo_dir)/audioc.ggo: $(ggo_dir)/loglevel.m4
+$(ggo_dir)/filter.ggo: $(ggo_dir)/loglevel.m4
+$(ggo_dir)/fsck.ggo: $(ggo_dir)/loglevel.m4
+$(ggo_dir)/gui.ggo: $(ggo_dir)/loglevel.m4
+$(ggo_dir)/recv.ggo: $(ggo_dir)/loglevel.m4
+$(ggo_dir)/write.ggo: $(ggo_dir)/loglevel.m4
+$(ggo_dir)/client.ggo: $(ggo_dir)/loglevel.m4 $(ggo_dir)/config_file.m4
+
+$(ggo_dir)/%.ggo: $(ggo_dir)/%.m4 $(ggo_dir)/header.m4
+       (cd $(ggo_dir) && m4 $(<F)) > $@
diff --git a/ggo/mp3dec_filter.ggo b/ggo/mp3dec_filter.ggo
new file mode 100644 (file)
index 0000000..a34c30a
--- /dev/null
@@ -0,0 +1,22 @@
+option "bufsize" b
+#~~~~~~~~~~~~~~~~~
+"size of output buffer"
+int typestr="kilobyte"
+default="128"
+optional
+details="
+       Increase this if you encounter output buffer overrun
+       errors. Smaller values make the mp3dec filter use less
+       memory. The minimal size is 32K.
+"
+
+option "ignore-crc" i
+#~~~~~~~~~~~~~~~~~~~~
+"ignore CRC information in the audio stream."
+flag off
+details="
+       This causes frames with CRC errors to be decoded and played
+       anyway. This option is not recommended, but since some encoders
+       have been known to generate bad CRC information, this option
+       is a work-around to play streams from such encoders.
+"
diff --git a/ggo/oggdec_filter.ggo b/ggo/oggdec_filter.ggo
new file mode 100644 (file)
index 0000000..e2d653d
--- /dev/null
@@ -0,0 +1,21 @@
+option "bufsize" b
+#~~~~~~~~~~~~~~~~~
+"size of output buffer"
+int typestr="kilobyte"
+default="128"
+optional
+details="
+       Increase this if you encounter output buffer overrun errors. Smaller
+       values make the oggdec filter use less memory.
+"
+
+option "initial_buffer" i
+#~~~~~~~~~~~~~~~~~~~~~~~~
+"size of initial input buffer"
+int typestr="kilobyte"
+default="16"
+optional
+details="
+       On startup, defer decoding until that many kilobytes are
+       available in the input buffer.
+"
diff --git a/ggo/osx_write.ggo b/ggo/osx_write.ggo
new file mode 100644 (file)
index 0000000..ce2792e
--- /dev/null
@@ -0,0 +1,31 @@
+section "osx options"
+#####################
+
+option "channels" c
+#~~~~~~~~~~~~~~~~~~
+"number of channels (only neccessary for raw
+audio)"
+
+       int typestr="num"
+       default="2"
+       optional
+
+option "samplerate" s
+#~~~~~~~~~~~~~~~~~~~~~
+
+"force given sample rate (only neccessary for
+raw audio)"
+
+       int typestr="num"
+       default="44100"
+       optional
+
+option "numbuffers" n
+#~~~~~~~~~~~~~~~~~~~~~
+
+"number of audio buffers to allocate (increase if
+you get buffer underruns)"
+
+       int typestr="num"
+       default="5"
+       optional
diff --git a/ggo/recv.m4 b/ggo/recv.m4
new file mode 100644 (file)
index 0000000..9702e12
--- /dev/null
@@ -0,0 +1,16 @@
+include(header.m4)
+include(loglevel.m4)
+
+<qu>
+option "receiver" r
+"Select receiver"
+string typestr="receiver_spec"
+default="http"
+optional
+details="
+       Any options for the selected receiver must
+       be quoted. Example:
+
+               -r 'http -i www.paraslash.org -p 8009'
+"
+</qu>
diff --git a/ggo/server.m4 b/ggo/server.m4
new file mode 100644 (file)
index 0000000..30c3b41
--- /dev/null
@@ -0,0 +1,302 @@
+include(header.m4)
+define(CURRENT_PROGRAM,para_server)
+define(DEFAULT_CONFIG_FILE,~/.paraslash/server.conf)
+
+<qu>
+#########################
+section "General options"
+#########################
+</qu>
+
+include(loglevel.m4)
+include(color.m4)
+include(daemon.m4)
+include(user.m4)
+include(group.m4)
+
+<qu>
+option "port" p
+#~~~~~~~~~~~~~~
+"listening port"
+int typestr="portnumber"
+default="2990"
+optional
+details="
+       para_server listens on this tcp port for incoming connections
+       from clients such as para_client. If the default port is
+       changed, the corresponding option of para_client must be used
+       to connect to para_server.
+"
+
+#############################
+section "Configuration files"
+#############################
+</qu>
+
+include(logfile.m4)
+include(config_file.m4)
+
+<qu>
+option "user_list" -
+#~~~~~~~~~~~~~~~~~~~
+"(default='~/.paraslash/server.users')"
+
+string typestr="filename"
+optional
+
+
+##################################
+section "virtual streaming system"
+##################################
+
+
+option "autoplay" a
+#~~~~~~~~~~~~~~~~~~
+"start playing on startup"
+flag off
+
+option "autoplay_delay" -
+#~~~~~~~~~~~~~~~~~~~~~~~~
+"time to wait before streaming"
+int typestr="ms"
+default="0"
+optional
+dependon="autoplay"
+details="
+       If para_server is started with the autoplay option, this option
+       may be used to set up a delay before para_server streams its
+       first audio file. This is useful for example if para_server
+       and para_audiod are started during system startup. The delay
+       time should be choosen large enough so that para_audiod is
+       already up when para_server starts to stream. Of course, this
+       option depends on the autoplay option.
+"
+option "announce_time" A
+#~~~~~~~~~~~~~~~~~~~~~~~
+"grace time for clients"
+
+int typestr="ms"
+default="300"
+optional
+details="
+       Clients such as para_audiod connect to para_server and execute
+       the stat command to find out whether an audio stream is
+       currently available. This sets the delay betweeen announcing
+       the stream via the output of the stat command and sending
+       the first chunk of data.
+"
+
+#############################
+section "audio file selector"
+#############################
+
+option "afs_database_dir" D
+#~~~~~~~~~~~~~~~~~~~~~~~~~~
+"location of the database"
+string typestr="path"
+optional
+details="
+       Where para_server should look for the osl database of the audio
+       file selector. The default is '~/.paraslash/afs_database'.
+"
+
+option "afs_socket" s
+#~~~~~~~~~~~~~~~~~~~~
+"Command socket for afs"
+string typestr="path"
+default="/var/paraslash/afs_command_socket"
+optional
+details="
+       For each server command that is handled by the audio file
+       selector, the child process of para_server connects to the
+       audio file selector via a local socket. This option specifies
+       the location of that socket in the file system.
+"
+option "afs_initial_mode" i
+#~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+"Mood or playlist to load on startup."
+string typestr="<specifier>/<name>"
+optional
+
+details="
+       The argument of this option must be prefixed with either 'p/'
+       or 'm/' to indicate whether a playlist or a mood should be
+       loaded. Example:
+               --afs_initial_mode p/foo
+       loads the playlist named 'foo'.
+"
+
+#####################
+section "http sender"
+#####################
+
+
+option "http_port" -
+#~~~~~~~~~~~~~~~~~~~
+"tcp port for http streaming"
+int typestr="portnumber"
+default="8000"
+optional
+details="
+       The http sender of para_server listens on this port for
+       incoming connections. Clients are expected to send the usual
+       http request message such as 'GET / HTTP/'.
+"
+
+option "http_default_deny" -
+#~~~~~~~~~~~~~~~~~~~~~~~~~~~
+"make the http ACL a whitelist"
+flag off
+details="
+       The default is to use blacklists instead, i.e. connections
+       to the http sender are allowed unless the connecting host
+       matches a pattern given by a http_access option. This allows
+       to use access control the other way round: Connections are
+       denied from hosts which are not explicitly allowed by one or
+       more http_access options.
+"
+
+option "http_access" -
+#~~~~~~~~~~~~~~~~~~~~~
+"add an entry to the http ACL"
+string typestr="a.b.c.d/n"
+optional
+multiple
+details="
+       Add given host/network to access control list (whitelist if
+       http_default_deny was given, blacklist otherwise) before
+       opening the tcp port. This option can be given multiple
+       times. Example: '192.168.0.0/24' whitelists/blacklists the
+       256 hosts 192.168.0.x
+"
+
+option "http_no_autostart" -
+#~~~~~~~~~~~~~~~~~~~~~~~~~~~
+"do not open tcp port on startup"
+flag off
+details="
+       If this option is given, the http sender does not listen on
+       its tcp port. It may be instructed to open this port at a
+       later time by using the sender command.
+"
+
+option "http_max_clients" -
+#~~~~~~~~~~~~~~~~~~~~~~~~~~
+"maximal number of connections"
+int typestr="number"
+default="-1"
+optional
+details="
+       The http sender will refuse connections if already that number
+       of clients are currently connected. A non-positive value
+       (the default) allows an unlimited number of simultaneous
+       connections.
+"
+
+#####################
+section "dccp sender"
+#####################
+
+
+option "dccp_port" -
+#~~~~~~~~~~~~~~~~~~~
+"port for dccp streaming"
+int typestr="portnumber"
+default="8000"
+optional
+details="
+       See http_port for details.
+"
+
+option "dccp_default_deny" -
+#~~~~~~~~~~~~~~~~~~~~~~~~~~~
+"make the dccp ACL a whitelist"
+flag off
+details="
+       See http_default_deny for details.
+"
+
+option "dccp_access" -
+#~~~~~~~~~~~~~~~~~~~~~
+"add an entry to the dccp ACL"
+string typestr="a.b.c.d/n"
+optional
+multiple
+details="
+       See http_access for details.
+"
+
+option "dccp_max_clients" -
+#~~~~~~~~~~~~~~~~~~~~~~~~~~
+"maximal number of connections"
+int typestr="number"
+default="-1"
+optional
+details="
+       See http_max_clients for details.
+"
+
+####################
+section "udp sender"
+####################
+
+option "udp_target" -
+#~~~~~~~~~~~~~~~~~~~~
+"add udp target"
+string typestr="a.b.c.d:p"
+optional
+multiple
+details="
+       Add given host/port to the list of targets.  This option
+       can be given multiple times. Example: '224.0.1.38:1500'
+       instructs the udp sender to send to udp port 1500 on host
+       224.0.1.38 (unassigned ip in the Local Network Control Block
+       224.0.0/24). This is useful for multicast streaming.
+"
+
+option "udp_no_autostart" -
+#~~~~~~~~~~~~~~~~~~~~~~~~~~
+"do not start sending"
+flag off
+details="
+       If this option is given, udp streaming may be activated at
+       a later time by using the sender command.
+"
+
+option "udp_default_port" -
+#~~~~~~~~~~~~~~~~~~~~~~~~~~
+"udp port to send to"
+int typestr="port"
+default="8000"
+optional
+
+option "udp_header_interval" H
+#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+"duration for sending header"
+int typestr="ms"
+default="2000"
+optional
+details="
+       As the udp sender has no idea about connected clients it
+       sends the audio file header periodically if necessary. This
+       option is used to specify the duration of the interval between
+       sending the header. Shorter values decrease the average time
+       clients have to wait before being able to start playback,
+       but this also increases the amount network traffic. Note
+       that this affects only ogg vorbis streams as this is the only
+       audio format that needs an audio file header.
+"
+
+option "udp_ttl" t
+#~~~~~~~~~~~~~~~~~
+"set time to live value"
+int typestr="num"
+default="10"
+optional
+details="
+       This option instructs the udp sender to set the time to live to
+       \"num\" for the sending udp socket. Only useful for multicast
+       udp streaming.
+"
+</qu>
diff --git a/ggo/udp_recv.ggo b/ggo/udp_recv.ggo
new file mode 100644 (file)
index 0000000..6ad09f4
--- /dev/null
@@ -0,0 +1,13 @@
+option "host" i
+"ip or host to receive udp packets from"
+string default="224.0.1.38"
+optional
+details="
+       The default address resoves to DANTZ.MCAST.NET and activates
+       multicast.
+"
+
+option "port" p "udp port"
+int typestr="portnumber"
+default="8000"
+optional
diff --git a/ggo/user.m4 b/ggo/user.m4
new file mode 100644 (file)
index 0000000..1bd5c59
--- /dev/null
@@ -0,0 +1,21 @@
+<qu>
+option "user" u
+#~~~~~~~~~~~~~~
+"run as the given user"
+string typestr="name"
+optional
+details="
+       </qu>CURRENT_PROGRAM<qu> does not need any special privileges.
+
+       If started as root (EUID == 0) this option must
+       be given at the command line (not in the configuration
+       file) so that </qu>CURRENT_PROGRAM<qu> can drop the root
+       privileges right after parsing the command line options,
+       but before parsing the configuration file. In this case,
+       real/effective/saved UID are all set to the UID of 'name'. As
+       the configuration file is read afterwards, those options that
+       have a default value depending on the UID (e.g. the directory
+       for the configuration file) are computed by using the uid of
+       'name'. This option has no effect if </qu>CURRENT_PROGRAM<qu>
+       is started as a non-root user (i.e.  EUID != 0).
+" </qu>
diff --git a/ggo/write.m4 b/ggo/write.m4
new file mode 100644 (file)
index 0000000..41e44dd
--- /dev/null
@@ -0,0 +1,31 @@
+include(header.m4)
+include(loglevel.m4)
+
+option "bufsize" b
+#~~~~~~~~~~~~~~~~~
+"input buffer size"
+int typestr="kilobytes"
+default="64"
+optional
+
+option "writer" w
+#~~~~~~~~~~~~~~~~
+"select stream writer"
+string typestr="name"
+default="alsa (file if alsa is unsupported)"
+optional
+multiple
+details="
+       May be give multiple times. The same writer may be specified
+       more than once.
+"
+
+option "start_time" t
+#~~~~~~~~~~~~~~~~~~~~
+"defer playback"
+string typestr="timeval"
+optional
+details="
+       Start playback at given time which must be in a:b format where
+       a denotes seconds and b denotes microseconds since the epoch.
+"
index b9d70147bb63de054005be4eb17f13e5ae42ee43..e419a723b9b856ddbc595c6130951c86d4e3155a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/grab_client.ggo b/grab_client.ggo
deleted file mode 100644 (file)
index 5527143..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-option "filter_num" f
-       "point of filter chain to grab"
-       int typestr="num"
-       default="0"
-       optional
-
-option "slot" s
-       "only grab this slot; grab any slot if negative"
-       int typestr="num"
-       default="-1"
-       optional
-
-option "audio_format" a
-       "only grab this type of input stream;
-       grab any if empty"
-       string typestr="name"
-       default=""
-       optional
-
-option "input_grab" i
-       "grab the filter input instead of its output"
-       flag off
-
-option "one_shot" o
-       "stop grabbing if audio file changes"
-       flag off
-
-option "mode" m
-       "select grab mode"
-       typestr="grab_mode"
-       values="sloppy","aggressive","pedantic"
-       default="sloppy"
-       optional
diff --git a/gui.c b/gui.c
index 616890299047629dcaad4541a239efae19f2b76c..499845d9dadcdb6802b6ac49ab470d969729314c 100644 (file)
--- a/gui.c
+++ b/gui.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1998-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1998-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -489,17 +489,19 @@ static int add_output_line(char *line, __a_unused void *data)
        return 1;
 }
 
+static int loglevel;
+
 __printf_2_3 void para_log(int ll, const char *fmt,...)
 {
        int color;
        char *msg;
 
-       if (ll < conf.loglevel_arg || !curses_active)
+       if (ll < loglevel || !curses_active)
                return;
        switch (ll) {
-               case DEBUG:
-               case INFO:
-               case NOTICE:
+               case LL_DEBUG:
+               case LL_INFO:
+               case LL_NOTICE:
                        color = COLOR_MSG;
                        break;
                default:
@@ -562,8 +564,7 @@ __noreturn __printf_2_3 static void msg_n_exit(int ret, const char* fmt, ...)
 
 static void print_welcome(void)
 {
-       int ll = conf.loglevel_arg;
-       if (ll > NOTICE)
+       if (loglevel > LL_NOTICE)
                return;
        outputf(COLOR_WELCOME, "Welcome to para_gui " PACKAGE_VERSION
                " \"" CODENAME "\". Theme: %s", theme.name);
@@ -1168,24 +1169,24 @@ err_out:
 
 static void com_ll_decr(void)
 {
-       if (conf.loglevel_arg <= DEBUG) {
+       if (loglevel <= LL_DEBUG) {
                print_in_bar(COLOR_ERRMSG,
                        "loglevel already at maximal verbosity\n");
                return;
        }
-       conf.loglevel_arg--;
-       print_in_bar(COLOR_MSG, "loglevel set to %d\n", conf.loglevel_arg);
+       loglevel--;
+       print_in_bar(COLOR_MSG, "loglevel set to %d\n", loglevel);
 }
 
 static void com_ll_incr(void)
 {
-       if (conf.loglevel_arg >= EMERG) {
+       if (loglevel >= LL_EMERG) {
                print_in_bar(COLOR_ERRMSG,
                        "loglevel already at miminal verbosity\n");
                return;
        }
-       conf.loglevel_arg++;
-       print_in_bar(COLOR_MSG, "loglevel set to %d\n", conf.loglevel_arg);
+       loglevel++;
+       print_in_bar(COLOR_MSG, "loglevel set to %d\n", loglevel);
 }
 
 /*
@@ -1391,6 +1392,7 @@ int main(int argc, char *argv[])
                };
                gui_cmdline_parser_config_file(cf, &conf, &params);
        }
+       loglevel = get_loglevel_by_name(conf.loglevel_arg);
        if (check_key_map_args() < 0) {
                fprintf(stderr, "invalid key map in config file\n");
                exit(EXIT_FAILURE);
diff --git a/gui.ggo b/gui.ggo
deleted file mode 100644 (file)
index 40a4056..0000000
--- a/gui.ggo
+++ /dev/null
@@ -1,52 +0,0 @@
-#------------------------
-section "general options"
-#------------------------
-
-option "config_file" c
-#~~~~~~~~~~~~~~~~~~~~~~
-"(default='~/.paraslash/gui.conf')"
-
-       string typestr="filename"
-       optional
-
-option "loglevel" l
-#~~~~~~~~~~~~~~~~~~
- "set loglevel (0-6)"
-
-       int typestr="level"
-       default="4"
-       optional
-
-option "timeout" t
-#~~~~~~~~~~~~~~~~~
-"set timeout"
-
-       int typestr="milliseconds"
-       default="30"
-       optional
-
-option "stat_cmd" s
-#~~~~~~~~~~~~~~~~~~
-"command to read server and audiod status
-data from"
-
-       string typestr="command"
-       default="para_audioc stat"
-       optional
-
-#---------------------------------
-section "mapping keys to commands"
-#---------------------------------
-
-option "key_map" k
-#~~~~~~~~~~~~~~~~~
-
-"Map key k to command c using mode m. Mode
-may be d, x or p for display, external and
-paraslash commands, respectively. Of course,
-this option may be given multiple times, one
-for each key mapping."
-
-       string typestr="k:m:c"
-       optional
-       multiple
diff --git a/gui.h b/gui.h
index 26628b1c5a41da5d6c4ff2c3dc9c7ee630c12a5b..abc3191befcb29abd0fda8bb93d3c51c3a697f38 100644 (file)
--- a/gui.h
+++ b/gui.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index ce79ca63e694a3c438d68dbc764d7f8e5ce16cc6..9345f0ed5e10c0860801d455977a00be0a29082e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/hash.h b/hash.h
index 2d6de8ab25baedad30a039da8f3fa0dba4d3b165..8a14e3a763529a6a47c6479dea828b15ee8e594e 100644 (file)
--- a/hash.h
+++ b/hash.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 7716bb0f9f9c5ba5439bb7cd70c2055887e7e3c1..7f130341d16e1f0cc36cb43d691da66a92775235 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/http_recv.ggo b/http_recv.ggo
deleted file mode 100644 (file)
index 2f1b4d6..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-option "host" i
-#~~~~~~~~~~~~~~
-"ip or host"
-string
-default="localhost"
-optional
-details="
-       Both IPv4 and IPv6 addresses are supported.
-"
-
-option "port" p
-#~~~~~~~~~~~~~~
-"tcp port to connect to"
-int default="8000"
-optional
index 8ebbbc9c8a676d52f7b78348af10333ed6ec9dea..ce308ab723117cf671cf7010801efa260e7203d0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/ipc.c b/ipc.c
index cf8a8989e95f1dd8c1ebd8432658ad6c56aea890..c64cc89c6d8803416a9686890b09592c97a9272e 100644 (file)
--- a/ipc.c
+++ b/ipc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/mood.c b/mood.c
index cdc0745a255f994eb1a37c661cbfa1dfe1952221..57f3f00ab5b4e11ee4f9d78bb82f683eed361092 100644 (file)
--- a/mood.c
+++ b/mood.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index b809e8b3611d278d41b6ad7f965aa547389e52d3..41874b86404cfc239a24891c30dcb6545b887f38 100644 (file)
--- a/mp3_afh.c
+++ b/mp3_afh.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2003-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -82,7 +82,7 @@ static char *get_latin1(id3_ucs4_t const *string)
        return (char *)id3_ucs4_latin1duplicate(string);
 }
 
-char *get_stringlist(union id3_field *field)
+static char *get_stringlist(union id3_field *field)
 {
        unsigned int k, nstrings = id3_field_getnstrings(field);
        char *result = NULL;
index ce6cfbcb6e78eebe60764a5dc617cf5b89fd1b53..90293f0a7e0e76dd2b53daf5901b4f185533861d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/mp3dec_filter.ggo b/mp3dec_filter.ggo
deleted file mode 100644 (file)
index a34c30a..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-option "bufsize" b
-#~~~~~~~~~~~~~~~~~
-"size of output buffer"
-int typestr="kilobyte"
-default="128"
-optional
-details="
-       Increase this if you encounter output buffer overrun
-       errors. Smaller values make the mp3dec filter use less
-       memory. The minimal size is 32K.
-"
-
-option "ignore-crc" i
-#~~~~~~~~~~~~~~~~~~~~
-"ignore CRC information in the audio stream."
-flag off
-details="
-       This causes frames with CRC errors to be decoded and played
-       anyway. This option is not recommended, but since some encoders
-       have been known to generate bad CRC information, this option
-       is a work-around to play streams from such encoders.
-"
diff --git a/net.c b/net.c
index 9309ac1f02dc63edcc7af2939686b10b6d9b0599..312a68546f08bc5493699a9ae32d6a4b96164e13 100644 (file)
--- a/net.c
+++ b/net.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -755,3 +755,142 @@ out:
        free(buf);
        return ret;
 }
+
+static int resolve(const char *hostname, unsigned short port,
+               struct sockaddr_in *addr)
+{
+       struct hostent *host;
+
+       assert(hostname);
+       host = gethostbyname(hostname);
+       if (!host)
+               return -ERRNO_TO_PARA_ERROR(h_errno);
+       if (addr) {
+               memcpy(&addr->sin_addr, host->h_addr_list[0], host->h_length);
+               addr->sin_port = port;
+       }
+       return 1;
+}
+
+/*
+ * Create an UDP socket.
+ *
+ * If the given address is a multicast adress, the socket will be set
+ * to use the multicast TTL ttl and sets the datagrams to loop back.
+ *
+ * \return The fd of the socket on success, negative on errors.
+ */
+static int create_udp_socket(struct sockaddr_in *addr,
+               unsigned short port, unsigned char ttl)
+{
+       int ret, fd, yes = 1;
+
+       assert(addr);
+       ret = socket(PF_INET, SOCK_DGRAM, 0);
+       if (ret < 0)
+               return -ERRNO_TO_PARA_ERROR(errno);
+       fd = ret;
+       /* reuse addresses */
+       ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
+       if (ret < 0) {
+               ret = -ERRNO_TO_PARA_ERROR(errno);
+               goto err;
+       }
+       addr->sin_family = AF_INET;
+       addr->sin_port = htons(port);
+       /* set the TTL and turn on multicast loop */
+       if (IN_MULTICAST(htonl(addr->sin_addr.s_addr))) {
+               unsigned char loop = 1;
+               ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
+                       sizeof(ttl));
+               if (ret < 0) {
+                       ret = -ERRNO_TO_PARA_ERROR(errno);
+                       goto err;
+               }
+               ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop,
+                       sizeof(loop));
+               if (ret < 0) {
+                       ret = -ERRNO_TO_PARA_ERROR(errno);
+                       goto err;
+               }
+       }
+       return fd;
+err:
+       close(fd);
+       return ret;
+}
+
+/**
+ * Create and connect a sending UDP socket.
+ *
+ * \param hostname Where to send to (name or IPv4 address).
+ * \param port The udp port to use.
+ * \param ttl Time to live (only relevant for multicast).
+ *
+ * \return The fd of the socket on success, negative on error.
+ */
+int create_udp_send_socket(char *hostname, unsigned short port,
+               unsigned char ttl)
+{
+       struct sockaddr_in addr;
+       int fd, ret = resolve(hostname, port, &addr);
+
+       if (ret < 0)
+               return ret;
+       ret = create_udp_socket(&addr, port, ttl);
+       if (ret < 0)
+               return ret;
+       fd = ret;
+       ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
+       if (ret >= 0)
+               return fd;
+       ret = -ERRNO_TO_PARA_ERROR(errno);
+       close(fd);
+       return ret;
+}
+
+/**
+ * Create and bind a receiving UDP socket.
+ *
+ * Bind the created UDP socket to \a hostname, and add multicast membership if
+ * hostname is a multicast hostname.
+ *
+ * \param hostname Name or IPv4 address to receive from.
+ * \param port The udp port.
+ *
+ * \return The fd of the socket on success, negative on errors.
+ */
+int create_udp_recv_socket(char *hostname, unsigned short port)
+{
+       struct sockaddr_in addr;
+       int fd, ret = resolve(hostname, port, &addr);
+
+       if (ret < 0)
+               memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
+       ret = create_udp_socket(&addr, port, 1);
+       if (ret < 0)
+               return ret;
+       fd = ret;
+       ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
+       if (ret < 0) {
+               ret = -ERRNO_TO_PARA_ERROR(errno);
+               goto err;
+       }
+       /* Add multicast membership */
+       if (IN_MULTICAST(htonl(addr.sin_addr.s_addr))) {
+               struct ip_mreq mreq;
+
+               mreq.imr_multiaddr.s_addr = addr.sin_addr.s_addr;
+               mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+               ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+                       &mreq, sizeof(mreq));
+               if (ret < 0) {
+                       ret = -ERRNO_TO_PARA_ERROR(errno);
+                       goto err;
+               }
+       }
+       return fd;
+err:
+       close(fd);
+       return ret;
+}
diff --git a/net.h b/net.h
index 0cb2767c72181e4d98222fbf6c8d6f54f312071e..7cfee2eb69d081fd545ba525916796774c9dd706 100644 (file)
--- a/net.h
+++ b/net.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -61,3 +61,6 @@ int recv_pattern(int fd, const char *pattern, size_t bufsize);
 void enable_crypt(int fd, crypt_function *recv_f, crypt_function *send_f,
        void *private_data);
 void disable_crypt(int fd);
+int create_udp_recv_socket(char *hostname, unsigned short port);
+int create_udp_send_socket(char *hostname, unsigned short port,
+               unsigned char ttl);
index 2030eada238a85e939a325c0ef9ad0b771f0e8d2..c633f92f23615b490395253b7869fd7f219511b0 100644 (file)
--- a/ogg_afh.c
+++ b/ogg_afh.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2004-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 0653f7dadd0d7223e27ea9e339d113420aaa7a5f..8d1abb99b4f9cf47e329fa74c3186b7e47030de8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/oggdec_filter.ggo b/oggdec_filter.ggo
deleted file mode 100644 (file)
index e2d653d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-option "bufsize" b
-#~~~~~~~~~~~~~~~~~
-"size of output buffer"
-int typestr="kilobyte"
-default="128"
-optional
-details="
-       Increase this if you encounter output buffer overrun errors. Smaller
-       values make the oggdec filter use less memory.
-"
-
-option "initial_buffer" i
-#~~~~~~~~~~~~~~~~~~~~~~~~
-"size of initial input buffer"
-int typestr="kilobyte"
-default="16"
-optional
-details="
-       On startup, defer decoding until that many kilobytes are
-       available in the input buffer.
-"
diff --git a/ortp.h b/ortp.h
deleted file mode 100644 (file)
index a3205b3..0000000
--- a/ortp.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
-
-/** \file ortp.h some macros used by ortp_send.c and ortp_recv.c*/
-
-/** the possible packet types */
-enum ortp_audio_packet_type {ORTP_EOF, ORTP_BOF, ORTP_HEADER, ORTP_DATA};
-
-/** number of bytes of the paraslash ortp header */
-#define ORTP_AUDIO_HEADER_LEN 10
-
-/** write type of this packet to \a buf */
-#define WRITE_PACKET_TYPE(buf, x) (buf)[0] = (unsigned char)((x)&0xff)
-/** get type of this packet */
-#define READ_PACKET_TYPE(buf) (unsigned)(buf)[0]
-
-/** write the chunk time for this packet to \a buf */
-#define WRITE_CHUNK_TIME(buf, x) (buf)[1] = (unsigned char)((x)&0xff);\
-       (buf)[2] = (unsigned char)(((x)>>8)&0xff);\
-       (buf)[3] = (unsigned char)(((x)>>16)&0xff);\
-       (buf)[4] = (unsigned char)(((x)>>24)&0xff);
-
-/** get the chunk time of this packet */
-#define READ_CHUNK_TIME(buf) (unsigned char)(buf)[1] + \
-       ((unsigned char)(buf)[2] << 8) + \
-       ((unsigned char)(buf)[3] << 16) + \
-       ((unsigned char)(buf)[4] << 24)
-
-/** write the chunk timestamp */
-#define WRITE_CHUNK_TS(buf, x) (buf)[5] = (unsigned char)((x) & 0xff); \
-       (buf)[6] = (unsigned char)(((x >> 8) & 0xff));
-/** get the chunk timestamp */
-#define READ_CHUNK_TS(buf) (unsigned char)(buf)[5] + \
-       ((unsigned char)(buf)[6] << 8)
-
-/** write the stream type (header or headerless) */
-#define WRITE_STREAM_TYPE(buf, x) (buf)[7] = (unsigned char)((x)&0xff)
-/** get the type of the stream (header or headerless) */
-#define READ_STREAM_TYPE(buf) (unsigned)(buf)[7]
-
-/** write the length of the header (only used for streams with header) */
-#define WRITE_HEADER_LEN(buf, x) (buf)[8] = (unsigned char)((x) & 0xff); \
-       (buf)[9] = (unsigned char)(((x >> 8) & 0xff));
-
-/** get the length of the header (only used for packets containing a header) */
-#define READ_HEADER_LEN(buf) (unsigned char)(buf)[8] + \
-       ((unsigned char)(buf)[9] << 8)
diff --git a/ortp_recv.c b/ortp_recv.c
deleted file mode 100644 (file)
index 102fe9a..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
-/** \file ortp_recv.c paraslash's ortp receiver */
-
-#include <ortp/ortp.h>
-#include "para.h"
-
-#include "ortp.h"
-#include "list.h"
-#include "sched.h"
-#include "ggo.h"
-#include "recv.h"
-#include "ortp_recv.cmdline.h"
-
-#include "error.h"
-#include "audiod.h"
-#include "string.h"
-
-#define CHUNK_SIZE 128 * 1024
-
-/**
- * data specific to the ortp receiver
- *
- * \sa receiver receiver_node
- */
-struct private_ortp_recv_data {
-/**
- *
- *
- * whether a header was received
- *
- * A flag indicating whether the ortp receiver already received a packet which
- * contains the audio file header.
- *
- * This flag has no effect if the audio stream indicates that no extra headers
- * will be sent (mp3).  Otherwise, all data packets are dropped until the
- * header is received.
- */
-int have_header;
-/** the ortp session this instance of the receiver belongs to */
-RtpSession *session;
-/** the time the first data or header packet was received */
-struct timeval start;
-/** ETA of the next chunk */
-struct timeval next_chunk;
-/** number of consecutive bad chunks */
-int c_bad;
-/** the current timestamp which is passed to the receiving function of libortp */
-uint32_t timestamp;
-/** \a timestamp increases by this amount */
-uint32_t chunk_ts;
-};
-
-
-static int msg_to_buf(mblk_t *mp, char *buffer, int len)
-{
-       mblk_t *m, *mprev;
-       size_t mlen, rlen = len;
-
-       m = mp->b_cont;
-       mprev = mp;
-       while (m != NULL) {
-               mlen = m->b_wptr - m->b_rptr;
-               if (mlen <= rlen) {
-                       mblk_t *consumed = m;
-                       memcpy(buffer, m->b_rptr, mlen);
-                       /* go to next mblk_t */
-                       mprev->b_cont = m->b_cont;
-                       m = m->b_cont;
-                       consumed->b_cont = NULL;
-                       freeb (consumed);
-                       buffer += mlen;
-                       rlen -= mlen;
-               } else {
-                       memcpy (buffer, m->b_rptr, rlen);
-                       m->b_rptr += rlen;
-                       return len;
-               }
-       }
-       return len - rlen;
-}
-
-
-static void ortp_recv_pre_select(struct sched *s, struct task *t)
-{
-       struct receiver_node *rn = container_of(t, struct receiver_node, task);
-       struct private_ortp_recv_data *pord = rn->private_data;
-       struct timeval tmp;
-
-       if (tv_diff(now, &pord->next_chunk, &tmp) >= 0) {
-               tmp.tv_sec = 0;
-               tmp.tv_usec = 1000;
-       }
-       if (tv_diff(&s->timeout, &tmp, NULL) > 0)
-               s->timeout = tmp;
-}
-
-static void compute_next_chunk(unsigned chunk_time,
-               struct private_ortp_recv_data *pord)
-{
-       struct timeval chunk_tv = {0, chunk_time};
-       struct timeval tmp;
-
-       tv_add(&chunk_tv, &pord->next_chunk, &tmp);
-       pord->next_chunk = tmp;
-       pord->timestamp += pord->chunk_ts;
-//     PARA_DEBUG_LOG("next chunk (ts = %d) due at %lu:%lu\n",
-//             pord->timestamp, pord->next_chunk.tv_sec,
-//             pord->next_chunk.tv_usec);
-}
-
-static void ortp_recv_post_select(__a_unused struct sched *s, struct task *t)
-{
-       struct receiver_node *rn = container_of(t, struct receiver_node, task);
-       struct private_ortp_recv_data *pord = rn->private_data;
-       mblk_t *mp;
-       int packet_type, stream_type;
-       char tmpbuf[CHUNK_SIZE + 3];
-       unsigned chunk_time;
-       size_t packet_size;
-
-//     PARA_INFO_LOG("rn: %p, pord: %p, session: %p\n", rn, pord, pord->session);
-       if (rn->output_error && *rn->output_error < 0) {
-               t->error = *rn->output_error;
-               return;
-       }
-       if (pord->start.tv_sec)
-               if (tv_diff(now, &pord->next_chunk, NULL) < 0)
-                       return;
-       mp = rtp_session_recvm_with_ts(pord->session, pord->timestamp);
-       if (!mp) {
-               struct timeval min_delay = {0, 100};
-//             PARA_INFO_LOG("nope, chunk_ts = %d, loaded: %d, bad: %d\n",
-//                     pord->timestamp, rn->loaded, pord->c_bad);
-               pord->c_bad++;
-               if ((pord->c_bad > 5000 && pord->start.tv_sec) || pord->c_bad > 10000) {
-                       t->error = -E_TOO_MANY_BAD_CHUNKS;
-                       return;
-               }
-               tv_add(now, &min_delay, &pord->next_chunk);
-               return;
-       }
-       /* okay, we have a chunk of data */
-       if (!pord->start.tv_sec)
-               pord->start = *now;
-       t->error = msg_to_buf(mp, tmpbuf, CHUNK_SIZE);
-       if (t->error < ORTP_AUDIO_HEADER_LEN) {
-               if (t->error < 0)
-                       t->error = -E_MSG_TO_BUF;
-               else
-                       t->error = -E_ORTP_RECV_EOF;
-               goto err_out;
-       }
-       packet_size = t->error;
-       packet_type = READ_PACKET_TYPE(tmpbuf);
-       stream_type = READ_STREAM_TYPE(tmpbuf);
-       chunk_time = READ_CHUNK_TIME(tmpbuf);
-       pord->chunk_ts = READ_CHUNK_TS(tmpbuf);
-//     PARA_INFO_LOG("packet type: %d, stream type: %d, chunk time: %u,"
-//             " chunk_ts: %u, loaded: %u, bad: %d\n", packet_type,
-//             stream_type, chunk_time, pord->chunk_ts, rn->loaded, pord->c_bad);
-       switch (packet_type) {
-       unsigned header_len, payload_len;
-       case ORTP_EOF:
-               t->error = -E_RECV_EOF;
-               goto err_out;
-       case ORTP_BOF:
-               PARA_INFO_LOG("bof (%zu)\n", packet_size);
-               pord->have_header = 1;
-               /* fall through */
-       case ORTP_DATA:
-               if (!pord->have_header && stream_type)
-               /* can't use the data, wait for header */
-                       goto success;
-               if (packet_size + rn->loaded >= CHUNK_SIZE + ORTP_AUDIO_HEADER_LEN) {
-                       t->error = -E_OVERRUN;
-                       goto err_out;
-               }
-               if (packet_size > ORTP_AUDIO_HEADER_LEN) {
-                       memcpy(rn->buf + rn->loaded, tmpbuf + ORTP_AUDIO_HEADER_LEN,
-                               packet_size - ORTP_AUDIO_HEADER_LEN);
-                       rn->loaded += packet_size - ORTP_AUDIO_HEADER_LEN;
-               }
-               goto success;
-       case ORTP_HEADER:
-               header_len = READ_HEADER_LEN(tmpbuf);
-               PARA_DEBUG_LOG("header packet (%zu bytes), header len: %d\n",
-                       packet_size, header_len);
-               if (!pord->have_header) {
-                       pord->have_header = 1;
-                       memcpy(rn->buf, tmpbuf + ORTP_AUDIO_HEADER_LEN,
-                               packet_size - ORTP_AUDIO_HEADER_LEN);
-                       rn->loaded = packet_size - ORTP_AUDIO_HEADER_LEN;
-                       goto success;
-               }
-               if (header_len + ORTP_AUDIO_HEADER_LEN > packet_size) {
-                       t->error = -E_INVALID_HEADER;
-                       goto err_out;
-               }
-               payload_len = packet_size - ORTP_AUDIO_HEADER_LEN - header_len;
-               if (rn->loaded + payload_len > CHUNK_SIZE) {
-                       t->error = -E_OVERRUN;
-                       goto err_out;
-               }
-               if (payload_len)
-                       memcpy(rn->buf + rn->loaded, tmpbuf
-                               + (packet_size - payload_len), payload_len);
-               rn->loaded += payload_len;
-       }
-success:
-       t->error = 0;
-       freemsg(mp);
-       if (pord->c_bad) {
-               pord->c_bad = 0;
-               pord->next_chunk = *now;
-       }
-       compute_next_chunk(chunk_time, pord);
-       return;
-err_out:
-       freemsg(mp);
-}
-
-static void ortp_shutdown(void)
-{
-//     ortp_global_stats_display();
-       ortp_exit();
-}
-
-static void ortp_recv_close(struct receiver_node *rn)
-{
-       struct private_ortp_recv_data *pord = rn->private_data;
-
-       rtp_session_destroy(pord->session);
-       free(rn->private_data);
-       free(rn->buf);
-}
-
-static void *ortp_recv_parse_config(int argc, char **argv)
-{
-       int ret;
-
-       struct ortp_recv_args_info *tmp =
-               para_calloc(sizeof(struct ortp_recv_args_info));
-
-       ret = ortp_recv_cmdline_parser(argc, argv, tmp)? -E_ORTP_SYNTAX : 1;
-       if (ret > 0)
-               return tmp;
-       free(tmp);
-       return NULL;
-}
-
-static int ortp_recv_open(struct receiver_node *rn)
-{
-       struct private_ortp_recv_data *pord;
-       struct ortp_recv_args_info *c = rn->conf;
-
-       rn->buf = para_calloc(CHUNK_SIZE);
-
-       rn->private_data = para_calloc(sizeof(struct private_ortp_recv_data));
-       pord = rn->private_data;
-       pord->session = rtp_session_new(RTP_SESSION_RECVONLY);
-       PARA_NOTICE_LOG("receiving from %s:%d\n", c->host_arg, c->port_arg);
-       rtp_session_set_local_addr(pord->session, c->host_arg, c->port_arg);
-       rtp_session_set_remote_addr(pord->session, c->host_arg, c->port_arg);
-       rtp_session_set_payload_type(pord->session, PAYLOAD_AUDIO_CONTINUOUS);
-       rtp_session_enable_adaptive_jitter_compensation(pord->session, TRUE);
-       rtp_session_set_jitter_compensation(pord->session,
-                       c->jitter_compensation_arg);
-       return 1;
-}
-
-/**
- * the init function of the ortp receiver
- *
- * \param r pointer to the receiver struct to initialize
- *
- * Initialize all function pointers of \a r and call libortp's ortp_init().
- */
-void ortp_recv_init(struct receiver *r)
-{
-       struct ortp_recv_args_info dummy;
-
-       ortp_recv_cmdline_parser_init(&dummy);
-       r->shutdown = ortp_shutdown;
-       r->open = ortp_recv_open;
-       r->close = ortp_recv_close;
-       r->pre_select = ortp_recv_pre_select;
-       r->post_select = ortp_recv_post_select;
-       r->parse_config = ortp_recv_parse_config;
-       r->help = (struct ggo_help) {
-               .short_help = ortp_recv_args_info_help,
-               .detailed_help = ortp_recv_args_info_detailed_help
-       };
-
-       ortp_init();
-}
diff --git a/ortp_recv.ggo b/ortp_recv.ggo
deleted file mode 100644 (file)
index a706d54..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-option "host" i
-"ip or host to receive rtp packets from"
-string default="224.0.1.38"
-optional
-details="
-       The default address resoves to DANTZ.MCAST.NET and activates
-       multicast.
-"
-
-option "port" p "udp port"
-int typestr="portnumber"
-default="1500"
-optional
-
-option "jitter_compensation" j
-"set ortp's adaptive jitter compensation"
-int typestr="milliseconds"
-default="0"
-optional
diff --git a/ortp_send.c b/ortp_send.c
deleted file mode 100644 (file)
index 17f14d1..0000000
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
-
-/** \file ortp_send.c para_server's ortp sender */
-
-#include <ortp/ortp.h>
-#include <ortp/port.h>
-
-#include "server.cmdline.h"
-#include "para.h"
-#include "error.h"
-#include "string.h"
-#include "afh.h"
-#include "afs.h"
-#include "server.h"
-#include "vss.h"
-#include "list.h"
-#include "send.h"
-#include "ortp.h"
-
-/** Convert in_addr to ascii. */
-#define TARGET_ADDR(oc) inet_ntoa((oc)->addr)
-
-/** Describes one entry in the list of targets for the ortp sender. */
-struct ortp_target {
-       /** Address info. */
-       struct in_addr addr;
-       /** Whether the ortp sender is activated. */
-       int status;
-       /** The ortp timestamp increases by this amount. */
-       uint32_t chunk_ts;
-       /** The currently used timestamp for this target. */
-       uint32_t last_ts;
-       /** The position of this target in the list of targets. */
-       struct list_head node;
-       /** The UDP port. */
-       int port;
-       /** Non-zero if at least one chunk has been sent to this target. */
-       int streaming;
-       /** The session pointer from libortp. */
-       RtpSession *session;
-};
-
-static struct list_head targets;
-static struct sender *self;
-static int sender_status;
-
-static void ortp_delete_target(struct ortp_target *ot, const char *msg)
-{
-       PARA_NOTICE_LOG("deleting %s:%d (%s) from list\n", TARGET_ADDR(ot),
-               ot->port, msg);
-       if (ot->session) {
-               rtp_session_destroy(ot->session);
-               ot->session = NULL;
-       }
-       list_del(&ot->node);
-       free(ot);
-}
-
-static void ortp_send_buf(char *buf, size_t len, long unsigned chunks_sent)
-{
-       struct ortp_target *ot, *tmp;
-       int ret, ortp_len = len; /* rtp_session_send_with_ts expects int */
-
-       if (ortp_len < 0)
-               return;
-       list_for_each_entry_safe(ot, tmp, &targets, node) {
-               uint32_t ts;
-               if (!ot->session)
-                       continue;
-               WRITE_CHUNK_TS(buf, ot->chunk_ts);
-               ts = ot->chunk_ts * chunks_sent;
-               ret = rtp_session_send_with_ts(ot->session,
-                       (unsigned char*)buf, ortp_len, ts);
-               ot->last_ts = ts;
-               if (ret < 0)
-                       ortp_delete_target(ot, "send error");
-               if (ret != len + 12)
-                       PARA_NOTICE_LOG("short write %d\n", ret);
-       }
-}
-
-static int set_multicast(RtpSession *s)
-{
-       unsigned char loop = 1;
-       int ret;
-
-       ret = setsockopt(s->rtp.socket,
-               IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
-       if (ret < 0) {
-               PARA_ERROR_LOG("IP_MULTICAST_LOOP error %d\n", ret);
-
-       }
-       return 1;
-}
-
-static void ortp_init_session(struct ortp_target *ot)
-{
-       RtpSession *s;
-       int ret;
-
-       PARA_NOTICE_LOG("sending to udp %s:%d\n", TARGET_ADDR(ot), ot->port);
-       ot->session = rtp_session_new(RTP_SESSION_SENDONLY);
-       if (!ot->session)
-               return;
-       s = ot->session;
-       if (conf.ortp_jitter_compensation_arg) {
-               rtp_session_enable_adaptive_jitter_compensation(ot->session, TRUE);
-               rtp_session_set_jitter_compensation(ot->session,
-                       conf.ortp_jitter_compensation_arg);
-       }
-       /* always successful */
-       rtp_session_set_send_payload_type(s, PAYLOAD_AUDIO_CONTINUOUS);
-       ret = rtp_session_set_remote_addr(s, TARGET_ADDR(ot), ot->port);
-       if (ret < 0) {
-               rtp_session_destroy(ot->session);
-               ot->session = NULL;
-               return;
-       }
-       set_multicast(s);
-}
-
-/* called by vss */
-static void ortp_shutdown_targets(void)
-{
-       unsigned char buf[ORTP_AUDIO_HEADER_LEN];
-       struct ortp_target *ot, *tmp;
-
-       WRITE_PACKET_TYPE(buf, ORTP_EOF);
-       list_for_each_entry_safe(ot, tmp, &targets, node) {
-               if (!ot->session || !ot->streaming)
-                       continue;
-               PARA_INFO_LOG("sending eof to ortp target %s:%d, ts = %d\n",
-                       TARGET_ADDR(ot), ot->port, ot->last_ts);
-               rtp_session_send_with_ts(ot->session, buf,
-                       ORTP_AUDIO_HEADER_LEN, ot->last_ts);
-               ot->streaming = 0;
-               ot->chunk_ts = 0;
-               rtp_session_reset(ot->session);
-       }
-}
-
-static int need_extra_header(long unsigned current_chunk)
-{
-       static struct timeval last_header;
-       struct timeval now, diff;
-
-       if (!current_chunk)
-               return 0;
-       gettimeofday(&now, NULL);
-       tv_diff(&now, &last_header, &diff);
-       if (tv2ms(&diff) < conf.ortp_header_interval_arg)
-               return 0;
-       last_header = now;
-       return 1;
-}
-
-static void ortp_send(long unsigned current_chunk, long unsigned chunks_sent,
-               const char *buf, size_t len, const char *header_buf,
-               size_t header_len)
-{
-       struct ortp_target *ot, *tmp;
-       size_t sendbuf_len;
-       int packet_type = ORTP_DATA;
-       char *sendbuf;
-       struct timeval *chunk_tv;
-
-       if (sender_status != SENDER_ON)
-               return;
-
-//     PARA_NOTICE_LOG("sending %lu\n", current_chunk);
-       chunk_tv = vss_chunk_time();
-       if (!chunk_tv)
-               return;
-       list_for_each_entry_safe(ot, tmp, &targets, node) {
-               if (!ot->session) {
-                       ortp_init_session(ot);
-                       if (!ot->session)
-                               continue;
-               }
-               if (!ot->chunk_ts)
-                       ot->chunk_ts = rtp_session_time_to_ts(ot->session,
-                               (int)tv2ms(chunk_tv));
-//             PARA_DEBUG_LOG("len: %d, ts: %lu, ts: %d\n",
-//                     len, ot->chunk_ts * chunks_sent, ot->chunk_ts);
-               ot->streaming = 1;
-       }
-       if (list_empty(&targets))
-               return;
-       if (!need_extra_header(current_chunk))
-               header_len = 0;
-       sendbuf_len = ORTP_AUDIO_HEADER_LEN + header_len + len;
-       sendbuf = para_malloc(sendbuf_len);
-       if (!current_chunk)
-               packet_type = ORTP_BOF;
-       else if (header_len)
-               packet_type = ORTP_HEADER;
-       WRITE_PACKET_TYPE(sendbuf, packet_type);
-       WRITE_CHUNK_TIME(sendbuf, chunk_tv->tv_usec);
-       WRITE_STREAM_TYPE(sendbuf,  header_buf? 1 : 0);
-       WRITE_HEADER_LEN(sendbuf, header_len);
-       if (header_len)
-               memcpy(sendbuf + ORTP_AUDIO_HEADER_LEN, header_buf,
-                       header_len);
-       memcpy(sendbuf + ORTP_AUDIO_HEADER_LEN + header_len, buf, len);
-       ortp_send_buf(sendbuf, sendbuf_len, chunks_sent);
-       free(sendbuf);
-}
-
-static int ortp_com_on(__a_unused struct sender_command_data *scd)
-{
-
-       sender_status = SENDER_ON;
-       return 1;
-}
-
-static int ortp_com_off(__a_unused struct sender_command_data *scd)
-{
-       ortp_shutdown_targets();
-       sender_status = SENDER_OFF;
-       return 1;
-}
-
-static int ortp_com_delete(struct sender_command_data *scd)
-{
-       char *a = para_strdup(inet_ntoa(scd->addr));
-       struct ortp_target *ot, *tmp;
-       list_for_each_entry_safe(ot, tmp, &targets, node) {
-               if (scd->port != ot->port)
-                       continue;
-               if (strcmp(TARGET_ADDR(ot), a))
-                       continue;
-               ortp_delete_target(ot, "com_delete");
-       }
-       return 1;
-}
-
-static void ortp_add_target(int port, struct in_addr *addr)
-{
-       struct ortp_target *ot = para_calloc(sizeof(struct ortp_target));
-       ot->port = port;
-       ot->addr = *addr;
-       PARA_INFO_LOG("adding to target list (%s:%d)\n",
-               TARGET_ADDR(ot), ot->port);
-       para_list_add(&ot->node, &targets);
-}
-
-static int ortp_com_add(struct sender_command_data *scd)
-{
-       int port = (scd->port > 0)? scd->port : conf.ortp_default_port_arg;
-       ortp_add_target(port, &scd->addr);
-       return 1;
-}
-
-static char *ortp_info(void)
-{
-       struct ortp_target *ot;
-       char *ret, *tgts = NULL;
-
-       list_for_each_entry(ot, &targets, node) {
-               char *tmp = make_message("%s%s:%d ", tgts? tgts : "",
-                       TARGET_ADDR(ot), ot->port);
-               free(tgts);
-               tgts = tmp;
-       }
-       ret = make_message(
-               "ortp sender:\n"
-               "\tstatus: %s\n"
-               "\tport: udp %d\n"
-               "\ttargets: %s\n",
-               (sender_status == SENDER_ON)? "on" : "off",
-               conf.ortp_default_port_arg,
-               tgts? tgts : "(none)"
-       );
-       free(tgts);
-       return ret;
-}
-
-static void ortp_init_target_list(void)
-{
-       int i;
-
-       INIT_LIST_HEAD(&targets);
-       for (i = 0; i < conf.ortp_target_given; i++) {
-               char *arg = para_strdup(conf.ortp_target_arg[i]);
-               char *p = strchr(arg, ':');
-               int port;
-               struct in_addr addr;
-
-               if (!p)
-                       goto err;
-               *p = '\0';
-               if (!inet_pton(AF_INET, arg, &addr))
-                       goto err;
-               port = atoi(++p);
-               if (port < 0 || port > 65535)
-                       port = conf.ortp_default_port_arg;
-               ortp_add_target(port, &addr);
-               goto success;
-err:
-               PARA_CRIT_LOG("syntax error for ortp_target option "
-                       "#%d, ignoring\n", i);
-success:
-               free(arg);
-               continue;
-       }
-}
-
-static char *ortp_help(void)
-{
-       return make_message(
-               "usage: {on|off}\n"
-               "usage: {add|delete} IP port\n"
-               "example: add 224.0.1.38 1500 (LAN-streaming)\n"
-       );
-}
-
-/**
- * the init function of para_server's ortp sender
- *
- * \param s pointer to the http sender struct
- *
- * It initializes all function pointers of \a s and the list of ortp targets.
- */
-void ortp_send_init(struct sender *s)
-{
-       ortp_init();
-       INIT_LIST_HEAD(&targets);
-       s->info = ortp_info;
-       s->help = ortp_help;
-       s->send = ortp_send;
-       s->pre_select = NULL;
-       s->post_select = NULL;
-       s->shutdown_clients = ortp_shutdown_targets;
-       s->client_cmds[SENDER_ON] = ortp_com_on;
-       s->client_cmds[SENDER_OFF] = ortp_com_off;
-       s->client_cmds[SENDER_DENY] = NULL;
-       s->client_cmds[SENDER_ALLOW] = NULL;
-       s->client_cmds[SENDER_ADD] = ortp_com_add;
-       s->client_cmds[SENDER_DELETE] = ortp_com_delete;
-       self = s;
-       sender_status = SENDER_OFF;
-       ortp_init_target_list();
-       if (!conf.ortp_no_autostart_given)
-               sender_status = SENDER_ON;
-       PARA_DEBUG_LOG("ortp sender init complete\n");
-}
diff --git a/osl.c b/osl.c
index 2aee5b6aa6e1b9e9f9361bb920933c305e0e9b5a..ff588713b320aad0ef7e80a5258ac80f0c148622 100644 (file)
--- a/osl.c
+++ b/osl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/osl.h b/osl.h
index 58969a4392aab2d22383cc93ecd90aa36599ec8c..3c35fd4eb5017d498529ba0987e2c28f78d4acd5 100644 (file)
--- a/osl.h
+++ b/osl.h
@@ -1,6 +1,6 @@
 #include <sys/mman.h>
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 5e2acaa0dc6fcc2074b9686724020be56d6f822f..de53cdd1f07390010c29ae3afecf8a74f2a41e7e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 057526e30b6900b5dbc747919c43401d0aa42c88..f67a63ac1cae42eea3e7a4776e3b3353aadfedcb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/osx_write.ggo b/osx_write.ggo
deleted file mode 100644 (file)
index ce2792e..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-section "osx options"
-#####################
-
-option "channels" c
-#~~~~~~~~~~~~~~~~~~
-"number of channels (only neccessary for raw
-audio)"
-
-       int typestr="num"
-       default="2"
-       optional
-
-option "samplerate" s
-#~~~~~~~~~~~~~~~~~~~~~
-
-"force given sample rate (only neccessary for
-raw audio)"
-
-       int typestr="num"
-       default="44100"
-       optional
-
-option "numbuffers" n
-#~~~~~~~~~~~~~~~~~~~~~
-
-"number of audio buffers to allocate (increase if
-you get buffer underruns)"
-
-       int typestr="num"
-       default="5"
-       optional
diff --git a/para.h b/para.h
index 218b8147add53bf6805b0a8135927a8e36faa95a..fcc24746be9b18d5460292b42504898106131689 100644 (file)
--- a/para.h
+++ b/para.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
        typeof(x) _x = (x); \
        _x > 0? _x : -_x; })
 
-/** debug loglevel, gets really noisy */
-#define DEBUG 1
-/** still noisy, but won't fill your disk */
-#define INFO  2
-/** normal, but significant event */
-#define NOTICE 3
-/** unexpected event that can be handled */
-#define WARNING 4
-/** unhandled error condition */
-#define ERROR 5
-/** system might be unreliable */
-#define CRIT 6
-/** last message before exit */
-#define EMERG 7
+/** Debug loglevel, gets really noisy. */
+#define LL_DEBUG 0
+/** Still noisy, but won't fill your disk. */
+#define LL_INFO  1
+/** Normal, but significant event. */
+#define LL_NOTICE 2
+/** Unexpected event that can be handled. */
+#define LL_WARNING 3
+/** Unhandled error condition. */
+#define LL_ERROR 4
+/** System might be unreliable. */
+#define LL_CRIT 5
+/** Last message before exit. */
+#define LL_EMERG 6
+/** Number of all loglevels. */
+#define NUM_LOGLEVELS 7
 
 /** Log messages with lower priority than that will not be compiled in. */
 #define COMPILE_TIME_LOGLEVEL 0
 
 /** \cond */
-#if DEBUG > COMPILE_TIME_LOGLEVEL
-#define PARA_DEBUG_LOG(f,...) para_log(DEBUG, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
+#if LL_DEBUG >= COMPILE_TIME_LOGLEVEL
+#define PARA_DEBUG_LOG(f,...) para_log(LL_DEBUG, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
 #else
 #define PARA_DEBUG_LOG(...) do {;} while (0)
 #endif
 
-#if INFO > COMPILE_TIME_LOGLEVEL
-#define PARA_INFO_LOG(f,...) para_log(INFO, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
+#if LL_INFO >= COMPILE_TIME_LOGLEVEL
+#define PARA_INFO_LOG(f,...) para_log(LL_INFO, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
 #else
 #define PARA_INFO_LOG(...) do {;} while (0)
 #endif
 
-#if NOTICE > COMPILE_TIME_LOGLEVEL
-#define PARA_NOTICE_LOG(f,...) para_log(NOTICE, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
+#if LL_NOTICE >= COMPILE_TIME_LOGLEVEL
+#define PARA_NOTICE_LOG(f,...) para_log(LL_NOTICE, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
 #else
 #define PARA_NOTICE_LOG(...) do {;} while (0)
 #endif
 
-#if WARNING > COMPILE_TIME_LOGLEVEL
-#define PARA_WARNING_LOG(f,...) para_log(WARNING, "%s: " f, __FUNCTION__, ##  __VA_ARGS__)
+#if LL_WARNING >= COMPILE_TIME_LOGLEVEL
+#define PARA_WARNING_LOG(f,...) para_log(LL_WARNING, "%s: " f, __FUNCTION__, ##  __VA_ARGS__)
 #else
 #define PARA_WARNING_LOG(...) do {;} while (0)
 #endif
 
-#if ERROR > COMPILE_TIME_LOGLEVEL
-#define PARA_ERROR_LOG(f,...) para_log(ERROR, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
+#if LL_ERROR >= COMPILE_TIME_LOGLEVEL
+#define PARA_ERROR_LOG(f,...) para_log(LL_ERROR, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
 #else
 #define PARA_ERROR_LOG(...) do {;} while (0)
 #endif
 
-#if CRIT > COMPILE_TIME_LOGLEVEL
-#define PARA_CRIT_LOG(f,...) para_log(CRIT, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
+#if LL_CRIT >= COMPILE_TIME_LOGLEVEL
+#define PARA_CRIT_LOG(f,...) para_log(LL_CRIT, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
 #else
 #define PARA_CRIT_LOG(...) do {;} while (0)
 #endif
 
-#if EMERG > COMPILE_TIME_LOGLEVEL
-#define PARA_EMERG_LOG(f,...) para_log(EMERG, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
+#if LL_EMERG >= COMPILE_TIME_LOGLEVEL
+#define PARA_EMERG_LOG(f,...) para_log(LL_EMERG, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
 #else
 #define PARA_EMERG_LOG(...)
 #endif
 
 /** version text used by various commands if -V switch was given */
 #define VERSION_TEXT(prefix) "para_" prefix " " PACKAGE_VERSION " (" CODENAME ")" "\n" \
-       "Copyright (C) 2008 Andre Noll\n" \
+       "Copyright (C) 2009 Andre Noll\n" \
        "This is free software with ABSOLUTELY NO WARRANTY." \
        " See COPYING for details.\n" \
        "Written by Andre Noll.\n" \
index 171ebab59938b79b0f18c61e60fdb40b9390b680..a9925cd3079a341135d398a664e167691d1406c6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index e296bcb2a3f141564062aaa56ff9447c92c8f398..c2ed8afc7b6462db1e74def18636c357d3c93cbd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/recv.c b/recv.c
index 52935a8840462af33589ed1378b481c593c405a1..df8b9ce99e445f3acce568486c02878276f03576 100644 (file)
--- a/recv.c
+++ b/recv.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 #include "recv.h"
 #include "recv.cmdline.h"
 #include "fd.h"
+#include "string.h"
 #include "error.h"
 #include "stdout.h"
 
 /** the gengetopt args info struct */
 struct recv_args_info conf;
 
-/** always log to stderr */
-INIT_STDERR_LOGGING(conf.loglevel_arg);
+static int loglevel;
+/** Always log to stderr. */
+INIT_STDERR_LOGGING(loglevel);
 
 /** init array of error codes used by para_recv */
 INIT_RECV_ERRLISTS;
@@ -85,6 +87,7 @@ int main(int argc, char *argv[])
                PARA_EMERG_LOG("parse failed\n");
                goto out;
        }
+       loglevel = get_loglevel_by_name(conf.loglevel_arg);
        r = &receivers[receiver_num];
        rn.receiver = r;
        ret = r->open(&rn);
diff --git a/recv.ggo b/recv.ggo
deleted file mode 100644 (file)
index b7003b0..0000000
--- a/recv.ggo
+++ /dev/null
@@ -1,19 +0,0 @@
-option "loglevel" l
-#~~~~~~~~~~~~~~~~~~
-"set loglevel (0-6)"
-int typestr="level"
-default="4"
-optional
-
-option "receiver" r
-"Select receiver"
-string typestr="receiver_spec"
-default="http"
-optional
-details="
-       Any options for the selected receiver must
-       be quoted. Example:
-
-               -r 'http -i www.paraslash.org -p 8009'
-"
-
diff --git a/recv.h b/recv.h
index 3aed018042d8217f5483197b819bb2ac43d67205..b82e04f506c3dcad9ac43ad8796d0786aa2f1d9b 100644 (file)
--- a/recv.h
+++ b/recv.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -29,7 +29,7 @@ struct receiver_node {
 /**
  * Describes one supported paraslash receiver.
  *
- * \sa http_recv.c, ortp_recv.c
+ * \sa http_recv.c, udp_recv.c
  */
 struct receiver {
        /**
@@ -41,7 +41,7 @@ struct receiver {
         *
         * It must fill in all other function pointers and is assumed to succeed.
         *
-        * \sa http_recv_init ortp_recv_init.
+        * \sa http_recv_init udp_recv_init.
         */
        void (*init)(struct receiver *r);
        /**
@@ -105,6 +105,7 @@ struct receiver {
         */
        void (*post_select)(struct sched *s, struct task *t);
 
+       /** The two help texts of this receiver. */
        struct ggo_help help;
 };
 
@@ -114,13 +115,8 @@ extern void http_recv_init(struct receiver *r);
 #define HTTP_RECEIVER {.name = "http", .init = http_recv_init},
 extern void dccp_recv_init(struct receiver *r);
 #define DCCP_RECEIVER {.name = "dccp", .init = dccp_recv_init},
-
-#ifdef HAVE_ORTP
-extern void ortp_recv_init(struct receiver *r);
-#define ORTP_RECEIVER {.name = "ortp", .init = ortp_recv_init},
-#else
-#define ORTP_RECEIVER
-#endif
+extern void udp_recv_init(struct receiver *r);
+#define UDP_RECEIVER {.name = "udp", .init = udp_recv_init},
 
 extern struct receiver receivers[];
 /** \endcond */
@@ -129,9 +125,10 @@ extern struct receiver receivers[];
 #define DEFINE_RECEIVER_ARRAY struct receiver receivers[] = { \
        HTTP_RECEIVER \
        DCCP_RECEIVER \
-       ORTP_RECEIVER \
+       UDP_RECEIVER \
        {.name = NULL}};
 
+/** Iterate over all available receivers. */
 #define FOR_EACH_RECEIVER(i) for (i = 0; receivers[i].name; i++)
 
 void *check_receiver_arg(char *ra, int *receiver_num);
index 5f2412b5a0b02c0a40b479ed4ed635c43adb617e..2840df00b4317d143bcadec5637e0ca4d1200ef7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -85,6 +85,11 @@ void *check_receiver_arg(char *ra, int *receiver_num)
        return NULL;
 }
 
+/**
+ * Print out the help texts to all receivers.
+ *
+ * \param detailed Whether the detailed help should be printed.
+ */
 void print_receiver_helps(int detailed)
 {
        int i;
index efe4fd053a9cee6fa6bc984ba7be03443faa381d..c45ed3fa21ba14f74c19459009b0e92affb634d2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 2bea374e67673245bca959868e05943e432ee2c1..a7488429fe7aa7d0a4403577414c9daac134d84d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/sched.c b/sched.c
index 4df32fa1b16aa388eb46683bdd307c2a127c070c..9e346df20f5f4d03e6d1dfaa4322a3eace524db1 100644 (file)
--- a/sched.c
+++ b/sched.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/sched.h b/sched.h
index 4d57c75f3e3bf9b3076e60012bd80fba7cb4567c..26aaabe9a5678621b9e3fe4d1ba4c27d34fbfb4f 100644 (file)
--- a/sched.h
+++ b/sched.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/score.c b/score.c
index f2a28b7559bd49308559262fa3d475d041cab88f..51ec1e4a69a92e43d5af8274b1b769b3ce8f9181 100644 (file)
--- a/score.c
+++ b/score.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/send.h b/send.h
index 2fe1cc56ad0c35f773dfc608b8cfd628baf33417..c1ed00cf33a628e3aec9862874a2d1d3d1809ebe 100644 (file)
--- a/send.h
+++ b/send.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -12,7 +12,7 @@ enum {SENDER_ADD, SENDER_DELETE, SENDER_ALLOW, SENDER_DENY, SENDER_ON, SENDER_OF
 /**
  * Describes one supported sender of para_server.
  *
- * \sa http_send.c ortp_send.c, dccp_send.c.
+ * \sa http_send.c udp_send.c, dccp_send.c.
  */
 struct sender {
        /** The name of the sender. */
@@ -141,3 +141,5 @@ int generic_com_on(struct sender_status *ss, unsigned protocol);
 void generic_com_off(struct sender_status *ss);
 char *generic_sender_help(void);
 struct sender_client *accept_sender_client(struct sender_status *ss);
+int send_queued_chunks(int fd, struct chunk_queue *cq,
+               size_t max_bytes_per_write);
index 3d87008850a8ab3c39b3f1711d5aca1b2e2f3a45..d1dcaeb199e4b8f55b5871bfc89664acdc4d56d3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -93,45 +93,6 @@ void shutdown_clients(struct sender_status *ss)
                shutdown_client(sc, ss);
 }
 
-/**
- * Write a buffer to a non-blocking file descriptor.
- *
- * \param fd The file descriptor.
- * \param buf the buffer to write.
- * \param len the number of bytes of \a buf.
- * \param max_bytes_per_write Do not write more than that many bytes at once.
- *
- * If \a max_bytes_per_write is non-zero, do not send more than that many bytes
- * per write().
- *
- * EAGAIN is not considered an error condition.  For example CCID3 has a
- * sending wait queue which fills up and is emptied asynchronously. The EAGAIN
- * case means that there is currently no space in the wait queue, but this can
- * change at any moment.
- *
- * \return Negative on errors, number of bytes written else.
- */
-static int write_nonblock(int fd, const char *buf, size_t len,
-               size_t max_bytes_per_write)
-{
-       size_t written = 0;
-       int ret = 0;
-
-       while (written < len) {
-               size_t num = len - written;
-
-               if (max_bytes_per_write && max_bytes_per_write < num)
-                       num = max_bytes_per_write;
-               ret = write(fd, buf + written, num);
-               if (ret < 0 && errno == EAGAIN)
-                       return written;
-               if (ret < 0)
-                       return -ERRNO_TO_PARA_ERROR(errno);
-               written += ret;
-       }
-       return written;
-}
-
 static int queue_chunk_or_shutdown(struct sender_client *sc,
                struct sender_status *ss, const char *buf, size_t num_bytes)
 {
@@ -141,23 +102,31 @@ static int queue_chunk_or_shutdown(struct sender_client *sc,
        return ret;
 }
 
-/* return: negative on errors, zero if not everything was sent, one otherwise */
-static int send_queued_chunks(struct sender_client *sc,
+/**
+ * Try to empty the chunk queue for this fd.
+ *
+ * \param fd The file descriptor.
+ * \param cq The list of queued chunks.
+ * \param max_bytes_per_write Do not send more than this in one go.
+ *
+ * \return Negative on errors, zero if not everything was sent, one otherwise.
+ */
+int send_queued_chunks(int fd, struct chunk_queue *cq,
                size_t max_bytes_per_write)
 {
        struct queued_chunk *qc;
-       while ((qc = cq_peek(sc->cq))) {
+       while ((qc = cq_peek(cq))) {
                const char *buf;
                size_t len;
                int ret;
                cq_get(qc, &buf, &len);
-               ret = write_nonblock(sc->fd, buf, len, max_bytes_per_write);
+               ret = write_nonblock(fd, buf, len, max_bytes_per_write);
                if (ret < 0)
                        return ret;
-               cq_update(sc->cq, ret);
+               cq_update(cq, ret);
                if (ret != len)
                        return 0;
-               cq_dequeue(sc->cq);
+               cq_dequeue(cq);
        }
        return 1;
 }
@@ -192,7 +161,7 @@ void send_chunk(struct sender_client *sc, struct sender_status *ss,
                }
                sc->header_sent = 1;
        }
-       ret = send_queued_chunks(sc, max_bytes_per_write);
+       ret = send_queued_chunks(sc->fd, sc->cq, max_bytes_per_write);
        if (ret < 0) {
                shutdown_client(sc, ss);
                goto out;
index 6aa7c1f4c597fd92d4574aa43f3742604e6c9df9..5823cb28d5f458e9b885bf6cddb2795275ac3aa9 100644 (file)
--- a/server.c
+++ b/server.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -27,7 +27,7 @@
  *     - Volume normalizer: \ref compress_filter.c,
  *     - Output: \ref alsa_write.c, \ref osx_write.c,
  *     - http: \ref http_recv.c, \ref http_send.c,
- *     - ortp: \ref ortp_recv.c, \ref ortp_send.c,
+ *     - udp: \ref udp_recv.c, \ref udp_send.c,
  *     - dccp: \ref dccp_recv.c, \ref dccp_send.c,
  *     - Audio file selector: \ref afs.c, \ref aft.c, \ref mood.c,
  *     - Afs structures: \ref afs_table, \ref audio_file_data,
@@ -64,6 +64,7 @@
 
 #include <signal.h>
 #include <dirent.h>
+#include <sys/time.h>
 
 #include "para.h"
 #include "error.h"
@@ -84,6 +85,7 @@
 #include "sched.h"
 #include "signal.h"
 #include "user_list.h"
+#include "color.h"
 
 /** Define the array of error lists needed by para_server. */
 INIT_SERVER_ERRLISTS;
@@ -111,8 +113,6 @@ uint32_t afs_socket_cookie;
 /** The mutex protecting the shared memory area containing the mmd struct. */
 int mmd_mutex;
 
-/* global variables for server-internal use */
-static FILE *logfile;
 /** The file containing user information (public key, permissions). */
 static char *user_list_file = NULL;
 static int mmd_shm_id;
@@ -130,42 +130,36 @@ struct server_command_task {
        struct task task;
 };
 
-/**
- * Para_server's log function.
- *
- * \param ll The log level.
- * \param fmt The format string describing the log message.
- */
-__printf_2_3 void para_log(int ll, const char* fmt,...)
+static int want_colors(void)
+{
+       if (conf.color_arg == color_arg_no)
+               return 0;
+       if (conf.color_arg == color_arg_yes)
+               return 1;
+       if (conf.logfile_given)
+               return 0;
+       return isatty(STDERR_FILENO);
+}
+
+static void init_colors_or_die(void)
 {
-       va_list argp;
-       FILE *outfd;
-       struct tm *tm;
-       time_t t1;
-       char str[MAXLINE] = "";
-       pid_t mypid;
-
-       if (ll < conf.loglevel_arg)
+       int ret, i;
+
+       if (!want_colors())
                return;
-       outfd = logfile? logfile : stderr;
-       time(&t1);
-       tm = localtime(&t1);
-       strftime(str, MAXLINE, "%b %d %H:%M:%S", tm);
-       fprintf(outfd, "%s ", str);
-       if (conf.loglevel_arg <= INFO)
-               fprintf(outfd, "%i: ", ll);
-       mypid = getpid();
-       if (conf.loglevel_arg <= INFO)
-               fprintf(outfd, "(%d) ", (int)mypid);
-       va_start(argp, fmt);
-       vfprintf(outfd, fmt, argp);
-       va_end(argp);
+       daemon_set_flag(DF_COLOR_LOG);
+       daemon_set_default_log_colors();
+       for (i = 0; i < conf.log_color_given; i++) {
+               ret = daemon_set_log_color(conf.log_color_arg[i]);
+               if (ret < 0)
+                       exit(EXIT_FAILURE);
+       }
 }
 
 /*
  * setup shared memory area and get mutex for locking
  */
-static void shm_init(void)
+static void init_ipc_or_die(void)
 {
        void *shm;
        int ret = shm_new(sizeof(struct misc_meta_data));
@@ -197,13 +191,21 @@ err_out:
        exit(EXIT_FAILURE);
 }
 
-static void parse_config(int override)
+/**
+ * (Re-)read the server configuration files.
+ *
+ * \param override Passed to gengetopt to activate the override feature.
+ *
+ * This function also re-opens the logfile and sets the global \a
+ * user_list_file variable.
+ */
+void parse_config_or_die(int override)
 {
        char *home = para_homedir();
-       struct stat statbuf;
        int ret;
        char *cf;
 
+       daemon_close_log();
        if (conf.config_file_given)
                cf = para_strdup(conf.config_file_arg);
        else
@@ -213,13 +215,13 @@ static void parse_config(int override)
                user_list_file = make_message("%s/.paraslash/server.users", home);
        else
                user_list_file = para_strdup(conf.user_list_arg);
-       ret = stat(cf, &statbuf);
-       if (ret && conf.config_file_given) {
+       ret = file_exists(cf);
+       if (conf.config_file_given && !ret)  {
                ret = -1;
-               PARA_EMERG_LOG("can not stat config file %s\n", cf);
+               PARA_EMERG_LOG("can not read config file %s\n", cf);
                goto out;
        }
-       if (!ret) {
+       if (ret) {
                int tmp = conf.daemon_given;
                struct server_cmdline_parser_params params = {
                        .override = override,
@@ -231,8 +233,15 @@ static void parse_config(int override)
                server_cmdline_parser_config_file(cf, &conf, &params);
                conf.daemon_given = tmp;
        }
-       if (conf.logfile_given)
-               logfile = open_log(conf.logfile_arg);
+       if (conf.logfile_given) {
+               daemon_set_logfile(conf.logfile_arg);
+               daemon_open_log_or_die();
+       }
+       daemon_set_loglevel(conf.loglevel_arg);
+       init_colors_or_die();
+       daemon_set_flag(DF_LOG_PID);
+       daemon_set_flag(DF_LOG_LL);
+       daemon_set_flag(DF_LOG_TIME);
        ret = 1;
 out:
        free(cf);
@@ -256,9 +265,7 @@ static void signal_pre_select(struct sched *s, struct task *t)
 static void handle_sighup(void)
 {
        PARA_NOTICE_LOG("SIGHUP\n");
-       close_log(logfile); /* gets reopened if necessary by parse_config */
-       logfile = NULL;
-       parse_config(1); /* reopens log */
+       parse_config_or_die(1); /* reopens log */
        init_user_list(user_list_file); /* reload user list */
        if (mmd->afs_pid)
                kill(mmd->afs_pid, SIGHUP);
@@ -481,16 +488,18 @@ static void server_init(int argc, char **argv)
        /* parse command line options */
        server_cmdline_parser_ext(argc, argv, &conf, &params);
        HANDLE_VERSION_FLAG("server", conf);
-       para_drop_privileges(conf.user_arg, conf.group_arg);
+       drop_privileges_or_die(conf.user_arg, conf.group_arg);
        /* parse config file, open log and set defaults */
-       parse_config(0);
-       log_welcome("para_server", conf.loglevel_arg);
-       shm_init(); /* init mmd struct */
+       parse_config_or_die(0);
+       log_welcome("para_server");
+       init_ipc_or_die(); /* init mmd struct and mmd->lock */
+       /* make sure, the global now pointer is uptodate */
+       gettimeofday(now, NULL);
        server_uptime(UPTIME_SET); /* reset server uptime */
        init_user_list(user_list_file);
        /* become daemon */
        if (conf.daemon_given)
-               daemon_init();
+               daemonize();
        PARA_NOTICE_LOG("initializing audio format handlers\n");
        afh_init();
        PARA_NOTICE_LOG("initializing the audio file selector\n");
diff --git a/server.ggo b/server.ggo
deleted file mode 100644 (file)
index 9f39120..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-#########################
-section "General options"
-#########################
-
-option "loglevel" l
-#~~~~~~~~~~~~~~~~~~
-"set loglevel (1-6)"
-int typestr="level"
-default="4"
-optional
-details="
-       Larger values mean less verbose output. Loglevel 1 (debug) gets
-       really noisy; a value of 2 (info) produces still noisy output,
-       but this won't fill up the disk quicky. Messaged logged with
-       loglevel 3 (notice) indicate normal but significant events
-       while level 4 (warning) logs unexpected events that can be
-       handled. Unhandled error conditions are logged with loglevel
-       5 (error) and crititcal errors are logged using loglevel 6
-       (crit).  Finally, loglevel 7 (emerg) is reserved for messages
-       that cause para_server to terminate immediately.
-"
-
-option "port" p
-#~~~~~~~~~~~~~~
-"listening port"
-int typestr="portnumber"
-default="2990"
-optional
-details="
-       para_server listens on this tcp port for incoming connections
-       from clients such as para_client. If the default port is
-       changed, the corresponding option of para_client must be used
-       to connect to para_server.
-"
-
-option "daemon" d
-#~~~~~~~~~~~~~~~~
-"run as background daemon"
-flag off
-dependon="logfile"
-details="
-       Note that para_server refuses to start in daemon mode if no
-       logfile was specified.
-"
-
-option "user" u
-#~~~~~~~~~~~~~~
-"run as the given user"
-string typestr="name"
-optional
-details="
-       para_server does not need any special privileges. If started
-       as root (EUID == 0) this option must be given at the command
-       line (not in the configuration file) so that para_server
-       can drop the root privileges right after parsing the command
-       line options, but before parsing the configuration file. In
-       this case, real/effective/saved UID are all set to the UID
-       of 'name'. As the configuration file is read afterwards,
-       those options that have a default value depending on the UID
-       (e.g. the directory for the configuration file) are computed
-       by using the uid of 'name'.  This option has no effect if
-       para_server is started as a non-root user (i.e.  EUID != 0)
-"
-
-
-option "group" g
-#~~~~~~~~~~~~~~~
-"set group id"
-string typestr="group"
-optional
-details="
-       This option sets the group id according to 'group'. This option
-       is silently ignored if EUID != 0. Otherwise, real/effective
-       GID and the saved set-group ID are all set to the GID given by
-       'group'. Must not be given in the config file.
-"
-
-#############################
-section "Configuration files"
-#############################
-
-
-option "logfile" L
-#~~~~~~~~~~~~~~~~~
-"where to write log output"
-string typestr="filename"
-optional
-details="
-       If this option is not given, para_server writes the log
-       messages to to stderr
-"
-
-option "config_file" c
-#~~~~~~~~~~~~~~~~~~~~~
-"(default='~/.paraslash/server.conf'"
-string typestr="filename"
-optional
-details="
-       para_server reads its config file right after parsing
-       the options that were given at the command line. If an
-       option is given both at the command line and in the
-       config file, the value that was specified at the command line
-       takes precedence.
-"
-
-option "user_list" -
-#~~~~~~~~~~~~~~~~~~~
-"(default='~/.paraslash/server.users')"
-
-string typestr="filename"
-optional
-
-
-##################################
-section "virtual streaming system"
-##################################
-
-
-option "autoplay" a
-#~~~~~~~~~~~~~~~~~~
-"start playing on startup"
-flag off
-
-option "autoplay_delay" -
-#~~~~~~~~~~~~~~~~~~~~~~~~
-"time to wait before streaming"
-int typestr="ms"
-default="0"
-optional
-dependon="autoplay"
-details="
-       If para_server is started with the autoplay option, this option
-       may be used to set up a delay before para_server streams its
-       first audio file. This is useful for example if para_server
-       and para_audiod are started during system startup. The delay
-       time should be choosen large enough so that para_audiod is
-       already up when para_server starts to stream. Of course, this
-       option depends on the autoplay option.
-"
-option "announce_time" A
-#~~~~~~~~~~~~~~~~~~~~~~~
-"grace time for clients"
-
-int typestr="ms"
-default="300"
-optional
-details="
-       Clients such as para_audiod connect to para_server and execute
-       the stat command to find out whether an audio stream is
-       currently available. This sets the delay betweeen announcing
-       the stream via the output of the stat command and sending
-       the first chunk of data.
-"
-
-#############################
-section "audio file selector"
-#############################
-
-option "afs_database_dir" D
-#~~~~~~~~~~~~~~~~~~~~~~~~~~
-"location of the database"
-string typestr="path"
-optional
-details="
-       Where para_server should look for the osl database of the audio
-       file selector. The default is '~/.paraslash/afs_database'.
-"
-
-option "afs_socket" s
-#~~~~~~~~~~~~~~~~~~~~
-"Command socket for afs"
-string typestr="path"
-default="/var/paraslash/afs_command_socket"
-optional
-details="
-       For each server command that is handled by the audio file
-       selector, the child process of para_server connects to the
-       audio file selector via a local socket. This option specifies
-       the location of that socket in the file system.
-"
-option "afs_initial_mode" i
-#~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-"Mood or playlist to load on startup."
-string typestr="<specifier>/<name>"
-optional
-
-details="
-       The argument of this option must be prefixed with either 'p/'
-       or 'm/' to indicate whether a playlist or a mood should be
-       loaded. Example:
-               --afs_initial_mode p/foo
-       loads the playlist named 'foo'.
-"
-
-#####################
-section "http sender"
-#####################
-
-
-option "http_port" -
-#~~~~~~~~~~~~~~~~~~~
-"tcp port for http streaming"
-int typestr="portnumber"
-default="8000"
-optional
-details="
-       The http sender of para_server listens on this port for
-       incoming connections. Clients are expected to send the usual
-       http request message such as 'GET / HTTP/'.
-"
-
-option "http_default_deny" -
-#~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"make the http ACL a whitelist"
-flag off
-details="
-       The default is to use blacklists instead, i.e. connections
-       to the http sender are allowed unless the connecting host
-       matches a pattern given by a http_access option. This allows
-       to use access control the other way round: Connections are
-       denied from hosts which are not explicitly allowed by one or
-       more http_access options.
-"
-
-option "http_access" -
-#~~~~~~~~~~~~~~~~~~~~~
-"add an entry to the http ACL"
-string typestr="a.b.c.d/n"
-optional
-multiple
-details="
-       Add given host/network to access control list (whitelist if
-       http_default_deny was given, blacklist otherwise) before
-       opening the tcp port. This option can be given multiple
-       times. Example: '192.168.0.0/24' whitelists/blacklists the
-       256 hosts 192.168.0.x
-"
-
-option "http_no_autostart" -
-#~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"do not open tcp port on startup"
-flag off
-details="
-       If this option is given, the http sender does not listen on
-       its tcp port. It may be instructed to open this port at a
-       later time by using the sender command.
-"
-
-option "http_max_clients" -
-#~~~~~~~~~~~~~~~~~~~~~~~~~~
-"maximal number of connections"
-int typestr="number"
-default="-1"
-optional
-details="
-       The http sender will refuse connections if already that number
-       of clients are currently connected. A non-positive value
-       (the default) allows an unlimited number of simultaneous
-       connections.
-"
-
-#####################
-section "dccp sender"
-#####################
-
-
-option "dccp_port" -
-#~~~~~~~~~~~~~~~~~~~
-"port for dccp streaming"
-int typestr="portnumber"
-default="8000"
-optional
-details="
-       See http_port for details.
-"
-
-option "dccp_default_deny" -
-#~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"make the dccp ACL a whitelist"
-flag off
-details="
-       See http_default_deny for details.
-"
-
-option "dccp_access" -
-#~~~~~~~~~~~~~~~~~~~~~
-"add an entry to the dccp ACL"
-string typestr="a.b.c.d/n"
-optional
-multiple
-details="
-       See http_access for details.
-"
-
-option "dccp_max_clients" -
-#~~~~~~~~~~~~~~~~~~~~~~~~~~
-"maximal number of connections"
-int typestr="number"
-default="-1"
-optional
-details="
-       See http_max_clients for details.
-"
-
-#####################
-section "ortp sender"
-#####################
-
-option "ortp_target" -
-#~~~~~~~~~~~~~~~~~~~~~
-"add ortp target"
-string typestr="a.b.c.d:p"
-optional
-multiple
-details="
-       Add given host/port to the list of targets.  This option
-       can be given multiple times.  Example: '224.0.1.38:1500'
-       instructs the ortp sender to send to udp port 1500 on host
-       224.0.1.38 (unassigned ip in the Local Network Control Block
-       224.0.0/24). This is useful for LAN-streaming.
-"
-
-option "ortp_no_autostart" -
-#~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"do not start sending"
-flag off
-details="
-       If this option is given, ortp streaming may be activated at
-       a later time by using the sender command.
-"
-
-option "ortp_default_port" -
-#~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"udp port to send to"
-int typestr="port"
-default="1500"
-optional
-
-option "ortp_header_interval" H
-#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"duration for sending header"
-int typestr="ms"
-default="2000"
-optional
-details="
-       As the ortp sender has no idea about connected clients it
-       sends the audio file header periodically if necessary. This
-       option is used to specify the duration of the interval between
-       sending the header. Shorter values decrease the average time
-       clients have to wait before being able to start playback,
-       but this also increases the amount network traffic. Note
-       that this affects only ogg vorbis streams as this is the only
-       audio format that needs an audio file header.
-"
-
-option "ortp_jitter_compensation" j
-#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"configure jitter compensation"
-int typestr="ms"
-default="400"
-optional
-details="
-       ortp's adaptive jitter compensation gets activated whenever
-       this value is greater than zero. See the ortp documentation
-       about details on this feature.
-"
index b37c9f13921908701f284f989ef17ac7c2c6bb24..b133d82eb66f3b72c8090eda2641611369a85300 100644 (file)
--- a/server.h
+++ b/server.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -106,3 +106,4 @@ struct misc_meta_data {
 extern struct server_args_info conf;
 
 __noreturn void handle_connect(int fd, const char *peername);
+void parse_config_or_die(int override);
diff --git a/sha1.c b/sha1.c
index af4dbc654c70008f3d89c7ddf093ffc8d18694ee..65524bc5119f3d187eb20c679d63bfff4c9d01d1 100644 (file)
--- a/sha1.c
+++ b/sha1.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 9168e918205a5f6733761db31ea7fc6573b2bbae..acc87802b33a841f8f5d7f90b971ae97a3edc3b0 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2004-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 68c0ae1fceb762c0fb278e064168c57f07ec147d..962e074a5ed481b9c9de21708bdb07a42c91a3c7 100644 (file)
--- a/signal.h
+++ b/signal.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/stat.c b/stat.c
index e640e4c6994ca830e769c34dc6072a17ac254606..4ba1b0e8485a8125d2fcdd6353e8508e83417340 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/stdin.c b/stdin.c
index 0b84cdc72011e369bf290f671ae96d6e8cab8569..fea30dd90ca0e493bb6f4ce54f1515ea072761dc 100644 (file)
--- a/stdin.c
+++ b/stdin.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/stdin.h b/stdin.h
index 99233f9ffbbd79b62035371cfed88510e36cb914..edb72cf894e6f2bf8e7d994f6dea0b45e83ebb5d 100644 (file)
--- a/stdin.h
+++ b/stdin.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 87bf711f0d7a3794b7a6539c698a44457e984c28..ce0d22093486281f4fd489c2fcb07d0bb25ef01c 100644 (file)
--- a/stdout.c
+++ b/stdout.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 6a6400ce96c2b8b1f10ed5d8e43a3a186ca213c8..4149dad39155a1ed569bbd11a4d51f6bfa5337df 100644 (file)
--- a/stdout.h
+++ b/stdout.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index d23e43c1eecb1d34e4eaefda77423da076ab412a..3c80d27cc6b6ad73a95392c17cdb041837ec6ba5 100644 (file)
--- a/string.c
+++ b/string.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2004-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -328,27 +328,6 @@ __must_check unsigned split_args(char *args, char *** const argv_ptr, const char
        return n;
 }
 
-/**
- * Ensure that file descriptors 0, 1, and 2 are valid.
- *
- * Common approach that opens /dev/null until it gets a file descriptor greater
- * than two.
- *
- * \sa okir's Black Hats Manual.
- */
-void valid_fd_012(void)
-{
-       while (1) {
-               int fd = open("/dev/null", O_RDWR);
-               if (fd < 0)
-                       exit(EXIT_FAILURE);
-               if (fd > 2) {
-                       close(fd);
-                       break;
-               }
-       }
-}
-
 /**
  * Get the own hostname.
  *
@@ -607,3 +586,22 @@ int para_atoi32(const char *str, int32_t *value)
        *value = tmp;
        return 1;
 }
+
+int get_loglevel_by_name(const char *txt)
+{
+       if (!strcasecmp(txt, "debug"))
+               return LL_DEBUG;
+       if (!strcasecmp(txt, "info"))
+               return LL_INFO;
+       if (!strcasecmp(txt, "notice"))
+               return LL_NOTICE;
+       if (!strcasecmp(txt, "warning"))
+               return LL_WARNING;
+       if (!strcasecmp(txt, "error"))
+               return LL_ERROR;
+       if (!strcasecmp(txt, "crit"))
+               return LL_CRIT;
+       if (!strcasecmp(txt, "emerg"))
+               return LL_EMERG;
+       return -1;
+}
index 561ff4e8705c4d20baf0b01999503f725cadb820..77e62e907263b6c15e4d470f2dc86951d9581269 100644 (file)
--- a/string.h
+++ b/string.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -40,7 +40,6 @@ __must_check __malloc char *para_logname(void);
 __must_check __malloc char *para_homedir(void);
 __must_check unsigned split_args(char *args, char *** const argv_ptr, const char *delim);
 __malloc char *para_hostname(void);
-void valid_fd_012(void);
 __printf_2_3 int para_printf(struct para_buffer *b, const char *fmt, ...);
 /** Used for for_each_line() and for_each_line_ro(). */
 typedef int line_handler_t(char *, void *);
@@ -50,3 +49,4 @@ int for_each_line_ro(char *buf, size_t size, line_handler_t *line_handler,
        void *private_data);
 int para_atoi64(const char *str, int64_t *result);
 int para_atoi32(const char *str, int32_t *value);
+int get_loglevel_by_name(const char *txt);
diff --git a/time.c b/time.c
index 0ebc6ec0c8f3f10e66f77ffe18d0f8fe05d7210a..6e1d603d2751566f3afa55d518367e162ae1b06b 100644 (file)
--- a/time.c
+++ b/time.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/udp_header.h b/udp_header.h
new file mode 100644 (file)
index 0000000..83157e6
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file udp_header.h some macros used by udp_send.c and udp_recv.c. */
+
+/**
+ * Number of bytes of the paraslash udp header.
+ *
+ * The udp sender prepends a header at the beginning of each data chunk. Within
+ * this header, the type of the current audio stream and the * type of this
+ * data chunk is coded.
+ */
+#define UDP_AUDIO_HEADER_LEN 16
+
+/** The possible stream types. */
+enum udp_stream_type {
+       /** Used for mp3 and aac streams. */
+       UDP_PLAIN_STREAM,
+       /** Ogg vorbis streams. */
+       UDP_HEADER_STREAM,
+       /** stream type not yet known. */
+       UDP_UNKNOWN_STREAM
+};
+
+/** The possible packet types. */
+enum udp_audio_packet_type {
+       /** Beginning of file. */
+       UDP_BOF_PACKET,
+       /** End of file. */
+       UDP_EOF_PACKET,
+       /** Combined header/data packet (ogg only). */
+       UDP_HEADER_PACKET,
+       /** Packet contains only audio file data. */
+       UDP_DATA_PACKET,
+       /** Invalid packet type. */
+       UDP_UNKNOWN_PACKET
+};
+
+/** The contents of an udp audio header. */
+struct udp_audio_header {
+       /** see \ref udp_stream_type. */
+       uint8_t stream_type;
+       /** see \ref udp_audio_packet_type. */
+       uint8_t packet_type;
+       /** Non-zero only for header packets. */
+       uint16_t header_len;
+       /** Length of header plus audio file data. */
+       uint16_t payload_len;
+};
+
+/**
+ * Write a struct udp_audio_header to a buffer.
+ *
+ * \param buf The buffer to write to.
+ * \param h The audio header to write.
+ *
+ * Used by the udp sender.
+ *
+ */
+_static_inline_ void write_udp_audio_header(char *buf, struct udp_audio_header *h)
+{
+       memcpy(buf, "UDPM", 4);
+       write_u8(buf + 4, h->stream_type);
+       write_u8(buf + 5, h->packet_type);
+       write_u16(buf + 6, h->header_len);
+       write_u16(buf + 8, h->payload_len);
+       memset(buf + 10, 0, 6);
+}
+
+/**
+ * Used by the udp receiver to read a struct udp_audio_header from a buffer.
+ *
+ * \param buf The buffer to read from.
+ * \param len The length of \a buf.
+ * \param h Result pointer.
+ *
+ * \return 1 if \a buf contains a valid udp audio header, -1 else.
+ */
+_static_inline_ int read_udp_audio_header(char *buf, size_t len,
+               struct udp_audio_header *h)
+{
+       if (len < 4)
+               goto err;
+       if (memcmp(buf, "UDPM", 4))
+               goto err;
+       h->stream_type = read_u8(buf + 4);
+       h->packet_type = read_u8(buf + 5);
+       h->header_len = read_u16(buf + 6);
+       h->payload_len = read_u16(buf + 8);
+       return 1;
+err:
+       h->stream_type = UDP_UNKNOWN_STREAM;
+       h->packet_type = UDP_UNKNOWN_PACKET;
+       h->header_len = h->payload_len = 0;
+       return -1;
+}
diff --git a/udp_recv.c b/udp_recv.c
new file mode 100644 (file)
index 0000000..bdc2541
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+/** \file udp_recv.c Paraslash's udp receiver */
+
+#include <dirent.h>
+
+#include "para.h"
+#include "error.h"
+#include "portable_io.h"
+#include "udp_header.h"
+#include "list.h"
+#include "sched.h"
+#include "ggo.h"
+#include "recv.h"
+#include "udp_recv.cmdline.h"
+#include "audiod.h"
+#include "string.h"
+#include "net.h"
+#include "fd.h"
+
+/** The size of the receiver node buffer. */
+#define UDP_RECV_CHUNK_SIZE (128 * 1024)
+
+/**
+ * Data specific to the udp receiver.
+ *
+ * \sa \ref receiver, \ref receiver_node.
+ */
+struct private_udp_recv_data {
+       /**
+        * Whether a header was received.
+        *
+        * A flag indicating whether this receiver already received a packet
+        * which contains the audio file header.
+        *
+        * This flag has no effect if the audio stream indicates that no extra
+        * headers will be sent (mp3, aac).  Otherwise, all data packets are
+        * dropped until the header is received.
+        */
+       int have_header;
+       /** The socket file descriptor. */
+       int fd;
+       /** Non-zero on short reads. */
+       uint16_t need_more;
+       /** Copied from the first audio header received. */
+       uint16_t stream_type;
+};
+
+static void udp_recv_pre_select(struct sched *s, struct task *t)
+{
+       struct receiver_node *rn = container_of(t, struct receiver_node, task);
+       struct private_udp_recv_data *purd = rn->private_data;
+
+       para_fd_set(purd->fd, &s->rfds, &s->max_fileno);
+}
+
+static int enough_space(size_t nbytes, size_t loaded)
+{
+       return nbytes + loaded < UDP_RECV_CHUNK_SIZE;
+}
+
+/*
+ * Perform some sanity checks on an udp audio file header.
+ *
+ * return: negative on error, 0: discard data, 1: use data
+ */
+static int examine_audio_header(struct private_udp_recv_data *purd,
+               struct udp_audio_header *uah, size_t packet_size)
+{
+       /* payload_len includes header */
+       if (uah->payload_len < uah->header_len)
+               return -E_UDP_BAD_HEADER;
+       switch (uah->packet_type) {
+       case UDP_EOF_PACKET:
+               return -E_RECV_EOF;
+       case UDP_BOF_PACKET:
+               purd->have_header = 1;
+               /* fall through */
+       case UDP_DATA_PACKET:
+               if (uah->header_len) /* header in no-header packet */
+                       return -E_UDP_BAD_HEADER;
+               break;
+       case UDP_HEADER_PACKET:
+               if (!uah->header_len) /** no header in header packet */
+                       return -E_UDP_BAD_HEADER;
+               break;
+       default: /* bad packet type */
+               return -E_UDP_BAD_HEADER;
+       }
+       /* check stream type */
+       if (uah->stream_type != UDP_PLAIN_STREAM &&
+                       uah->stream_type != UDP_HEADER_STREAM)
+               return -E_UDP_BAD_STREAM_TYPE;
+       if (purd->stream_type == UDP_UNKNOWN_STREAM)
+               purd->stream_type = uah->stream_type;
+       /* stream type must not change */
+       if (uah->stream_type != purd->stream_type)
+               return -E_UDP_BAD_STREAM_TYPE;
+       if (!purd->have_header && uah->stream_type == UDP_HEADER_STREAM)
+               /* can't use the data, wait for header packet */
+               return 0;
+       if (packet_size < uah->payload_len + UDP_AUDIO_HEADER_LEN)
+               /* we read only a part of the package */
+               purd->need_more = uah->payload_len
+                       + UDP_AUDIO_HEADER_LEN - packet_size;
+       return 1;
+}
+
+static int add_rn_output(struct receiver_node *rn, char *buf, size_t len)
+{
+       if (!len)
+               return 1;
+       if (!enough_space(len, rn->loaded))
+               return -E_UDP_OVERRUN;
+       memcpy(rn->buf + rn->loaded, buf, len);
+       rn->loaded += len;
+       return 1;
+}
+
+static void udp_recv_post_select(__a_unused struct sched *s, struct task *t)
+{
+       struct receiver_node *rn = container_of(t, struct receiver_node, task);
+       struct private_udp_recv_data *purd = rn->private_data;
+       int ret;
+       char tmpbuf[UDP_RECV_CHUNK_SIZE];
+       uint16_t data_len;
+       char *data_buf;
+       size_t packet_size;
+       struct udp_audio_header uah;
+
+       if (rn->output_error && *rn->output_error < 0) {
+               t->error = *rn->output_error;
+               return;
+       }
+       if (!FD_ISSET(purd->fd, &s->rfds))
+               return;
+       ret = recv_bin_buffer(purd->fd, tmpbuf, UDP_RECV_CHUNK_SIZE);
+       if (ret < 0) {
+               if (is_errno(ret, EINTR) || is_errno(ret, EAGAIN))
+                       goto success;
+               t->error = ret;
+               return;
+       }
+       t->error = -E_RECV_EOF;
+       if (!ret)
+               return;
+       packet_size = ret;
+       for (;;) {
+               uint16_t num;
+
+               if (!purd->need_more) {
+                       ret = read_udp_audio_header(tmpbuf, packet_size, &uah);
+                       if (ret >= 0)
+                               break;
+                       goto success; /* drop data */
+               }
+               num = PARA_MIN(purd->need_more, (uint16_t)packet_size);
+               assert(num > 0);
+               t->error = add_rn_output(rn, tmpbuf, num);
+               if (t->error < 0)
+                       return;
+               purd->need_more -= num;
+               if (packet_size <= num)
+                       goto success;
+               packet_size -= num;
+               memmove(tmpbuf, tmpbuf + num, packet_size);
+       }
+       assert(!purd->need_more);
+       t->error = examine_audio_header(purd, &uah, packet_size);
+       if (t->error <= 0)
+               return;
+       data_len = uah.payload_len;
+       data_buf = tmpbuf + UDP_AUDIO_HEADER_LEN;
+       if (uah.packet_type == UDP_HEADER_PACKET) {
+               if (purd->have_header) { /* skip header */
+                       data_buf += uah.header_len;
+                       data_len -= uah.header_len;
+               } else { /* only use the header */
+                       purd->have_header = 1;
+                       data_len = uah.header_len;
+               }
+       }
+       t->error = add_rn_output(rn, data_buf, data_len);
+       return;
+success:
+       t->error = 1;
+}
+
+static void udp_shutdown(void)
+{
+       return;
+}
+
+static void udp_recv_close(struct receiver_node *rn)
+{
+       struct private_udp_recv_data *purd = rn->private_data;
+
+       if (purd->fd >= 0)
+               close(purd->fd);
+       free(rn->private_data);
+       free(rn->buf);
+}
+
+static void *udp_recv_parse_config(int argc, char **argv)
+{
+       int ret;
+       struct udp_recv_args_info *tmp =
+               para_calloc(sizeof(struct udp_recv_args_info));
+
+       ret = udp_recv_cmdline_parser(argc, argv, tmp)? -E_UDP_SYNTAX : 1;
+       if (ret >= 0)
+               return tmp;
+       free(tmp);
+       return NULL;
+}
+
+static int udp_recv_open(struct receiver_node *rn)
+{
+       struct private_udp_recv_data *purd;
+       struct udp_recv_args_info *c = rn->conf;
+       int ret;
+
+       rn->buf = para_calloc(UDP_RECV_CHUNK_SIZE);
+       rn->private_data = para_calloc(sizeof(struct private_udp_recv_data));
+       purd = rn->private_data;
+       ret = create_udp_recv_socket(c->host_arg, c->port_arg);
+       if (ret < 0)
+               goto err;
+       purd->fd = ret;
+       ret = mark_fd_nonblocking(purd->fd);
+       if (ret < 0)
+               goto err;
+       purd->stream_type = UDP_UNKNOWN_STREAM;
+       PARA_NOTICE_LOG("receiving from %s:%d, fd=%d\n", c->host_arg,
+               c->port_arg, purd->fd);
+       return purd->fd;
+err:
+       free(rn->private_data);
+       free(rn->buf);
+       return ret;
+}
+
+/**
+ * The init function of the udp receiver.
+ *
+ * \param r Pointer to the receiver struct to initialize.
+ *
+ * Initialize all function pointers of \a r.
+ */
+void udp_recv_init(struct receiver *r)
+{
+       struct udp_recv_args_info dummy;
+
+       udp_recv_cmdline_parser_init(&dummy);
+       r->shutdown = udp_shutdown;
+       r->open = udp_recv_open;
+       r->close = udp_recv_close;
+       r->pre_select = udp_recv_pre_select;
+       r->post_select = udp_recv_post_select;
+       r->parse_config = udp_recv_parse_config;
+       r->help = (struct ggo_help) {
+               .short_help = udp_recv_args_info_help,
+               .detailed_help = udp_recv_args_info_detailed_help
+       };
+}
diff --git a/udp_send.c b/udp_send.c
new file mode 100644 (file)
index 0000000..3804c39
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file udp_send.c Para_server's udp sender. */
+
+
+#include <sys/time.h>
+#include <dirent.h>
+
+#include "server.cmdline.h"
+#include "para.h"
+#include "error.h"
+#include "string.h"
+#include "afh.h"
+#include "afs.h"
+#include "server.h"
+#include "vss.h"
+#include "list.h"
+#include "send.h"
+#include "portable_io.h"
+#include "udp_header.h"
+#include "net.h"
+#include "fd.h"
+#include "sched.h"
+#include "close_on_fork.h"
+#include "chunk_queue.h"
+
+/** Convert in_addr to ascii. */
+#define TARGET_ADDR(oc) inet_ntoa((oc)->addr)
+
+/** Describes one entry in the list of targets for the udp sender. */
+struct udp_target {
+       /** Address info. */
+       struct in_addr addr;
+       /** The position of this target in the list of targets. */
+       struct list_head node;
+       /** The UDP port. */
+       int port;
+       /** The socket fd. */
+       int fd;
+       /** The list of queued chunks for this fd. */
+       struct chunk_queue *cq;
+};
+
+static struct list_head targets;
+static int sender_status;
+
+static void udp_close_target(struct udp_target *ut)
+{
+       if (ut->fd < 0)
+               return;
+       close(ut->fd);
+       del_close_on_fork_list(ut->fd);
+       cq_destroy(ut->cq);
+       ut->cq = NULL;
+       ut->fd = -1;
+}
+
+static void udp_delete_target(struct udp_target *ut, const char *msg)
+{
+       PARA_NOTICE_LOG("deleting %s:%d (%s) from list\n", TARGET_ADDR(ut),
+               ut->port, msg);
+       udp_close_target(ut);
+       list_del(&ut->node);
+       free(ut);
+}
+
+/** The maximal size of the per-target chunk queue. */
+#define UDP_CQ_BYTES 40000
+
+static int udp_init_session(struct udp_target *ut)
+{
+       int ret;
+
+       if (ut->fd >= 0) /* nothing to do */
+               return 0;
+       ret = create_udp_send_socket(TARGET_ADDR(ut), ut->port,
+               conf.udp_ttl_arg);
+       if (ret < 0)
+               return ret;
+       ut->fd = ret;
+       ret = mark_fd_nonblocking(ut->fd);
+       if (ret < 0) {
+               close(ut->fd);
+               return ret;
+       }
+       add_close_on_fork_list(ut->fd);
+       ut->cq = cq_new(UDP_CQ_BYTES);
+       PARA_NOTICE_LOG("sending to udp %s:%d\n", TARGET_ADDR(ut), ut->port);
+       return 1;
+}
+
+static void udp_send_buf(char *buf, size_t len)
+{
+       struct udp_target *ut, *tmp;
+       int ret;
+
+       list_for_each_entry_safe(ut, tmp, &targets, node) {
+               ret = udp_init_session(ut);
+               if (ret < 0) {
+                       udp_delete_target(ut, para_strerror(-ret));
+                       continue;
+               }
+               ret = send_queued_chunks(ut->fd, ut->cq, 0);
+               if (ret < 0) {
+                       udp_delete_target(ut, para_strerror(-ret));
+                       continue;
+               }
+               if (!len)
+                       continue;
+               if (!ret) { /* still data left in the queue */
+                       ret = cq_enqueue(ut->cq, buf, len);
+                       if (ret < 0) {
+                               udp_delete_target(ut, para_strerror(-ret));
+                               continue;
+                       }
+               }
+               ret = write_nonblock(ut->fd, buf, len, 0);
+               if (ret < 0) {
+                       udp_delete_target(ut, para_strerror(-ret));
+                       continue;
+               }
+               if (ret != len) {
+                       ret = cq_enqueue(ut->cq, buf + ret, len - ret);
+                       if (ret < 0) {
+                               udp_delete_target(ut, para_strerror(-ret));
+                               continue;
+                       }
+               }
+       }
+}
+
+static void udp_shutdown_targets(void)
+{
+       char buf[UDP_AUDIO_HEADER_LEN];
+       struct udp_target *ut, *tmp;
+       struct udp_audio_header uah = {
+               .stream_type = UDP_UNKNOWN_STREAM,
+               .packet_type = UDP_EOF_PACKET,
+       };
+
+       write_udp_audio_header(buf, &uah);
+       list_for_each_entry_safe(ut, tmp, &targets, node) {
+               if (ut->fd < 0)
+                       continue;
+               write(ut->fd, buf, UDP_AUDIO_HEADER_LEN);
+               udp_close_target(ut);
+       }
+}
+
+static int need_extra_header(long unsigned current_chunk)
+{
+       static struct timeval last_header;
+       struct timeval diff;
+
+       if (!current_chunk)
+               return 0;
+       tv_diff(now, &last_header, &diff);
+       if (tv2ms(&diff) < conf.udp_header_interval_arg)
+               return 0;
+       last_header = *now;
+       return 1;
+}
+
+static void udp_send(long unsigned current_chunk, __a_unused long unsigned chunks_sent,
+               const char *buf, size_t len, const char *header_buf,
+               size_t header_len)
+{
+       char *sendbuf;
+       size_t sendbuf_len;
+       struct timeval *chunk_tv;
+       struct udp_audio_header uah;
+
+//     PARA_NOTICE_LOG("len: %zd, header_len: %zd\n", len, header_len);
+       if (sender_status != SENDER_ON)
+               return;
+
+       /* we might not yet know the chunk time */
+       chunk_tv = vss_chunk_time();
+       if (!chunk_tv)
+               return;
+       if (list_empty(&targets))
+               return;
+       uah.stream_type = header_len? UDP_HEADER_STREAM : UDP_PLAIN_STREAM;
+       uah.header_len = need_extra_header(current_chunk)? header_len : 0;
+       if (!current_chunk)
+               uah.packet_type = UDP_BOF_PACKET;
+       else if (uah.header_len)
+               uah.packet_type = UDP_HEADER_PACKET;
+       else
+               uah.packet_type = UDP_DATA_PACKET;
+       uah.payload_len = uah.header_len + len;
+       sendbuf_len = UDP_AUDIO_HEADER_LEN + uah.payload_len;
+       sendbuf = para_malloc(sendbuf_len);
+       write_udp_audio_header(sendbuf, &uah);
+       if (uah.header_len)
+               memcpy(sendbuf + UDP_AUDIO_HEADER_LEN, header_buf,
+                       uah.header_len);
+       memcpy(sendbuf + UDP_AUDIO_HEADER_LEN + uah.header_len, buf, len);
+       udp_send_buf(sendbuf, sendbuf_len);
+       free(sendbuf);
+}
+
+static int udp_com_on(__a_unused struct sender_command_data *scd)
+{
+       sender_status = SENDER_ON;
+       return 1;
+}
+
+static int udp_com_off(__a_unused struct sender_command_data *scd)
+{
+       udp_shutdown_targets();
+       sender_status = SENDER_OFF;
+       return 1;
+}
+
+static int udp_com_delete(struct sender_command_data *scd)
+{
+       char *a = para_strdup(inet_ntoa(scd->addr));
+       struct udp_target *ut, *tmp;
+       list_for_each_entry_safe(ut, tmp, &targets, node) {
+               if (scd->port != ut->port)
+                       continue;
+               if (strcmp(TARGET_ADDR(ut), a))
+                       continue;
+               udp_delete_target(ut, "com_delete");
+       }
+       return 1;
+}
+
+static void udp_add_target(int port, struct in_addr *addr)
+{
+       struct udp_target *ut = para_calloc(sizeof(struct udp_target));
+       ut->port = port;
+       ut->addr = *addr;
+       ut->fd = -1; /* not yet connected */
+       PARA_INFO_LOG("adding to target list (%s:%d)\n",
+               TARGET_ADDR(ut), ut->port);
+       para_list_add(&ut->node, &targets);
+}
+
+static int udp_com_add(struct sender_command_data *scd)
+{
+       int port = (scd->port > 0)? scd->port : conf.udp_default_port_arg;
+       udp_add_target(port, &scd->addr);
+       return 1;
+}
+
+static char *udp_info(void)
+{
+       struct udp_target *ut;
+       char *ret, *tgts = NULL;
+
+       list_for_each_entry(ut, &targets, node) {
+               char *tmp = make_message("%s%s:%d ", tgts? tgts : "",
+                       TARGET_ADDR(ut), ut->port);
+               free(tgts);
+               tgts = tmp;
+       }
+       ret = make_message(
+               "udp sender:\n"
+               "\tstatus: %s\n"
+               "\tport: udp %d\n"
+               "\ttargets: %s\n",
+               (sender_status == SENDER_ON)? "on" : "off",
+               conf.udp_default_port_arg,
+               tgts? tgts : "(none)"
+       );
+       free(tgts);
+       return ret;
+}
+
+static void udp_init_target_list(void)
+{
+       int i;
+
+       INIT_LIST_HEAD(&targets);
+       for (i = 0; i < conf.udp_target_given; i++) {
+               char *arg = para_strdup(conf.udp_target_arg[i]);
+               char *p = strchr(arg, ':');
+               int port;
+               struct in_addr addr;
+
+               if (!p)
+                       goto err;
+               *p = '\0';
+               if (!inet_pton(AF_INET, arg, &addr))
+                       goto err;
+               port = atoi(++p);
+               if (port < 0 || port > 65535)
+                       port = conf.udp_default_port_arg;
+               udp_add_target(port, &addr);
+               goto success;
+err:
+               PARA_CRIT_LOG("syntax error for udp target option "
+                       "#%d, ignoring\n", i);
+success:
+               free(arg);
+               continue;
+       }
+}
+
+static char *udp_help(void)
+{
+       return make_message(
+               "usage: {on|off}\n"
+               "usage: {add|delete} IP port\n"
+               "example: add 224.0.1.38 8000 (multicast streaming)\n"
+       );
+}
+
+/**
+ * The init function of para_server's udp sender.
+ *
+ * \param s Pointer to the http sender struct.
+ *
+ * It initializes all function pointers of \a s and the list of udp targets.
+ */
+void udp_send_init(struct sender *s)
+{
+       INIT_LIST_HEAD(&targets);
+       s->info = udp_info;
+       s->help = udp_help;
+       s->send = udp_send;
+       s->pre_select = NULL;
+       s->post_select = NULL;
+       s->shutdown_clients = udp_shutdown_targets;
+       s->client_cmds[SENDER_ON] = udp_com_on;
+       s->client_cmds[SENDER_OFF] = udp_com_off;
+       s->client_cmds[SENDER_DENY] = NULL;
+       s->client_cmds[SENDER_ALLOW] = NULL;
+       s->client_cmds[SENDER_ADD] = udp_com_add;
+       s->client_cmds[SENDER_DELETE] = udp_com_delete;
+       sender_status = SENDER_OFF;
+       udp_init_target_list();
+       if (!conf.udp_no_autostart_given)
+               sender_status = SENDER_ON;
+       PARA_DEBUG_LOG("udp sender init complete\n");
+}
index 0748ef62f1c5030cc6e5de6975e579c7b4c83357..63bfdfc259878402f3f70c2a5c62be5d5fa96ce9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 36e958b2bf1e21d7cbe04d629a75846684f5fa62..5baceacc1c9b98f339defec5e05049862c0be9b8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/vss.c b/vss.c
index 4ed75792185f685e26db278ae88b49ff4d2cd59f..d205349370f69a9445ff1db7bb1c269b2d6431a7 100644 (file)
--- a/vss.c
+++ b/vss.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -32,7 +32,7 @@ extern struct misc_meta_data *mmd;
 
 extern void dccp_send_init(struct sender *);
 extern void http_send_init(struct sender *);
-extern void ortp_send_init(struct sender *);
+extern void udp_send_init(struct sender *);
 
 /** The list of supported senders. */
 struct sender senders[] = {
@@ -44,12 +44,10 @@ struct sender senders[] = {
                .name = "dccp",
                .init = dccp_send_init,
        },
-#ifdef HAVE_ORTP
        {
-               .name = "ortp",
-               .init = ortp_send_init,
+               .name = "udp",
+               .init = udp_send_init,
        },
-#endif
        {
                .name = NULL,
        }
@@ -67,15 +65,25 @@ enum afs_socket_status {
 
 /** The task structure for the virtual streaming system. */
 struct vss_task {
+       /** Copied from the -announce_time command line option. */
        struct timeval announce_tv;
+       /** End of the announcing interval. */
        struct timeval data_send_barrier;
+       /** End of the EOF interval. */
        struct timeval eof_barrier;
+       /** Only used if --autoplay_delay was given. */
        struct timeval autoplay_barrier;
+       /** Used for afs-server communication. */
        int afs_socket;
+       /** The current state of \a afs_socket. */
        enum afs_socket_status afsss;
+       /** The memory mapped audio file. */
        char *map;
+       /** Used by the scheduler. */
        struct task task;
+       /** Pointer to the header of the mapped audio file. */
        const char *header_buf;
+       /** Length of the audio file header. */
        size_t header_len;
 };
 
@@ -238,6 +246,8 @@ struct timeval *vss_chunk_time(void)
 
 static int need_to_request_new_audio_file(struct vss_task *vsst)
 {
+       struct timeval diff;
+
        if (vsst->map) /* have audio file */
                return 0;
        if (!vss_playing()) /* don't need one */
@@ -246,6 +256,9 @@ static int need_to_request_new_audio_file(struct vss_task *vsst)
                return 0;
        if (vsst->afsss == AFS_SOCKET_AFD_PENDING) /* already requested one */
                return 0;
+       if (chk_barrier("autoplay_delay", &vsst->autoplay_barrier,
+                       &diff, 1) < 0)
+               return 0;
        return 1;
 }
 
@@ -288,7 +301,6 @@ static void vss_pre_select(struct sched *s, struct task *t)
                mmd->current_chunk = mmd->repos_request;
                mmd->new_vss_status_flags &= ~VSS_REPOS;
        }
-
        if (need_to_request_new_audio_file(vsst)) {
                PARA_DEBUG_LOG("ready and playing, but no audio file\n");
                para_fd_set(vsst->afs_socket, &s->wfds, &s->max_fileno);
@@ -370,8 +382,10 @@ static void recv_afs_result(struct vss_task *vsst)
        }
        mmd->size = statbuf.st_size;
        mmd->mtime = statbuf.st_mtime;
-       vsst->map = para_mmap(mmd->size, PROT_READ, MAP_PRIVATE,
-               passed_fd, 0);
+       ret = para_mmap(mmd->size, PROT_READ, MAP_PRIVATE, passed_fd,
+               0, &vsst->map);
+       if (ret < 0)
+               goto err;
        close(passed_fd);
        mmd->chunks_sent = 0;
        mmd->current_chunk = 0;
@@ -379,7 +393,6 @@ static void recv_afs_result(struct vss_task *vsst)
        mmd->events++;
        mmd->num_played++;
        mmd->new_vss_status_flags &= (~VSS_NEXT);
-       tv_add(now, &vsst->announce_tv, &vsst->data_send_barrier);
        afh_get_header(&mmd->afd.afhi, vsst->map, &vsst->header_buf,
                &vsst->header_len);
        return;
@@ -468,6 +481,9 @@ static void vss_post_select(struct sched *s, struct task *t)
                        continue;
                senders[i].post_select(&s->rfds, &s->wfds);
        }
+       if ((vss_playing() && !(mmd->vss_status_flags & VSS_PLAYING)) ||
+                       (vss_next() && vss_playing()))
+               tv_add(now, &vsst->announce_tv, &vsst->data_send_barrier);
        vss_send_chunk(vsst);
 }
 
@@ -508,6 +524,8 @@ void init_vss_task(int afs_socket)
                mmd->new_vss_status_flags |= VSS_PLAYING;
                ms2tv(autoplay_delay, &tmp);
                tv_add(now, &tmp, &vsst->autoplay_barrier);
+               tv_add(&vsst->autoplay_barrier, &vsst->announce_tv,
+                       &vsst->data_send_barrier);
        }
        register_task(&vsst->task);
 }
diff --git a/vss.h b/vss.h
index f92fc8091cf7ce852d1e2fc97b462566c4199566..5c917e6d456a40672204c32aabb8cbc501ee4308 100644 (file)
--- a/vss.h
+++ b/vss.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index f5905f1f2ec13ab2d5d220bf59ad5cd02c0b8d7e..b7329c48bce647b113638a5609b39de698ef81fd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/write.c b/write.c
index 9b7a92113e69ff236e08ce235ca306c9c410fd07..238f2ab9d4d1c39f4b4b0e0bca46632c6c44762c 100644 (file)
--- a/write.c
+++ b/write.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -122,7 +122,8 @@ register_check_wav:
        s->timeout.tv_usec = 1;
 }
 
-INIT_STDERR_LOGGING(conf.loglevel_arg)
+static int loglevel;
+INIT_STDERR_LOGGING(loglevel)
 
 static struct writer_node_group *check_args(void)
 {
@@ -130,6 +131,7 @@ static struct writer_node_group *check_args(void)
        struct writer_node_group *g = NULL;
        struct initial_delay_task *idt = &the_initial_delay_task;
 
+       loglevel = get_loglevel_by_name(conf.loglevel_arg);
        if (conf.start_time_given) {
                long unsigned sec, usec;
                if (sscanf(conf.start_time_arg, "%lu:%lu",
diff --git a/write.ggo b/write.ggo
deleted file mode 100644 (file)
index 8f557bb..0000000
--- a/write.ggo
+++ /dev/null
@@ -1,35 +0,0 @@
-option "loglevel" l
-#~~~~~~~~~~~~~~~~~~
-"set loglevel (0-6)"
-int typestr="level"
-default="4"
-optional
-
-option "bufsize" b
-#~~~~~~~~~~~~~~~~~
-"input buffer size"
-int typestr="kilobytes"
-default="64"
-optional
-
-option "writer" w
-#~~~~~~~~~~~~~~~~
-"select stream writer"
-string typestr="name"
-default="alsa (file if alsa is unsupported)"
-optional
-multiple
-details="
-       May be give multiple times. The same writer may be specified
-       more than once.
-"
-
-option "start_time" t
-#~~~~~~~~~~~~~~~~~~~~
-"defer playback"
-string typestr="timeval"
-optional
-details="
-       Start playback at given time which must be in a:b format where
-       a denotes seconds and b denotes microseconds since the epoch.
-"
diff --git a/write.h b/write.h
index 7df62f9f08e68090afe45cb09ec43dde024b7fab..7ecb091ba9d6d83e94d7d976a1e37941985360c6 100644 (file)
--- a/write.h
+++ b/write.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 5896d91c4d415ee18989574b8e10c68cdf990f3b..8fb6c3d10797c4fc7ea4119de5c990271f177482 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 7f0bbc57501dc7416243e8b92e580daf742b5cc6..18e5e838fee3843852d424e60af62f1205f960e4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */