Merge branch 't/recv_fix'
authorAndre Noll <maan@systemlinux.org>
Thu, 31 Jul 2014 06:06:21 +0000 (08:06 +0200)
committerAndre Noll <maan@systemlinux.org>
Thu, 31 Jul 2014 06:06:21 +0000 (08:06 +0200)
Cooking for two months.

* t/recv_fix:
  recv: Don't segfault on invalid chunk values.

212 files changed:
.changelog_before_cvs [deleted file]
.changelog_cvs [deleted file]
.gitignore
Doxyfile
FEATURES
GIT-VERSION-GEN
INSTALL
Makefile.in
Makefile.real [new file with mode: 0644]
NEWS
README
aac.h
aac_afh.c
aac_common.c
aacdec_filter.c
acl.c
acl.h
afh.c
afh.h
afh_common.c
afh_recv.c
afs.c
afs.cmd
afs.h
aft.c
alsa_mix.c
alsa_write.c
amp_filter.c
ao_write.c
attribute.c
audioc.c
audiod.c
audiod.cmd
audiod.h
audiod_command.c
bash_completion
bitstream.c
bitstream.h
blob.c
buffer_tree.c
buffer_tree.h
check_wav.c
check_wav.h
chunk_queue.c
chunk_queue.h
client.c
client.h
client_common.c
close_on_fork.c
command.c
command.h
command_util.bash [new file with mode: 0755]
command_util.sh [deleted file]
compress_filter.c
configure.ac
convert_0.3-0.4.sh [deleted file]
crypt.c
crypt.h
crypt_backend.h
crypt_common.c
daemon.c
dccp_recv.c
dccp_send.c
error.h
error2.c [new file with mode: 0644]
error2.pl [deleted file]
exec.c
fade.c
fd.c
fd.h
fecdec_filter.c
file_write.c
filter.c
filter.h
filter_common.c
flac_afh.c
flacdec_filter.c
gcrypt.c
ggo.c
ggo.h
grab_client.c
grab_client.h
gui.c
gui.h
gui_theme.c
http_recv.c
http_send.c
imdct.c
install-sh [deleted file]
interactive.c
interactive.h
ipc.c
m4/gengetopt/afh.m4
m4/gengetopt/afh_recv.m4
m4/gengetopt/alsa_write.m4
m4/gengetopt/amp_filter.m4
m4/gengetopt/ao_write.m4
m4/gengetopt/audioc.m4
m4/gengetopt/audiod.m4
m4/gengetopt/client.m4
m4/gengetopt/color.m4
m4/gengetopt/compress_filter.m4
m4/gengetopt/config_file.m4
m4/gengetopt/dccp_recv.m4
m4/gengetopt/fade.m4
m4/gengetopt/file_write.m4
m4/gengetopt/filter.m4
m4/gengetopt/gui.m4
m4/gengetopt/history_file.m4
m4/gengetopt/http_recv.m4
m4/gengetopt/makefile
m4/gengetopt/mp3dec_filter.m4
m4/gengetopt/oss_write.m4
m4/gengetopt/osx_write.m4
m4/gengetopt/play.m4
m4/gengetopt/prebuffer_filter.m4
m4/gengetopt/recv.m4
m4/gengetopt/resample_filter.m4
m4/gengetopt/server.m4
m4/gengetopt/sync_filter.m4 [new file with mode: 0644]
m4/gengetopt/udp_recv.m4
m4/gengetopt/write.m4
man_util.bash [new file with mode: 0755]
mix.h
mm.c
mm.h
mood.c
mood.h
mp3_afh.c
mp3dec_filter.c
net.c
net.h
ogg_afh.c
ogg_afh_common.c
ogg_afh_common.h
oggdec_filter.c
opus_afh.c
opus_common.h
opusdec_filter.c
oss_mix.c
oss_write.c
osx_write.c
para.h
play.c
playlist.c
portable_io.h
prebuffer_filter.c
recv.c
recv.h
recv_common.c
resample_filter.c
ringbuffer.c
ringbuffer.h
sched.c
sched.h
score.c
send.h
send_common.c
server.c
server.h
sideband.c
sideband.h
signal.c
signal.h
skencil/overview.sk [deleted file]
spx.h
spx_afh.c
spx_common.c
spxdec_filter.c
stat.c
stdin.c
stdin.h
stdout.c
stdout.h
string.c
string.h
sync_filter.c [new file with mode: 0644]
t/makefile.test
t/t0004-server.sh
t/t0005-man.sh [new file with mode: 0755]
t/test-lib.sh
time.c
udp_recv.c
udp_send.c
user_list.c
user_list.h
version.c
vss.c
vss.h
wav_filter.c
web/dia/overview.dia [new file with mode: 0644]
web/documentation.in.html
web/gitweb.css [deleted file]
web/gitweb_header.html.in
web/header.html
web/header2.html
web/images/paraslash.ico
web/images/paraslash.png
web/index.in.html [deleted file]
web/manual.m4
web/para.css
web/screenshots/audiod.log
web/screenshots/gui.png
web/screenshots/server.log
wma.h
wma_afh.c
wma_common.c
wmadec_filter.c
write.c
write.h
write_common.c
write_common.h

diff --git a/.changelog_before_cvs b/.changelog_before_cvs
deleted file mode 100644 (file)
index 7f95255..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-This is the old Changelog, before the icc project switched to cvs.
-
-dbtool (sa): fix SEGFAULT when some attributes are NULL
-icc_dbtool.template: add help command
-Makefile: Check for mp3info
-dbtool.c: Handle files with Â«'» properly
-
-****** Version 91 (Sat Nov 30 13:52:37 MET 2002) *******
-Makefile: include icc_dbtool.conf.sample
-icebear: Remove unneeded signal handlers
-icc_dbtool.c Add documentation to upd command
-Documentation update
-dbtool.c: Add config file functionality
-icc_dbtool.c: Add upd command
-command.c: Bug: cs prints current stream in err msg
-zombies, zombies
-many fixes all over the place
-dbtool.c: new command: vrfy (verify entries in database)
-dbtool.c: implement clean command
-icc_dbtool: implement skip
-dont use pointers to malloced mem in shared area (causes SEGFAULT)
-icebear: SEGFAULT when cs was called after server had got HUP. Nasty bug
-icc_bash_completion: adapt to new syntax
-command.c: nuke drop_ss and new_ss
-dbtool.c: Add da (drop attribut) command (replaces old drop_ss)
-dbtool.c: Add na (new attribut) command (replaces old new_ss)
-Makefile: Changelog contains entries not yet done
-
-****** Version 90 (Wed Nov 13 02:05:34 MET 2002) *******
-icebear: kill unneeded signal handlers
-icebear: call info only if it is a valid command
-server: code cleanup
-command.c uptime: print #connections and #commands
-server: count #connections and #commands
-server/icebear/command: count/display number of songs already played
-icc.h: cleanup
-command.c: nuke ms command
-dbtool.c: add summary command
-dbtool.c: new command: sa, replaces old ss (set subset) command
-dbtool.c: new command: streams
-server: renew command list on SIGHUP
-icebear: call us only if it is a valid command
-command.c: sort command list alphabetically
-server: Nicify logging
-command.c: New command: perms
-command.c: Rewrite command handlers to use linked list
-command.c: introdule linked list of commands
-
-****** Version 89 (Sat Nov  9 17:27:32 MET 2002) *******
-command.c: Major cleanup
-
-****** Version 88 (Sat Nov  9 01:34:14 MET 2002) *******
-icebear: New command: cs
-init_icebear put default_stream to freshly allocated shared mem
-server: pass default_stream to init_icebear
-server: new configfile option: default_stream
-command.c help: call icc_dbtool help
-
-****** Version 87 (Fri Nov  8 23:03:03 MET 2002) *******
-Makefile: new target icc_dbtool
-icc_dbtool: Switch to mysql C API
-
-****** Version 86 (Thu Oct 17 22:38:37 MEST 2002) *******
-New file: README.dbtool
-client/server: use OPENSSL define of config.h instead of hard coded path
-client/server: include config.h
-README: add icecast to requirements
-
-****** Version 85 (Thu Oct 10 22:56:29 MEST 2002) *******
-Makefile: Don't include tdldb in tgz
-Makefile: New target: distclean (clean no longer removes Changelog, TODO and version.h)
-dbtool ms: print each dot only once (reduces size of ps from 171kb to 22kb)
-
-****** Version 84 (Fri Oct  4 15:01:54 MEST 2002) *******
-icc_server.conf.sample/icecast.conf.sample: Use same passwd
-Makefile: include icecast.conf.sample in tarball
-Makefile: mkdir ~/public_html
-
-****** Version 83 (Wed Sep 25 01:59:06 MEST 2002) *******
-Makefile tgz: php crap got messed up
-
-****** Version 82 (Wed Sep 25 01:56:55 MEST 2002) *******
-server: Reread configuration on SIGHUP
-Makefile: New Changelog format
-Makefile tgz: create archive with leading directory icc-$version
-
-************* Version 81 *************
-server update_str: fix bug: uptime string messed up
-README: add description of icc_bash_completion
-INSTALL: Update, extentions and nicifying
-icc_bash_completion: adapt to new layout of Â«icc help«
-
-************* Version 80 *************
-server: print uptime in welcome message
-server: new functions: uptime,uptime_str
-command.c: new commands: uptime,version
-icebear: exec_cmd: test if stopped for ff/jmp/next. Fixes Segfault when eg Â«next» was called with no file opened yet
-
-************* Version 79 *************
-server: implement remaining part of configuration part
-server: implement basic configuration file functionality
-
-************* Version 78 *************
-Makefile: install icc_client.conf.sample and also include it in tgz
-new file: icc_client.conf.sample
-client: actually print version and info if loglevel is at least info
-client: new function: print_version
-client: read_config: change verbose setting to loglevel
-client: new option -l (loglevel) obsoletes -v (verbose)
-client: Fix Â«if(verbose==TRUE)» madness, use loglevels instead
-client: write log function similar to server's log function
-README: Update icc_client description: Delete sentence on telnet
-
-************* Version 77 *************
-client: take localhost as default host, not p133
-client: new option -c (specify config file)
-client: implement reading of config file
-
-************* Version 76 *************
-server sigchld_handler: Add exit status also as numerical value
-command.c: Add description for drop_ss, fut, us
-
-************* Version 75 *************
-icebear: fix segfault on nomore (double close mp3_stream)
-icebear: nm->nomore
-command.c: add nomore command (got forgotten)
-client: catch SIGCHLD
-client: introduce internal variable debug to toggle debug before command line argumants are parsed (for verbose switch)
-client: Nicify verbose output
-client: Fix command line parsing
-
-************* Version 74 *************
-Makefile tgz: use prefix icc-0.0.
-Makefile tgz: bug: forget to read VERSION
-Makefile: Add .tdldb to sources
-
-************* Version 73 *************
-client: new option -V (version)
-server: new option -V (version)
-Makefile: new target: tgz (implies version)
-Makefile: fix version numbering
-Makefile: include INSTALL in sources
-Makefile: Use -p Option for tar
-
-************* Version 72 *************
-icc_server: print info on who we are serving to argv[0]
-icebear: print status to argv[0]
-command.c: Add missing descriptions to all internal commands
-dbtool.template: Use find instead of locate
-server: send proper error message if client sent unkown command
-
-************* Version 71 *************
-client: Added help option -h
-command.c help: Nicify output. Include needed permissions.
-command.c: Add description for stat, sb and term
-Makefile: Add target dbtool_install
-Makefile install: don't install dbtool
-server/client: print version number
-icc.h include version.h
-Makefile: added target version.h
-added INSTALL
-README: Remove Warning message concerning lack of authentification
-Makefile: implement PREFIX
-icebear: typo in jmp command
-icc_dbtool.template us: Don't print warning
-Makefile install: Install also icc_dbtool.template
-
-************* Version 70 *************
-
-************* Version 69 *************
-icc_dbtool.template: Change fut so that it does not need bogosort anymore
-
-************* Version 68 *************
-Makefile: include icc_dbtool.template in tgz package
-server: new command line options: P, i, ip
-server: kill global variable conn
-command.c parse_cmd: Fix SEGV when in interactive mode and no option given (reported by Christof Müller)
-Makefile: all: dont make TODO and Changelog
-icc.client: remove passwd
-icc.h remove maan
-
-************* Version 67 *************
-icebear: delete option for id3 comment in mp3info call
-icebear: Fix bug: pollret returns strange events
-icebear: fix division by 0 bug when length of file is zero seconds
-
-************* Version 66 *************
-
-************* Version 65 *************
-command.c: perror -> log
-command.c: new fuction: check_permissions
-command.c: insert dummy at the beginning of command list to let start command numbers by 1 instead of 0
-
-************* Version 64 *************
-server: add string strerror(errno) to log file entries
-command.c: make parse_command only return command number and call handle_cmd from main
-server: print log msg _before_ exit(1) if send fails
-server: exit(1) if send fails
-
-************* Version 63 *************
-command.c: code cleanup
-icc_server: implement option -c (specify config file)
-client: fix SEGFAULT when command line ends with invalid option
-client: add option -k (secret key file)
-
-************* Version 62 *************
-implement permission check for all commands
-
-************* Version 61 *************
-implement basic configuration file functionality
-icc_server/client: implement rsa authentification via openssl
-
-************* Version 60 *************
-command.c: add help text for jmp and ff commands
-command.c: help: print command handler and needed privileges
-icebear: minor code cleanups
-icebear: Nicify log output
-icebear: split poll_cmd_listener to allow blocking reads => no more sleep(1)
-
-************* Version 59 *************
-icebear: Code documentation
-icebear: move shout init/shoutdown to exec_cmd. This might fix pause command.
-
-************* Version 58 *************
-icebear: increase number of allowed invalid files before giving up to 100
-dbtool clean: Handle files with Â«'» properly
-
-************* Version 57 *************
-dbtool: add summary command
-icc_process_form.php: change strcmp(a,b)=0 to not strcmp(a,b)
-
-************* Version 56 *************
-
-************* Version 55 *************
-kill id3 code
-dbtool: change info and fut to avoid Lost connection to MySQL server during query
-icebear: It dies if there no valid songs. Stop and lurk for play instead
-icebear: code cleanup
-
-************* Version 54 *************
-icebear/icc.h: use long unsigned int to avoid overflow in status bar
-
-************* Version 53 *************
-server: BUG in help: dont check args if args=NULL
-command.c help: implement Â»help command«
-README: add LICENSE
-README: include description to php scripts
-server: kill guics command
-server: kill log command
-dbtool: kill pw
-dbtool: add local for all local vars
-
-************* Version 52 *************
-command.c, icc.h: cleanup declaration of command struct
-dbtool us: add option to specify update time
-add bash completion for icc_client
-
-************* Version 51 *************
-kill spl command
-dbtool: add ls command
-icc_server: add ls command
-icc_server: kill cd command
-
-************* Version 50 *************
-php/icc_form, php/icc_process_form: fix several bugs
-
-************* Version 49 *************
-add background gradient image
-
-************* Version 48 *************
-write mp3 search form icc_form.php
-icebear: log seconds with 2 digits
-icc_gui: Add sleep(2) before each reconnect
-php: delete unneeded pics
-
-************* Version 47 *************
-icc_server: add time and date to log
-
-************* Version 46 *************
-php/icc_dbgui: fix off by one bug
-dbtool: clean reports files as deleted which are still there
-remove wtc.jpg
-
-*** Version 45 ***
-improve php scripts
-
-*** Version 44 ***
-add php scripts for apache/mysql
-
-*** Version 43 ***
-icc.h changed #define ERR to #define ERROR
-
-*** Version 42 ***
-gui: make it survive window resize
-
-*** Version 41 ***
-Add short description of all icc tools to README
-
-*** Version 40 ***
-dbtool fut: replace use of ancient anplay variable by aprropriate one
-dbtool ss: make it work again when args _are_ given
-server: Add -p <port> option
-client: catch SIGINT
-
-*** Version 39 ***
-dbtool: ps does not work if no arg is given
-dbtool: ss does not work if no arg is given
-server: log GPL banner (loglevel INFO)
-client: Add GPL banner in welcome message
-dbtool last: print full filenames
-dbtool info: print name if no argument was given
-
-*** Version 38 ***
-icebear: make jmp,ff,next,pause,play,stop,nm actually respond via new pipe
-create new pipe icebear->server for responses to icebear commands
-
-*** Version 37 ***
-dbtool cs: print info if no argument is given
-
-*** Version 36 ***
-icebear: kill getenv code
-icebear: rewrite startup code to prevent icebear from playing on startup
-
-*** Version 35 ***
-icebear: nicify log messages
-icebear: make pause, play, stop work in all possible cases
-
-*** Version 34 ***
-Makefile version: include COPYRIGHT, GPL and README files in tarball
-Add COPYRIGHT and GPL files
-*.c *.h dbtool: Add GPL headers
-inplement option -L logfile
-client: Fix bug: commands with options don't work
-
-*** Version 33 ***
-Makefile: only put completed todos into Changelog
-server: implement Daemon mode
-icc_client: Dont send empty lines
-
-*** Version 32 ***
-command: Fix nasty bug which caused sending 2 nullbytes instead of only one
-dbtool info: print info on current song if no argument was given
-
-*** Version 31 ***
-dbtool: Another silly bug in info which prevented dir to be printed
-client: Fix silly bug caused it to send wrong number of bytes
-icc_server: implemented term command
-Makefile: strip away useless tdl info
-icc_dbtool: Changed Warning message for commands not yet implemented
-icc_server: Added help command
-icc_client: add readline support
-icc_dbtool fut: Fix bug when there is exactly one new song
-db_tool: implement skip
-db_tool: implement ss
-db_tool: implement clean
-db_tool: implement upd
-dbtool: implemented pw
-move icc ms to dbtool
-icc_shell: ms
-icc_server/dbtool: new command hist
-dbtool: implement last
-created icc_shell
-make icebear use icc_dbtool instead of mp3
-write db_tool basics (fut, ass, ps, info, us)
-Makefile improvements
-icc_client: Add verbose flag -v
-Adjust loglevels and make logging nicer
-icc_client: properly handle command line options
-icc_server: Dont start playing on startup
-take output of info command as misc info
-icc_client: treat nr_options correctly
-log messages cleanup
-log proper exit status (WIFSIGNALED...)
-icebear: stop actually restarts icebear
-icc_client: interactive mode
-icc_server: on errors send messages clients
-
-
diff --git a/.changelog_cvs b/.changelog_cvs
deleted file mode 100644 (file)
index 889f23c..0000000
+++ /dev/null
@@ -1,12680 +0,0 @@
-2006-02-20 07:52  maan
-
-       * filter.c: cosmetics
-
-2006-02-20 07:51  maan
-
-       * crypt.h: add doxygen file comment
-
-2006-02-20 07:50  maan
-
-       * Doxyfile: exclude some more files
-
-2006-02-20 07:16  maan
-
-       * NEWS: [no log message]
-
-2006-02-20 07:16  maan
-
-       * CREDITS: add Lorenzo Bettini
-
-2006-02-20 05:24  maan
-
-       * Makefile.in: with gengetopt-2.16 we no longer need the conversion
-         optind=1 -> optind=0. Get rid of it.
-
-2006-02-19 07:46  maan
-
-       * crypt.c: add documentation
-
-2006-02-19 05:55  maan
-
-       * crypt.c: para_decrypt_challenge() leaks 128 bytes if
-         para_decrypt_buffer() fails. Fix it
-
-2006-02-19 05:47  maan
-
-       * gcc-compat.h: trivial: fix comment
-
-2006-02-19 05:46  maan
-
-       * crypt.c: whitespace cleanup
-
-2006-02-19 05:46  maan
-
-       * Doxyfile: activate the source browser
-
-2006-02-19 05:34  maan
-
-       * fade.c: make fade() static
-
-2006-02-19 04:15  maan
-
-       * Doxyfile: deactivate latex and man output, activate search engine
-
-2006-02-19 03:35  maan
-
-       * sdl_gui.c: add missing file name in comment
-
-2006-02-18 01:52  maan
-
-       * scripts/demo-script: download paraslash-0.2.10
-
-2006-02-18 01:21  maan
-
-       * web/index.in.html: typo
-
-2006-02-18 00:51  maan
-
-       * Makefile.in, NEWS, configure.ac: new codename, reset version to
-         cvs
-
-2006-02-18 00:49  maan
-
-       * versions/: paraslash-0.2.10.tar.bz2,
-         paraslash-0.2.10.tar.bz2.asc: paraslash-0.2.10
-
-2006-02-18 00:48  maan
-
-       * Makefile.in, NEWS, configure.ac, web/index.in.html: paraslash
-         0.2.10
-
-2006-02-18 00:12  maan
-
-       * Doxyfile: config file for doxygen
-
-2006-02-17 23:23  maan
-
-       * ortp_recv.c: increase number of bad chunks before returning an
-         error
-
-2006-02-16 05:28  maan
-
-       * README.mysql: [no log message]
-
-2006-02-16 04:48  maan
-
-       * filter.ggo: update help text for --list_filters
-
-2006-02-16 02:37  maan
-
-       * web/: documentation.in.html, index.in.html: annonce the new API
-         Reference
-
-2006-02-16 02:36  maan
-
-       * Makefile.in: new targets: doxygen, web/header2.html. Target www
-         implies doxygen
-
-2006-02-16 02:32  maan
-
-       * server.c: rename 'Reference Manual' to 'API Reference'
-
-2006-02-16 02:31  maan
-
-       * web/header.html: use the new stylesheet
-
-2006-02-16 02:30  maan
-
-       * web/para.css: the new stylesheet for the paraslash web pages
-
-2006-02-16 00:41  maan
-
-       * db.h, dopey.c, filter.h, mysql.c, recv.h, server.c: some small
-         documentation cleanups and additions
-
-2006-02-15 22:56  maan
-
-       * http_send.c, ortp_send.c, send.h, server.c: struct sender: rename
-         set_fds/handle_fds to pre_select/post_select and add
-         documentation
-
-2006-02-15 22:55  maan
-
-       * http_recv.c: kill superfluous parenthesis
-
-2006-02-15 22:14  maan
-
-       * oggdec.c: rename private_ogg_data to private_oggdec_data
-
-2006-02-15 22:13  maan
-
-       * http_recv.c: add remaining documentation
-
-2006-02-15 22:12  maan
-
-       * afs.h, filter.h, mp3.c, ortp.h, recv.h, ringbuffer.h, signal.c,
-         string.c, string.h: add missing doxygen file comments
-
-2006-02-15 05:49  maan
-
-       * http.h: and doxygen file comments
-
-2006-02-15 05:49  maan
-
-       * net.h: add GPL header and doxygen file comments
-
-2006-02-15 05:04  maan
-
-       * exec.c: add documentation of all functions
-
-2006-02-15 04:19  maan
-
-       * recv_common.c: gcc-compat.h gets included by para.h
-
-2006-02-15 03:51  maan
-
-       * mysql.c, string.c, string.h: rename regex_list to para_macro and
-         add documentation
-
-2006-02-15 03:11  maan
-
-       * Makefile.in, afs.c, audioc.c, audiod.c, client.c,
-         close_on_fork.c, command.c, compress.c, crypt.c, daemon.c, db.c,
-         dbadm.c, dopey.c, exec.c, fade.c, filter.c, filter_chain.c,
-         grab_client.c, gui.c, http_recv.c, http_send.c, mp3dec.c,
-         mysql.c, net.c, ogg.c, oggdec.c, ortp_recv.c, ortp_send.c,
-         para.h, recv_common.c, ringbuffer.c, sdl_gui.c, server.c,
-         slider.c, stat.c, string.c, string.h, wav.c: move the function
-         prototypes of string.c from para.h to its own header file
-         string.h
-
-2006-02-15 02:20  maan
-
-       * ortp_send.c: add documentation of struct ortp_target
-
-2006-02-15 02:00  maan
-
-       * error.h: some new error messages for the mp3 audio format handler
-
-2006-02-15 01:59  maan
-
-       * mp3.c: use the error subsystem everywhere
-
-2006-02-15 01:27  maan
-
-       * mp3.c: whitespace cleanup, make mp3_read_chunk() static
-
-2006-02-15 01:21  maan
-
-       * mp3.c: typdefs are evil
-
-2006-02-15 00:35  maan
-
-       * mp3dec.c: another quite serious issue: do not try to convert if
-         the output buffer is almost full. Otherwise we risk that the next
-         frame does not fit into the ouput buffer and we only can error
-         out in this situation. This patch avoids the problem.
-
-2006-02-15 00:31  maan
-
-       * filter.c: fix serious bug: -1 is no valid error number for
-         filter.c. The proper error number is returned from filter_io()
-         anyway, so use that one.
-
-2006-02-14 23:24  maan
-
-       * server.c: doxification
-
-2006-02-14 23:24  maan
-
-       * http_send.c: typo
-
-2006-02-14 22:57  maan
-
-       * http_send.c, ortp_send.c, server.c: add documentation of all
-         structures used by http_send, rename para_http_init to
-         http_send_init, likewise for ortp
-
-2006-02-14 22:09  maan
-
-       * command.c, server.h: add documentation of struct misc_meta_data.
-         Kill the unused send field of struct_sender_command_data and add
-         documentation for that struct as well.
-
-2006-02-14 22:08  maan
-
-       * server.c: add documentation of mmd_lock() and mmd_unlock()
-
-2006-02-14 21:25  maan
-
-       * README: add gcc to the list of required software
-
-2006-02-14 21:07  maan
-
-       * Makefile.in: make gcc-2.95.4 happy
-
-2006-02-14 21:02  maan
-
-       * Makefile.in, configure.ac: let gcc produce the dependencies for
-         make rather than doing it by hand
-
-2006-02-14 20:17  maan
-
-       * para.h: kill another unused macro
-
-2006-02-14 19:46  maan
-
-       * para.h: kill two unused macros, change year in copyright to 2006
-
-2006-02-14 19:41  maan
-
-       * server.h: add more documentation on AFS_READ and friends
-
-2006-02-14 19:40  maan
-
-       * daemon.c, daemon.h, para.h: move enum uptime from para.h to
-         daemon.h. Include daemon.h from daemon.c
-
-2006-02-14 19:26  maan
-
-       * para.h: use the __printf_x_y macros
-
-2006-02-14 19:20  maan
-
-       * para.h, server.h: move permission flags from para.h to server.h,
-         turn them into an enum and doxify
-
-2006-02-14 19:14  maan
-
-       * command.c, dopey.c, mysql.c, server.h: rename usage to synopsis
-         in struct server_command
-
-2006-02-14 19:09  maan
-
-       * server.h: add documentation of struct server_command and
-         struct_user
-
-2006-02-14 19:04  maan
-
-       * Makefile.in, list.h, ortp_recv.c, server.h, web/download.in.html:
-         oops, the last commit was an accident, back to previous versions
-
-2006-02-14 18:59  maan
-
-       * Makefile.in, list.h, ortp_recv.c, server.h, web/download.in.html:
-         add documentation o
-
-2006-02-14 03:36  maan
-
-       * server.c: log error message if database init failed
-
-2006-02-14 03:34  maan
-
-       * error.h, mysql.c: add two more error messages
-
-2006-02-14 02:56  maan
-
-       * command.c, db.h, dopey.c, mysql.c, server.h: add some
-         documentation, rename struct command to struct server_command
-
-2006-02-14 02:16  maan
-
-       * grab_client.h: cosmetics
-
-2006-02-14 02:07  maan
-
-       * mysql.c: make a function static, add documentation
-
-2006-02-14 02:05  maan
-
-       * filter_chain.c: fix typo, add file comment
-
-2006-02-14 02:04  maan
-
-       * audiod.c: add documentation of struct slot_info
-
-2006-02-14 01:25  maan
-
-       * stat.c: cosmetics
-
-2006-02-13 22:29  maan
-
-       * audiod.c: rename struct stream_io to struct slot_info
-
-2006-02-13 20:59  maan
-
-       * audiod.c: struct audio_format_info: rename wcmd to write_command
-         and add documentation
-
-2006-02-13 20:39  maan
-
-       * audiod.c: add documentation of struct audiod_command
-
-2006-02-13 20:32  maan
-
-       * audiod.c: rename struct command to audiod_command
-
-2006-02-13 02:41  maan
-
-       * time.c: add documentation
-
-2006-02-13 01:49  maan
-
-       * audiod.c: kill unused filter_cmds field in struct stream_io, add
-         some documentation, minor cleanups
-
-2006-02-12 03:55  maan
-
-       * recv.c: make parse_config() static
-
-2006-02-12 03:44  maan
-
-       * recv.c: only print an error message if the return value is
-         negative
-
-2006-02-12 03:42  maan
-
-       * close_on_fork.c, close_on_fork.h: add documentation for all
-         public symbols
-
-2006-02-12 03:12  maan
-
-       * audiod.c: make two functions static. Add documentation of
-         para_audiod's different modes and of num_filters()
-
-2006-02-11 22:04  maan
-
-       * list.h: kill two unused macros
-
-2006-02-11 21:23  maan
-
-       * grab_client.c: finish documentation of all public functions
-
-2006-02-11 20:42  maan
-
-       * audiod.c, audiod.h, error.h, grab_client.c: make
-         get_audio_format_num() public and use it from grab_client.c, add
-         documentation of grab_client_new().
-
-2006-02-11 20:28  maan
-
-       * grab_client.h: add documentiation of struct grab_client
-
-2006-02-11 19:48  maan
-
-       * audiod.c: new function get_audio_format_num()
-
-2006-02-11 01:47  maan
-
-       * audiod.c, audiod.h, grab_client.c: nuke the 'name' field of
-         struct audio_format
-
-2006-02-11 00:57  maan
-
-       * audiod.h, grab_client.h: move AUDIO_FORMAT_MP3,
-         AUDIO_FORMAT_ARRAY and MAX_STREAM_SLOTS from grab_client.h to
-         audiod.h.
-
-2006-02-11 00:35  maan
-
-       * http_recv.c, ortp_recv.c: fix typo in comment
-
-2006-02-10 04:38  maan
-
-       * Makefile.in: add some missing dependencies
-
-2006-02-10 04:37  maan
-
-       * grab_client.h: oops, argc, argv _are_ used. Add them again.
-
-2006-02-10 03:37  maan
-
-       * grab_client.h: make mode type enum rather than int, nuke two
-         unused members in struct grab_client
-
-2006-02-10 03:32  maan
-
-       * grab_client.c: whitespace cleanup
-
-2006-02-10 02:42  maan
-
-       * oggdec.c: Use the pointer to the filter_node as datasource for
-         the ov_callbacks. This makes the filter chain info available for
-         the read callback via the new fn->fci pointer. Use that pointer
-         instead of keeping a copy of the relevant information in struct
-         private_ogg_data. As this simplifies oggdec.c quite a bit, add
-         documentation of struct private_ogg_data to compensate ;)
-
-2006-02-09 23:53  maan
-
-       * audiod.c, compress.c, daemon.c, filter.c, filter.h,
-         filter_chain.c, mp3dec.c, oggdec.c, ortp_send.c, wav.c: add new
-         pointer 'fci' to struct filter_node. It is initialized by
-         para_audiod/para_filter when the chain is constructed. This
-         allows to strip off the fci argument of the convert functions of
-         struct filter.
-
-2006-02-09 00:57  maan
-
-       * oggdec.c: simplify the read callback
-
-2006-02-09 00:01  maan
-
-       * mp3dec.c: remove unused mad_timer from private_mp3_data and add
-         documentation of said struct
-
-2006-02-08 23:19  maan
-
-       * ortp.h, ortp_recv.c, ortp_send.c: also encode the chunk timestamp
-         in each packet
-
-2006-02-08 20:23  maan
-
-       * http_recv.c: rename private_http_data to private_http_recv_data,
-         just to be consistent
-
-2006-02-08 20:21  maan
-
-       * db.c: add short description for db.c, fix a typo.
-
-2006-02-08 20:14  maan
-
-       * compress.c: add documentation of struct private_compress_data,
-         change clip and pn to unsigned type
-
-2006-02-08 19:46  maan
-
-       * Makefile.in, audiod.c, command.c, daemon.c, daemon.h, para.h,
-         server.c: move function prototypes for daemon.c to its own file
-
-2006-02-08 19:41  maan
-
-       * NEWS: [no log message]
-
-2006-02-08 17:49  maan
-
-       * ortp_send.c: fix a huge memory leak which was introduced
-         yesterday
-
-2006-02-08 04:46  maan
-
-       * audiod.c, command.c, daemon.c, para.h, server.c: add
-         documentation of daemon.c, minor cleanups
-
-2006-02-08 02:37  maan
-
-       * audiod.c, recv.h: nuke chunk_time from struct receiver_node
-
-2006-02-08 02:35  maan
-
-       * string.c: better docu of s_a_r()
-
-2006-02-08 02:05  maan
-
-       * filter_chain.c: filter_io: call the convert function of each
-         filter not just once, but in a loop that exits when nothing was
-         converted. Fixes drop outs with ortp and ogg.
-
-2006-02-08 01:28  maan
-
-       * error.h, ortp.h, ortp_recv.c, ortp_recv.ggo, ortp_send.c: encode
-         the chunk time and a flag which indicates whether headers get
-         streamed at the beginning of each data packet. This allows to
-         nuke the --chunk_time and --header command line options of the
-         ortp receiver.
-
-2006-02-08 01:00  maan
-
-       * wav.c: cosmetics
-
-2006-02-08 00:59  maan
-
-       * recv.c: print error message instead of error number
-
-2006-02-07 00:12  maan
-
-       * mp3dec.c: trvial rename: mp3dec_data -> private_mp3dec_data. Just
-         to keep naming consistent with the other filters/receivers
-
-2006-02-07 00:08  maan
-
-       * ortp_recv.c: finish documentation of struct private_ortp_data
-
-2006-02-06 18:43  maan
-
-       * ortp_recv.c: kill the timeout member of struct private_ortp_data.
-         Start documentation of this struct
-
-2006-02-06 17:48  maan
-
-       * filter.h: move the fancy macros to the end and exclude them from
-         doxification
-
-2006-02-06 17:46  maan
-
-       * afs.h: cosmetics
-
-2006-02-06 17:35  maan
-
-       * filter.h: add another reference
-
-2006-02-06 17:34  maan
-
-       * error.h, oggdec.c, recv.h: add some conditional sections to
-         nicify the doxygen output
-
-2006-02-06 17:22  maan
-
-       * afs.h: kill two unused prototypes
-
-2006-02-06 06:25  maan
-
-       * Makefile.in: add -Wunused-macros to DEBUG_CPPFLAGS
-
-2006-02-06 06:22  maan
-
-       * audiod.c, compress.c, sdl_gui.c: kill some more dead macros
-
-2006-02-06 06:18  maan
-
-       * gui.c: kill two unused macros
-
-2006-02-06 05:16  maan
-
-       * recv.h, recv_common.c: this array must be called 'receivers'
-         anyway as this is the name that gets exported a few lines above.
-         Hence, no need to make it a function-like macro.
-
-2006-02-06 05:09  maan
-
-       * recv.h: add documentation for struct receiver_node
-
-2006-02-06 04:42  maan
-
-       * filter.h: add some introductory text on paraslash filters, use
-         multi-line macros
-
-2006-02-06 04:00  maan
-
-       * http_recv.c, ortp_recv.c, recv.h: nuke unused print_help
-
-2006-02-06 03:55  maan
-
-       * recv.h: finish documentation of struct receiver
-
-2006-02-06 01:53  maan
-
-       * para.h: minor cleanup
-
-2006-02-06 01:52  maan
-
-       * http_recv.c: kill unused HTTP_DISCONNECTED, use named enum and
-         add documentaion of struct private_http_data
-
-2006-02-06 00:46  maan
-
-       * http_recv.c, ortp_recv.c, recv.c, recv.h: all receiver init
-         functions always return success. Let them return void instead.
-         Start doxification of recv.h. http_recv.c/ortp_recv.c: No need to
-         keep a copy of the configuration in the private data of each
-         receiver node. recv.c: Initialize the activated receiver only
-         once.
-
-2006-02-06 00:00  maan
-
-       * recv_common.c: delete two extern function declarations that are
-         already declared in recv.h
-
-2006-02-05 21:42  maan
-
-       * gui.c: cosmetics
-
-2006-02-05 21:38  maan
-
-       * http_send.c: do not use send_bin_buffer() as it retries on short
-         writes which might block. Use write() instead and queue the
-         remaining buffer on short writes.
-
-2006-02-05 21:34  maan
-
-       * audiod.c: add missing call to clear_slot()
-
-2006-02-05 19:41  maan
-
-       * gui.c: redraw bot win on SIGWINCH
-
-2006-02-05 02:09  maan
-
-       * Makefile.in: add ringbuffer.h to headers
-
-2006-02-05 00:52  maan
-
-       * gui.c: fix a off-by-one scrolling bug
-
-2006-02-05 00:11  maan
-
-       * gui.c: Kill the crappy output pager. It is no longer needed as
-         the bottom window is scrollable
-
-2006-02-04 22:33  maan
-
-       * recv.h: kill unused argc, argv from struct receiver_node
-
-2006-02-04 22:24  maan
-
-       * error.h: adjust NUM_SS
-
-2006-02-04 22:21  maan
-
-       * error.h: kill the unused first argument of PARA_ERROR()
-
-2006-02-04 22:09  maan
-
-       * error.h: doxyfication
-
-2006-02-04 20:36  maan
-
-       * audiod.c, filter.c, filter.h, filter_chain.c: make
-         check_filter_arg() return int (the filter number) which is a much
-         saner interface that what we've had before. Now, fn-conf is NULL
-         if no command line parser exists for that filter and
-         success/failure is detected by the return value. Add
-         documentation for filter_chain.c and the remaining part of
-         filter.h
-
-2006-02-04 03:08  maan
-
-       * audiod.c, compress.c, filter.c, filter.h, filter_chain.c,
-         mp3dec.c, oggdec.c, wav.c: init() and open() are always
-         successful, for all filters. So make them return void instead of
-         int. Include the mp3dec filter only if mad headers mad libs both
-         were detected. Make wav_open() static. Start doxyfication of
-         filter.h
-
-2006-02-04 00:01  maan
-
-       * audiod.c: use init_filters() instead of duplicating it
-
-2006-02-03 23:34  maan
-
-       * client.c, http_recv.c, net.c, net.h: rename do_connect() to
-         para_connect()
-
-2006-02-03 23:03  maan
-
-       * string.c: switch to doxygen format, add some references
-
-2006-02-03 22:40  maan
-
-       * Makefile.in, audioc.c, audiod.c, client.c, command.c, dopey.c,
-         http_recv.c, http_send.c, mysql.c, net.c, para.h, server.c,
-         string.c: add dependencies on new net.h, move para_hostname()
-         from net to string which makes afs independent of net as it
-         should be. No need to include gcc-compat.h twice.
-
-2006-02-03 22:37  maan
-
-       * net.h: contains function declarations for all non-static
-         functions in net.c. Yanked out from para.h.
-
-2006-02-03 21:47  maan
-
-       * Makefile.in: whitespace fixes
-
-2006-02-03 21:42  maan
-
-       * net.c: document all remaining non-static functions
-
-2006-02-03 21:41  maan
-
-       * stat.c: add documentation for stat_client_add()
-
-2006-02-03 07:13  maan
-
-       * audiod.c, para.h, stat.c: rename dump_stat_line() to
-         stat_client_write() and add documentation
-
-2006-02-02 18:42  maan
-
-       * afs.c, afs.h, mp3.c, ogg.c: simplify read_chunk()
-
-2006-02-02 16:48  maan
-
-       * afs.c, afs.h, db.h, ringbuffer.c, stat.c, string.c: switch to
-         doxygen comment style
-
-2006-02-02 16:47  maan
-
-       * db.c: whitespace fixes, switch to doxygen comment style
-
-2006-02-02 01:15  maan
-
-       * net.c, signal.c: switch to doxygen comment format
-
-2006-02-01 22:07  maan
-
-       * net.c, para.h: add more documentation, minor cleanups
-
-2006-02-01 22:06  maan
-
-       * ringbuffer.c: cosmetics
-
-2006-02-01 19:40  maan
-
-       * NEWS: [no log message]
-
-2006-02-01 19:40  maan
-
-       * error.h: add ringbuffer stuff
-
-2006-02-01 19:39  maan
-
-       * Makefile.in, configure.ac: gui and audiod need ringbuffer.o
-
-2006-02-01 19:38  maan
-
-       * gui.c: make bottom window scrollable
-
-2006-02-01 19:36  maan
-
-       * audiod.c: use the generic ringbuffer functions from ringbuffer.c
-
-2006-02-01 19:25  maan
-
-       * ringbuffer.c, ringbuffer.h: generic ring buffer routines to be
-         used by audiod and gui
-
-2006-02-01 19:24  maan
-
-       * http_send.c: comment out noisy debug message
-
-2006-01-29 21:52  maan
-
-       * oggdec.c: no source doc for static functions, kill obsolete
-         comment
-
-2006-01-29 21:30  maan
-
-       * mp3.c, play.c: no docbook for static functions
-
-2006-01-29 21:25  maan
-
-       * afs.c, db.h, dopey.c, server.c: make update_audio_file()
-         optional, add documentation of struct dbtool
-
-2006-01-29 14:38  maan
-
-       * pics/paraslash/no_pics.jpg: no need to include this in each
-         tarball
-
-2006-01-27 19:34  maan
-
-       * server.c: use ifdef HAVE_ORTP rather than ifdef HAVE_LIBORTP as
-         the former is only defined if libortp _and_ the ortp headers were
-         found, which is what we want here.
-
-2006-01-27 19:14  maan
-
-       * audiod.c: add missing <cr>
-
-2006-01-27 17:48  maan
-
-       * stat.c: add documentation for stat_line_valid()
-
-2006-01-27 17:35  maan
-
-       * configure.ac: fix ortp detection
-
-2006-01-27 15:28  maan
-
-       * string.c: fix some typos in documentation
-
-2006-01-27 15:17  maan
-
-       * stat.c: add documentation for for_each_line()
-
-2006-01-27 15:01  maan
-
-       * audiod.c, gui.c, gui_common.c, para.h, stat.c: rename
-         check_buf_for_items() to for_each_line()
-
-2006-01-27 13:14  maan
-
-       * NEWS, audiod.c, error.h, gui.c, http_recv.c, para.h, server.c,
-         signal.c: simplify para_signal_init(), add documentation for each
-         non-static function in signal.c
-
-2006-01-27 12:13  maan
-
-       * server.c: use para_reap_children() from signal.c rather than
-         duplicating its code in server.c
-
-2006-01-27 10:14  maan
-
-       * afs.h: add documentation for struct audio format
-
-2006-01-26 20:36  maan
-
-       * afs.c: add documentation for afs_send_chunk()
-
-2006-01-26 19:56  maan
-
-       * afs.c, afs.h, server.c: simplify afs_preselect() and add
-         documentation
-
-2006-01-26 19:29  maan
-
-       * afs.c: afs_preselect(): kill an unused variable and add some
-         documentation
-
-2006-01-26 19:08  maan
-
-       * afs.c, afs.h, server.c: rename afs_mainloop() to afs_preselect()
-
-2006-01-26 19:06  maan
-
-       * command.c: com_nomore(): only set the NO_MORE bit if playing or
-         paused
-
-2006-01-26 19:03  maan
-
-       * afs.c: add documentation of afs_init() and of afs_playing() and
-         friends
-
-2006-01-26 17:22  maan
-
-       * http_recv.c, net.c: use the return value of do_connect(). Move a
-         generic log message from http_recv.c to net.c.
-
-2006-01-26 15:34  maan
-
-       * error.h, net.c: E_HOST_INFO belongs to the net error list rather
-         than the recv error list. That fixes an audiod segfault when
-         given an invalid hostname as the http receiver option (because
-         the recv error list is undefined in audiod). Also, kill pointless
-         log message in get_host_info().
-
-2006-01-25 16:48  maan
-
-       * play.c: cosmetics
-
-2006-01-25 15:32  maan
-
-       * client.c, crypt.c, db.c, dopey.c, ogg.c: replace 2005 by 2006 in
-         GPL headers
-
-2006-01-25 15:23  maan
-
-       * error.h: fix NUM_SS
-
-2006-01-25 15:06  maan
-
-       * NEWS, command.c, db.h, error.h, mysql.c, server.c: convert the
-         remaining part of para_server to the new error subsystem
-
-2006-01-25 12:32  maan
-
-       * dopey.c, error.h: convert dopey.c to the new error subsystem
-
-2006-01-25 11:53  maan
-
-       * error.h, http_send.c, ortp_send.c, send.h: the return value of
-         sender.set_fds and sender.send is never checked. In fact, all
-         these functions always returned 1. Let them return void instead.
-
-2006-01-25 11:32  maan
-
-       * error.h, http_send.c, net.c, para.h: convert the http sender to
-         the new error subsystem
-
-2006-01-25 10:42  maan
-
-       * client.c, command.c, crypt.c, crypt.h: rename
-         para_encrypt/para_decrypt to
-         para_encrypt_challenge/para_decrypt_challenge
-
-2006-01-25 10:35  maan
-
-       * crypt.c, error.h: convert crypt.c to the new error subsystem
-
-2006-01-25 09:48  maan
-
-       * db.c, db.h, dopey.c, error.h, mysql.c: convert db.c to the new
-         error subsystem. Move the common directory changing/restoring
-         code from dopey.c/mysql.c to db.c. Add documentation for
-         find_audio_files().
-
-2006-01-25 08:06  maan
-
-       * mp3.c: kill the 'file' parameter of find_valid_start() as
-         find_valid_start() knows it anyway
-
-2006-01-25 07:57  maan
-
-       * afs.c, afs.h, error.h: convert afs to the new error subsystem. As
-         the return values of afs_send_chunk() and afs_mainloop() are
-         never used, change them to return void
-
-2006-01-24 13:21  maan
-
-       * afs.c, afs.h, server.c: kill unused afs_handle_sighup()
-
-2006-01-24 13:11  maan
-
-       * error.h, mp3.c, ogg.c: convert ogg.c to the new error subsystem
-
-2006-01-24 11:33  maan
-
-       * error.h, mp3.c: error messages for the mp3 format handler
-
-2006-01-24 10:37  maan
-
-       * error.h: first preparations for para_server towards the new error
-         subsystem
-
-2006-01-24 10:36  maan
-
-       * Makefile.in, configure.ac: cleanup of the build system
-
-2006-01-24 07:40  maan
-
-       * afs.c: cosmetics
-
-2006-01-24 05:54  maan
-
-       * Makefile.in, NEWS, configure.ac: new codename, reset version to
-         cvs
-
-2006-01-24 05:51  maan
-
-       * versions/: paraslash-0.2.9.tar.bz2, paraslash-0.2.9.tar.bz2.asc:
-         paraslash-0.2.9
-
-2006-01-24 05:50  maan
-
-       * Makefile.in, NEWS, configure.ac, scripts/demo-script,
-         web/index.in.html: paraslash 0.2.9
-
-2006-01-24 05:43  maan
-
-       * web/demo.in.html: kill the instructions for manual installation
-         as they do not work with paraslash-0.2.9 any more.
-
-2006-01-24 05:01  maan
-
-       * audiod.c: fix null pointer dereference in error log message
-         (s->receiver_node->receiver may well be NULL on errors)
-
-2006-01-24 03:54  maan
-
-       * README: [no log message]
-
-2006-01-24 03:16  maan
-
-       * command.c: initialize argv pointer to NULL as it is freed
-         unconditionally at the end of handle_connect()
-
-2006-01-23 14:18  maan
-
-       * FEATURES: [no log message]
-
-2006-01-23 08:52  maan
-
-       * web/license.in.html: add a link to a diff between v2 and v3 of
-         the GPL
-
-2006-01-23 08:08  maan
-
-       * Makefile.in: use para_util to make the changelog. Restrict output
-         to log messages newer than one year to reduce size
-
-2006-01-23 06:47  maan
-
-       * grab_client.c: handle short grab client writes properly according
-         to their grabbing mode: close pedantic grab clients, ignore the
-         short write for sloppy grab clients and rewrite the remaining
-         buffer in case of aggressive grab clients
-
-2006-01-23 06:44  maan
-
-       * audiod.c: make client_write() return an error on short writes,
-         always use the non-blocking write_client() instead of the
-         blocking send_buffer()
-
-2006-01-23 06:27  maan
-
-       * audiod.c: only set the filter chain error if there is a filter
-         chain. Fixes potential NULL pointer dereference.
-
-2006-01-23 06:25  maan
-
-       * grab_client.c: fix a use-after-free bug and remove the grab
-         client fd from the close_on_fork list in gc_close()
-
-2006-01-23 05:01  maan
-
-       * audiod.c, error.h, http_send.c, net.c, para.h, server.c:
-         generalize and simplify do_accept() so that it can also be used
-         by audiod. Rename it to para_accept() and add documentation as we
-         are at it.
-
-2006-01-23 04:29  maan
-
-       * gcc-compat.h, string.c: add documentation for each function in
-         string.c
-
-2006-01-23 01:54  maan
-
-       * Makefile.in: add some missing dependencies
-
-2006-01-23 01:43  maan
-
-       * mp3dec.c, ortp_send.c, wav.c: fix some signed issues noted by
-         gcc-4.0.2
-
-2006-01-23 01:39  maan
-
-       * filter.h: make gcc-4.0.2 happy
-
-2006-01-23 00:49  maan
-
-       * audiod.c, compress.c, filter_chain.c, http_send.c, oggdec.c: kill
-         some unused function parameters or mark them __unused if
-         appropriate
-
-2006-01-23 00:38  maan
-
-       * Makefile.in: add -W to DEBUG_CPPFLAGS instead of -Wunused wich
-         appeared tiwce
-
-2006-01-23 00:35  maan
-
-       * grab_client.c: fix serious typo
-
-2006-01-23 00:13  maan
-
-       * audiod.c: open_filters() exits immediately on errors, no need to
-         provide a return value
-
-2006-01-22 22:59  maan
-
-       * audioc.c, command.c, http_send.c, mp3.c, play.c, recv.c,
-         server.c, signal.c, stat.c, string.c, wav.c: change 2005 to 2006
-         in GPL header
-
-2006-01-22 22:59  maan
-
-       * NEWS: [no log message]
-
-2006-01-22 22:53  maan
-
-       * daemon.c: cosmetics
-
-2006-01-22 22:41  maan
-
-       * FEATURES: typo
-
-2006-01-22 08:13  maan
-
-       * README.mysql: [no log message]
-
-2006-01-22 07:52  maan
-
-       * FEATURES: [no log message]
-
-2006-01-22 07:19  maan
-
-       * skencil/overview.sk: update to forthcoming v0.2.9
-
-2006-01-22 05:22  maan
-
-       * command.c, server.c: shut down non-authorized connections after
-         10 seconds
-
-2006-01-22 04:41  maan
-
-       * audiod.c, filter_chain.c, recv_common.c: comment out some debug
-         messages
-
-2006-01-22 04:41  maan
-
-       * Makefile.in: format the output of cvs2cl to avoid long lines
-
-2006-01-22 04:32  maan
-
-       * Makefile.in: typo
-
-2006-01-22 04:27  maan
-
-       * Makefile.in: adjust filename of startup 'screenshots'
-
-2006-01-22 04:23  maan
-
-       * web/screenshots.in.html: adjust filename of startup 'screenshots'
-
-2006-01-22 04:21  maan
-
-       * pics/screenshots/: para_audiod-startup.txt,
-         para_server-startup.txt: recent versions
-
-2006-01-22 04:19  maan
-
-       * pics/screenshots/: para_audiod-2005-11-10.loglevel1.txt,
-         para_server-2005-10-13.loglevel1.txt: replaced by
-         para_audiod-startup.txt and para_server-startup.txt
-
-2006-01-22 03:55  maan
-
-       * audiod.c, daemon.c, para.h, server.c, string.c: make sure fd 0,
-         1, and 2 are valid. In daemon mode, dup2() these fds to /dev/null
-
-2006-01-22 03:27  maan
-
-       * audiod.c, audiod.ggo: new command line option:
-         --no_default_filters to deactivate the automatic filter
-         activation. Kill ifdefs HAVE_MAD and HAVE_OGGVORBIS as audiod now
-         supports both mp3 and ogg even if the mp3dec/oggdec filter is not
-         compiled in. Use --no_default_filters and e.g 'madplay -' as the
-         stream write command in this case.
-
-2006-01-22 00:37  maan
-
-       * ortp_recv.c: loglevel adjustment
-
-2006-01-22 00:36  maan
-
-       * audiod.c: filter_io() returns a proper error value, so set
-         fci->error accordingly
-
-2006-01-21 23:57  maan
-
-       * http_send.c: replace http_check_perms() by a saner version and
-         rename it to host_in_access_perm_list()
-
-2006-01-21 22:12  maan
-
-       * audiod.c: remove an unused variable
-
-2006-01-21 22:08  maan
-
-       * Makefile.in, NEWS, audiod.c, configure.ac, error.h, exec.c,
-         filter.c, filter_chain.c, grab_client.c, grab_client.h,
-         http_recv.c, mp3.c, mp3dec.c, net.c, oggdec.c, ortp_recv.c,
-         para.h, recv.c, recv.h, recv_common.c, signal.c, stat.c,
-         string.c: the shiny new error subsystem
-
-2006-01-21 22:07  maan
-
-       * web/download.in.html: mention that the nightly snapshot may or
-         may not compile
-
-2006-01-21 22:06  maan
-
-       * wav.c: write the wave header and the first chunk in one run if
-         output buffer can hold both
-
-2006-01-21 22:01  maan
-
-       * compress_filter.ggo: reduce default value of gain_max
-
-2006-01-18 20:39  maan
-
-       * compress.c: fix a nasty casting bug which sometimes caused an
-         output buffer overflow by 2 bytes. Also make sure we always
-         convert an even number of bytes
-
-2006-01-16 00:23  maan
-
-       * audiod.c: do not close filters as long as writer pid > 0
-
-2006-01-16 00:19  maan
-
-       * para.h: add some missing parentheses
-
-2006-01-15 18:07  maan
-
-       * audiod.c: fix nasty thinko: close_decoder_if_idle() might close
-         the receiver node, so s->receiver_node becomes NULL in this case.
-         The current code, however, saves s->receiver node in the local
-         variable 'rn' _before_ it calls close_decoder_if_idle() which
-         means that rn points to memory already freed. Fix is trivial:
-         Just call close_decoder_if_idle() at the beginning of the
-         FOR_EACH_SLOT loop
-
-2006-01-15 16:53  maan
-
-       * ortp_send.c: comment out two noisy debug messages
-
-2006-01-15 07:30  maan
-
-       * configure.ac: set mad_defs to the empty string if mad was not
-         detected
-
-2006-01-15 07:30  maan
-
-       * grab_client.c: cosmetics
-
-2006-01-15 06:56  maan
-
-       * NEWS: [no log message]
-
-2006-01-15 06:33  maan
-
-       * FEATURES, INSTALL, Makefile.in, NEWS, README, audiod.c,
-         audiod.ggo, compress.c, compress_filter.ggo, configure.ac,
-         filter.c, filter.h, filter_chain.c, grab_client.c, grab_client.h,
-         http_recv.c, mp3dec.c, oggdec.c, oggdec_filter.ggo, ortp.h,
-         ortp_recv.c, ortp_recv.ggo, ortp_send.c, para.h, recv.c, recv.h:
-         integrate para_recv and para_filter into para_audiod
-
-2006-01-15 06:27  maan
-
-       * net.c: add GPL header, use sizeof(struct ucred) instead of
-         sizeof(*cred) for the length argument of memcopy
-
-2006-01-15 06:06  maan
-
-       * audioc.c: avoid an extra <cr>
-
-2006-01-15 06:03  maan
-
-       * audiod.h: ATM, only one function prototype that is used by the
-         grabbing routines
-
-2006-01-15 06:01  maan
-
-       * recv_common.c: contains functions that are shared between
-         para_audiod and para_recv
-
-2006-01-15 06:00  maan
-
-       * grab_client.c, grab_client.ggo, grab_client.h: functions and
-         command line options for the grab command of audiod.
-
-2006-01-07 13:32  maan
-
-       * play.c: fix prebuffering
-
-2006-01-06 15:29  maan
-
-       * mp3dec.c: do not feed more than 4k to libmad
-
-2006-01-02 11:37  maan
-
-       * INSTALL, Makefile.in, configure.ac, http_recv.c, http_recv.ggo,
-         oggdec.c, ortp_recv.c, ortp_recv.ggo, recv.c, recv.ggo, recv.h:
-         receivers use their own command line parser
-
-2006-01-02 06:48  maan
-
-       * Makefile.in, NEWS, configure.ac: new codename, reset version to
-         cvs
-
-2006-01-02 06:46  maan
-
-       * versions/: paraslash-0.2.8.tar.bz2, paraslash-0.2.8.tar.bz2.asc:
-         paraslash-0.2.8
-
-2006-01-02 06:45  maan
-
-       * Makefile.in, NEWS, configure.ac, scripts/demo-script,
-         web/index.in.html: paraslash 0.2.8
-
-2006-01-02 05:31  maan
-
-       * filter.h: make the FILTER_INIT macro work also in the unsupported
-         case
-
-2006-01-02 05:04  maan
-
-       * compress.ggo, compress_filter.ggo: rename compress.cmdline.h to
-         compress_filter.cmdline.h
-
-2006-01-02 04:50  maan
-
-       * configure.ac: Add oggdec_filter.cmdline.o to $ogg_filter_objs.
-
-2006-01-02 04:50  maan
-
-       * filter.c: Do not print help via the -L option. Use the -f
-         filtername:-h instead.
-
-2006-01-02 04:50  maan
-
-       * Makefile.in: Use the same gengetopt options for all
-         xxx_filter.ggo files.
-
-2006-01-02 04:50  maan
-
-       * compress.ggo: cosmetics.
-
-2006-01-02 04:50  maan
-
-       * filter.h: new macros DECLARE_EXTERN_FILTER_INIT and FILTER_INIT
-         filter.h
-
-2006-01-02 04:50  maan
-
-       * compress.c: replace compress.cmdline.h by
-         compress_filter.cmdline.h, simplify compress_parse_config().
-
-2006-01-02 04:49  maan
-
-       * filter_chain.c: check_filter_arg(): only check filter args if the
-         filter has a config parser.
-
-2006-01-02 04:47  maan
-
-       * oggdec.c, oggdec_filter.ggo: make the ogg output buffer size a
-         config option
-
-2005-12-31 11:53  maan
-
-       * Makefile.in, compress.c, filter.c, filter.ggo, filter.h,
-         filter_chain.c, mp3dec.c, wav.c: make the filters use their own
-         ggo command line parser
-
-2005-12-31 05:31  maan
-
-       * Makefile.in, http_recv.c, ortp_recv.c, recv.c, recv.ggo, recv.h:
-         http_recv and ortp_recv no longer depend on the args_info struct.
-         This should allow that code to be reused from within para_audiod.
-
-2005-12-31 02:25  maan
-
-       * filter.c, server.ggo: cosmetics
-
-2005-12-30 11:52  maan
-
-       * command.c: com_version(): nicify output
-
-2005-12-30 10:26  maan
-
-       * compress.c: cosmetics
-
-2005-12-30 10:19  maan
-
-       * oggdec.c: make some functions static
-
-2005-12-30 07:00  maan
-
-       * filter.ggo: the command line options for para_filter
-
-2005-12-30 06:48  maan
-
-       * INSTALL, Makefile.in, NEWS, README, compress.c, configure.ac,
-         filter.c, filter.h, filter_chain.c, mp3dec.c, oggdec.c, wav.c:
-         the new modular filter design
-
-2005-12-30 04:48  maan
-
-       * ortp_send.c: turn off jitter compensation as it also delays the
-         EOF packet
-
-2005-12-29 03:04  maan
-
-       * play.c: fix nasty bug that caused para_play to stall: We must not
-         read more than chunk_buf bytes.
-
-2005-12-27 20:31  maan
-
-       * web/index.in.html: paraslash-0.2.7
-
-2005-12-27 20:21  maan
-
-       * Makefile.in, NEWS, configure.ac: new codename, reset version to
-         cvs
-
-2005-12-27 20:18  maan
-
-       * versions/: paraslash-0.2.7.tar.bz2, paraslash-0.2.7.tar.bz2.asc:
-         paraslash-0.2.7
-
-2005-12-27 20:17  maan
-
-       * Makefile.in, NEWS, configure.ac, index.html, scripts/demo-script:
-         paraslash 0.2.7
-
-2005-12-27 18:47  maan
-
-       * oggdec.c: use ov_raw_tell() to determine the initial delay in
-         case of holes in data
-
-2005-12-27 18:44  maan
-
-       * ogg.c: increase eof_timeout, reintroduce chunk_table shift
-
-2005-12-27 18:37  maan
-
-       * ortp_send.c: only reset each connection once
-
-2005-12-26 20:10  maan
-
-       * compress.ggo: better default values for gain_smooth and gain_max
-
-2005-12-26 20:03  maan
-
-       * afs.c: introduce a small delay before shutting down the senders.
-         This allows com_stat() to send 'audio_format=-1' in between
-
-2005-12-26 19:49  maan
-
-       * ortp_send.c: use rtp_session_reset() instead of
-         rtp_session_destroy()
-
-2005-12-26 19:25  maan
-
-       * daemon.c: fix minor mem leak
-
-2005-12-24 20:43  maan
-
-       * audiod.c: fix thinko in do_filter_io(): We tested ret==len (short
-         write) _AFTER_ decrementing len which triggred the memmove to
-         shift the buffer even if we had written the whole damn thing. But
-         the real bug is that the memmove was not executed in some rare
-         cases where we did have a short write. Kill that nasty bug with
-         pleasure and simplify the surrounding code a bit while we're at
-         it.
-
-2005-12-24 19:51  maan
-
-       * oggdec.c: distinguish between OV_HOLE and other errors
-
-2005-12-24 19:44  maan
-
-       * ortp_send.c: loglevel adjustment: use NOTICE loglevel for removal
-         of targets
-
-2005-12-23 23:27  maan
-
-       * audiod.c: clear play_time when stopped
-
-2005-12-23 23:26  maan
-
-       * ortp_send.c: turn off libortp's debug logging
-
-2005-12-23 23:23  maan
-
-       * http_recv.c, ortp_recv.c: para_log() is already declared in
-         para.h
-
-2005-12-23 23:00  maan
-
-       * CREDITS: add Jaroslav Kysela
-
-2005-12-23 22:41  maan
-
-       * command.c: com_stat(): only print mtime if we have a valid audio
-         file
-
-2005-12-23 22:40  maan
-
-       * afs.c: new function afs_eof() to be called when the 'next' flag
-         is set. Reset audio file info, dbinfo etc.
-
-2005-12-23 22:36  maan
-
-       * server.c: also refresh status after afs_send() if neccessary
-
-2005-12-23 19:34  maan
-
-       * command.c: get_status(): always use the copy of the mmd struct as
-         we do not hold the mmd_lock
-
-2005-12-23 19:12  maan
-
-       * command.c: com_stat(): kill an unused variable
-
-2005-12-22 23:48  maan
-
-       * http_send.c: kill unused http_send_header(). http_send(): the
-         current_chunk arg _is_ used, so nuke the __unused annotation
-
-2005-12-22 18:37  maan
-
-       * http_send.c: cosmetics
-
-2005-12-22 04:55  maan
-
-       * play.ggo, recv.ggo: typo
-
-2005-12-22 02:19  maan
-
-       * http_send.c: cosmetics
-
-2005-12-22 02:03  maan
-
-       * audiod.c: store last death time instead of last start time for
-         each format and use it together with the new MIN_PENALTY_MS to
-         avoid immediate restart of the (wrong) decoder
-
-2005-12-22 01:59  maan
-
-       * http_send.c: fix send-double-header-sent bug
-
-2005-12-21 22:12  maan
-
-       * server.c: kill an unused variable, add debug message
-
-2005-12-21 22:12  maan
-
-       * audiod.c: The previous change was a brain fart. Revert it.
-
-2005-12-21 22:11  maan
-
-       * audiod.ggo: reduce default stream delay to 200ms
-
-2005-12-21 17:09  maan
-
-       * audiod.c: wait for the audio format to be resent by para_server
-         before restarting the stream reader
-
-2005-12-21 02:28  maan
-
-       * recv.c: cosmetics
-
-2005-12-21 01:43  maan
-
-       * recv.c: add GPL header, whitespace cleanup
-
-2005-12-20 22:48  maan
-
-       * INSTALL, NEWS, README, audiod.c, audiod.ggo, http_recv.c: replace
-         para_http_recv and para_ortp_recv by para_recv
-
-2005-12-20 22:36  maan
-
-       * NEWS: [no log message]
-
-2005-12-20 22:36  maan
-
-       * play.c, string.c: cosmetics
-
-2005-12-20 22:35  maan
-
-       * list.h: reintroduce list_add_tail() as it is needed by
-         http_send.c
-
-2005-12-20 22:34  maan
-
-       * mp3.c: write chunk info as 'num_chunks x chunk_time' as this info
-         is read by audiod, increase eof time
-
-2005-12-20 22:34  maan
-
-       * ogg.c: write chunk info as 'num_chunks x chunk_time' as this info
-         is read by audiod. comment out some rather strange workaround
-         code in tunetable()
-
-2005-12-20 22:31  maan
-
-       * audiod.ggo: specify delay in milliseconds
-
-2005-12-20 22:30  maan
-
-       * oggdec.c: prebuffer data if hole was detected, increase output
-         buffer size
-
-2005-12-20 22:26  maan
-
-       * audiod.c: read the chunk time from server info and push that time
-         to the executed commands via the new CHUNK_TIME() macro. Use
-         milliseconds for the stream delay. Some misc fixes also
-
-2005-12-20 22:19  maan
-
-       * http_recv.c: rewrite to fit into the new receiver struct which is
-         also used by the ortp receiver. This should ease the inclusion
-         into para_audiod
-
-2005-12-20 22:16  maan
-
-       * ortp_recv.c: almost a complete rewrite. The inclusion into
-         para_recv, the update to ortp-0.8.x  and the new ORTP_EMPTY
-         packet type made this neccessary. Should chew less CPU now
-
-2005-12-20 22:12  maan
-
-       * http_send.c: implement a per-client packet queue that holds
-         packets which can not be sent out immediately
-
-2005-12-20 22:10  maan
-
-       * afs.c: always call the senders, even if there is no data to send.
-         This allows the senders to send out buffered data
-
-2005-12-20 22:08  maan
-
-       * recv.ggo: combined ortp_recv.ggo and http_recv.ggo, slightly
-         modified
-
-2005-12-20 22:07  maan
-
-       * http_recv.ggo, ortp_recv.ggo: these went to recv.ggo
-
-2005-12-20 22:05  maan
-
-       * Makefile.in, configure.ac, recv.c, recv.h: this combines
-         para_ortp_recv and para_http_recv into one binary
-
-2005-12-20 22:03  maan
-
-       * ortp.h, ortp_send.c: use the new ORTP_EMPTY packet to indicate
-         that no data packet is going to be sent right now, compute the
-         timestamp of the packet always by multiplying chunk_time and
-         chunks_sent instead of asking the ortp library, turn off
-         scheduling mode
-
-2005-12-17 22:16  maan
-
-       * compress.c: kill some dead code
-
-2005-12-15 15:26  maan
-
-       * ortp_send.c: use rtp_session_time_to_ts() instead of
-         rtp_session_get_current_send_ts() for computing the timestamp
-
-2005-12-15 15:24  maan
-
-       * afs.c: compute offset after reading the first chunk
-
-2005-12-08 16:02  maan
-
-       * web/footer.html: comment out ssi for last modification date.
-
-2005-12-08 12:52  maan
-
-       * afs.c: add some docu
-
-2005-12-08 12:52  maan
-
-       * mysql.c: com_streams(): If called with arg 'current_stream',
-         print the name of the current stream. This info is also availabe
-         by calling cs (change stream) with no args, but cs is restricted
-         to users with DB_WRITE privileges..
-
-2005-12-08 12:48  maan
-
-       * play.c: prebuffer data if start_time is not reached rather than
-         simply sleep until that time. Add some documentation
-
-2005-11-28 23:05  maan
-
-       * ortp_send.c: destroy session also in case EOF notifier could not
-         be sent
-
-2005-11-28 23:04  maan
-
-       * web/demo.in.html: mention -Z option for mpg123
-
-2005-11-23 16:42  maan
-
-       * web/contact.in.html: [no log message]
-
-2005-11-23 16:41  maan
-
-       * server.c: Oops. Fix random number generation.
-
-2005-11-15 14:48  maan
-
-       * sdl_gui.c: fix zombie bug
-
-2005-11-13 19:57  maan
-
-       * Makefile.in: add ChangeLog to phony targets. This way it gets
-         always rebuild.
-
-2005-11-13 19:29  maan
-
-       * Makefile.in: modify rule for PUBLIC_KEY so that it also applies
-         to key.anonymous
-
-2005-11-13 19:16  maan
-
-       * Makefile.in: add anonyous key to web_misc
-
-2005-11-13 19:11  maan
-
-       * key.anonymous: for www.paraslash.org
-
-2005-11-13 18:47  maan
-
-       * Makefile.in: move some stuff around, make web/sync, use sk2ps
-
-2005-11-13 18:17  maan
-
-       * pics/screenshots/: gui-2005-11-12.png,
-         para_audiod-2005-11-10.loglevel1.txt,
-         para_server-2005-10-13.loglevel1.txt: new screenshots
-
-2005-11-13 18:13  maan
-
-       * web/: contact.in.html, demo.in.html, documentation.in.html,
-         download.in.html, footer.html, header.html, index.in.html,
-         license.in.html, screenshots.in.html: new web pages
-
-2005-11-13 18:04  maan
-
-       * Makefile.in: add target www that replaces the old html target
-
-2005-11-13 04:00  maan
-
-       * dopey.c: add some more comments
-
-2005-11-13 03:59  maan
-
-       * CREDITS, FEATURES, INSTALL, NEWS, README, README.mysql: minor
-         corrections and cleanups
-
-2005-11-13 03:58  maan
-
-       * gcc-compat.h: make gcc 3.3.5 happy
-
-2005-11-10 23:28  maan
-
-       * afs.c, audiod.c, command.c, dopey.c, play.c, string.c: add some
-         missing includes
-
-2005-11-10 23:28  maan
-
-       * Makefile.in: tell gcc to bail out on implicit function
-         declarations
-
-2005-11-10 23:27  maan
-
-       * gui.c: para_gui does not kill any decoders. Remove obsolete help
-         text.
-
-2005-11-10 23:25  maan
-
-       * README: [no log message]
-
-2005-11-07 21:36  maan
-
-       * net.c, para.h: remove some incdudes which are not needed and move
-         inclusion ofnetdb.h from para.h to net.c
-
-2005-11-07 21:15  maan
-
-       * dbadm.c: whitespace cleanup
-
-2005-11-07 16:53  maan
-
-       * para.h: kill unused para_open_fifo()
-
-2005-11-07 16:28  maan
-
-       * stat.c: shutdown stat_client connection if corresponding fd is
-         not ready for writing
-
-2005-11-07 13:34  maan
-
-       * gcc-compat.h: remove the __const macro. It is not used by
-         paraslash, but alsa seems to use it for something else so gcc
-         produces the following warning: passing arg 4 of __assert_fail
-         discards qualifiers from pointer target type
-
-2005-11-06 19:08  maan
-
-       * index.html: typo
-
-2005-11-06 18:45  maan
-
-       * Makefile.in: make it work again for gcc-2.95.4
-
-2005-11-06 18:43  maan
-
-       * server.c: change #if HAVE_MYSQL to #ifdef HAVE_MYSQL
-
-2005-11-06 18:42  maan
-
-       * command.c, para.h: malloc.h is only needed from command.c, so
-         move the include from para.h to command.c
-
-2005-11-06 18:41  maan
-
-       * index.html: add icon, nicify layout, use :hover to highlight
-         links
-
-2005-11-06 18:37  maan
-
-       * pics/web/paraslash.ico: icon resource file
-
-2005-11-06 18:35  maan
-
-       * list.h: include stddef.h, kill unused macros
-
-2005-11-06 18:34  maan
-
-       * audiod.c: only list.h needs stddef.h, so include it from there
-
-2005-11-06 18:31  maan
-
-       * INSTALL: [no log message]
-
-2005-11-06 15:41  maan
-
-       * NEWS: [no log message]
-
-2005-11-06 15:41  maan
-
-       * Makefile.in: use common rule to let all object files depend on
-         gcc-compat.h and on para.h, add some more -W flags
-
-2005-11-06 14:53  maan
-
-       * daemon.c: fix warning: getpwnam discards qualifiers from pointer
-         target type
-
-2005-11-06 14:46  maan
-
-       * audiod.c: include gcc-compat.h and mark unused args as such.
-         Also, change third arg of accept() to proper type socklen_t*
-
-2005-11-06 14:42  maan
-
-       * client.c: include gcc-compat.h and mark arg of sigint_handler()
-         as unused
-
-2005-11-06 14:42  maan
-
-       * command.c: include gcc-compat.h and use __unused macros for
-         commands that take no args or do not output anything. Be a little
-         more anal and return -E_SYNTAX for commands that take no args in
-         case args were given
-
-2005-11-06 14:39  maan
-
-       * dbadm.c, audioc.c: include gcc-compat.h and mark args of dummy
-         para_log() as unused
-
-2005-11-06 14:37  maan
-
-       * db.c, dopey.c: kill unused arg dir, include and use gcc-compat.h
-
-2005-11-05 23:31  maan
-
-       * fade.c: include gcc-compat.h and mark loglevel arg of para_log()
-         as unused
-
-2005-11-05 23:30  maan
-
-       * http_send.c: include gcc-compat.h and use __unused macros for
-         unused args of http_send() (those are used by the ogg audio
-         format handler so we cannot simply kill the unused args),
-         http_handle_fds() no longer takes pointer to max_fileno. Mark
-         unused args of com_on() and com_off()
-
-2005-11-05 23:26  maan
-
-       * oggdec.c: use int main(void) as all args are unused
-
-2005-11-05 23:25  maan
-
-       * list.h: kill empty prefetch()
-
-2005-11-05 23:24  maan
-
-       * mysql.c: include gcc-compat.h and use __unused macros for
-         commands that take no args. Be a little more anal and return
-         -E_SYNTAX for commands that take no args in case args were given
-
-2005-11-05 23:22  maan
-
-       * net.c: include gcc-compat.h and use __printf and __must_check
-         macros
-
-2005-11-05 23:20  maan
-
-       * mp3dec.c: fix signedness bug, use int main(void) as all args are
-         unused
-
-2005-11-05 23:15  maan
-
-       * ortp_recv.c: include gcc-compat.h and use __printf macro
-
-2005-11-05 23:14  maan
-
-       * para.h: kill struct gui_command which was moved to gui.c, include
-         gcc-compat.h and use __must_check and __malloc macros
-
-2005-11-05 23:12  maan
-
-       * sdl_gui.c: use C99 array initializers, include gcc-compat.h and
-         mark loglevel arg of para_log() as unused
-
-2005-11-05 23:11  maan
-
-       * send.h: handle_fds() does no longer take a pointer to max_fileno
-
-2005-11-05 23:11  maan
-
-       * server.c: use macros from gcc-compat.h, move para_log(), no need
-         to init fd in init_random_seed(), handle_fds() does no longer
-         take a pointer to max_fileno
-
-2005-11-05 22:59  maan
-
-       * string.c: add __malloc and __must_check
-
-2005-11-05 22:57  maan
-
-       * gui.c: commands do not need to know the key which was pressed to
-         invoke them, just kill the arg. Move struct gui_command from
-         para.h to gui.c, use new __printf macro
-
-2005-11-05 17:22  maan
-
-       * gcc-compat.h: add __printf
-
-2005-11-05 17:19  maan
-
-       * afs.c, afs.h, mp3.c, ogg.c: no need to pass FILE pointer to
-         close_audio_file() as the audio format handlers know it anyway.
-         Kill unused function parameter raw_total in
-         ogg_compute_chunk_table()
-
-2005-11-05 17:12  maan
-
-       * index.html: new design with menu on the left
-
-2005-11-05 16:14  maan
-
-       * FEATURES: [no log message]
-
-2005-11-04 18:05  maan
-
-       * index.html: html links to directories should have a trailing
-         slash
-
-2005-11-01 13:57  maan
-
-       * http_send.c: fix dangerous typo in case of invalid get request
-
-2005-10-31 22:57  maan
-
-       * stat.c: use ISO C99 array initializers
-
-2005-10-31 22:56  maan
-
-       * Makefile.in: fix dependencies on close_on_fork.h, add
-         dependencies on new gcc-compat.h
-
-2005-10-31 22:53  maan
-
-       * audioc.c: add GPL header
-
-2005-10-31 22:05  maan
-
-       * client.c, command.c, crypt.c, net.c: fix some gcc-4 signedness
-         warnings regarding char vs unsigned char
-
-2005-10-31 22:05  maan
-
-       * play.c: fix gcc-4 signedness warning
-
-2005-10-31 22:02  maan
-
-       * audiod.c: use __noreturn gcc extenstion where appropriate which
-         allows to kill some bogus 'return 42' statements. Rename .buflen
-         of struct stream_io to .loaded (as in struct filter)
-
-2005-10-31 21:59  maan
-
-       * gcc-compat.h: beautified GCC extensions that define away for
-         non-gcc compilers and gcc 2. Kudos to Rob Love who mentioned that
-         at kernelplanet
-
-2005-10-29 22:19  maan
-
-       * Makefile.in, NEWS, configure.ac: new codename, reset version to
-         cvs, turn on debugging
-
-2005-10-29 22:16  maan
-
-       * versions/: paraslash-0.2.6.tar.bz2, paraslash-0.2.6.tar.bz2.asc:
-         paraslash-0.2.6
-
-2005-10-29 22:14  maan
-
-       * NEWS, configure.ac, index.html, scripts/demo-script: paraslash
-         0.2.6
-
-2005-10-29 21:18  maan
-
-       * Makefile.in: turn off debugging (-g)
-
-2005-10-29 18:32  maan
-
-       * command.c: cosmetics
-
-2005-10-29 18:32  maan
-
-       * compress.ggo: increase default values of gain_max and gain_smooth
-
-2005-10-28 21:46  maan
-
-       * command.c: cosmetics
-
-2005-10-28 21:38  maan
-
-       * command.c: mention the afs status bits in the help text of the
-         relevant commands
-
-2005-10-28 20:07  maan
-
-       * mysql.c: add some examples
-
-2005-10-28 18:12  maan
-
-       * mysql.c: typo
-
-2005-10-28 18:04  maan
-
-       * command.c: use 'audio file' instead of 'song'
-
-2005-10-28 17:56  maan
-
-       * afs.c, db.h, dopey.c, mysql.c: use 'audio file' instead of 'song'
-         also in struct dbtool
-
-2005-10-28 17:50  maan
-
-       * mysql.c: use 'audio file' instead of 'song', extend docu of ls
-
-2005-10-28 17:35  maan
-
-       * mysql.c: improve mbox docu
-
-2005-10-28 12:42  maan
-
-       * INSTALL, NEWS: [no log message]
-
-2005-10-27 20:48  maan
-
-       * crypt.h, crypt.c: fix debian compiler warning: passing arg 2 of
-         RSA_public_encrypt discards qualifiers from pointer target type
-
-2005-10-27 20:36  maan
-
-       * README: replace dead xiph link
-
-2005-10-27 20:25  maan
-
-       * INSTALL, README: [no log message]
-
-2005-10-27 19:55  maan
-
-       * index.html: mention new manual pages
-
-2005-10-27 19:32  maan
-
-       * mysql.c: typo
-
-2005-10-27 19:28  maan
-
-       * command.c: reformat help text of com_help
-
-2005-10-27 19:04  maan
-
-       * Makefile.in, index.html: include man pages that replace
-         manual.txt
-
-2005-10-27 18:29  maan
-
-       * 1.0, NEWS, command.c, mysql.c: further documentation cleanup
-
-2005-10-27 00:50  maan
-
-       * exec.c: kill unused para_open_fifo()
-
-2005-10-27 00:23  maan
-
-       * audiod.c, command.c, dopey.c, mysql.c: reformat, beautify and
-         improve documentation
-
-2005-10-26 01:37  maan
-
-       * net.c: whitespace cleanup
-
-2005-10-25 04:02  maan
-
-       * command.c: fix status update on db_write commands
-
-2005-10-24 01:26  maan
-
-       * client.c: kill debug message
-
-2005-10-23 21:16  maan
-
-       * audiod.c: handle short writes for grab clients properly according
-         to grab mode, logging improvements
-
-2005-10-23 20:50  maan
-
-       * audioc.c: use recv_bin_buffer() instead of recv_buffer(). Fixes
-         grab command
-
-2005-10-23 17:04  maan
-
-       * audiod.c, compress.c, dopey.c, para.h, string.c: introduce
-         para_calloc() and use it where aprropriate
-
-2005-10-23 16:57  maan
-
-       * NEWS: typo
-
-2005-10-23 16:37  maan
-
-       * client.c: kill unused function get_exit_status(), make two other
-         functions static
-
-2005-10-23 05:13  maan
-
-       * NEWS: [no log message]
-
-2005-10-23 04:56  maan
-
-       * stat.c: add GPL header
-
-2005-10-23 04:55  maan
-
-       * command.c, server.c: init random seed in parent, rather that in
-         each client. As reads of /dev/random may block, clients were
-         blocked under load if many connections arrived at the same time.
-
-2005-10-23 04:41  maan
-
-       * Makefile.in: add two missing header files to the tarball
-
-2005-10-23 04:07  maan
-
-       * audiod.c, para.h, stat.c: use macros from list.h for stat_client
-         list rather than homebrewed list logic, some smallish cleanups
-         also.
-
-2005-10-23 02:03  maan
-
-       * Makefile.in, audiod.c, stat.c: add stream readers/writers/filters
-         as well as grab/stat clients to the list of fds to be closed in
-         para_exec()
-
-2005-10-22 23:36  maan
-
-       * Makefile.in, audiod.c, exec.c: para_exec(): close fds on
-         close_on_fork after forking. Mark audiod's local socket fd for
-         close after fork
-
-2005-10-22 23:09  maan
-
-       * Makefile.in, http_send.c, server.c: use new close_on_fork list to
-         mark fds for closing in the child after fork
-
-2005-10-22 23:07  maan
-
-       * close_on_fork.c, close_on_fork.h: implement list of fds that
-         should be closed in the child after fork together with simple
-         functions to add/delete fds from that list as well a a function
-         that closes all fds on the list
-
-2005-10-22 20:18  maan
-
-       * gui.c: speed up display of command output by refreshing the
-         screen only after it is completely filled or there is no more
-         output available
-
-2005-10-22 19:58  maan
-
-       * gui.c, net.c, para.h, string.c: new macro: PARA_VSPRINTF, a
-         user-friendly and secure version of vsprintf(). Replace all
-         occurences of vsprintf by PARA_VSPRINTF, thus fixing some
-         potential buffer overflows in gui.c. Moreover, the new macro
-         allows to get rid of some duplicate code in make_message() and
-         send_va_buffer()
-
-2005-10-22 19:57  maan
-
-       * fade.c: simplify para_log()
-
-2005-10-22 19:48  maan
-
-       * NEWS: [no log message]
-
-2005-10-22 18:36  maan
-
-       * audiod.c: nuke another unused variable
-
-2005-10-22 18:33  maan
-
-       * audiod.c: nuke unused variable rb_bytes
-
-2005-10-22 17:28  maan
-
-       * client.c, command.c, para.h: major para_client cleanup: remove
-         sigchild-handling, change some old crufty code to use
-         make_message() and para_strcat(), improve SIGINT handling,
-         #define CHALLENGE_RESPONSE_MSG in para.h and use it from server
-         and client rather than harcoding the message text.
-
-2005-10-22 15:55  maan
-
-       * client.c: fix interactive mode (only the first command worked)
-
-2005-10-22 15:48  maan
-
-       * 1.0, Makefile.in, NEWS, audioc.c, audiod.c, client.c, client.ggo,
-         command.c, crypt.c, crypt.h, http_recv.c, net.c, para.h, rc4.h:
-         implement crypted connections by using openssl's rc4 stream
-         cipher algorithm
-
-2005-10-20 15:26  maan
-
-       * command.c: kill outdated comment
-
-2005-10-19 15:22  maan
-
-       * net.c: remove unused pass_fd()
-
-2005-10-19 15:18  maan
-
-       * net.c, para.h: make do_bind() static
-
-2005-10-19 15:17  maan
-
-       * net.c, para.h: make setserversockopts() static
-
-2005-10-19 11:52  maan
-
-       * server.h: whitespace cleanup
-
-2005-10-19 11:51  maan
-
-       * Makefile.in, NEWS, afs.c, command.c, db.c, db.h, dopey.c,
-         http_send.c, mp3.c, mysql.c, ogg.c, ortp_send.c, server.c,
-         server.h: major header cleanup
-
-2005-10-19 11:50  maan
-
-       * afs.h: contains afs related stuff, pulled out from server.h
-
-2005-10-17 09:45  maan
-
-       * SFont.c: cosmetics
-
-2005-10-17 07:54  maan
-
-       * Makefile.in, NEWS, README.mysql, client.c, dopey.c, mysql.c,
-         server.ggo, server.h: implement, use and document an internal
-         find command and get rid of exec.o in para_server
-
-2005-10-17 07:53  maan
-
-       * db.c, db.h: functions common to all database tools. ATM, only the
-         new internal find command
-
-2005-10-17 02:27  maan
-
-       * SFont.c: remove superflous include
-
-2005-10-16 22:15  maan
-
-       * net.c: cosmetics
-
-2005-10-16 22:13  maan
-
-       * INSTALL: [no log message]
-
-2005-10-14 10:10  maan
-
-       * krell.c: replace old email address
-
-2005-10-14 10:10  maan
-
-       * http_send.c: loglevel adjustment
-
-2005-10-14 05:23  maan
-
-       * README.mysql: whitespace cleanup
-
-2005-10-14 01:15  maan
-
-       * http_send.c, ortp_send.c, send.h, server.c: as senders can be
-         controlled at runtime, there is no need to panic on
-         sender-related syntax errors in command line args or  in the
-         config file. Just ignore invalid options and make corresponding
-         functions return void.
-
-2005-10-14 00:54  maan
-
-       * afs.c, mp3.c, ogg.c, server.c, server.h: afs_init is always
-         successful. Change it to return void.
-
-2005-10-14 00:45  maan
-
-       * afs.c, command.c, server.h: the set of supported audio formats is
-         known at compile time. So make it a preproccessor macro and
-         remove the function that computed this constant value. Also
-         introduce an array-version of all supported audio formats.
-
-2005-10-14 00:07  maan
-
-       * index.html: typo
-
-2005-10-13 23:00  maan
-
-       * Makefile.in, NEWS, configure.ac: new codename, reset version to
-         cvs
-
-2005-10-13 22:56  maan
-
-       * versions/: paraslash-0.2.5.tar.bz2, paraslash-0.2.5.tar.bz2.asc:
-         paraslash-0.2.5
-
-2005-10-13 22:55  maan
-
-       * NEWS, configure.ac, index.html, scripts/demo-script: paraslash
-         0.2.5
-
-2005-10-13 22:34  maan
-
-       * mysql.c: make debian's gcc-2.95.4 happy
-
-2005-10-13 20:56  maan
-
-       * server.c: another small memory leak
-
-2005-10-13 20:56  maan
-
-       * ogg.c: fix a memory leak
-
-2005-10-13 10:37  maan
-
-       * audioc.c, para.h, string.c: move concat_args() from string.c to
-         audioc.c. As it is only used there, make it static
-
-2005-10-13 10:33  maan
-
-       * daemon.c, string.c: move uptime_str() from string.c to daemon.c.
-         It is only used by para_server and by para_audiod
-
-2005-10-13 10:14  maan
-
-       * http_send.c: cosmetics
-
-2005-10-13 10:05  maan
-
-       * http_recv.c: decrease buffer size: 8k should be enough.
-
-2005-10-13 09:45  maan
-
-       * http_recv.c: add GPL header
-
-2005-10-13 09:00  maan
-
-       * exec.c, para.h, string.c: move split_args() from exec.c to
-         string.c. Each caller of split_args() links string.o anyway.
-         Moreover, para_server needs it, and the plan is to make
-         para_server fully single-threaded..
-
-2005-10-13 08:50  maan
-
-       * string.c: no need to include server.h. para.h is enough
-
-2005-10-13 07:35  maan
-
-       * command.c, http_send.c, ortp_send.c, send.h: add sender-specific
-         help commands
-
-2005-10-13 07:28  maan
-
-       * NEWS: [no log message]
-
-2005-10-13 05:29  maan
-
-       * ogg.c: free buffers on song exit, take packet-end time into
-         aacount when computing the chunk table (should fix dropouts at
-         the beginnin)
-
-2005-10-13 03:21  maan
-
-       * audiod.c: fix segfault in get_empty_slot() for invalid
-         stream_read commands
-
-2005-10-13 00:19  maan
-
-       * audiod.c: simplify check_sigchld(), fix potential segfault on
-         server shutdown
-
-2005-10-12 22:02  maan
-
-       * skencil/overview.sk: nuke para_send, change version to 0.2.5
-
-2005-10-11 21:15  maan
-
-       * oggdec.c: kill bogus usleep, increase bufsize to 64k, handle
-         short writes
-
-2005-10-11 21:03  maan
-
-       * ortp_send.c: check return values from rtp_session_send_with_ts()
-         and shut down target on errors
-
-2005-10-11 04:52  maan
-
-       * gui.c: fix memory leak in client_cmd_cmdline()
-
-2005-10-11 03:27  maan
-
-       * ortp_send.c: fix null pointer bug in com_si()
-
-2005-10-11 03:26  maan
-
-       * audiod.c: kill reader, writer and filters on stream timeout, fix
-         close_unused_stream_fds() in case stream writer dies first
-
-2005-10-10 07:30  maan
-
-       * ortp_send.c: cosmetics
-
-2005-10-10 06:08  maan
-
-       * mysql.c: fix a memory leak in get_query()
-
-2005-10-10 06:04  maan
-
-       * http.h, http_recv.c, http_send.c, net.c, para.h: send/recv proper
-         get request, not just a minimal one, so para_http_recv works also
-         with other http streamers like poc-http
-
-2005-10-10 06:00  maan
-
-       * Makefile.in: add missing dependencies of http_recv, add new
-         header files for the tarball, use -O0 optimization -- it produces
-         smaller binaries (on my current system) and valgrind likes it too
-
-2005-10-10 05:58  maan
-
-       * INSTALL: [no log message]
-
-2005-10-10 03:23  maan
-
-       * audiod.c: fix memory leak in handle_connect()
-
-2005-10-10 03:20  maan
-
-       * ortp_send.c: whitespace cleanup
-
-2005-10-10 03:18  maan
-
-       * ortp_recv.c: include ortp_recv.cmdline.h instead of former
-         recv.cmdline.h
-
-2005-10-10 03:17  maan
-
-       * server.c: fix memory leak in parse_config(), replace sprintf() by
-         make_message()
-
-2005-10-10 03:15  maan
-
-       * exec.c: fix memory leak in para_exec_cmdline_pid()
-
-2005-10-10 03:14  maan
-
-       * command.c: fix memory leak in com_si()
-
-2005-10-10 03:13  maan
-
-       * NEWS: [no log message]
-
-2005-10-07 10:15  maan
-
-       * Makefile.in: kill para_send-related targets
-
-2005-10-07 01:41  maan
-
-       * send.c, send.ggo: no more need for the stand-alone sender
-
-2005-10-07 01:35  maan
-
-       * audiod.c, audiod.ggo: make para_http_recv the default receiver
-
-2005-10-07 01:33  maan
-
-       * Makefile.in, configure.ac: change para_recv to para_ortp_recv
-
-2005-10-07 01:20  maan
-
-       * ortp_recv.c, ortp_recv.ggo: former recv.c and recv.ggo
-
-2005-10-07 01:20  maan
-
-       * recv.c, recv.ggo: renamed to ortp_recv.c and ortp_recv.ggo
-
-2005-10-07 01:16  maan
-
-       * ortp_send.c, server.ggo: new option: ortp_header_interval
-
-2005-10-07 01:15  maan
-
-       * afs.c: remove bogus check, only call the send functions if buffer
-         is non-empty
-
-2005-10-07 01:14  maan
-
-       * INSTALL, NEWS: [no log message]
-
-2005-10-04 01:31  maan
-
-       * afs.c: kill unused eof_time
-
-2005-10-04 00:10  maan
-
-       * afs.c: remove outdated comment
-
-2005-10-04 00:10  maan
-
-       * http_send.c, mp3.c, ogg.c, server.h: remove send_header function
-         pointer from struct audio format
-
-2005-10-03 21:59  maan
-
-       * afs.c: kill send_function(). It's kinda pointless.
-
-2005-10-03 21:28  maan
-
-       * afs.c, mp3.c, ogg.c, server.h: remove fifo. fifoname and sw_pid
-         from struct audio format
-
-2005-10-03 21:19  maan
-
-       * Makefile.in: afs depends on send.h
-
-2005-10-03 21:19  maan
-
-       * server.ggo: remove option stream_write_cmd
-
-2005-10-03 21:18  maan
-
-       * afs.c: kill some dead code: af->sw_pid is always -1
-
-2005-10-03 20:48  maan
-
-       * afs.c, server.h: kill open_cmd in struct audio info, kill
-         setup_stream_command()
-
-2005-10-03 20:47  maan
-
-       * command.c: increase event counter on pause
-
-2005-10-03 19:04  maan
-
-       * afs.c, command.c, server.h: kill the AFS_STREAM_WRITER flag
-
-2005-09-30 10:12  maan
-
-       * index.html: cosmetics
-
-2005-09-30 05:23  maan
-
-       * afs.c: fix paused mode: only set eof_barrier once
-
-2005-09-30 05:07  maan
-
-       * afs.c: fix status flags on eof when AFS_NOMORE is set
-
-2005-09-30 04:21  maan
-
-       * afs.c: sw_restart_barrier is no longer needed
-
-2005-09-30 04:18  maan
-
-       * afs.c: kill unused SW_RESTART_TIME
-
-2005-09-30 04:17  maan
-
-       * afs.c: kill unneeded sw_restart_tv
-
-2005-09-30 04:13  maan
-
-       * afs.c, server.c: there are no more children to handle for afs
-
-2005-09-30 03:58  maan
-
-       * server.c: only call afs_send_chunk() if select timeout expired
-
-2005-09-30 03:48  maan
-
-       * afs.c: kill afs_open_fifo(). It has no more callers
-
-2005-09-30 03:32  maan
-
-       * mp3.c, ogg.c, server.h: kill the mainloops themselves
-
-2005-09-30 03:16  maan
-
-       * afs.c: kill the call to the mainloop of audio format handlers as
-         it is no longer needed
-
-2005-09-30 02:45  maan
-
-       * afs.c: reset mmd->chunks_sent on sender shutdown rather than on
-         stream writer death
-
-2005-09-30 02:21  maan
-
-       * afs.c: compute data send barrier on repos and after sucessfully
-         getting the next audio file rather than after stream writer exec
-
-2005-09-30 01:09  maan
-
-       * afs.c, server.c: afs_compute_timeout: return -1 rather than 1
-         when chunk is overdue, otherwise select blocks on bof. server.c:
-         No more need to check the stream writer fd. It is no longer used.
-
-2005-09-29 23:58  maan
-
-       * afs.c: introduce extra check in afs_send_chunk() that tests
-         whether chunk is really due. This was previously broken: Whenever
-         select returned we sent a chunk which might happen too early. Not
-         serious though as the time got corrected automatically during the
-         next call to afs_mainloop()
-
-2005-09-29 23:41  maan
-
-       * afs.c: do not reset audio_format in afs_send_chunk() if eof was
-         encountered as this causes the audio file not to be closed in the
-         following call to afs_mainloop(). Also, invalidate af pointer
-         after closing the audio file
-
-2005-09-29 23:17  maan
-
-       * mp3.c: kill two unused functions
-
-2005-09-29 23:13  maan
-
-       * afs.c, mp3.c, ogg.c: call the new close_audio_file function from
-         afs.c rather than closing the file in the mainloop of the audio
-         format handler
-
-2005-09-29 23:02  maan
-
-       * mp3.c, ogg.c, server.h: new function pointer in struct audio
-         format: close_audio_file
-
-2005-09-29 22:48  maan
-
-       * afs.c, mp3.c, ogg.c: compute mmd->offset in afs.c rather than in
-         the audio format handlers
-
-2005-09-29 12:01  maan
-
-       * FEATURES, README: update docu wrt internal senders
-
-2005-09-29 09:56  maan
-
-       * afs.c: simplify AFS_NOMORE handling
-
-2005-09-29 09:15  maan
-
-       * afs.c, ogg.c: kill three unused variables
-
-2005-09-29 09:13  maan
-
-       * afs.c, mp3.c, ogg.c, server.h: nuke function parameter eof_time
-         which is no longer used
-
-2005-09-29 09:06  maan
-
-       * afs.c: compute eof_barrier from new eof field in struct audio
-         format. Also, do not base computation on stream writer death time
-         but on sender shutdown time
-
-2005-09-29 08:39  maan
-
-       * mp3.c, ogg.c, server.h: new element in struct audio format:
-         eof_tv
-
-2005-09-29 08:22  maan
-
-       * afs.c, mp3.c, ogg.c: move repositioning handling from audio file
-         handlers to afs.c
-
-2005-09-29 07:59  maan
-
-       * mp3.c, ogg.c, server.h: new function pointer in struct audio
-         format: reposition_stream
-
-2005-09-29 07:50  maan
-
-       * afs.c, mp3.c, ogg.c, server.h: remove calculation of next chunk
-         time from format handlers
-
-2005-09-29 07:44  maan
-
-       * afs.c: kill unused variable
-
-2005-09-29 07:42  maan
-
-       * afs.c: do calculation of next chunk time in afs.c rather than in
-         the audio format handlers
-
-2005-09-29 06:30  maan
-
-       * ogg.c: oops, we are not using milliseocnds..
-
-2005-09-29 03:10  maan
-
-       * mp3.c, ogg.c, server.h: new element in struct audio format:
-         chunk_tv that is filled in by the audio format handler
-
-2005-09-29 03:09  maan
-
-       * Makefile.in: add more missing dependencies
-
-2005-09-29 01:29  maan
-
-       * afs.c, mp3.c, ogg.c, server.h: kill send_chunk
-
-2005-09-29 01:24  maan
-
-       * afs.c, mp3.c, ogg.c, server.h: new function pointer in struct
-         audio format: read_chunk which is going to replace send_chunk as
-         the sending functions are better invoked from afs.c
-
-2005-09-29 01:14  maan
-
-       * string.c: typos
-
-2005-09-28 23:48  maan
-
-       * afs.c, http_send.c, mp3.c, ogg.c, send.h, server.c, server.ggo,
-         server.h: include support for the new ortp sender
-
-2005-09-28 23:48  maan
-
-       * net.c: log short writes
-
-2005-09-28 23:45  maan
-
-       * command.c: off by one bug
-
-2005-09-28 23:44  maan
-
-       * recv.c: use enums from new ortp.h
-
-2005-09-28 23:43  maan
-
-       * recv.ggo: change default host from XINGTV.MCAST.NET to the
-         officially unasaigned ip 224.0.1.38 which happens to resolve to
-         DANTZ.MCAST.NET. Change default port to 1500
-
-2005-09-28 23:39  maan
-
-       * Makefile.in, configure.ac: build the ortp sender if libortp was
-         found, add some missing dependencies
-
-2005-09-28 23:37  maan
-
-       * ortp.h, ortp_send.c: the new internal ortp sender
-
-2005-09-28 07:09  maan
-
-       * http_send.c, mp3.c, ogg.c, server.h: new function pointer in
-         struct audio_format: get_header_info. Use it in http_send.c
-         instead of the obsolete send_header function pointer
-
-2005-09-28 06:32  maan
-
-       * ogg.c: save header of starup rather than seeking the file
-
-2005-09-28 01:04  maan
-
-       * afs.c, http_send.c, server.c: more cosmetics
-
-2005-09-28 00:37  maan
-
-       * audiod.c, command.c, http_send.c, mp3.c: cosmetics
-
-2005-09-27 23:57  maan
-
-       * http_send.c: whitespace cleanup
-
-2005-09-27 23:57  maan
-
-       * command.c: comment out debug message
-
-2005-09-27 23:49  maan
-
-       * send.h, server.h: new struct sender_command_data for server
-         callbacks
-
-2005-09-27 23:48  maan
-
-       * server.c: implement callbacks for sender commands, only call send
-         functions if status is on
-
-2005-09-27 23:46  maan
-
-       * ogg.c: comment out noisy debug message
-
-2005-09-27 23:44  maan
-
-       * http_send.c: use new http sender options, implement sender
-         commands allow, deny, on, off, info
-
-2005-09-27 23:41  maan
-
-       * server.ggo: add some http sender options
-
-2005-09-27 23:40  maan
-
-       * command.c: implement new sender command
-
-2005-09-27 23:39  maan
-
-       * Makefile.in: add some more dependencies on server.cmdline.h
-
-2005-09-27 04:32  maan
-
-       * server.h: prototypes for new functions for testing
-         afs_status_flags. No need to pass status flags to the mainloop
-         and send_chunk functions
-
-2005-09-27 04:30  maan
-
-       * server.c: support for internal senders. Use init_tcp_socket from
-         net.c
-
-2005-09-27 04:27  maan
-
-       * para.h: add the two new function prototypes from net.c
-
-2005-09-27 04:26  maan
-
-       * oggdec.c: delay if hole in data was found
-
-2005-09-27 04:25  maan
-
-       * ogg.c: use new functions for testing afs_status_flags, support
-         for internal senders. Nuke initial_chunk logic.
-
-2005-09-27 04:22  maan
-
-       * net.c: pull init_tcp_socket() from server.c. It is also used by
-         http_send.c. New function rec_pattern to be used by both servers
-         and clients.
-
-2005-09-27 04:18  maan
-
-       * mp3.c: use new functions for testing afs_status_flags, support
-         for internal senders
-
-2005-09-27 04:17  maan
-
-       * afs.c: new functions for testing the afs_status_flags, support
-         for internal senders
-
-2005-09-27 04:16  maan
-
-       * Makefile.in: build http_recv, add http_send.o to server objects,
-         add some more header dependencies that were lost
-
-2005-09-27 04:12  maan
-
-       * http.h, http_recv.c, http_recv.ggo, http_send.c, send.h: internal
-         sender and external receiver
-
-2005-09-25 20:53  maan
-
-       * index.html: kernziel is dead
-
-2005-09-23 21:42  maan
-
-       * server.h: remove unused liked_cmd_list
-
-2005-09-22 00:40  maan
-
-       * mysql.c: fix empty stream definitions, ignore errors on remove
-
-2005-09-22 00:22  maan
-
-       * para.h: replace __func__ by __FUNCTION__ as this seems to be
-         supported by a wider class of complilers
-
-2005-09-21 20:07  maan
-
-       * Makefile.in, NEWS, configure.ac: new codename, reset version to
-         cvs
-
-2005-09-21 20:05  maan
-
-       * versions/: paraslash-0.2.4.tar.bz2, paraslash-0.2.4.tar.bz2.asc:
-         paraslash-0.2.4
-
-2005-09-21 20:04  maan
-
-       * NEWS, configure.ac, index.html, scripts/demo-script: paraslash
-         0.2.4
-
-2005-09-21 06:36  maan
-
-       * command.c: cosmetics
-
-2005-09-20 00:32  maan
-
-       * audiod.c: cosmetics
-
-2005-09-20 00:23  maan
-
-       * audiod.c: typo, make max_deviation a constant, no need to check
-         for items if itemnum < 0
-
-2005-09-19 22:12  maan
-
-       * audiod.c: simplify check_stat_line()
-
-2005-09-19 22:11  maan
-
-       * Makefile.in: audiod no longer needs gui_common.o
-
-2005-09-19 22:10  maan
-
-       * gui_common.c, para.h, stat.c: move some functions from
-         gui_common.c to stat.c since they are also needed by audiod.
-
-2005-09-19 20:35  maan
-
-       * gui_common.c: kill unused variable
-
-2005-09-19 20:24  maan
-
-       * command.c, server.c, server.h: logging improvements
-
-2005-09-19 05:17  maan
-
-       * mp3.c: loglevel adjustment
-
-2005-09-19 05:00  maan
-
-       * daemon.c: simplify log_welcome()
-
-2005-09-19 05:00  maan
-
-       * gui_common.c: fix check_buf_for_items()
-
-2005-09-19 04:58  maan
-
-       * server.c: fix logging for higher loglevels
-
-2005-09-18 19:08  maan
-
-       * ogg.c: increase eof time
-
-2005-09-18 00:54  maan
-
-       * gui.c: rename struct args_info to conf
-
-2005-09-18 00:38  maan
-
-       * server.c: simplify parse_config()
-
-2005-09-18 00:32  maan
-
-       * NEWS, afs.c, server.ggo: make announce_time a run-time option
-
-2005-09-18 00:28  maan
-
-       * Makefile.in: add some missing dependencies
-
-2005-09-12 16:48  maan
-
-       * NEWS, README: [no log message]
-
-2005-09-12 15:41  maan
-
-       * command.c: com_si(): report total size of memory allocated with
-         sbrk by malloc, in kbytes.
-
-2005-09-12 15:36  maan
-
-       * NEWS: [no log message]
-
-2005-09-12 15:36  maan
-
-       * configure.ac: check for presence and usability of some more
-         headers
-
-2005-09-12 15:35  maan
-
-       * crypt.c: fix potential memory leak
-
-2005-09-11 22:16  maan
-
-       * para.h: small cleanup and more comments
-
-2005-09-11 22:15  maan
-
-       * server.c: remove old crap from para_log(), typo, do not write to
-         console in daemon mode, close fd 0,1,2 in daemon mode
-
-2005-09-09 06:44  maan
-
-       * oggdec.c: make write_header() static. Cosmetics
-
-2005-09-09 05:28  maan
-
-       * audiod.c: replace global var by local ones
-
-2005-09-09 05:12  maan
-
-       * audiod.c: some more trivial cleanups
-
-2005-09-09 04:56  maan
-
-       * audiod.c: reorder global vars, defines and the like. Trivial.
-
-2005-09-09 04:46  maan
-
-       * audiod.c: remove an unused variable, man cmds[] static
-
-2005-09-09 04:43  maan
-
-       * audiod.c: make functions static where possible
-
-2005-09-09 04:39  maan
-
-       * audiod.c: remove pointless NULL-check in ring_buffer_free()
-
-2005-09-09 04:34  maan
-
-       * audiod.c: fix nasty mem leak. We must not reset s->format too
-         early as it is needed in the filter-free loop
-
-2005-09-08 23:48  maan
-
-       * NEWS: [no log message]
-
-2005-09-08 23:47  maan
-
-       * sdl_gui.c: better layout
-
-2005-09-08 16:15  maan
-
-       * configure.ac: new configure option: --enable-ssldir=path, fix
-         typo
-
-2005-09-06 01:17  maan
-
-       * play.c: use stringification macro to print err msg
-
-2005-09-06 00:55  maan
-
-       * Makefile.in: audiod.o depends on list.h. Add list.h to the
-         tarball
-
-2005-09-06 00:51  maan
-
-       * list.h: Needed by audiod. Copied from the Linux kernel source
-         tree.
-
-2005-09-06 00:50  maan
-
-       * NEWS: [no log message]
-
-2005-09-06 00:49  maan
-
-       * mp3dec.c: comment out debug message
-
-2005-09-06 00:37  maan
-
-       * audiod.c: new command: grab. Close fd 0,1,2 in deamon mode
-
-2005-09-06 00:32  maan
-
-       * audioc.ggo: new option: --bufsize
-
-2005-09-06 00:32  maan
-
-       * audioc.c: new option: --bufsize. Use select() rather than plain
-         read/write to avoid blocking writes writes when there is space
-         left in the buffer
-
-2005-09-06 00:29  maan
-
-       * client.c: only check the first data buffer for the
-         AWAITING_DATA_MSG. Always use full buffersize for recv
-
-2005-09-06 00:27  maan
-
-       * net.c: no need to waste one byte
-
-2005-09-04 11:05  maan
-
-       * client.ggo: add typestr to options
-
-2005-09-04 11:05  maan
-
-       * Makefile.in: use --unamed-opts only if neccessary
-
-2005-09-02 14:43  maan
-
-       * audiod.c: do_filter_io(): only add return value of read() to
-         loaded bytes if it is positive
-
-2005-09-02 14:41  maan
-
-       * index.html: typo
-
-2005-09-01 20:14  maan
-
-       * Makefile.in, NEWS, configure.ac: new codename, reset version to
-         cvs
-
-2005-09-01 20:12  maan
-
-       * versions/: paraslash-0.2.3.tar.bz2, paraslash-0.2.3.tar.bz2.asc:
-         paraslash-0.2.3
-
-2005-09-01 20:11  maan
-
-       * NEWS, configure.ac, index.html, scripts/demo-script: paraslash
-         0.2.3
-
-2005-09-01 19:49  maan
-
-       * NEWS: [no log message]
-
-2005-09-01 14:14  maan
-
-       * audiod.c: typo
-
-2005-09-01 13:44  maan
-
-       * NEWS, audiod.c, audiod.ggo: new audiod option: --stream_delay,
-         used if new macro START_TIME() was given for stream_write_cmd.
-
-2005-09-01 13:43  maan
-
-       * compress.ggo: use maximal volume as default
-
-2005-09-01 03:04  maan
-
-       * NEWS: [no log message]
-
-2005-09-01 02:09  maan
-
-       * index.html: add list of releases to top of page
-
-2005-09-01 01:04  maan
-
-       * Makefile.in: make xxx.cmdline.o always the first prerequisite,
-         use multiple targets in gengetopt rule
-
-2005-09-01 00:33  maan
-
-       * Makefile.in, play.c, play.ggo: command line options for para_play
-
-2005-08-31 22:06  maan
-
-       * FEATURES, README: mention para_compress
-
-2005-08-31 21:49  maan
-
-       * NEWS, audiod.c, audiod.ggo: better syntax for stream/filter
-         commands
-
-2005-08-31 18:42  maan
-
-       * CREDITS, Makefile.in, NEWS: add para_compress
-
-2005-08-31 18:41  maan
-
-       * compress.c, compress.ggo: a dynamic range compressor, derived
-         from AudioCompress-1.5.2
-
-2005-08-31 18:40  maan
-
-       * recv.c: save header, delay sending until first data packet
-         _after_ header arrives
-
-2005-08-31 18:38  maan
-
-       * play.c: make it understand wave headers, use plug_swmix for
-         snd_pcm_open()
-
-2005-08-29 06:49  maan
-
-       * net.c: do not use fprintf in net.c, whitespace cleanup
-
-2005-08-29 04:09  maan
-
-       * mysql.c: whitespace cleanup
-
-2005-08-26 13:51  maan
-
-       * mysql.c: tell mysql version on init
-
-2005-08-26 03:55  maan
-
-       * play.c: do not exit on buffer underruns, reduce sleep time on
-         -EAGAIN
-
-2005-08-26 03:54  maan
-
-       * audiod.c: also kill filters in kill_decoder()
-
-2005-08-26 02:32  maan
-
-       * FEATURES, Makefile.in, NEWS, README, configure.ac: include
-         para_play
-
-2005-08-26 02:31  maan
-
-       * play.c: a tiny alsa player
-
-2005-08-26 00:10  maan
-
-       * NEWS, audiod.c, audiod.ggo: implement filtering inside audiod
-
-2005-08-25 01:11  maan
-
-       * NEWS, mysql.c, stat.c: cosmetics
-
-2005-08-25 01:11  maan
-
-       * Makefile.in: remove funny characters around codename in version
-         string
-
-2005-08-24 11:27  maan
-
-       * afs.c: whitespace clenaup ;)
-
-2005-08-19 22:08  maan
-
-       * signal.c: add GPL header
-
-2005-08-19 21:32  maan
-
-       * scripts/demo-script: make it download paraslash.0.2.0
-
-2005-08-19 10:03  maan
-
-       * client.conf.sample, fade.conf.sample, sdl_gui.conf.sample,
-         server.conf.sample: these are both outdated and really pointless.
-         Read the nice online help instead
-
-2005-08-19 06:30  maan
-
-       * Makefile.in, NEWS, configure.ac: new codename, reset version to
-         cvs
-
-2005-08-19 06:28  maan
-
-       * versions/: paraslash-0.2.2.tar.bz2, paraslash-0.2.2.tar.bz2.asc:
-         paraslash-0.2.2
-
-2005-08-19 06:24  maan
-
-       * Makefile.in, NEWS, configure.ac: paraslash 0.2.2
-
-2005-08-19 02:24  maan
-
-       * mysql.c: cosmetics
-
-2005-08-19 02:16  maan
-
-       * NEWS, mysql.c: new command snp (set numplayed)
-
-2005-08-19 01:57  maan
-
-       * mysql.c: cosmetics
-
-2005-08-19 01:50  maan
-
-       * mysql.c: com_mv(): also update the name in the dir-table
-
-2005-08-19 00:57  maan
-
-       * net.c:
-         work around a gcc-4.1 bug (?) that caused send_cred_buffer() to
-         send only zeros. With this workaround, para_audioc works again.
-
-2005-08-18 07:44  maan
-
-       * scripts/demo-script: use -N option for wget to overwrite any
-         tarballs downloaded earlier
-
-2005-08-18 05:37  maan
-
-       * client.c: whitespace cleanup
-
-2005-08-18 04:01  maan
-
-       * INSTALL: typo
-
-2005-08-18 03:59  maan
-
-       * INSTALL: correct instructions for manual streaming
-
-2005-08-18 03:38  maan
-
-       * exec.c: fix fd leak in para_exec() just introduced
-
-2005-08-18 03:22  maan
-
-       * exec.c: trivial simplifications
-
-2005-08-18 02:56  maan
-
-       * exec.c: whitespace cleanup
-
-2005-08-18 01:29  maan
-
-       * Makefile.in, NEWS, dbadm.c, exec.c, fade.c, gui.c, mysql.c,
-         para.h: change all remaining users of popen_*() to use para_exec
-         instead. nuke popen_* functions from exec.c
-
-2005-08-17 04:37  maan
-
-       * NEWS, mysql.c: add command ne (new entry)
-
-2005-08-17 04:33  maan
-
-       * README: [no log message]
-
-2005-08-17 03:40  maan
-
-       * mysql.c, para.h, string.c: new mysql command: mv (rename
-         entries). This needs another helper, para_dirname(), which was
-         added to string.c. Use const attribute for para_dirname() and add
-         it to para_basename too.
-
-2005-08-17 02:13  maan
-
-       * audiod.c, client.c, dbadm.c, oggdec.c, server.c: cosmetics
-
-2005-08-17 01:35  maan
-
-       * NEWS, mysql.c: new command: rm to remove entries from the
-         database
-
-2005-08-17 01:35  maan
-
-       * command.c: cosmetics
-
-2005-08-17 00:41  maan
-
-       * skencil/overview.sk: change 0.2.0 to 0.2.x
-
-2005-08-17 00:37  maan
-
-       * fade.c: cosmetics
-
-2005-08-17 00:35  maan
-
-       * string.c, fade.c: whitespace cleanup
-
-2005-08-17 00:24  maan
-
-       * audioc.c, audiod.c, client.c, daemon.c, fade.c, gui.c, para.h,
-         recv.c, sdl_gui.c, send.c, server.c, slider.c: rename clog to
-         para_log
-
-2005-08-17 00:11  maan
-
-       * audiod.c, gui.c, para.h, server.c, signal.c: simplify
-         para_signal_init()
-
-2005-08-17 00:01  maan
-
-       * afs.c, audiod.c, client.c, command.c, daemon.c, dopey.c, fade.c,
-         mp3.c, mysql.c, net.c, ogg.c, recv.c, send.c, server.c, signal.c,
-         stat.c, string.c: nuke superflous __func__
-
-2005-08-16 23:31  maan
-
-       * krell.c: whitespace cleanup, change email address
-
-2005-08-16 22:47  maan
-
-       * NEWS, afs.c, audiod.c, client.c, command.c, daemon.c, dopey.c,
-         fade.c, gui.c, mp3.c, mysql.c, net.c, ogg.c, para.h, recv.c,
-         send.c, server.c, signal.c, stat.c, string.c: new log macros that
-         do not require __func__ each time and can be optimized away
-         easily
-
-2005-08-16 21:07  maan
-
-       * para.h: whitespace cleanup
-
-2005-08-16 21:06  maan
-
-       * audiod.c, gui.c, para.h, server.c: nuke loglevel VERBOSE
-
-2005-08-16 21:06  maan
-
-       * Makefile.in: use -O3 and add -Wuninitialized and
-         -Wredundant-decls
-
-2005-08-16 20:58  maan
-
-       * scripts/demo-script: make it download paraslash-0.2.1
-
-2005-08-16 20:48  maan
-
-       * audiod.c: stream readers do not read from stdin
-
-2005-08-16 20:45  maan
-
-       * exec.c: serious thinko. Close the right fds in para_exec(). This
-         was obviously incorrect before. Strange that only gcc 4 produced
-         a non-working audiod..
-
-2005-08-16 20:36  maan
-
-       * client.c, command.c, crypt.c: fix some signedness issues
-
-2005-08-15 23:28  maan
-
-       * Makefile.in, NEWS, configure.ac: new codename, reset version to
-         cvs
-
-2005-08-15 23:09  maan
-
-       * versions/: paraslash-0.2.1.tar.bz2, paraslash-0.2.1.tar.bz2.asc:
-         paraslash-0.2.1
-
-2005-08-15 23:04  maan
-
-       * NEWS, configure.ac: paraslash 0.2.1
-
-2005-08-15 22:35  maan
-
-       * Makefile.in: older versions of libreadline and libssl come with
-         header files that produce lots of warnings about redundant
-         redeclarations. Deactivate -Wredundant-decls for now
-
-2005-08-15 22:23  maan
-
-       * audiod.c: make gcc happy
-
-2005-08-15 07:47  maan
-
-       * mp3.c: simplify mp3_seek_next_header(), use para_fread() instead
-         of plain fread() and check the retval. Nuke unused id3 genre.
-
-2005-08-14 20:15  maan
-
-       * audiod.c: fix serious memory leak
-
-2005-08-13 21:45  maan
-
-       * audiod.c: kill decoders and close status pipe in clean_exit()
-
-2005-08-13 21:43  maan
-
-       * client.c, crypt.c, crypt.h: remove some redundant ssl includes
-
-2005-08-13 20:36  maan
-
-       * command.c: kill extra newline
-
-2005-08-13 04:32  maan
-
-       * audiod.c, command.c: oops, the previous whitespace cleanup was
-         only for slider.c. Revert to previous version.
-
-2005-08-13 04:27  maan
-
-       * audiod.c, command.c, slider.c: whitespace cleanup slider.c
-
-2005-08-10 22:08  maan
-
-       * NEWS, audiod.c: nuke hup command. It is both pointless and
-         non-trivial to get it right
-
-2005-08-10 11:14  maan
-
-       * NEWS: [no log message]
-
-2005-08-10 03:23  maan
-
-       * gui_theme.c: whitespace cleanup
-
-2005-08-10 03:21  maan
-
-       * NEWS, audiod.c, command.c, daemon.c, gui_theme.c, para.h,
-         server.c, server.h, stat.c, string.c: new status item:
-         audiod_uptime. Reduce size of mtime string, reduce number of
-         audiod slots to 5, redirect stdout of audiod stream writer to
-         /dev/null
-
-2005-08-09 23:30  maan
-
-       * stat.c: whitespace cleanup
-
-2005-08-09 23:29  maan
-
-       * Makefile.in: maintainer-clean: remove tar.bz files
-
-2005-08-09 23:16  maan
-
-       * Makefile.in, configure.ac: deactivate -O and -Wuninitialized, add
-         crypt.h to the set of headers shipped in the tarball, use a macro
-         from the autoconf archive for detecting openssl.
-
-2005-08-09 08:45  maan
-
-       * FEATURES, README: [no log message]
-
-2005-08-09 07:15  maan
-
-       * INSTALL: mention --stream_write_cmd
-
-2005-08-09 06:21  maan
-
-       * mp3dec.c: whitespace cleanup
-
-2005-08-08 02:18  maan
-
-       * afs.c, command.c, mp3.c, ogg.c: fix some (hopefully all) format
-         string mismatches
-
-2005-08-08 02:04  maan
-
-       * audiod.c, client.c, command.c, fade.c, gui.c, net.c, para.h,
-         server.c, string.c: nuke some redundant redeclarations
-
-2005-08-08 02:04  maan
-
-       * Makefile.in: add -Wredundant-decls to CPPFLAGS
-
-2005-08-08 01:54  maan
-
-       * client.c, dbadm.c, sdl_gui.c, server.c: fix some missing voids.
-         Harmless
-
-2005-08-08 01:54  maan
-
-       * Makefile.in: add -Wstrict-prototypes
-
-2005-08-08 01:46  maan
-
-       * afs.c, audiod.c, command.c, dbadm.c, fade.c, gui.c, mysql.c,
-         net.c, ogg.c, string.c: fix some potential uses of uninitialized
-         vars. Nothing serious I think
-
-2005-08-08 01:38  maan
-
-       * Makefile.in: make gcc a bit more anal: turn on warnings for
-         uninitialized vars
-
-2005-08-07 23:39  maan
-
-       * NEWS: [no log message]
-
-2005-08-07 23:34  maan
-
-       * sdl_gui.c, sdl_gui.ggo: new options: stat_cmd, pic_cmd, adapt to
-         new syntax of para_open_audiod_pipe(), use para_exec instead of
-         popen, add typestrings to options
-
-2005-08-07 23:32  maan
-
-       * gui.c, gui.ggo, para.h: new option: stat_cmd, adapt to new syntax
-         of para_open_audiod_pipe()
-
-2005-08-07 23:30  maan
-
-       * gui_common.c: let it take the command as an argument, use
-         para_exec instead of popen
-
-2005-08-07 23:29  maan
-
-       * audioc.ggo: oops, this option belongs to audiod
-
-2005-08-07 22:11  maan
-
-       * NEWS, audioc.ggo, audiod.c, audiod.ggo, server.ggo: implement
-         --user option also for audiod
-
-2005-08-07 21:50  maan
-
-       * NEWS, daemon.c, para.h, server.c, server.ggo: new option --user
-         to switch to the given user when invoked as root
-
-2005-08-07 21:48  maan
-
-       * mysql.c: do not log (null) as the username although it is
-         perfectly OK to pass a NULL pointer to mysql_real_connect()
-
-2005-08-07 20:15  maan
-
-       * daemon.c: whitespace cleanup
-
-2005-08-07 09:02  maan
-
-       * 1.0: [no log message]
-
-2005-08-07 09:02  maan
-
-       * dopey.c: too dopey to get dopey right: avoid theoretical double
-         free bug that can only bite when given a invalid dopey_dir
-
-2005-08-07 07:26  maan
-
-       * crypt.c: add GPL header
-
-2005-08-07 07:11  maan
-
-       * client.c, command.c: kill old encrypt/decrypt functions that used
-         fork and exec. Replace it by new functions from crypt.c. This
-         should be much faster and, more importantly, fully transparent,
-         i.e. para_client-0.2.0 can still connect to newer versions of
-         para_server and vice versa, even when using 0.1.x keys.
-
-2005-08-07 07:10  maan
-
-       * NEWS: [no log message]
-
-2005-08-07 07:02  maan
-
-       * configure.ac: cleanup, make it check for the libssl lib rather
-         than for the openssl command line utility
-
-2005-08-07 07:00  maan
-
-       * Makefile.in: major cleanup, link crypt.o and the ssl libraries to
-         server and client
-
-2005-08-07 06:56  maan
-
-       * mp3.c: kill noisy debug message
-
-2005-08-07 06:56  maan
-
-       * crypt.c, crypt.h: rsa encrypt/decrypt routines
-
-2005-08-07 06:52  maan
-
-       * scripts/demo-script: make it download paraslash-0.2.0 instead of
-         paraslash-cvs
-
-2005-08-06 21:11  maan
-
-       * skencil/overview.sk: replace mp3 by pcm
-
-2005-08-06 21:01  maan
-
-       * index.html: another typo
-
-2005-08-06 20:55  maan
-
-       * index.html: provide quick-links at top of page
-
-2005-08-06 20:20  maan
-
-       * index.html: typo
-
-2005-08-06 20:06  maan
-
-       * index.html: announce the overview and provide a link to the pdf
-         file
-
-2005-08-06 19:55  maan
-
-       * skencil/overview.sk: make it a bit smaller since xpdf does not
-         show the upper part of the sketch
-
-2005-08-06 19:31  maan
-
-       * skencil/overview.sk: a skencil file containing a sketch which
-         illustrates how the pieces of paraslash work together
-
-2005-08-06 18:58  maan
-
-       * index.html: update live demo to use 0.2.0
-
-2005-08-06 18:58  maan
-
-       * Makefile.in, NEWS, configure.ac: change codename, reset version
-         to cvs
-
-2005-08-06 18:31  maan
-
-       * versions/: paraslash-0.2.0.tar.bz2, paraslash-0.2.0.tar.bz2.asc:
-         for the history
-
-2005-08-06 18:24  maan
-
-       * NEWS, configure.ac: paraslash-0.2.0
-
-2005-08-05 21:37  maan
-
-       * Makefile.in: oggdec needs to be linked also against libvorbis on
-         some systems
-
-2005-08-03 20:48  maan
-
-       * audiod.c: kill noisy debug message
-
-2005-08-03 19:59  maan
-
-       * audiod.c: fix self-correcting time display
-
-2005-08-03 06:18  maan
-
-       * pics/screenshots/loglevel1-2005-03-23.txt,
-         versions/paraslash-0.0.99.tgz, versions/paraslash-0.0.99.tgz.asc,
-         versions/paraslash-0.1.0.tgz, versions/paraslash-0.1.0.tgz.asc,
-         versions/paraslash-0.1.1.tgz, versions/paraslash-0.1.1.tgz.asc,
-         versions/paraslash-0.1.2.tgz, versions/paraslash-0.1.2.tgz.asc,
-         versions/paraslash-0.1.3.tgz, versions/paraslash-0.1.3.tgz.asc,
-         versions/paraslash-0.1.4.tgz, versions/paraslash-0.1.4.tgz.asc,
-         versions/paraslash-0.1.5.tgz, versions/paraslash-0.1.5.tgz.asc,
-         versions/paraslash-0.1.6.tgz, versions/paraslash-0.1.6.tgz.asc,
-         versions/paraslash-0.1.7.tgz, versions/paraslash-0.1.7.tgz.asc:
-         just for the history
-
-2005-08-03 06:03  maan
-
-       * mp3.c: make it work again for vbr, whitespace cleanup
-
-2005-08-02 18:47  maan
-
-       * mp3.c: fix length computation (fixes Loser_Pils problem)
-
-2005-08-02 18:43  maan
-
-       * para.h: add prototype for tv_divide()
-
-2005-08-02 18:39  maan
-
-       * recv.c: rename bytes_written to header_status, add a comment
-
-2005-08-02 05:15  maan
-
-       * command.c: also before calling the command handler, mention
-         usename when logging with loglevel NOTICE
-
-2005-08-02 03:25  maan
-
-       * audiod.c, client.c, fade.c, server.c, string.c: activate format
-         string checks
-
-2005-08-02 03:25  maan
-
-       * daemon.c: typo
-
-2005-08-02 03:02  maan
-
-       * server.h: kill AFS_REREAD_DB_INFO. Refreshing the database info
-         is done from within the mysql commands that change the info.
-
-2005-08-02 03:00  maan
-
-       * command.c: only send error message to client if the cause of the
-         error was different from E_SEND
-
-2005-08-02 02:58  maan
-
-       * audiod.ggo, mp3.c, ogg.c, recv.c, recv.ggo, send.c, send.ggo,
-         server.ggo, audiod.c: simpler syntax for para_recv and para_send
-
-2005-08-02 02:54  maan
-
-       * afs.c: increase SW_RESTART_TIME and ANNOUNCE_TIME
-
-2005-08-02 01:06  maan
-
-       * send.c: simplify stupid control flow in do_io()
-
-2005-08-01 23:46  maan
-
-       * command.c: com_sc(): optional argument for iteration count
-
-2005-08-01 22:58  maan
-
-       * recv.c: make ogg work again
-
-2005-08-01 20:52  maan
-
-       * recv.ggo: nuke outfile option
-
-2005-08-01 20:51  maan
-
-       * recv.c: always write to stdout
-
-2005-08-01 20:39  maan
-
-       * NEWS: whitespace cleanup
-
-2005-08-01 19:42  maan
-
-       * send.c: read a full initial chunk, not just the header length and
-         send it out to ortp in little small pieces.
-
-2005-08-01 19:41  maan
-
-       * recv.c: fix return value, better timing
-
-2005-08-01 19:37  maan
-
-       * afs.c, command.c, mp3.c, server.h, ogg.c: introduce time barriers
-         for start streaming/exec the stream writer, new status flag W
-         (stream writer running). Make ogg work with really nasty vbr
-         files
-
-2005-08-01 19:32  maan
-
-       * index.html: announce live stream, anonymous cvs access and
-         nightly snapshots
-
-2005-08-01 19:15  maan
-
-       * scripts/demo-script: script to download and install a demo-client
-         to retrieve the stream from www.paraslash.org
-
-2005-08-01 04:25  maan
-
-       * time.c: whitespace cleanup
-
-2005-08-01 04:24  maan
-
-       * time.c: Use const where aprropriate in tv_diff(), really
-
-2005-08-01 03:34  maan
-
-       * para.h, time.c: new function ms2tv, convert milliseconds to
-         struct timeval. Use const where aprropriate in tv_diff()
-
-2005-07-30 05:34  maan
-
-       * mysql.c: cosmetics
-
-2005-07-30 05:26  maan
-
-       * gui.ggo: nuke obsolete stream-related command line options that
-         have been gone long ago
-
-2005-07-30 05:26  maan
-
-       * gui.c: replace help text as ':' is not mapped by default
-
-2005-07-30 05:16  maan
-
-       * client.c, client.ggo: new option: user
-
-2005-07-29 01:54  maan
-
-       * sdl_gui.c, afs.c: whitespace cleanup
-
-2005-07-29 01:51  maan
-
-       * command.c: whitespace cleanup
-
-2005-07-29 01:44  maan
-
-       * mysql.c: whitespace cleanup
-
-2005-07-29 01:37  maan
-
-       * audiod.c, gui.c: whitespace cleanup
-
-2005-07-29 01:33  maan
-
-       * server.c: whitespace cleanup
-
-2005-07-29 01:31  maan
-
-       * audiod.c: the test diff < max_diff was broken. Also, fix empty
-         line in stat output
-
-2005-07-29 01:29  maan
-
-       * para.h, time.c: make tv_convex_combination() accept also negative
-         coefficients
-
-2005-07-27 21:42  maan
-
-       * mp3.c: still one more unused variable
-
-2005-07-27 21:35  maan
-
-       * mp3.c: nuke another unused variable
-
-2005-07-27 21:30  maan
-
-       * mp3.c: simplify write_chunk()
-
-2005-07-27 21:23  maan
-
-       * mp3.c: nuke two unused variables
-
-2005-07-27 21:20  maan
-
-       * mp3.c: make it work for bitrates different from 44100, some
-         trivial cleanups
-
-2005-07-25 22:37  maan
-
-       * Makefile.in, NEWS: switch from gzip to bzip2
-
-2005-07-25 22:08  maan
-
-       * Makefile.in: remove some cruft that is not needed for nomal
-         compilation, so it's better done from private scripts
-
-2005-07-25 21:21  maan
-
-       * afs.c: make gcc 2.95 happy
-
-2005-07-25 20:32  maan
-
-       * command.c: cosmetics
-
-2005-07-25 19:39  maan
-
-       * PUBLIC_KEY: old public key, but added uid maan@systemlinux.org
-         and maan@paraslash.org
-
-2005-07-25 03:32  maan
-
-       * recv.ggo, server.ggo: delete some unused options
-
-2005-07-25 00:08  maan
-
-       * Makefile.in, afs.c, audioc.c, audiod.c, client.c, client.ggo,
-         fade.c, fade.ggo, gui.c, gui.ggo, mp3.c, ogg.c, para.h,
-         sdl_gui.c, sdl_gui.ggo, server.c, server.ggo, slider.c, string.c:
-         do not rely on environment HOME and LOGNAME. Use getuid() and
-         entries from /etc/passwd instead
-
-2005-07-24 21:21  maan
-
-       * recv.c: nuke unused have_header
-
-2005-07-24 21:19  maan
-
-       * ogg.c: fix pause, nuke initial_chunks
-
-2005-07-24 21:15  maan
-
-       * exec.c: para_exec: close all unneeded fds
-
-2005-07-24 21:14  maan
-
-       * command.c: thinko
-
-2005-07-24 21:14  maan
-
-       * audiod.c: increase max time deviation for fallback to server
-         stream time to 5 seconds, other smallish cleanups
-
-2005-07-24 21:11  maan
-
-       * afs.c: introduce announce delay when switching from pause to play
-
-2005-07-22 06:20  maan
-
-       * audiod.c, send.c: cosmetics
-
-2005-07-22 04:07  maan
-
-       * audiod.c, client.c, fade.c, gui.c, recv.c, send.c, server.c,
-         string.c: add __attribute__ format for printf-like functions
-         (commented out by now) and fix some mismatches
-
-2005-07-22 03:13  maan
-
-       * audiod.c: loglevel adjustments
-
-2005-07-22 01:09  maan
-
-       * stat.c: fix removal of stat clients
-
-2005-07-22 01:08  maan
-
-       * audiod.c: dup stderr of stream writer to /dev/null
-
-2005-07-21 22:52  maan
-
-       * INSTALL, audiod.c: rename standby to sb, it is much easier to
-         type
-
-2005-07-21 22:15  maan
-
-       * audiod.c: cosmetics
-
-2005-07-21 05:03  maan
-
-       * command.c: fix integer overflow in frame math for large mp3
-         files, print new status item current_time in com_stat.
-
-2005-07-21 05:02  maan
-
-       * mp3.c: fix integer overflow in frame math for large mp3 files
-
-2005-07-21 01:36  maan
-
-       * audiod.c: use new status item current_time to sync time with
-         server, so the stream_start status item info can also be used if
-         server and audiod clock differ
-
-2005-07-21 01:32  maan
-
-       * para.h, stat.c, time.c: new status item: current_time. New
-         functions for manipulating struct timeval
-
-2005-07-18 21:04  maan
-
-       * audiod.c: cosmetics
-
-2005-07-18 21:04  maan
-
-       * ogg.c: simplify get_chunk_size(), moderate debug logging
-
-2005-07-17 05:55  maan
-
-       * time.c: tv_diff(): compute a - b instead just returning -1 if a >
-         b
-
-2005-07-17 03:04  maan
-
-       * exec.c: remove some unused functions
-
-2005-07-17 02:43  maan
-
-       * time.c: this change should not make any difference, but it looks
-         saner this way
-
-2005-07-17 02:41  maan
-
-       * mp3.c: add an error message if file was not recognized as an mp3
-         file
-
-2005-07-17 02:40  maan
-
-       * exec.c: unused label
-
-2005-07-17 02:39  maan
-
-       * ogg.c: okay, the previous version did not recognize any ogg
-         files, valid or not. Fixed.
-
-2005-07-16 19:18  maan
-
-       * ogg.c: move initialization of ogg stuff to the beginning of the
-         function. That fixes a segfault for (non-ogg) files, when that
-         stuff got freed without being initialized
-
-2005-07-16 18:48  maan
-
-       * recv.c: nuke prebuffer code. Prebuffering should be done in the
-         player only
-
-2005-07-16 18:20  maan
-
-       * ogg.c: fix fake errors on eof, rename bytes to loaded_bytes and
-         make it global
-
-2005-07-16 17:42  maan
-
-       * audiod.c, send.c: signedness issues
-
-2005-07-16 17:38  maan
-
-       * afs.c, mp3.c: move log message from mp3.c to afs.c as it is
-         generic
-
-2005-07-16 17:33  maan
-
-       * net.c: signedness issues
-
-2005-07-15 04:27  maan
-
-       * audiod.c, gui_theme.c, para.h, sdl_gui.c, stat.c: replace
-         SI_DECODER_OUTPUT by SI_PLAY_TIME
-
-2005-07-15 04:09  maan
-
-       * gui.c: kill debug message
-
-2005-07-15 04:02  maan
-
-       * audiod.c: kill all decoders if server connection breaks down
-
-2005-07-15 03:45  maan
-
-       * NEWS: [no log message]
-
-2005-07-15 03:44  maan
-
-       * para.h, stat.c: typo
-
-2005-07-15 03:37  maan
-
-       * audiod.c: new function close_stat_pipe() that basically does
-         everything that com_off previously did. Besides from com_off it
-         is also called if connection to para_server breaks down
-
-2005-07-15 02:26  maan
-
-       * audiod.c: use quadratic growth rather than exponential growth for
-         penalty timings
-
-2005-07-15 01:46  maan
-
-       * command.c: fix com_ff
-
-2005-07-15 01:02  maan
-
-       * mp3.c: fix time display after pause
-
-2005-07-15 00:23  maan
-
-       * mp3.c: fix more potential segfaults (that actually never
-         triggered, but anyway)
-
-2005-07-15 00:11  maan
-
-       * mp3.c: fix computation of bitrate and frequency. Nuke
-         header_is_valid, it does not work for vbr. Fix potential segfault
-         in header_frequency()
-
-2005-07-14 23:14  maan
-
-       * audiod.c: simplify closing of stream fds. They are all closed
-         from one central function now. This fixes a problem when paused:
-         the write fd was not closed until the timeout was reached. With
-         this patch it is closed immediately
-
-2005-07-14 20:06  maan
-
-       * mp3.c: reset header_isvalid and id3_isvalid. Use a valid header
-         for computing the freq rather than the first header we can find
-
-2005-07-14 20:04  maan
-
-       * audiod.ggo: we do not read the HOSTNAME ENV anymore
-
-2005-07-14 20:03  maan
-
-       * para.h: make para_mkstemp public
-
-2005-07-14 20:02  maan
-
-       * mysql.c: cosmetics
-
-2005-07-14 19:55  maan
-
-       * mysql.c: do not leak fds on errors
-
-2005-07-14 19:18  maan
-
-       * mysql.c: cosmetics
-
-2005-07-14 19:12  maan
-
-       * mysql.c: com_upd: use para_mkstemp() for creating the infile in
-         /tmp
-
-2005-07-14 19:11  maan
-
-       * string.c: new function para_mkstemp()
-
-2005-07-14 18:30  maan
-
-       * string.c: add a comment for usage of para_tmpname()
-
-2005-07-14 18:21  maan
-
-       * afs.c: do not fall back to /tmp if $HOME is unset for security
-         reasons. Just bail out
-
-2005-07-14 17:59  maan
-
-       * net.c: delete some old code that was commented out anyway
-
-2005-07-14 17:55  maan
-
-       * server.ggo: add documentation for command line macros to -h
-         output
-
-2005-07-14 17:35  maan
-
-       * audioc.c: use para_hostname instead of getenv()
-
-2005-07-14 17:06  maan
-
-       * mp3dec.c: fix decoding of mono mp3s
-
-2005-07-14 06:43  maan
-
-       * command.c: increase event counter _after_ command has finished
-
-2005-07-14 06:13  maan
-
-       * mp3.c: write info string only at begin of file rather than on
-         each frame. This made an old bug show up: The header frequency
-         display was always wrong for the first time that info was sent by
-         com_stat.
-
-2005-07-14 05:21  maan
-
-       * mp3.c: fix computation of average bitrate for vbr mp3s
-
-2005-07-14 04:21  maan
-
-       * mysql.c: use para_tmpname instead of just the pid
-
-2005-07-13 19:45  maan
-
-       * afs.c: missing __func__, incorrect comment
-
-2005-07-13 09:21  maan
-
-       * audiod.c, gui_common.c, para.h: move open_stat_pipe from
-         gui_common.c to audiod.c and change it to use para_exec() instead
-         of obsolete popen_read_client_cmdline(). Nuke s->err_fd. New
-         functions check_reader() and check_writer(). They return whether
-         we should include the corresponding fd in the fd set for
-         select().
-
-2005-07-13 09:17  maan
-
-       * audioc.c: wrong indent
-
-2005-07-13 09:15  maan
-
-       * exec.c: remove an obsolete function
-
-2005-07-12 18:27  maan
-
-       * mp3dec.c: write wav header, switch to little endian
-
-2005-07-12 17:49  maan
-
-       * mp3dec.c: simplify read_chunk()
-
-2005-07-09 19:43  maan
-
-       * audiod.c: dec_out is no longer a good name
-
-2005-07-09 19:41  maan
-
-       * audiod.c: nuke decoder_output code
-
-2005-07-09 19:36  maan
-
-       * ogg.c: double initial chunks for mono
-
-2005-07-09 18:19  maan
-
-       * send.c: fix serious(?) off-by-one in header save_ov_headers()
-
-2005-07-09 18:17  maan
-
-       * ogg.c: simplify mainloop, introduce initial_chunks, number of
-         chunks that are sent immediately
-
-2005-07-09 18:13  maan
-
-       * audiod.c: fix time display if paused. Clear stat items when
-         stopped, dump audiod status in mainloop
-
-2005-07-09 18:13  maan
-
-       * para.h, stat.c: new function: dump_empty_status. To be called
-         when current status is known to be invalid
-
-2005-07-09 18:09  maan
-
-       * afs.c: introduce extra delay to announce the stream
-
-2005-07-09 01:26  maan
-
-       * afs.c, audiod.c, command.c, mp3.c, ogg.c, para.h, server.h,
-         stat.c: introduce mmd->stream_start as a fallback time source for
-         audiod when it starts its decoder in the middle of a audio file
-
-2005-07-08 04:11  maan
-
-       * net.c: use uname() to get the hostname instead of
-         getenv("HOSTNAME")
-
-2005-07-08 03:46  maan
-
-       * afs.c: use para_hostname() instead of getenv()
-
-2005-07-08 03:31  maan
-
-       * ogg.c: comment out noisy debug messages
-
-2005-07-08 03:29  maan
-
-       * ogg.c: use para_hostname() instead of getenv()
-
-2005-07-08 03:23  maan
-
-       * audiod.c: use para_hostname() instead of getenv()
-
-2005-07-08 03:12  maan
-
-       * oggdec.c: nuke time display as time is now computed by audiod
-
-2005-07-08 03:10  maan
-
-       * mp3dec.c: nuke print_status() as time is now computed by audiod
-
-2005-07-08 03:06  maan
-
-       * audiod.c: use para_malloc instead of malloc
-
-2005-07-08 02:38  maan
-
-       * stat.c: fix memory leak
-
-2005-07-08 01:53  maan
-
-       * audiod.c: use para_hostname instead of getenv
-
-2005-07-08 01:41  maan
-
-       * gui.c: use make_message instead of sprintf
-
-2005-07-07 03:38  maan
-
-       * afs.c, mp3.c, ogg.c, server.h: change handling of repositioning
-         the stream. The corresponding timing is now done from within the
-         audio format handler
-
-2005-07-07 03:31  maan
-
-       * net.c: cosmetics
-
-2005-07-07 03:27  maan
-
-       * command.c: do not mess around with offset in command.c The offset
-         is better computed from the audio format handler
-
-2005-07-07 03:24  maan
-
-       * audioc.c: check config file
-
-2005-07-07 03:18  maan
-
-       * audiod.c: record start time of both reader and writer. Start
-         reader again even if writer exists
-
-2005-07-07 03:17  maan
-
-       * NEWS: [no log message]
-
-2005-07-07 03:16  maan
-
-       * Makefile.in: clean: remove also manual.txt
-
-2005-07-03 22:50  maan
-
-       * audiod.c: keep track of number of stat clients and refuse to
-         accept more stat connections if limit is reached
-
-2005-07-03 22:18  maan
-
-       * para.h, stat.c: client_add and() dump_stat_line() now return the
-         number of connected clients.
-
-2005-07-03 22:17  maan
-
-       * net.c: return positive value on success. Let's hope that this
-         does not break anything..
-
-2005-07-03 22:11  maan
-
-       * audiod.c: trivial cleanup, loglevel adjustments
-
-2005-07-03 20:51  maan
-
-       * audiod.c: close fd if ring_buffer_dump failed
-
-2005-07-03 20:33  maan
-
-       * audiod.c: oops. In handle_connect(), close fd only for invalid
-         commands as it is closed by each command handler if neccessary.
-
-2005-07-03 19:02  maan
-
-       * audiod.c: serious(?) typo. Nuke unused function
-
-2005-07-03 18:48  maan
-
-       * audiod.c: fix memory leak
-
-2005-07-03 18:41  maan
-
-       * audiod.c: rewrite audiod_status_string() to use the decoder that
-         was last started for time display rather than current_decoder
-         which is sent by server and might contain the new docoder while
-         the old one is still running. Send status string only if it has
-         changed
-
-2005-07-01 17:18  maan
-
-       * mp3.c: print average bitrate for vbr files, additional log
-         message at eof, more precise timing
-
-2005-07-01 17:14  maan
-
-       * para.h, time.c: new function: tv_scale()
-
-2005-06-27 18:57  maan
-
-       * command.c: fix com_ff()
-
-2005-06-26 17:42  maan
-
-       * afs.c, mp3.c, ogg.c, server.h: handle REPOS in mainloop() rather
-         than in send_chunk(). Fix eof_delay for jump and next
-
-2005-06-22 00:29  maan
-
-       * command.c: serious bug: only install dummy SIGUSR1 signal handler
-         for com_stat(). This caused com_upd (and likely all other mysql
-         commands) to break if a server event occured during execution
-
-2005-06-21 23:45  maan
-
-       * mysql.c: do not nuke dirlist if find command did not find
-         anything
-
-2005-06-21 16:48  maan
-
-       * README: [no log message]
-
-2005-06-21 16:29  maan
-
-       * audiod.c: re-init streamio in com_hup()
-
-2005-06-21 15:36  maan
-
-       * Makefile.in, audiod.c: reactivate and fix penalty timings
-
-2005-06-21 14:46  maan
-
-       * audiod.c: clear_slot(): Only close stderr if it is a valid fd
-
-2005-06-20 23:43  maan
-
-       * README.mysql: nuke doku on DIR_LIKE macro.
-
-2005-06-20 23:39  maan
-
-       * mysql.c: nuke DIR_LIKE macro. Is the only one that requires an
-         O(n^2) query.
-
-2005-06-20 23:36  maan
-
-       * INSTALL, NEWS: [no log message]
-
-2005-06-19 21:55  maan
-
-       * index.html: reduce size of headline, fix some html errors to make
-         it valid html 4.01 transitional and include corresponding logo.
-
-2005-06-19 17:18  maan
-
-       * audiod.c: fix com_help(). This time for real.
-
-2005-06-19 17:11  maan
-
-       * audiod.c: fix com_help()
-
-2005-06-19 16:02  maan
-
-       * net.c, para.h: new function: para_hostname()
-
-2005-06-19 16:02  maan
-
-       * mysql.c: ps and ns change current_stream, so they should require
-         DB_WRITE privileges. Extend get_query() to optionally do a
-         cheaper O(n) query for a given stream if full pathnames are not
-         required and use this cheaper query where possible. Moreover, do
-         not store the full result and truncate afterwards, but use a
-         mysql limit clause to get only the required number of matches
-
-2005-06-19 15:57  maan
-
-       * mp3.c: use para_hostname instead of getenc()
-
-2005-06-19 15:52  maan
-
-       * exec.c: abort if fork fails
-
-2005-06-19 15:52  maan
-
-       * audiod.c: fix several memory leaks
-
-2005-06-02 20:30  maan
-
-       * client.c, client.conf.sample, client.ggo, fade.ggo, gui.ggo,
-         sdl_gui.ggo, server.ggo: replace USER by LOGNAME
-
-2005-06-02 20:30  maan
-
-       * stat.c: list.h never really existed
-
-2005-06-02 19:37  maan
-
-       * send.c: do not sleep at all. This is now done from within afs
-
-2005-06-02 19:36  maan
-
-       * recv.c: make prebuffer time dependent on audio format
-
-2005-06-02 19:16  maan
-
-       * mp3.c: terminate stream writer on repos. That is the easiest way
-         to circumwent sound clipping
-
-2005-06-02 19:15  maan
-
-       * gui_common.c: stat.h was only a (bad) idea..
-
-2005-06-02 19:14  maan
-
-       * gui.c: serious typo that caused segfaults for terminals that are
-         too small for the current theme
-
-2005-06-02 19:13  maan
-
-       * audiod.c: dump stderr to /dev/null
-
-2005-06-02 19:13  maan
-
-       * afs.c: extra sleep between song changes. Needs to be redone
-         properly
-
-2005-06-02 17:38  maan
-
-       * mysql.c: com_cs changes the database
-
-2005-06-02 15:45  maan
-
-       * stat.c: comment out noisy debug messages
-
-2005-05-30 20:06  maan
-
-       * audiod.c, para.h, stat.c: move stat_client related functions to
-         from audiod.c to stat.c
-
-2005-05-26 17:30  maan
-
-       * audiod.c, audiod.ggo, net.c: new option: force (unlinks socket)
-
-2005-05-26 16:59  maan
-
-       * NEWS: [no log message]
-
-2005-05-26 16:59  maan
-
-       * audiod.ggo: nuke unused option auto_decode
-
-2005-05-26 07:28  maan
-
-       * net.c: give credit to okir
-
-2005-05-26 07:12  maan
-
-       * audiod.c, audiod.ggo: add user_alow option
-
-2005-05-26 06:57  maan
-
-       * audioc.c: do not crash with no args
-
-2005-05-26 06:57  maan
-
-       * NEWS, README: [no log message]
-
-2005-05-26 06:27  maan
-
-       * audiod.c, audiod.ggo: rename fifo to socket
-
-2005-05-26 06:23  maan
-
-       * audioc.c, audioc.ggo: rename fifdor to tmpdir
-
-2005-05-26 06:05  maan
-
-       * audioc.c, audioc.ggo: replace fifo by socket
-
-2005-05-26 06:01  maan
-
-       * audioc.c: nuke fifo code
-
-2005-05-26 05:41  maan
-
-       * audiod.c: remove some old fifo code
-
-2005-05-26 05:36  maan
-
-       * audiod.c: simplify handle_connect()
-
-2005-05-26 05:35  maan
-
-       * net.c: zero out the user buffer, not the control buffer
-
-2005-05-26 05:05  maan
-
-       * audiod.c, net.c: zero-out all buffers, 255 byte is enough
-
-2005-05-26 04:52  maan
-
-       * Makefile.in, audioc.c, audiod.c, net.c, para.h: switch from
-         cmd_fifo to unix sockets using SCM_CREDENTIALS
-
-2005-05-25 19:37  maan
-
-       * slider.c: update to libzmw-0.1.0
-
-2005-05-20 19:10  maan
-
-       * command.c: fix com_next and com_nomore that used afs_status_flags
-         directly
-
-2005-05-20 18:39  maan
-
-       * mysql.c: fix com_csp
-
-2005-05-19 23:35  maan
-
-       * slider.c: decrease slider size. That makes sliders work again if
-         one of them is at 100%. Don't ask why..
-
-2005-05-19 20:21  maan
-
-       * gui.c: do not hog cpu if no audiod
-
-2005-05-19 20:06  maan
-
-       * gui.c, gui_common.c, para.h, sdl_gui.c: rename open_audiod_pipe
-         to para_open_audiod_pipe
-
-2005-05-19 19:56  maan
-
-       * audioc.c: unlink fifo just after select indicates that audiod has
-         opened that fifo
-
-2005-05-19 19:55  maan
-
-       * command.c: add missing stat items
-
-2005-05-19 01:53  maan
-
-       * Makefile.in, command.c, gui_common.c, gui_theme.c: remove
-         volatile from command.c, compute everything in one run instead.
-         Replace hardcoded status strings by their equivalent in
-         status_item_list[]. Do not print SI_LENGTH_MIN and SI_LENGTH_SEC
-         as SI_LENGTH should be enough for everyone.
-
-2005-05-19 01:50  maan
-
-       * stat.c: contains common code concerning the para_server stat and
-         para_audiod stat commands. Used by server, gui and sdl_gui
-
-2005-05-19 00:17  maan
-
-       * README: [no log message]
-
-2005-05-18 20:27  maan
-
-       * gui.c, gui_common.c, gui_theme.c, para.h, sdl_gui.c: make sdl gui
-         use para_audioc instead of directly contacting the server. Move
-         some generic code from gui.c to gui_common.c
-
-2005-05-18 20:22  maan
-
-       * afs.c: comment out noisy debug messages
-
-2005-05-18 17:01  maan
-
-       * string.c: s_a_r(): return an empty string if src is NULL
-
-2005-05-18 16:59  maan
-
-       * ogg.c: fix crash on sighup, use sw_pid = -1 for 'no
-         stream_writer'
-
-2005-05-18 16:58  maan
-
-       * mp3.c: use sw_pid = -1 for 'no stream_writer'
-
-2005-05-18 16:58  maan
-
-       * command.c, server.c: use new_afs_status_flags
-
-2005-05-18 16:58  maan
-
-       * audiod.c: It is not an error if we can not find a stream writer,
-         just do nothing in that case
-
-2005-05-18 16:57  maan
-
-       * afs.c: use sw_pid = -1 for 'no stream_writer', use
-         new_afs_status_flags
-
-2005-05-17 17:38  maan
-
-       * slider.c: use something like x - 1/x for the  score formula
-
-2005-05-17 17:38  maan
-
-       * server.ggo: use something like x - 1/x for the default score
-
-2005-05-17 17:37  maan
-
-       * recv.c: do not prebuffer so much
-
-2005-05-17 17:37  maan
-
-       * server.c: use new_afs_status_flags
-
-2005-05-17 17:34  maan
-
-       * send.c: fix brown paper bug that caused the beginning of an ogg
-         file to be corrupted, sleep _after_ shutting down ortp
-
-2005-05-17 17:32  maan
-
-       * server.h: new: mmd->new_status_flags, make afs_open_fifo take an
-         array of fds (APUE trick)
-
-2005-05-17 17:31  maan
-
-       * string.c: s_a_r does not modify any of its args, dup the string
-         if no match was found
-
-2005-05-17 17:19  maan
-
-       * para.h: s_a_r does not modify any of its args
-
-2005-05-17 17:18  maan
-
-       * ogg.c: fix start of playing, use Close also the new fifo, start
-         para_send on demand
-
-2005-05-17 17:16  maan
-
-       * mp3.c: cosmetics, compute af_open_cmd on demand instead of only
-         once. Fixes segfault on sighup. Close also the new fifo from the
-         APUE trick
-
-2005-05-17 17:07  maan
-
-       * krell.c: fetch exit status of para_stat
-
-2005-05-17 17:03  maan
-
-       * index.html: [no log message]
-
-2005-05-17 17:03  maan
-
-       * exec.c: remove some unused code
-
-2005-05-17 17:03  maan
-
-       * command.c: com_next(): do not set afs_status_flags directly,
-         rather use the new mmd->new_afs_status_flags in order to prevent
-         audiod to start the (possibly wrong) decoder too early
-
-2005-05-17 17:01  maan
-
-       * audiod.c: fix percentage display, move kill_xxx functions to top,
-         kill reader if writer dies unexpected. Assume that valid fds are
-         > 0
-
-2005-05-17 16:56  maan
-
-       * afs.c: introduce afl[i].show_offset, open stream write fifo also
-         for reading, prevent hard locks on invalid stream_write command
-
-2005-05-17 16:39  maan
-
-       * NEWS: [no log message]
-
-2005-05-12 20:58  maan
-
-       * audiod.c: fix sound artefacts while jumping
-
-2005-05-11 23:16  maan
-
-       * audiod.c: use para_exec instead of popen_read_cmdline_pid(),
-         switch from FILE *s->write to int s->write_fd
-
-2005-05-11 23:15  maan
-
-       * exec.c: typo that caused duping to /dev/null to break
-
-2005-05-11 22:21  maan
-
-       * audiod.c: use para_exec instead of popen_read_cmdline_pid(),
-         switch from FILE *s->read to int s->read_fd
-
-2005-05-11 22:02  maan
-
-       * audiod.c: cosmetics
-
-2005-05-11 21:40  maan
-
-       * gui_theme.c: include audiod status also in simple theme
-
-2005-05-11 21:40  maan
-
-       * audiod.c: use new syntax for para_exec
-
-2005-05-11 21:38  maan
-
-       * INSTALL: [no log message]
-
-2005-05-11 21:19  maan
-
-       * exec.c: triple choice for para_exec: dup fd, dup fd to /dev/null,
-         or leave fd alone
-
-2005-05-11 07:25  maan
-
-       * mp3dec.c: reduce buffer size and hence latency
-
-2005-05-11 07:24  maan
-
-       * mp3.c: use correct value for computing the length of the song,
-         now that is has become important...
-
-2005-05-11 07:23  maan
-
-       * gui_theme.c: dont print length of audio file twice
-
-2005-05-11 06:48  maan
-
-       * NEWS: [no log message]
-
-2005-05-11 05:28  maan
-
-       * krell.c: fix crash on server exit
-
-2005-05-11 04:52  maan
-
-       * audiod.c: clear slots and compute decoder flags based on
-         existence of the corresponding process rather than on whether we
-         have closed the pipe
-
-2005-05-11 04:32  maan
-
-       * audiod.c: typos
-
-2005-05-11 04:06  maan
-
-       * mp3.c: okay, the improved time magic wasnt better at all..
-
-2005-05-11 03:56  maan
-
-       * audiod.ggo: better explanation of stream_read_cmd
-
-2005-05-11 03:38  maan
-
-       * exec.c: para_exec_cmdline_pid(): use a temporary copy of the
-         given command line for split_args
-
-2005-05-11 03:37  maan
-
-       * client.c: oops, missing check for write errors
-
-2005-05-11 03:19  maan
-
-       * audiod.c, command.c, server.c, server.h: major change: server
-         sends full status info whenever a event occurs. audiod: Fix time
-         display for most cases. Clients connect only once to get status
-         info, manage a list of stat-clients and send info to each of them
-         whenever we read a line from para_server. Improve starting of
-         decoders: Restart reader as soon as old reader dies, but defer
-         starting of writer to the moment we read the first data
-
-2005-05-11 03:07  maan
-
-       * afs.c: introduce .show_offset flag. On for mp3, off for ogg.
-
-2005-05-11 03:05  maan
-
-       * mp3dec.c: fix last-chunk-wasnt-played bug
-
-2005-05-11 03:03  maan
-
-       * ogg.c: typo
-
-2005-05-11 03:03  maan
-
-       * gui_theme.c: reserve more space for time display
-
-2005-05-11 03:02  maan
-
-       * mp3.c: better time magic
-
-2005-05-11 03:01  maan
-
-       * gui_common.c, para.h: SI_LENGTH is there for ages
-
-2005-05-11 03:00  maan
-
-       * gui.c: dont do things twice. Use popen(audioc) instead to get the
-         status.
-
-2005-05-11 02:57  maan
-
-       * string.c: para_strcat(): it's okay to append to a NULL pointer
-
-2005-05-11 02:50  maan
-
-       * audioc.c: nuke SIGALARM crap, check for write errors. Check for
-         timeout once and use blocking reads afterwards.
-
-2005-05-11 02:47  maan
-
-       * README: [no log message]
-
-2005-05-08 18:31  maan
-
-       * mp3.c, ogg.c, recv.c, recv.ggo, send.c, send.ggo, server.ggo: use
-         different default ports depending on -a option
-
-2005-05-08 17:59  maan
-
-       * COPYING, README, afs.c, client.c, command.c, configure.ac,
-         daemon.c, dopey.c, fade.c, gui.c, gui_theme.c, index.html, mp3.c,
-         mp3dec.c, mysql.c, ogg.c, oggdec.c, para.h, recv.c, sdl_gui.c,
-         send.c, server.c, server.h, slider.c, string.c: change email
-         adress
-
-2005-05-08 17:41  maan
-
-       * FEATURES, INSTALL, NEWS, README: [no log message]
-
-2005-05-08 17:19  maan
-
-       * server.ggo: document new defaults
-
-2005-05-08 17:18  maan
-
-       * para.h, string.c: check for NULL pointers in s_a_r()
-
-2005-05-08 17:17  maan
-
-       * ogg.c: change default from para_ovsend to para_send
-
-2005-05-08 17:17  maan
-
-       * mp3.c: change default from poc to para_send
-
-2005-05-08 17:16  maan
-
-       * afs.c: use s_a_r to compute open_cmd
-
-2005-05-08 16:28  maan
-
-       * Makefile.in, configure.ac, recv.c, send.c: adapt to new names
-
-2005-05-08 16:16  maan
-
-       * recv.c, recv.ggo: former ovrecv
-
-2005-05-08 16:16  maan
-
-       * ovrecv.c, ovrecv.ggo: renamed to recv
-
-2005-05-08 16:09  maan
-
-       * send.c, send.ggo: former ovsend
-
-2005-05-08 16:08  maan
-
-       * ovsend.c, ovsend.ggo: renamed to send
-
-2005-05-08 15:59  maan
-
-       * command.c: fix time display
-
-2005-05-08 15:51  maan
-
-       * Makefile.in, configure.ac: ovsend/ovrec do no longer depend on
-         libvorbis
-
-2005-05-08 15:51  maan
-
-       * string.c: use const where appropriate
-
-2005-05-08 15:50  maan
-
-       * para.h: make s_a_r public
-
-2005-05-08 15:49  maan
-
-       * ovsend.ggo: specify header length by command line
-
-2005-05-08 15:49  maan
-
-       * ogg.c, ovsend.c: move code that depends on libvorbis from
-         ovsend.c to ogg.c
-
-2005-05-08 15:47  maan
-
-       * mp3.c: remove noisy log message
-
-2005-05-08 15:46  maan
-
-       * afs.c: cosmetics
-
-2005-05-08 15:41  maan
-
-       * audiod.c: always check for streamio, not only when playing
-
-2005-05-08 02:14  maan
-
-       * ovrecv.c, ovsend.c, ovsend.ggo, ovrecv.ggo: implement streaming
-         of mp3 files, remove all dependencies on libvorbisfile
-
-2005-05-07 16:28  maan
-
-       * mp3.c: do timing for sending data inside mp3.c rather than
-         sending data whenever the fd would not block
-
-2005-05-07 16:26  maan
-
-       * mp3dec.c: implement prebuffering
-
-2005-05-06 21:42  maan
-
-       * slider.c: cosmetics
-
-2005-05-06 21:13  maan
-
-       * slider.c: make input text field work again
-
-2005-05-06 18:11  maan
-
-       * mysql.c: typos, found by testing gcc 4.1.0
-
-2005-05-05 23:15  maan
-
-       * audiod.c: remove fifo on com_hup, new option: mode (to be used on
-         startup)
-
-2005-05-05 23:15  maan
-
-       * audiod.ggo: oops, forgot to check in
-
-2005-05-05 20:42  maan
-
-       * mp3dec.c: print output only once per second
-
-2005-05-05 19:58  maan
-
-       * audiod.c: nuke offset_change crap. Remember number of decoder
-         that was started last and use that as the current decoder
-         instead. Still doesn't work properly when jumping.
-
-2005-05-05 18:45  maan
-
-       * audiod.c: use APUE trick to prevent EOF from being generated when
-         #clients goes from 1 to 0. Log hostname, abort if cmd fifo
-         exists, remove cmd_fifo on exit
-
-2005-05-05 16:43  maan
-
-       * ogg.c: do not flood logs
-
-2005-05-05 16:42  maan
-
-       * gui_theme.c: cosmetics
-
-2005-05-05 16:42  maan
-
-       * Makefile.in: manual.txt: add audiod commands. audiod_objs: remove
-         repeated object file
-
-2005-05-05 16:41  maan
-
-       * 1.0, NEWS: [no log message]
-
-2005-05-05 06:13  maan
-
-       * gui.c: use one one (random) fifo for reading audiod stat info
-
-2005-05-05 04:10  maan
-
-       * slider.c: automatically translated to libzmw 0.0.12 by shipped
-         script zmw-upgrade.py. Seems to work.
-
-2005-05-04 19:57  maan
-
-       * server.c: read only once from signal pipe
-
-2005-05-04 19:11  maan
-
-       * gui.c: fix some memory leaks, simplify print_status_bar()
-
-2005-05-04 18:23  maan
-
-       * audiod.c: still more memory leaks in dump_ring_buffer()
-
-2005-05-04 18:15  maan
-
-       * audiod.c: fix more memory leaks
-
-2005-05-04 17:58  maan
-
-       * command.c: fix severe memory leak in com_stat()
-
-2005-05-04 17:45  maan
-
-       * index.html: typo
-
-2005-05-04 17:45  maan
-
-       * gui.ggo: new option: timeout
-
-2005-05-04 17:44  maan
-
-       * gui.c: detect if audiod is running and print error message if it
-         is not. Print the keysym for unknown keys.
-
-2005-05-04 17:39  maan
-
-       * audiod.c: help for com_hup, more log messages
-
-2005-04-28 22:30  maan
-
-       * gui.c: open also write fifo in read-only mode
-
-2005-04-28 21:03  maan
-
-       * audioc.c: do not block forever if audiod is not running
-
-2005-04-28 20:51  maan
-
-       * audiod.c: do not dup stdout when execing decoder
-
-2005-04-28 20:51  maan
-
-       * exec.c: improve para_exec(): It is now possible to dup only some
-         of the three std fds
-
-2005-04-28 20:14  maan
-
-       * para.h: status_item_list update, make more function declarations
-         public
-
-2005-04-28 20:14  maan
-
-       * gui_theme.c: set the new varbables on theme init. New functions:
-         prev_theme() and next_theme()
-
-2005-04-28 20:12  maan
-
-       * gui_common.c: remove old cruft, status_item_list update
-
-2005-04-28 20:11  maan
-
-       * command.c: simplify com_stat(), set offset in com_jmp()
-
-2005-04-28 20:07  maan
-
-       * audiod.c: new commands: help and cycle. Do not call kill() if pid
-         <=0, check for offset change in stat output
-
-2005-04-28 20:04  maan
-
-       * audioc.c: use make_message() and new concat_arg() instead of
-         sprintf
-
-2005-04-28 20:04  maan
-
-       * gui.c: make many hardcoded constants themable. Don't exec
-         para_audioc, implement it as a function instead
-
-2005-04-28 19:57  maan
-
-       * string.c: new function: concat_args
-
-2005-04-28 19:57  maan
-
-       * server.h: add chunk_offset to mmd
-
-2005-04-28 19:56  maan
-
-       * gui.ggo: nuke top_lines since it is now set by theme
-
-2005-04-28 19:55  maan
-
-       * afs.c: reset chunk_offset on song change
-
-2005-04-28 19:54  maan
-
-       * NEWS: [no log message]
-
-2005-04-28 19:54  maan
-
-       * Makefile.in: audiod depends on gui_common
-
-2005-04-26 04:21  maan
-
-       * gui.c: make para_gui themable
-
-2005-04-26 04:18  maan
-
-       * Makefile.in, gui.c, gui_common.c, para.h: make para_gui themable
-
-2005-04-26 04:11  maan
-
-       * gui_theme.c: contains color and position information for
-         displaying stat items
-
-2005-04-25 18:58  maan
-
-       * gui.c: remove stream I/O code. This is now done by para_audiod
-
-2005-04-25 18:21  maan
-
-       * FEATURES: [no log message]
-
-2005-04-25 18:06  maan
-
-       * server.c: remove unused variable, child closes socket after fork
-
-2005-04-25 18:05  maan
-
-       * audiod.c: why was that commented out? Reactivate
-
-2005-04-25 18:04  maan
-
-       * audioc.ggo: new option: timeout
-
-2005-04-25 18:04  maan
-
-       * audioc.c: new option: timeout. catch signals, use positive error
-         codes and 0 for success
-
-2005-04-25 17:56  maan
-
-       * NEWS, README: [no log message]
-
-2005-04-25 17:56  maan
-
-       * Makefile.in: make install: create vardir, stripping is done at
-         install time, no need to use -s option for gcc
-
-2005-04-25 17:54  maan
-
-       * INSTALL: major update
-
-2005-04-25 06:06  maan
-
-       * README: mention the new executables
-
-2005-04-25 06:03  maan
-
-       * daemon.c, para.h: remove an unused function
-
-2005-04-25 06:02  maan
-
-       * audiod.c: do not log if daemon and no logfile, ignore
-         conf.daemon_given on sighup
-
-2005-04-25 05:55  maan
-
-       * mp3.c: always use default if af->open_cmd is null
-
-2005-04-25 05:52  maan
-
-       * server.c: remove some dead code
-
-2005-04-25 05:49  maan
-
-       * server.c: do not log if daemon and no logfile, ignore
-         conf.daemon_given on sighup, become daemon earlier. That fixes
-         hangs on startup.
-
-2005-04-25 02:40  maan
-
-       * Makefile.in: add daemon.o to objs where neccessary. audioc
-         depends on audioc.cmdlin.o
-
-2005-04-25 02:38  maan
-
-       * audiod.c: new command: hup, use functions from daemon.c to
-         daemonize and for logging to specified log file. Die on sigint,
-         reload conf on sighup
-
-2005-04-25 02:35  maan
-
-       * para.h, server.h: make functions from daemon.c public
-
-2005-04-25 02:34  maan
-
-       * server.c: move daemon generic functions to daemon.c
-
-2005-04-25 02:33  maan
-
-       * daemon.c: contains common stuff between para_server and
-         para_audiod
-
-2005-04-25 02:32  maan
-
-       * ovrecv.c, ovsend.c: switch to void instead of static void to
-         avoid compiler warnings
-
-2005-04-25 02:31  maan
-
-       * fade.c: switch to logging with to fixed args, like in any other
-         paraslash executable
-
-2005-04-25 02:30  maan
-
-       * NEWS: [no log message]
-
-2005-04-25 02:29  maan
-
-       * audioc.c: add gengetopt command line options
-
-2005-04-25 02:29  maan
-
-       * audioc.ggo: command line options for the audio client
-
-2005-04-24 21:27  maan
-
-       * audiod.c: implement audiod commands: stat term on off standby
-
-2005-04-24 20:25  maan
-
-       * Makefile.in, configure.ac: add para_oggdec
-
-2005-04-24 20:25  maan
-
-       * oggdec.c: a teensy oggvorbis decoder
-
-2005-04-24 20:02  maan
-
-       * audioc.c: simple client that opens two fifos to communicatw with
-         para_audiod.
-
-2005-04-24 20:01  maan
-
-       * audiod.c: remove underscore to match other stat items
-
-2005-04-24 20:00  maan
-
-       * para.h, string.c: new function: para_tmpname(). Pseudo random.
-
-2005-04-24 18:55  maan
-
-       * audiod.c: add decoder flags in ring buffer dump output
-
-2005-04-24 18:14  maan
-
-       * audiod.c: always check err_fd, close err_fd in any case
-
-2005-04-24 05:04  maan
-
-       * audiod.c: read also stderr of stream writers
-
-2005-04-24 05:04  maan
-
-       * exec.c, para.h: add para_exec functions that redirect stdin,
-         stdout, and stderr
-
-2005-04-24 02:54  maan
-
-       * NEWS: [no log message]
-
-2005-04-24 02:53  maan
-
-       * slider.c: add gpl header
-
-2005-04-24 02:52  maan
-
-       * Makefile.in, configure.ac: add para_mp3dec
-
-2005-04-24 02:52  maan
-
-       * mp3dec.c: A teensy mp3 decoder
-
-2005-04-24 02:51  maan
-
-       * CREDITS: add Thierry Excoffier and Robert Leslie
-
-2005-04-24 02:17  maan
-
-       * server.c: fix brown paper bag bug that caused server to hang on
-         song change
-
-2005-04-24 02:16  maan
-
-       * afs.c, exec.c, para.h: move open_fifo from afs.c to exec.c
-
-2005-04-24 02:15  maan
-
-       * Makefile.in: add para_audiod
-
-2005-04-24 02:15  maan
-
-       * audiod.c: the audio daemon
-
-2005-04-21 17:39  maan
-
-       * exec.c, para.h: make some functions static
-
-2005-04-21 17:33  maan
-
-       * para.h: remove unused defines
-
-2005-04-21 17:33  maan
-
-       * Makefile.in, NEWS, configure.ac: change version, codename
-
-2005-04-18 20:30  maan
-
-       * NEWS, configure.ac: paraslash 0.1.7
-
-2005-04-18 20:08  maan
-
-       * slider.c: give -1000 points if file was just played
-
-2005-04-18 00:37  maan
-
-       * mysql.c: com_cam(): fix stupid cut and paste bug
-
-2005-04-18 00:08  maan
-
-       * Makefile.in: para_ovrecv depends on string.o
-
-2005-04-18 00:07  maan
-
-       * gui.ggo: re-increase default stream_timeout to 10 secs because 5
-         secs is not enough for 22kh mono
-
-2005-04-18 00:06  maan
-
-       * ovrecv.c, ovrecv.ggo: introduce prebuffering
-
-2005-04-18 00:04  maan
-
-       * ogg.c: nuke grace_time()
-
-2005-04-17 21:30  maan
-
-       * NEWS: [no log message]
-
-2005-04-17 21:27  maan
-
-       * gui.c, gui.ggo: new command line option: --stream_timeout
-
-2005-04-17 21:16  maan
-
-       * para.h, time.c: use const where apropriate, round tv_usec
-
-2005-04-17 21:15  maan
-
-       * mp3.c: cosmetics
-
-2005-04-17 21:12  maan
-
-       * NEWS, README: [no log message]
-
-2005-04-11 20:06  maan
-
-       * ogg.c: whitespace fixes, improve timings, move time-related stuff
-         to time.c
-
-2005-04-11 20:04  maan
-
-       * ovsend.c: whitespace fixes, improve timings, get rid of some
-         sleep
-
-2005-04-11 20:02  maan
-
-       * bash_completion: make it work without having sourced
-         bash_competion
-
-2005-04-11 20:01  maan
-
-       * afs.c: move tv2ms() from to time.c, do not sleep in
-         call_all_mainloops()
-
-2005-04-11 20:00  maan
-
-       * Makefile.in: server, ovsend, ovrecv depend on time.c/time.o
-
-2005-04-11 19:59  maan
-
-       * time.c: contains time-related functions: tv_add(), tv_diff()...
-
-2005-04-11 19:58  maan
-
-       * ovsend.ggo: set default header interval to 3 seconds
-
-2005-04-11 19:57  maan
-
-       * para.h, server.h: mv time-related declarations to para.h
-
-2005-04-10 14:55  maan
-
-       * ogg.c: fix pause
-
-2005-04-10 00:07  maan
-
-       * afs.c: cosmetics
-
-2005-04-09 23:27  maan
-
-       * afs.c, mp3.c, ogg.c: Fix nasty double free bug: If
-         get_file_info() from the first audio format (mp3) failed, it
-         closed the corresponding fd, so get_file_info() for the second
-         audio format (ogg) got passed an already closed fd. Even worse,
-         get_file_info() closed that fd again. Nasty thing here is that
-         neither ov_open() nor the second fclose() segfaulted but
-         corrupted memory in some way which caused subsequent mysql
-         queries to crash.
-
-         The fix is easy: Do not close the fd at the audio format layer
-         (ogg, mp3), but at the higher afs layer, and of course only if
-         _all_ get_file_info()'s failed.
-
-2005-04-09 23:11  maan
-
-       * NEWS: [no log message]
-
-2005-03-30 22:17  maan
-
-       * slider.c: two new sliders: lastplayed and numplayed
-
-2005-03-28 23:40  maan
-
-       * krell.c: comment out unneeded destroy_song_change()
-
-2005-03-28 23:26  maan
-
-       * server.c: avoid openssl zombies, make old gcc happy
-
-2005-03-28 23:26  maan
-
-       * command.c: avoid openssl zombies
-
-2005-03-28 22:28  maan
-
-       * krell.c: fix memory leak
-
-2005-03-28 21:42  maan
-
-       * mp3.c: make 2.95.4 happy
-
-2005-03-27 20:51  maan
-
-       * ogg.c: rewrite ogg_mainloop() in the style of mp3_mainloop()
-
-2005-03-27 20:50  maan
-
-       * mp3.c: only start stream writer when we have a valid file and
-         current audio format is mp3
-
-2005-03-27 20:49  maan
-
-       * afs.c: simplify afs_mainloop(), init afl[i].fifo
-
-2005-03-26 18:22  maan
-
-       * mp3.c: move check for AFS_NEXT from send_chunk to mainloop
-
-2005-03-26 17:31  maan
-
-       * mp3.c: reorder functions
-
-2005-03-26 17:23  maan
-
-       * README.mysql: typo
-
-2005-03-26 17:22  maan
-
-       * mp3.c: fix playing when switching from ogg to mp3
-
-2005-03-25 02:03  maan
-
-       * exec.c: fixup totally borked exec_vp_pid_bg()
-
-2005-03-25 01:47  maan
-
-       * server.h: add prototypes for afs_handle_sigchild() and
-         afs_open_fifo(), add fifoname, fifo to struct audio_format, kill
-         sw from struct audio_format()
-
-2005-03-25 01:46  maan
-
-       * server.c: call afs_handle_sigchild for each child that has died
-
-2005-03-25 01:45  maan
-
-       * ogg.c: switch from global variabless for fifo to af->fifo,
-         af->fifoname, move open_fifo() to afs.c
-
-2005-03-25 01:42  maan
-
-       * mp3.c: use fifo rather than stdin, handle repos request from
-         within mp3_mainloop() rather than in mp3_send_chunk()
-
-2005-03-25 01:36  maan
-
-       * afs.c: new function handle_sigchild() which resets af->sw_pid,
-         move open_fifo from ogg.c to afs.c since it is generic for all
-         audio formats now
-
-2005-03-25 01:31  maan
-
-       * NEWS: [no log message]
-
-2005-03-25 01:31  maan
-
-       * CREDITS: add Simon Morlat
-
-2005-03-23 22:31  maan
-
-       * ogg.c: do not compute timestamps if current audio format is not
-         ogg. Move open_fifo() up, some small other cleanups
-
-2005-03-23 22:28  maan
-
-       * server.c: nicer startup message
-
-2005-03-23 22:28  maan
-
-       * mp3.c: remove pointless logging
-
-2005-03-23 22:27  maan
-
-       * command.c: typo
-
-2005-03-23 22:27  maan
-
-       * afs.c: use 1 as first argument of afl[i].mainloop() iff i is
-         current audio format
-
-2005-03-23 22:25  maan
-
-       * README: mention para_ovsend/para_ovrecv
-
-2005-03-23 18:12  maan
-
-       * afs.c, ogg.c: create fifo if not present, detect if fifofile
-         exists but is no fifo, better handling of fifo errors from
-         ogg_mainloop(), loglevel adjustments
-
-2005-03-23 06:05  maan
-
-       * ovrecv.c: new function for handling extra packages, a lot of
-         cleanups
-
-2005-03-23 05:49  maan
-
-       * FEATURES, README: describe ovsend/ovrecv
-
-2005-03-23 03:18  maan
-
-       * ovsend.c: simplify do_io()
-
-2005-03-23 02:46  maan
-
-       * ovsend.c: whitespace cleanup
-
-2005-03-23 02:42  maan
-
-       * gui.c, para.h: sys/time.h is needed by ogg.c and server.c, afs.c,
-         gui.c. Move its inclusion to para.h
-
-2005-03-23 02:35  maan
-
-       * command.c: fix com_nomore()
-
-2005-03-23 02:31  maan
-
-       * afs.c: fix com_nomore()
-
-2005-03-23 01:32  maan
-
-       * server.h: rename afs_preselect(), add two timeval related
-         functions, change syntax of send_chunk()
-
-2005-03-23 01:28  maan
-
-       * server.ggo: change default stream writer from pogg-http to
-         para_ovsend
-
-2005-03-23 01:27  maan
-
-       * server.c: always call afs_mainloop() (not only when playing) to
-         obtain a fd and a timeout which is fed to select(). Close all
-         filedescriptors which are marked FD_CLOEXEC just after forking
-         which is needed for the ogg code
-
-2005-03-23 01:22  maan
-
-       * para.h, string.c: add para_fread(), a wrapper for fread() with
-         sane return values
-
-2005-03-23 01:21  maan
-
-       * ogg.c: complete rewrite. ogg.c does its own timing for writing
-         out data chunks rather than writing to a pipe until it's full
-         like the mp3 code does
-
-2005-03-23 01:19  maan
-
-       * mp3.c: adapt to new syntax (return always NULL as timestamp),
-         move para_fread() to string.c, cosmetics
-
-2005-03-23 01:13  maan
-
-       * configure.ac: check for libortp and libzmw
-
-2005-03-23 01:11  maan
-
-       * NEWS: [no log message]
-
-2005-03-23 01:11  maan
-
-       * autogen.sh: clean up before and after updating
-
-2005-03-23 01:09  maan
-
-       * afs.c: rename afs_preselect() to afs_mainloop(). Call each audio
-         format's mainloop to obtain a filedescriptor and a timestamp.
-         Return the data of the current audio format to main
-
-2005-03-23 01:05  maan
-
-       * Makefile.in: add targets for ovsend and ovrecv
-
-2005-03-23 01:05  maan
-
-       * ovrecv.c, ovrecv.ggo, ovsend.c, ovsend.ggo: two new executables
-         for sending/retrieving ogg vorbis files via rtp
-
-2005-03-22 04:19  maan
-
-       * Makefile.in: do not print silly release date
-
-2005-03-05 17:12  maan
-
-       * README.mysql: minor cleanup
-
-2005-03-05 15:38  maan
-
-       * NEWS, configure.ac: paraslash 0.1.6
-
-2005-03-05 15:12  maan
-
-       * autogen.sh: also build the package. Redirect messages to
-         /dev/null
-
-2005-03-05 15:12  maan
-
-       * Makefile.in, configure.ac: remove pob_ogg
-
-2005-03-05 15:11  maan
-
-       * pob-ogg.c, pob-ogg.ggo: no longer needed
-
-2005-03-05 14:50  maan
-
-       * ogg.c: call end_of_input() directly after freeing ogg_buf.
-         Introduce sleep(1) for now.
-
-2005-03-02 01:29  maan
-
-       * command.c: com_stat(): fix status bar
-
-2005-02-28 14:58  maan
-
-       * NEWS: [no log message]
-
-2005-02-28 00:58  maan
-
-       * mp3.c: close mp3 file on exit
-
-2005-02-28 00:16  maan
-
-       * gui.c: typo
-
-2005-02-27 23:49  maan
-
-       * server.ggo: cosmetics
-
-2005-02-27 23:18  maan
-
-       * server.c: cosmetics
-
-2005-02-27 23:18  maan
-
-       * NEWS: [no log message]
-
-2005-02-27 23:06  maan
-
-       * gui.c: make reload_Config() also reread stream_read_cmd and
-         stream_write_cmd
-
-2005-02-27 22:55  maan
-
-       * gui.c: delay start of decoder rather than going to sleep if
-         penalty > 0
-
-2005-02-27 20:12  maan
-
-       * ogg.c: localize use of var page
-
-2005-02-27 19:46  maan
-
-       * string.c: add a comment
-
-2005-02-27 19:32  maan
-
-       * afs.c: trivial cleanups
-
-2005-02-27 19:27  maan
-
-       * afs.c: simplify afs_preselect()
-
-2005-02-27 19:14  maan
-
-       * afs.c, mp3.c, ogg.c, server.h: handle afs flags NEXT and REPOS
-         inside send chunk
-
-2005-02-27 13:59  maan
-
-       * ogg.c: nuke unneeded clear_page()
-
-2005-02-27 13:34  maan
-
-       * ogg.c: ogg_close_audio_file() is only called from
-         ogg_end_of_input(). Move it there and nuke
-         ogg_close_audio_file().
-
-2005-02-27 13:30  maan
-
-       * ogg.c: submit_headers_to_stream() does not need an argument.
-
-2005-02-27 04:55  maan
-
-       * ogg.c: whitespace cleanup
-
-2005-02-27 04:53  maan
-
-       * ogg.c: move OggVorbis_File into struct para_ogg_state
-
-2005-02-27 04:46  maan
-
-       * ogg.c: rename vcut_state to para_ogg_state
-
-2005-02-27 04:41  maan
-
-       * ogg.c: process_headers() does not need an argument.
-
-2005-02-27 04:34  maan
-
-       * ogg.c: get_page() does not need an argument.
-
-2005-02-27 04:29  maan
-
-       * ogg.c: nuke var vcutstate since vcutstate==s always.
-
-2005-02-27 04:15  maan
-
-       * ogg.c: vcut_new() is only called from ogg_init(). Move it there
-         and nuke vcut_new().
-
-2005-02-27 03:47  maan
-
-       * ogg.c: headers_to_buf() is only called from
-         init_oggvorbis_file(). Move it there and nuke headers_to_buf().
-
-2005-02-27 03:34  maan
-
-       * ogg.c: get rid of sent_headers variable
-
-2005-02-25 21:36  maan
-
-       * ogg.c: do not kill stream writer, wait for it to die instead.
-
-2005-02-25 21:16  maan
-
-       * mysql.c: use load data infile rather than load data local infile.
-         Change tmpdir to /tmp and umask of tmpfile to 022 in order to
-         make it readable by mysqld.
-
-2005-02-23 06:37  maan
-
-       * ogg.c: nuke brain dead have_page logic
-
-2005-02-23 06:22  maan
-
-       * ogg.c: reset offset and packet_no on end of input. Fixes para
-         next
-
-2005-02-23 05:33  maan
-
-       * ogg.c: fix jumping
-
-2005-02-23 05:14  maan
-
-       * ogg.c: remove some unused stuff
-
-2005-02-23 05:12  maan
-
-       * ogg.c: remove old read_chunk/write_chunk pair
-
-2005-02-23 05:10  maan
-
-       * ogg.c: switch to send_chunk, major code reorganization (old code
-         still there to be removed soon).
-
-2005-02-23 05:08  maan
-
-       * afs.c, mp3.c, server.h: switch to send_chunk, rather than the
-         combination of read_chunk/write_chunk
-
-2005-02-22 23:49  maan
-
-       * ogg.c: do not request new page if offset_granulepos is invalid,
-         fix type of offset_granulepos, more logging
-
-2005-02-22 23:13  maan
-
-       * server.h: fix refreshing of stream_write command on sighup
-
-2005-02-22 17:45  maan
-
-       * krell.c: fix compiler warning
-
-2005-02-22 17:44  maan
-
-       * gui.c: use reasonable defaults, increase MAX_STREAM_SLOTS to 10,
-         adapt penalty timing, init slots on startup
-
-2005-02-22 16:13  maan
-
-       * Makefile.in: make clean: remove para_slider
-
-2005-02-22 15:51  maan
-
-       * pics/screenshots/: para_krell-2005-02.png,
-         para_slider-2004-12.png: two more screenshots
-
-2005-02-22 14:47  maan
-
-       * afs.c, server.c: stop playing on read/write errors, fix
-         refreshing of stream_write command on sighup
-
-2005-02-22 00:10  maan
-
-       * afs.c, server.c, server.h: send_chunk() knows the stream writer
-         fd, no need to pass it as an argument
-
-2005-02-21 20:06  maan
-
-       * gui.c: cosmetics
-
-2005-02-21 00:32  maan
-
-       * gui.c: whitespace cleanups
-
-2005-02-21 00:30  maan
-
-       * gui.c: replace num by slot
-
-2005-02-21 00:19  maan
-
-       * gui.c: logging improvements
-
-2005-02-20 23:30  maan
-
-       * gui.c: more checks for active curses
-
-2005-02-20 22:42  maan
-
-       * gui.c: various cleanups, fix siol vs afi mix up
-
-2005-02-13 22:28  maan
-
-       * fade.c: more logging
-
-2005-02-13 22:27  maan
-
-       * Makefile.in: gui depends on string.o
-
-2005-02-13 22:26  maan
-
-       * COPYING: 2004->2005
-
-2005-02-01 22:16  maan
-
-       * ogg.c: delete unnecessary packet_clear()
-
-2005-01-27 01:59  maan
-
-       * ogg.c: do header stuff during file init rather than on first
-         read, fix serious memory leak
-
-2005-01-25 20:20  maan
-
-       * ogg.c: function reordering
-
-2005-01-24 22:57  maan
-
-       * ogg.c: whitespace cleanup
-
-2005-01-24 22:53  maan
-
-       * ogg.c: nuke another unused variable
-
-2005-01-24 22:47  maan
-
-       * ogg.c: use update_sync() rather that using fread() directly
-
-2005-01-24 22:31  maan
-
-       * ogg.c: move out_state to vcutstate, destroy streams and sync_in,
-         more debug messages
-
-2005-01-24 18:58  maan
-
-       * ogg.c: nuke unneeded variables
-
-2005-01-23 20:45  maan
-
-       * ogg.c: simplify process_headers()
-
-2005-01-23 20:28  maan
-
-       * ogg.c: use para_malloc(), simplify vcut_new(), more debugging
-         messages
-
-2005-01-14 14:32  maan
-
-       * gui.c: some small cleanups
-
-2005-01-09 23:31  maan
-
-       * gui.c: major stream I/O reearrangements (slots)
-
-2005-01-09 23:29  maan
-
-       * mysql.c: com_pidel(): reset pic_id to 1 for all files having the
-         picid that is going to be deleted
-
-2005-01-09 17:01  maan
-
-       * ogg.c: fix it again by reverting the changes made in revision
-         1.39. They caused most ogg files to be skipped..
-
-2005-01-08 13:09  maan
-
-       * ogg.c: reset packetno only once
-
-2005-01-07 20:17  maan
-
-       * ogg.c: fix some memory leaks
-
-2005-01-03 20:29  maan
-
-       * server.c: always log startup message
-
-2005-01-02 20:42  maan
-
-       * afs.c, client.c, command.c, dopey.c, fade.c, gui.c, krell.c,
-         mp3.c, mysql.c, ogg.c, para.h, pob-ogg.c, sdl_gui.c, server.c,
-         server.h, string.c: change year to 2005
-
-2005-01-02 18:47  maan
-
-       * command.c: fix another memory leak in get_sb_string(). Again
-         serious for the same reason.
-
-2005-01-02 18:34  maan
-
-       * afs.c, mysql.c: cosmetics
-
-2005-01-02 18:34  maan
-
-       * command.c: fix memory leak in compute_status_volatile(). Serious
-         because it is called by com_stat().
-
-2005-01-01 21:49  maan
-
-       * mysql.c: fix com_picadd()
-
-2005-01-01 16:56  maan
-
-       * mysql.c, server.ggo: rename default database name from music to
-         paraslash
-
-2004-12-31 23:18  maan
-
-       * mysql.c: fix three small memory leaks
-
-2004-12-31 23:17  maan
-
-       * string.c: fix serious memory leak
-
-2004-12-31 20:04  maan
-
-       * mysql.c: fix memory leak in get_dbinfo()
-
-2004-12-31 18:55  maan
-
-       * NEWS, configure.ac: paraslash 0.1.5
-
-2004-12-31 18:44  maan
-
-       * configure.ac: do not check for glib. It is only needed for
-         para_slider
-
-2004-12-31 18:43  maan
-
-       * README.mysql, mysql.c: rename command create_db back to cdb
-
-2004-12-31 18:17  maan
-
-       * pob-ogg.c: remove some suerflous variabbles
-
-2004-12-31 18:08  maan
-
-       * FEATURES, gui.c, mysql.c: cosmetics
-
-2004-12-27 01:33  maan
-
-       * gui.c, net.c: cosmetics
-
-2004-12-27 01:01  maan
-
-       * gui.c: reap children as early as possible. Avoid double killing
-         children.
-
-2004-12-27 00:08  maan
-
-       * NEWS: [no log message]
-
-2004-12-27 00:08  maan
-
-       * server.c, slider.c: cosmetics
-
-2004-12-26 23:53  maan
-
-       * command.c, server.c, server.h: Reload dbtool on SIGHUP. Move
-         restoring of signals to handle_connect() in command.c. Make
-         handle_connect() return int
-
-2004-12-26 23:06  maan
-
-       * NEWS: [no log message]
-
-2004-12-26 22:51  maan
-
-       * gui.c: use signal handling from signal.c. Should be race-free
-         now. Reduce select timeout to 200ms as that feels much better and
-         does not hurt.
-
-2004-12-26 22:46  maan
-
-       * para.h: simplified install sighandler function, new:
-         reap_child(), reap_children()
-
-2004-12-26 22:45  maan
-
-       * signal.c: new: reap_child(), reap_children() that replace
-         handle_sigchild()
-
-2004-12-26 22:43  maan
-
-       * server.c: always use the generic signal handler. That allows to
-         simplify install_sighandler() and to get rid of internal
-         handlers. Also: restore signals to default values right after
-         fork().
-
-2004-12-26 20:06  maan
-
-       * para.h: add signal function declarations
-
-2004-12-26 20:06  maan
-
-       * Makefile.in: link signal.o to server and gui
-
-2004-12-26 20:05  maan
-
-       * server.c: move signal-related functions to own file (signal.c)
-
-2004-12-26 20:04  maan
-
-       * signal.c: contains signal handling functions pulled out from
-         server.c
-
-2004-12-24 19:57  maan
-
-       * README, README.mysql, index.html, slider.c: [no log message]
-
-2004-12-24 19:11  maan
-
-       * NEWS, README: [no log message]
-
-2004-12-24 18:23  maan
-
-       * README: [no log message]
-
-2004-12-24 18:19  maan
-
-       * NEWS, README: [no log message]
-
-2004-12-24 18:13  maan
-
-       * krell.c: replace some commands by others
-
-2004-12-24 18:11  maan
-
-       * configure.ac: add detection of glib and libzmw. Commented out for
-         now.
-
-2004-12-24 18:10  maan
-
-       * autogen.sh: run configure with given command line options
-
-2004-12-24 18:09  maan
-
-       * README: add slider doku
-
-2004-12-24 18:08  maan
-
-       * NEWS: [no log message]
-
-2004-12-24 18:08  maan
-
-       * Makefile.in: Add target para_slider. Not built automatically.
-         Change Codename.
-
-2004-12-24 18:07  maan
-
-       * FEATURES: only short descriptions here. Detailed info goes to
-         README. Add slider.
-
-2004-12-22 14:47  maan
-
-       * mysql.c: better online help for com_sl()
-
-2004-12-22 14:46  maan
-
-       * command.c: use proper err_list on permission errors
-
-2004-12-22 14:45  maan
-
-       * 1.0, INSTALL: [no log message]
-
-2004-12-20 19:15  maan
-
-       * net.c: use default loglevel info for network errors. Some of them
-         are perfectly ok, so they should not pollute the log.
-
-2004-12-20 19:12  maan
-
-       * README: typo
-
-2004-12-19 18:07  maan
-
-       * README.mysql: [no log message]
-
-2004-12-19 17:38  maan
-
-       * configure.ac: paraslash 0.1.4
-
-2004-12-19 17:37  maan
-
-       * NEWS: [no log message]
-
-2004-12-19 17:20  maan
-
-       * server.c: typo
-
-2004-12-19 17:14  maan
-
-       * server.c: On dbtool change, always shutdown and re-init, even if
-         old == new
-
-2004-12-19 17:12  maan
-
-       * mysql.c: return always success on init to give the user the
-         chance to create the database
-
-2004-12-19 17:10  maan
-
-       * README.mysql: [no log message]
-
-2004-12-19 16:58  maan
-
-       * README.mysql: [no log message]
-
-2004-12-19 07:31  maan
-
-       * mysql.c: print_results(): abort if send_buffer fails
-
-2004-12-19 06:54  maan
-
-       * krell.c, server.c: cosmetics
-
-2004-12-19 06:03  maan
-
-       * command.c: cosmetics
-
-2004-12-19 05:49  maan
-
-       * command.c: report error text also on errors during initial
-         handshake
-
-2004-12-19 04:50  maan
-
-       * command.c, server.h: make some functions static
-
-2004-12-19 04:49  maan
-
-       * command.c, server.c, server.h: move handle_connect from server.c
-         to command.c
-
-2004-12-19 04:42  maan
-
-       * client.c: terminate buffer
-
-2004-12-19 04:30  maan
-
-       * client.c: do not try do decrypt server response if it has length
-         not equal to 64. Regard response as error message in that case
-         and report it instead.
-
-2004-12-19 04:30  maan
-
-       * server.c: only send error text if we have a valid err_list
-
-2004-12-18 15:35  maan
-
-       * NEWS: [no log message]
-
-2004-12-17 22:55  maan
-
-       * command.c: report proper error messages also for internal
-         commands
-
-2004-12-17 22:33  maan
-
-       * command.c, mysql.c, pob-ogg.c, server.c, server.h: introduce
-         err_list, a list of error messages. Report error message
-         corresponding to return value of command handler to client if
-         this value is negative
-
-2004-12-17 22:29  maan
-
-       * gui.c: write chunk if buffer contains data even if reader has
-         died
-
-2004-12-17 22:28  maan
-
-       * NEWS: [no log message]
-
-2004-12-17 14:51  maan
-
-       * ogg.c: nuke unused dummy variable
-
-2004-12-17 14:06  maan
-
-       * NEWS: [no log message]
-
-2004-12-17 13:21  maan
-
-       * mysql.c: make stradd/picadd overwrite previous definition if it
-         exists, rather than returning errors
-
-2004-12-16 02:26  maan
-
-       * ogg.c: further simplify read_chunk(): nuke first_page logic
-
-2004-12-15 22:45  maan
-
-       * gui.c: oops, forgot to remove the if-statement
-
-2004-12-15 22:30  maan
-
-       * gui.c: remove unneeded variable stream_buf_bytes
-
-2004-12-15 20:32  maan
-
-       * ogg.c: always use ogg_stream_flush() which simplifies page_out()
-
-2004-12-15 20:14  maan
-
-       * ogg.c: further simplify read_chunk(), kill have_packet
-
-2004-12-15 19:40  maan
-
-       * ogg.c, pob-ogg.c, server.c: simplify read_chunk(), avoid frequent
-         page_out errors
-
-2004-12-15 16:45  maan
-
-       * gui.c: fix serious typo: stream WRITE command option was used for
-         READING.
-
-2004-12-15 03:41  maan
-
-       * ogg.c: trivial cleanups
-
-2004-12-13 17:05  maan
-
-       * krell.c: reap the children to avoid zombies. Fixes zombie flood
-         if started with no server running.
-
-2004-12-13 17:02  maan
-
-       * command.c: report server pid instead of current database tool as
-         the latter is already contained in output of stat
-
-2004-12-11 17:04  maan
-
-       * gui.c: reintroduce one second sleep on errors to avoid busy loops
-         if server is unavailable
-
-2004-12-11 17:01  maan
-
-       * mysql.c: fix playing in case no stream was selected
-
-2004-12-11 16:38  maan
-
-       * afs.c: enter stopped mode when only invalid files were found
-
-2004-12-11 16:06  maan
-
-       * gui.c: simplify SIGINT handling, get rid of sleep(1)
-
-2004-12-11 15:43  maan
-
-       * gui.c: Hm, signal handling must have changed in recent linux
-         kernels. Make SIGINT work again.
-
-2004-12-11 14:01  maan
-
-       * mysql.c: com_hist(): query got messed up, fix it.
-
-2004-12-10 22:37  maan
-
-       * gui.c: nuke query_stream command. Can be done by key mappings
-
-2004-12-10 22:32  maan
-
-       * mysql.c: com_strq(): Use current stream if invoked without args
-
-2004-12-10 18:01  maan
-
-       * mysql.c: com_upd(): comment out noisy debug message
-
-2004-12-10 17:55  maan
-
-       * mysql.c: check return value of send_buffer()
-
-2004-12-10 16:50  maan
-
-       * server.c: cosmetics
-
-2004-12-10 16:50  maan
-
-       * Makefile.in: change codename
-
-2004-12-10 16:49  maan
-
-       * mysql.c: oops, com_picadd() got lost during merging. Here it is
-         again.
-
-2004-12-10 15:42  maan
-
-       * server.c: simplify handle_connect()
-
-2004-12-10 14:35  maan
-
-       * NEWS: [no log message]
-
-2004-12-10 14:35  maan
-
-       * server.c: forgotten goto
-
-2004-12-10 14:20  maan
-
-       * server.c: cosmetics
-
-2004-12-10 13:21  maan
-
-       * NEWS, configure.ac: bump version to 0.1.3
-
-2004-12-10 13:04  maan
-
-       * NEWS: [no log message]
-
-2004-12-09 22:12  maan
-
-       * server.c, server.ggo: new option: dbtool. Choose dbtool which
-         dbtool is used on startup
-
-2004-12-09 21:21  maan
-
-       * mysql.c: update mmd->dbinfo on successful init
-
-2004-12-09 21:21  maan
-
-       * dopey.c: terminate song song list by NULL
-
-2004-12-09 20:46  maan
-
-       * mysql.c: kill superfluous semicolen that caused gcc-2.95.4 to
-         fail
-
-2004-12-09 20:28  maan
-
-       * dopey.c: make get_song_list() return NULL on errors, rather than
-         an empty list
-
-2004-12-09 20:19  maan
-
-       * command.c, dopey.c, mysql.c, server.c, server.h: handle dbtool
-         change by server. The client only sets mmd->dbt_change which is
-         noticed by server when select() returns.
-
-2004-12-09 19:35  maan
-
-       * command.c, mysql.c, server.h: nuke modus from struct command
-
-2004-12-09 19:33  maan
-
-       * mysql.c: rename cdb to create_db
-
-2004-12-09 19:13  maan
-
-       * FEATURES: [no log message]
-
-2004-12-09 19:13  maan
-
-       * server.ggo, mysql.c: prefix all mysql options by mysql_
-
-2004-12-09 19:02  maan
-
-       * INSTALL: [no log message]
-
-2004-12-09 18:46  maan
-
-       * README: [no log message]
-
-2004-12-09 18:30  maan
-
-       * server.c: fix autoplay, move mmd_lock before networ init
-
-2004-12-09 18:21  maan
-
-       * index.html, mysql.c: cosmetics/typos
-
-2004-12-09 18:21  maan
-
-       * gui.c, sdl_gui.c: replace obsolete score by uptime
-
-2004-12-09 18:20  maan
-
-       * command.c: do not include seconds in server's uptime and report
-         the uptime in com_stat()
-
-2004-12-09 17:56  maan
-
-       * README.mysql: update for 0.1.3
-
-2004-12-09 17:27  maan
-
-       * Makefile.in, index.html: change README.dbtool to README.mysql
-
-2004-12-09 17:25  maan
-
-       * NEWS, README.mysql: former README.dbtool
-
-2004-12-09 17:24  maan
-
-       * README.dbtool: renamed to README.mysql
-
-2004-12-09 17:04  maan
-
-       * command.c, server.c, server.h: field 'initialized' in struct
-         dbtool was a bad idea. We must allow switching to the mysql
-         dbtool even if its init routine failed because that's the only
-         way to initially create the database.
-
-2004-12-09 02:21  maan
-
-       * gui.c, sdl_gui.c: replace obsolete streams in stat_items[] by
-         dbtool
-
-2004-12-09 02:20  maan
-
-       * command.c: print current dbtool in com_stat()
-
-2004-12-09 02:07  maan
-
-       * NEWS: [no log message]
-
-2004-12-09 02:02  maan
-
-       * NEWS: [no log message]
-
-2004-12-09 01:03  maan
-
-       * command.c: new command: ctd: change dbtool on the fly
-
-2004-12-09 01:03  maan
-
-       * mysql.c: remove the silly try to report the cause of an error.
-         Provide shutdown function (deactivated for now)
-
-2004-12-09 01:00  maan
-
-       * dopey.c, server.c, server.h: init all dbtools on startup. Fall
-         back to dopey if all other dbtools fail to init.
-
-2004-12-08 23:34  maan
-
-       * mysql.c: rename cdb to create_db
-
-2004-12-08 23:23  maan
-
-       * dbtool.conf.sample: long obsolete
-
-2004-12-08 23:18  maan
-
-       * dbtool_template.c: got obsoleted by dopey
-
-2004-12-08 23:16  maan
-
-       * dbtool.c, dbtool.ggo: no longer needed
-
-2004-12-08 23:13  maan
-
-       * para.h, string.c: fix some compiler warnings
-
-2004-12-08 23:05  maan
-
-       * dopey.c: redirect stderr of find command to null
-
-2004-12-08 22:46  maan
-
-       * dopey.c: fix memory leak
-
-2004-12-08 22:46  maan
-
-       * Makefile.in, configure.ac: fixup autoconf stuff
-
-2004-12-08 22:15  maan
-
-       * net.c: remove unused variable
-
-2004-12-08 22:14  maan
-
-       * Makefile.in, configure.ac, server.c: Fix build on systems without
-         mysql. They'll get dopey ;) Do not build obsolete dbtool any
-         more.
-
-2004-12-08 21:58  maan
-
-       * dopey.c: dopey help update
-
-2004-12-08 21:56  maan
-
-       * Makefile.in, command.c, dopey.c, server.c, server.ggo, server.h:
-         the dopey database tool, codename 'ddt'
-
-2004-12-08 20:25  maan
-
-       * para.h, string.c: use const qualifiers in para_strcat()
-
-2004-12-08 20:25  maan
-
-       * command.c:  report dbtool info in com_si()
-
-2004-12-08 20:10  maan
-
-       * afs.c, command.c, mysql.c, server.c, server.h: switch from single
-         struct dbtool to array of struct dbtool as a preparation for
-         supporting several database tools.
-
-2004-12-08 04:24  maan
-
-       * afs.c, command.c, server.h: change type of mmd->mtime to time_t
-
-2004-12-08 04:10  maan
-
-       * command.c, server.c, server.h: kill num_connects(). A simple
-         variable is enough.
-
-2004-12-08 04:00  maan
-
-       * server.c: get_user(): scan at most 200 chars per entry avoiding
-         possible buffer overflow with bad user_list file
-
-2004-12-08 03:58  maan
-
-       * mysql.c: Fix high-quality double free bug which was sitting there
-         for quite some time since it was hard to trigger. This sucker
-         made _subsequent_ sql queries hang. Kill it with pleasure.
-
-2004-12-08 02:34  maan
-
-       * exec.c: fix dup2 stderr
-
-2004-12-08 02:16  maan
-
-       * mysql.c: rename _clean to clean
-
-2004-12-08 02:16  maan
-
-       * gui.c: do not kill writer immediately when reader dies.
-
-2004-12-08 02:01  maan
-
-       * gui.c: Nuke com_sl. Can be done via key mapping
-
-2004-12-08 00:49  maan
-
-       * command.c: nasty use before init bug
-
-2004-12-07 22:50  maan
-
-       * command.c: simplify cmd_perms_itohuman()
-
-2004-12-07 22:44  maan
-
-       * afs.c, command.c, server.h: move afs_get_status_flags() to
-         command.c. It's only needed there, so make it static. Use dynamic
-         buffer.
-
-2004-12-07 22:38  maan
-
-       * command.c: afs_status_tohuman(): return dynamic buffer
-
-2004-12-07 22:33  maan
-
-       * afs.c, command.c, server.h: move afs_status_tohuman() to
-         command.c. It's only needed there, so make it static.
-
-2004-12-07 22:24  maan
-
-       * server.c: report loglevel on startup
-
-2004-12-07 22:23  maan
-
-       * para.h: kill unused loglevel ALERT
-
-2004-12-07 22:23  maan
-
-       * afs.c: remove some old code
-
-2004-12-07 22:11  maan
-
-       * afs.c, mysql.c, ogg.c, server.c: some smallish cleanups
-
-2004-12-07 22:10  maan
-
-       * server.ggo: set default loglevel to 4
-
-2004-12-07 21:28  maan
-
-       * afs.c, server.c: simplify setup_stream_command(). Abort on
-         errors.
-
-2004-12-07 02:09  maan
-
-       * mysql.c: reintroduce com_la as it is needed by dbadm
-
-2004-12-07 01:56  maan
-
-       * command.c: do not divide by zero
-
-2004-12-07 01:51  maan
-
-       * ogg.c: loglevel adjustments
-
-2004-12-07 01:38  maan
-
-       * command.c: Delete unused stuff. Fairly impressive patch :)
-
-2004-12-07 01:32  maan
-
-       * command.c: sort commands alphabetically
-
-2004-12-07 01:23  maan
-
-       * command.c, server.c: clean up com_sc()
-
-2004-12-07 01:07  maan
-
-       * command.c: clean up com_stat() and compute_status_volatile()
-
-2004-12-07 00:18  maan
-
-       * command.c: make uptime_str() return dynamically allocated buffer.
-         Clean up com_si().
-
-2004-12-07 00:10  maan
-
-       * command.c: rename compute_sb_string() to get_sb_string() and
-         return dynamically allocated buffer.
-
-2004-12-06 23:37  maan
-
-       * command.c: rename compute_status() to get_status() and return
-         dynamically allocated buffer
-
-2004-12-06 23:00  maan
-
-       * command.c: make cmd_perms_itohuman() return dynamically allocated
-         4 char permission string. Used by com_help(). This makes
-         com_perms obsolete. Comment out
-
-2004-12-06 22:15  maan
-
-       * command.c: rename find_cmd(). No good name.
-
-2004-12-06 22:11  maan
-
-       * command.c: make find_command() also return the handler (server or
-         dbtool). That makes cmd_handler_itohuman() obsolete, and in turn
-         other functions unused. Comment out what is unneeded.
-
-2004-12-06 21:51  maan
-
-       * command.c: found still more lcl stuff, kill unused var:
-         dbtool_has_pic
-
-2004-12-06 21:49  maan
-
-       * command.c: comment out remaining lcl stuff
-
-2004-12-06 21:48  maan
-
-       * command.c, string.c: move chop() from command.c to string.c
-
-2004-12-06 21:45  maan
-
-       * command.c: comment out unused lcl_init()
-
-2004-12-06 21:42  maan
-
-       * server.c: deactivate lcl stuff
-
-2004-12-06 21:41  maan
-
-       * command.c: fix silly bug that crept in by the last patch
-
-2004-12-06 21:36  maan
-
-       * command.c: simplify send_descriptions(), find_command() and fix
-         com_help()
-
-2004-12-06 20:28  maan
-
-       * command.c: kill useless dummy entries, documentation update.
-
-2004-12-06 20:21  maan
-
-       * afs.c, command.c, server.c: Since we hold a dbtool pointer in mmd
-         there is no need to export it any longer
-
-2004-12-06 20:06  maan
-
-       * command.c: make com_perms() use the internal command list rather
-         than old linked command list
-
-2004-12-06 20:05  maan
-
-       * mysql.c: set name in init
-
-2004-12-06 20:04  maan
-
-       * server.c: set mmd->dbtool in do_inits()
-
-2004-12-06 20:03  maan
-
-       * server.h: New field in struct dbtool: name to be used by
-         com_perms(). New field in mmd: dbtool, a pointer to the currently
-         selected database tool, also used in com_perms(). Currently,
-         there is only one, but this will change once ddt, the dopey
-         database tool, is born.
-
-2004-12-06 19:10  maan
-
-       * command.c: comment out obsolete server-based com_pic()
-
-2004-12-06 04:08  maan
-
-       * mysql.c: make com_cam() also copy the meta data
-
-2004-12-06 03:25  maan
-
-       * mysql.c: as we have extern struct conf in mysql.c there is no
-         need to shadow its values
-
-2004-12-06 03:11  maan
-
-       * mysql.c: some more cosmetics
-
-2004-12-06 03:04  maan
-
-       * mysql.c: only while space cleanups
-
-2004-12-06 02:57  maan
-
-       * mysql.c: nuke get_very_last() which was commented out anyway
-
-2004-12-06 02:52  maan
-
-       * mysql.c: reorganize functions,  simplify com_info()
-
-2004-12-06 02:31  maan
-
-       * mysql.c: new function: get_dir(). Switch back to three-line
-         dbinfo output
-
-2004-12-06 01:39  maan
-
-       * mysql.c: fix get_dbinfo()
-
-2004-12-06 01:20  maan
-
-       * mysql.c: simplify com_cdb() a bit
-
-2004-12-06 01:10  maan
-
-       * mysql.c: port the last dbtool command: com_picch()
-
-2004-12-06 00:56  maan
-
-       * mysql.c: port com_piclistl()
-
-2004-12-06 00:49  maan
-
-       * mysql.c: port com_picdel()
-
-2004-12-06 00:40  maan
-
-       * mysql.c: port com_picass()
-
-2004-12-06 00:22  maan
-
-       * mysql.c: port com_pic()
-
-2004-12-05 23:48  maan
-
-       * mysql.c: port com_verb()
-
-2004-12-05 23:37  maan
-
-       * mysql.c: simplify get_all_attributes(), fix two nasty
-         free()-related bugs
-
-2004-12-05 22:59  maan
-
-       * mysql.c: port com_cam()
-
-2004-12-05 20:51  maan
-
-       * mysql.c: port com_da()
-
-2004-12-05 20:46  maan
-
-       * mysql.c, para.h, string.c: introduce para_basename(), port
-         com_na()
-
-2004-12-05 17:20  maan
-
-       * mysql.c: port com_hist()
-
-2004-12-05 17:13  maan
-
-       * mysql.c: port mbox()
-
-2004-12-05 16:48  maan
-
-       * mysql.c: port com_ls()
-
-2004-12-05 07:12  maan
-
-       * command.c: fix segfault on invalid commands
-
-2004-12-05 07:10  maan
-
-       * server.c: report error message if command failed
-
-2004-12-05 06:03  maan
-
-       * server.c: nuke unused get_song_list()
-
-2004-12-05 05:24  maan
-
-       * mysql.c: port com_last()
-
-2004-12-05 05:04  maan
-
-       * mysql.c: simplify and fix get_all_attributes(), port com_laa()
-
-2004-12-05 04:36  maan
-
-       * mysql.c: refresh mmd->dbinfo also in commands sa and cs
-
-2004-12-05 04:20  maan
-
-       * mysql.c: use mmd-based get_current_song() instead of mysql's
-         entry with newest lastplayed time. That matters in view of
-         com_skip().
-
-2004-12-05 03:46  maan
-
-       * command.c: clean up com_help
-
-2004-12-05 03:20  maan
-
-       * mysql.c: update help for vrfy and us
-
-2004-12-05 03:20  maan
-
-       * command.c: simplify lcl_find and switch to help for new commands
-
-2004-12-05 02:40  maan
-
-       * mysql.c: port com_sa(). Simplify get_last()/get_very_last().
-
-2004-12-05 00:36  maan
-
-       * mysql.c: port com_skip()
-
-2004-12-05 00:26  maan
-
-       * mysql.c: activate new cdb/clean/upd/vrfy commands
-
-2004-12-05 00:15  maan
-
-       * mysql.c: port com_strq()
-
-2004-12-04 23:59  maan
-
-       * mysql.c: port com_strdel(), change current stream to '(none)' if
-         it gets deleted by strdel
-
-2004-12-04 23:39  maan
-
-       * mysql.c: make conf an extern variable in mysql.c, so there is no
-         need to pass it via init. Port com_cdb(), several small fixes.
-
-2004-12-04 23:37  maan
-
-       * server.c, server.h: make conf an extern variable in mysql.c, so
-         there is no need to pass it via init
-
-2004-12-04 21:23  maan
-
-       * mysql.c: port com_vrfy/clean
-
-2004-12-04 20:43  maan
-
-       * mysql.c: port com_upd(). This is not backward compatible. It
-         requires modification of find_cmd in server.conf. So it is
-         disabled until vrfy/clean are also ported.
-
-2004-12-04 20:40  maan
-
-       * exec.c: only close fd[1] if we dup2'ed it
-
-2004-12-04 20:39  maan
-
-       * server.c: abort if dbtool init failed
-
-2004-12-04 15:42  maan
-
-       * mysql.c: port stradd/picadd
-
-2004-12-04 15:33  maan
-
-       * server.ggo: nuke sstream option
-
-2004-12-04 14:31  maan
-
-       * fade.c: use csp instead of play
-
-2004-12-04 14:27  maan
-
-       * mysql.c: new command: csp (change stream and play). Needed since
-         com_play() no longer knows about streams and ignores its
-         arguments.
-
-2004-12-04 14:24  maan
-
-       * afs.c: update_mmd(): fix logging message for unknown audio format
-
-2004-12-04 14:15  maan
-
-       * afs.c: get_song(): log filenames as they are tried to open
-
-2004-12-04 02:23  maan
-
-       * mysql.c: fix com_sl. It used row[1] in results which contained
-         only one column. Fix help of com_streams().
-
-2004-12-04 02:21  maan
-
-       * afs.c: comment out obsolete popen dabtool us
-
-2004-12-03 21:36  maan
-
-       * mysql.c: omit current_stream in ps/ns/streams
-
-2004-12-03 21:28  maan
-
-       * command.c, server.h: com_stat: don't print score
-
-2004-12-03 20:51  maan
-
-       * mysql.c: make ps/ns refresh dbinfo
-
-2004-12-03 20:36  maan
-
-       * mysql.c: port com_ps() and com_ns()
-
-2004-12-03 20:08  maan
-
-       * afs.c, command.c, server.c, server.h: comment out obsolete stream
-         handling code. Internal commands don't know about streams any
-         more
-
-2004-12-03 19:46  maan
-
-       * afs.c, mysql.c, server.c, server.h: make dbtool write directly to
-         shared memory area, get_song_list() now returns char** (full path
-         list without scores)
-
-2004-12-03 17:21  maan
-
-       * afs.c, server.c: comment out old update_dbinfo()
-
-2004-12-03 00:17  maan
-
-       * mysql.c: also print score and stream in dbinfo
-
-2004-12-02 23:24  maan
-
-       * afs.c, mysql.c: use info string provided by  dbtool's
-         get_song_list (overwrite output of old para_dbtool). Other
-         smallish fixes also.
-
-2004-12-02 20:54  maan
-
-       * mysql.c: after the fork we will never see when the stream changes
-
-2004-12-02 20:53  maan
-
-       * mysql.c: remove global variable current_stream. It just doesn't
-         work because
-
-2004-12-02 03:18  maan
-
-       * afs.c, mysql.c: port com_cs() and activate new stream handling
-
-2004-12-02 01:43  maan
-
-       * afs.c: new implementation of get_song() that calls dbtool's
-         get_song function directly rather than calling popen_dbtool()
-         (not yet activated since com_cs is not yet ported)
-
-2004-12-02 01:33  maan
-
-       * mysql.c: new function get_song list to be called directly by afs
-         on song change via server's glue function
-
-2004-12-02 01:29  maan
-
-       * server.c: get_song glue function
-
-2004-12-02 01:28  maan
-
-       * server.h: new struct: db_song_info
-
-2004-12-02 01:27  maan
-
-       * string.c: para_strdup: return empty string if arg is NULL
-
-2004-12-01 22:10  maan
-
-       * mysql.c: port com_streams()
-
-2004-12-01 21:57  maan
-
-       * mysql.c: activate new com_sl()
-
-2004-12-01 04:39  maan
-
-       * mysql.c: fix theoretical memory leak
-
-2004-12-01 04:23  maan
-
-       * mysql.c: get_query: make sure to return NULL on errors
-
-2004-12-01 04:20  maan
-
-       * mysql.c: remove length[] check. We cover length[0]==0 anyway.
-
-2004-12-01 04:11  maan
-
-       * mysql.c: cosmetics
-
-2004-12-01 04:04  maan
-
-       * mysql.c: remove unnused variable 'ret'. reduce size of the last
-         remaining static buffer for sscanf.
-
-2004-12-01 04:00  maan
-
-       * mysql.c: make get_query() return char*, reducing one more static
-         buffer allocation. Free also accept/deny_opts ;)
-
-2004-12-01 03:42  maan
-
-       * mysql.c: further simplify string handling in where_clause
-
-2004-12-01 03:35  maan
-
-       * mysql.c: simplify where_clause logic, free all variables
-
-2004-12-01 02:42  maan
-
-       * mysql.c: get_query: further removal of static buffers
-
-2004-12-01 02:32  maan
-
-       * mysql.c: get_query: remove underscores as it is no longer needed
-
-2004-12-01 02:30  maan
-
-       * mysql.c: Clean up get_query, part II
-
-2004-12-01 02:17  maan
-
-       * mysql.c, para.h, string.c: remove 'dest' argument from
-         s_a_r_list(). Clean up get_query, part I
-
-2004-12-01 00:43  maan
-
-       * mysql.c: port com_sl()
-
-2004-12-01 00:40  maan
-
-       * net.c, string.c: cosmetics
-
-2004-12-01 00:29  maan
-
-       * string.c: loglevel adjustments
-
-2004-12-01 00:25  maan
-
-       * string.c: fix s_a_r in case of several matches
-
-2004-11-30 23:58  maan
-
-       * para.h, string.c: no more static buffers in s_a_r() and friends
-
-2004-11-30 22:18  maan
-
-       * dbtool.c, para.h, string.c: port regex stuff from dbtool.c to
-         string.c
-
-2004-11-30 21:38  maan
-
-       * net.c, para.h: new function: send_va_buffer. Oh yeah!
-
-2004-11-30 21:14  maan
-
-       * Makefile.in: link string.o to all executables that need it
-
-2004-11-30 20:42  maan
-
-       * mysql.c: activate new com_info() (by changing _info to info)
-
-2004-11-30 20:41  maan
-
-       * command.c: com help: also print commands from new api
-
-2004-11-30 20:25  maan
-
-       * Makefile.in, mysql.c, para.h, string.c: contains string handling
-         functions that might be useful for any part of paraslash
-
-2004-11-30 20:10  maan
-
-       * command.c, server.c, server.h: make dbtool an extern variable in
-         command.c
-
-2004-11-30 03:07  maan
-
-       * mysql.c: small cleanups in com_info()
-
-2004-11-30 02:39  maan
-
-       * mysql.c: simplify sql query for dir.dir
-
-2004-11-30 02:30  maan
-
-       * mysql.c: simplify get_atts a lot
-
-2004-11-30 02:03  maan
-
-       * mysql.c: port com_info, introduce para_strcat and para_strdup
-
-2004-11-30 00:24  maan
-
-       * mysql.c: use dynamic buffers provided by new make_message().
-         Introduce para_malloc and para_realloc to avoid checking malloc's
-         return value for each malloc call
-
-2004-11-29 21:54  maan
-
-       * mysql.c: port com_us to the new api
-
-2004-11-29 02:17  maan
-
-       * mysql.c: cosmetics
-
-2004-11-29 02:08  maan
-
-       * Makefile.in, mysql.c, server.c, server.h: port the first command,
-         summary, to the new api. It is called _summary for now
-
-2004-11-29 01:10  maan
-
-       * mysql.c, server.c, server.h: check config file directly in
-         mysql_init
-
-2004-11-29 00:40  maan
-
-       * mysql.c, server.c, server.h: port config file parsing from
-         dbtool.c to mysql.c
-
-2004-11-28 23:47  maan
-
-       * command.c, server.c, server.h: pass dbtool pointer to parse_cmd
-         and actually search the (new, but still empty) dbtool list for
-         commands
-
-2004-11-28 23:29  maan
-
-       * command.c: first search the commands in (emtpy, by now) command
-         list which was returned by mysql_init
-
-2004-11-28 23:11  maan
-
-       * command.c, server.c, server.h: simplify command handling (let
-         functions return struct command* instead of struct
-         linked_cmd_list* which is going to be removed soon)
-
-2004-11-28 23:00  maan
-
-       * Makefile.in, NEWS, server.c, server.ggo, server.h: first
-         preparations (that shouldn't break anything) to include dbtool
-         inside para_server
-
-2004-11-28 22:58  maan
-
-       * mysql.c: this will replace dbtool.c
-
-2004-11-28 22:10  maan
-
-       * Makefile.in, NEWS, configure.ac: bump version to 0.1.2
-
-2004-11-28 21:41  maan
-
-       * afs.c: afs_send_chunk: close stream writer on errors
-
-2004-11-28 21:40  maan
-
-       * dbtool.c: cosmetics
-
-2004-11-28 20:15  maan
-
-       * dbtool.c: make all commands take 3 arguments as required by
-         struct command from server.h
-
-2004-11-28 20:04  maan
-
-       * dbtool.c: simplify decls
-
-2004-11-28 20:01  maan
-
-       * dbtool.c: remove unneeded #includes
-
-2004-11-28 19:57  maan
-
-       * dbtool.c: rename .func to .handler in struct com to match it more
-         closely to struct command defined in server.h
-
-2004-11-25 21:05  maan
-
-       * gui.c: C+L does not clear the screen. Do not claim it will do so
-         in online help
-
-2004-11-25 21:02  maan
-
-       * server.ggo: better online help
-
-2004-11-12 14:56  maan
-
-       * NEWS: [no log message]
-
-2004-11-12 14:56  maan
-
-       * dbtool.c: rename ca to cam (copy all meta data). It now also
-         copies numplayed and lastplayed time as well as the picture id.
-
-2004-11-05 15:40  maan
-
-       * NEWS, configure.ac: bump version to 0.1.1
-
-2004-11-05 15:28  maan
-
-       * NEWS: [no log message]
-
-2004-11-05 15:27  maan
-
-       * ogg.c: add gpl header and mention that it is derived from vcut.c
-
-2004-11-05 15:25  maan
-
-       * CREDITS: add Michael Smith (vcut)
-
-2004-11-05 15:17  maan
-
-       * dbtool.c: new command: mbox
-
-2004-11-05 13:44  maan
-
-       * server.c: set afs_status_flags to AFS_PLAYING | AFS_NEXT if -a
-         and -s were given
-
-2004-11-01 19:20  maan
-
-       * NEWS: [no log message]
-
-2004-10-27 18:39  maan
-
-       * README: add para_krell
-
-2004-10-25 04:21  maan
-
-       * mp3.c, ogg.c: set default values for open_cmd. Fixes segfault
-         with empty config file.
-
-2004-10-25 03:51  maan
-
-       * dbtool.c: get_a: return -1 if database has no attributes
-
-2004-10-25 00:09  maan
-
-       * sdl_gui.c: refresh pic after executing command
-
-2004-10-24 23:32  maan
-
-       * FEATURES: [no log message]
-
-2004-10-24 23:29  maan
-
-       * autogen.sh: simple script for autoconf etc
-
-2004-10-24 20:50  maan
-
-       * addons/gkrellm_cmd_display/Makefile: remove para_ctrl stuff
-
-2004-10-24 20:49  maan
-
-       * addons/gkrellm_cmd_display/para_ctrl.c: it is now called krell.c
-         and belongs to the main tree
-
-2004-10-24 20:41  maan
-
-       * configure.ac: check for gtk2 and build para_krell only if it was
-         found
-
-2004-10-24 20:40  maan
-
-       * Makefile.in: new target: para_krell
-
-2004-10-24 20:39  maan
-
-       * krell.c: former para_ctrl
-
-2004-10-24 05:01  maan
-
-       * dbtool.c: cosmetics
-
-2004-10-22 21:26  maan
-
-       * Makefile.in: change codename
-
-2004-10-22 21:26  maan
-
-       * NEWS: [no log message]
-
-2004-10-22 18:42  maan
-
-       * addons/gkrellm_cmd_display/para_ctrl.c: new macro PRINTF
-
-2004-10-22 18:04  maan
-
-       * addons/gkrellm_cmd_display/para_ctrl.c: More duku, __func__
-
-2004-10-22 15:15  maan
-
-       * addons/gkrellm_cmd_display/para_ctrl.c: do not eat cpu if there
-         is no para_server
-
-2004-10-22 13:18  maan
-
-       * configure.ac: bump version to 0.1.0
-
-2004-10-22 13:00  maan
-
-       * mp3.c, ogg.c: cosmetics
-
-2004-10-17 21:46  maan
-
-       * index.html: mention that all files are signed
-
-2004-10-17 21:20  maan
-
-       * PUBLIC_KEY: gnupg public key
-
-2004-10-17 19:59  maan
-
-       * dbtool.c: kill unused init_seed()
-
-2004-10-17 17:58  maan
-
-       * command.c: compute percentage defensively also in com_ff
-
-2004-10-17 17:55  maan
-
-       * gui.c: kill all decoders if status pipe dies
-
-2004-10-17 17:54  maan
-
-       * command.c: compute percentage defensively
-
-2004-10-17 17:05  maan
-
-       * README.dbtool: english improvements
-
-2004-10-14 23:17  maan
-
-       * dbtool.c: remove the magic recursive randomizer. It is no longer
-         used since Lastplayed is never null
-
-2004-10-14 22:45  maan
-
-       * gui.c: clear top win in init_wins. This should fix stray
-         characters in top.win after resizing the xterm
-
-2004-10-14 22:32  maan
-
-       * gui.c: kill unused #define
-
-2004-10-14 22:28  maan
-
-       * gui.c: do not include header files twice
-
-2004-10-14 21:42  maan
-
-       * README.dbtool, dbtool.c, dbtool.ggo: replace option emph_np by
-         more general default_score. This actually _reduces_ code size.
-
-2004-10-14 20:54  maan
-
-       * dbtool.c: simplify s_a_r_array
-
-2004-10-13 23:19  maan
-
-       * dbtool.c: insert _valid_ default value into colum lastplayed for
-         new songs
-
-2004-10-11 20:30  maan
-
-       * Makefile.in: use new picdir for the internal pics of para_server
-
-2004-10-11 20:21  maan
-
-       * pics/paraslash/: default.jpg, no_pics.jpg: moved from ..
-
-2004-10-11 20:20  maan
-
-       * pics/: default.jpg, no_pics.jpg: moved to pics/paraslash
-
-2004-10-11 20:18  maan
-
-       * pics/web/paraslash.png: moved from ../
-
-2004-10-11 20:18  maan
-
-       * pics/paraslash.png: moved to web
-
-2004-10-11 20:17  maan
-
-       * Makefile.in: small cleanups
-
-2004-10-11 19:57  maan
-
-       * pics/screenshots/: gui-2004-07-11.png, gui-2004-09-02.png,
-         gui-old.png, loglevel1-2004-07-28.txt, sdl_gui.jpg: more or less
-         old screenshots
-
-2004-10-11 19:16  maan
-
-       * index.html: it is now called manual.html, not manual.txt.html
-
-2004-10-11 19:15  maan
-
-       * Makefile.in: nuke targets tags and web as they only work on my
-         local machine anyway
-
-2004-10-11 17:59  maan
-
-       * pics/paraslash.png: logo from web page
-
-2004-10-11 17:20  maan
-
-       * index.html: the paraslash web page
-
-2004-10-10 23:10  maan
-
-       * NEWS: [no log message]
-
-2004-10-10 23:09  maan
-
-       * para.h: no more restrictions on comand length (I hope)
-
-2004-10-10 23:09  maan
-
-       * command.c: chop() can not be static since it is used by server
-         also
-
-2004-10-10 23:08  maan
-
-       * dbtool.c: cosmetics
-
-2004-10-10 23:02  maan
-
-       * client.c, server.c: no more restrictions on comand length (I
-         hope)
-
-2004-10-10 22:30  maan
-
-       * client.c: cosmetics
-
-2004-10-10 20:22  maan
-
-       * client.c: cosmetics
-
-2004-10-10 20:19  maan
-
-       * client.c: fix buffer overflow with long command lines
-
-2004-10-10 19:55  maan
-
-       * client.c: cosmetics
-
-2004-10-08 21:18  maan
-
-       * configure.ac: it runs fine with 2.53 (debian stable)
-
-2004-10-08 21:15  maan
-
-       * pob-ogg.ggo: forgotten to check it in
-
-2004-10-07 22:11  maan
-
-       * afs.c, gui.c, mp3.c, ogg.c, server.h: make gcc 2.95.4 happy
-
-2004-10-07 18:21  maan
-
-       * gui.c: close status pipe on read errors
-
-2004-10-07 18:10  maan
-
-       * command.c: free mem in correct order, fixes segfault on HUP
-
-2004-10-07 02:11  maan
-
-       * sdl_gui.c: make functions static where possible
-
-2004-10-07 00:18  maan
-
-       * README.dbtool: [no log message]
-
-2004-10-06 23:12  maan
-
-       * sdl_gui.c: make pictures work again
-
-2004-10-06 21:07  maan
-
-       * command.c, gui.c, server.c: cosmetics
-
-2004-10-06 20:35  maan
-
-       * command.c: make functions static where possible
-
-2004-10-06 20:32  maan
-
-       * command.c, server.h: use dynamically aloocated buffers in struct
-         command
-
-2004-10-06 19:33  maan
-
-       * dbtool.c: kill dead code in com_vrfy(): check for NULL entries
-
-2004-10-06 19:28  maan
-
-       * dbtool.c: always check return value of init()
-
-2004-10-06 19:24  maan
-
-       * dbtool.c: com_ca: shut down mysql connection
-
-2004-10-06 19:15  maan
-
-       * dbtool.c: fix memory leak
-
-2004-10-06 18:55  maan
-
-       * dbtool.c: free correct pointer
-
-2004-10-06 18:53  maan
-
-       * dbtool.c: refuse to insert too long stream/pic names
-
-2004-10-06 18:42  maan
-
-       * server.c: fix autoplay
-
-2004-10-06 18:33  maan
-
-       * README.dbtool: para_client hup is no longer necessary
-
-2004-10-06 18:30  maan
-
-       * afs.c, command.c, server.c, server.h: read stream list on demand
-         instead of keeping a (possibly obsolete) copy in memory. This
-         fixes com_stat which used stale pointers to current stream name
-         if server reloaded its stream_list due to SIGHUP. Another
-         advantage is that we don't need to send SIGHUP to the server any
-         more when modifying the stream list
-
-2004-10-04 03:14  maan
-
-       * command.c: fix integer overflow for very long (ogg) files
-
-2004-10-04 02:53  maan
-
-       * afs.c: return NULL on next request
-
-2004-10-04 02:52  maan
-
-       * ogg.c: end_of_input: close file and, more important, reset
-         short_write. This bug could cause files to be skipped. Ogg is
-         almost usable now
-
-2004-10-04 02:49  maan
-
-       * server.c: kill unneeded variable sw_pid
-
-2004-10-03 20:59  maan
-
-       * dbtool.c: set pic_id to 1 for new files
-
-2004-10-03 02:24  maan
-
-       * dbtool.c: com_sl: comment out debugging message
-
-2004-10-03 01:42  maan
-
-       * dbtool.c: set all but one filed as notnull. NULLs suck when
-         sorting
-
-2004-10-03 01:06  maan
-
-       * client.c: fix wrong order of arguments to clog that could cause
-         random segfaults
-
-2004-09-30 01:40  maan
-
-       * gui.c: fixup rereading of config file
-
-2004-09-27 02:53  maan
-
-       * command.c: fix integer overflow in stat output for very long ogg
-         files
-
-2004-09-27 02:27  maan
-
-       * ogg.c: dont update time when sending first page or when
-         repos_request
-
-2004-09-27 01:45  maan
-
-       * gui.c: reset buflen when deactivating stream io
-
-2004-09-27 01:28  maan
-
-       * gui.c: delete old stream io handling code
-
-2004-09-27 00:00  maan
-
-       * gui.c: loop over all audio formats in do_select and kill decoder
-         when inactive
-
-2004-09-26 19:09  maan
-
-       * gui.c: clog: print msg to stderr if curses not yet active
-
-2004-09-26 19:07  maan
-
-       * dbtool.c: so not duplicate info
-
-2004-09-26 18:44  maan
-
-       * ogg.c: do not log short writes
-
-2004-09-26 18:43  maan
-
-       * afs.c: set stream writer fd to non-blocking io
-
-2004-09-26 18:41  maan
-
-       * ogg.c: handle short writes properly (do not even try to rewrite)
-
-2004-09-26 16:20  maan
-
-       * server.c, server.ggo: new option: autoplay
-
-2004-09-26 15:44  maan
-
-       * afs.c: more fixes of the same kind
-
-2004-09-26 15:37  maan
-
-       * afs.c: do not segfault in audio_format_name() if no audio_format
-         was selected yet
-
-2004-09-26 14:33  maan
-
-       * fade.c: more detailed output about what is going on
-
-2004-09-24 13:45  maan
-
-       * gui.c: cosmetics
-
-2004-09-24 04:23  maan
-
-       * gui.c: kill reader if writer died and vice versa
-
-2004-09-24 03:09  maan
-
-       * afs.c, server.c: comment out noisy debugging messages
-
-2004-09-24 03:04  maan
-
-       * afs.c, mp3.c, ogg.c, server.c, server.h: major rearrangement of
-         struct audio_format
-
-2004-09-23 19:20  maan
-
-       * ogg.c: reintroduce first_page, clear vcut on errors
-
-2004-09-23 18:43  maan
-
-       * mp3.c: avoid double close on errors
-
-2004-09-23 01:06  maan
-
-       * fade.conf.sample: adapt to new syntax
-
-2004-09-23 01:01  maan
-
-       * gui.conf.sample: kill obsolete commands
-
-2004-09-23 00:52  maan
-
-       * gui.c: new internal key bindings for adjusting loglevel
-
-2004-09-22 22:27  maan
-
-       * ogg.c: rename label aaa, kill dead code
-
-2004-09-22 22:10  maan
-
-       * ogg.c: kill dead code
-
-2004-09-22 22:07  maan
-
-       * ogg.c: nuke first_page
-
-2004-09-22 21:54  maan
-
-       * ogg.c: get output of first page right (I hope)
-
-2004-09-22 21:10  maan
-
-       * gui.c: don't segfault when stopping decoder manually. Avoid
-         kill_decoder also.
-
-2004-09-22 20:32  maan
-
-       * ogg.c: nuke unneeded cutpoint
-
-2004-09-22 20:06  maan
-
-       * 1.0: [no log message]
-
-2004-09-22 13:41  maan
-
-       * INSTALL: typo
-
-2004-09-22 02:56  maan
-
-       * ogg.c: remove more useless variables
-
-2004-09-22 02:52  maan
-
-       * ogg.c: replace fprintf by clog
-
-2004-09-22 02:47  maan
-
-       * ogg.c: cosmetics
-
-2004-09-22 02:34  maan
-
-       * ogg.c: remove unused variables
-
-2004-09-22 01:27  maan
-
-       * gui.c: loglevel adjustment
-
-2004-09-22 00:47  maan
-
-       * gui.ggo: default loglevel: 4
-
-2004-09-22 00:46  maan
-
-       * README.dbtool: typo
-
-2004-09-22 00:03  maan
-
-       * gui.c, gui.ggo: new option loglevel
-
-2004-09-21 23:53  maan
-
-       * gui.c: new function clog, log more info to bot win instead of
-         status bar
-
-2004-09-21 22:01  maan
-
-       * gui.c: increase sleep time after reader/writer has died
-
-2004-09-21 21:16  maan
-
-       * gui.c: cosmetics
-
-2004-09-21 21:13  maan
-
-       * server.c: only send chunk if we are still playing
-
-2004-09-21 21:12  maan
-
-       * ogg.c: return early if there is no stream writer
-
-2004-09-21 21:10  maan
-
-       * pob-ogg.c: check return value of write and abort on errors. ifdef
-         out buffering for now.
-
-2004-09-21 20:53  maan
-
-       * gui.c, gui.ggo: introduce struct stream_io and siol[], an array
-         of such structs, each member holding all relevant information for
-         one audio format. Simplify options and add some docu for para_gui
-         -h.
-
-2004-09-21 18:12  maan
-
-       * gui.c: do not include \n in outputf
-
-2004-09-21 18:05  maan
-
-       * gui.c: print info top bot win when starting/stopping decoder
-
-2004-09-21 14:52  maan
-
-       * afs.c, command.c, gui.c, sdl_gui.c, server.h: print afs status
-         flags as extra line in stat output
-
-2004-09-20 03:23  maan
-
-       * ogg.c: loglevel adjustments
-
-2004-09-20 02:16  maan
-
-       * ogg.c: jumping appears to work
-
-2004-09-20 01:15  maan
-
-       * ogg.c: first version with jumping kind of working
-
-2004-09-19 23:31  maan
-
-       * command.c, mp3.c, server.h: long unsigned is enough
-
-2004-09-19 23:29  maan
-
-       * afs.c: return early from afs_send_chunk if there was a reposition
-         request
-
-2004-09-19 21:37  maan
-
-       * ogg.c: make granpos global and get rid of update_chunk_count
-
-2004-09-19 21:27  maan
-
-       * ogg.c: do not crash on jump in ogg files. Jumping still is not
-         working, but we are getting closer...
-
-2004-09-19 18:12  maan
-
-       * ogg.c: minor improvements
-
-2004-09-19 17:56  maan
-
-       * afs.c: use stop_stream instead of closing file manually
-
-2004-09-19 17:26  maan
-
-       * pob-ogg.c: skip initial crap before first ogg packet, more
-         logging, fix config_file thinko
-
-2004-09-19 15:42  maan
-
-       * pob-ogg.c: Oh boy, that was buggy. For instance, it included
-         client_cmdline.h instead of pob-ogg.cmdline.h
-
-2004-09-18 15:29  maan
-
-       * configure.ac: build para_pob-ogg if oggvorbis libs are found
-
-2004-09-18 15:08  maan
-
-       * mp3.c: comment out noisy debug message
-
-2004-09-18 15:07  maan
-
-       * afs.c: add audio format heuristics (based on filename)
-
-2004-09-18 13:44  maan
-
-       * command.c, mp3.c, para.h, server.c: nuke PETER_B ;) As in real
-         life, PETER_B happened to be useless for anything
-
-2004-09-18 13:09  maan
-
-       * mp3.c: stop stream writer on repos request. This gets rid of all
-         remaining cases of audio clipping, I hope
-
-2004-09-18 13:07  maan
-
-       * mp3.c: rename reposition_stream() to mp3_reposition_stream
-
-2004-09-18 13:06  maan
-
-       * mp3.c: split mp3_stop_stream, new function stop_stream_writer()
-
-2004-09-18 13:03  maan
-
-       * mp3.c: rename stop_stream to mp3_stop_stream
-
-2004-09-17 04:39  maan
-
-       * ogg.c: new function: get_page. Makes ogg_read_chunk much more
-         readable
-
-2004-09-17 04:14  maan
-
-       * ogg.c: remove dead code
-
-2004-09-17 04:12  maan
-
-       * ogg.c: no need to set have_page twice
-
-2004-09-17 04:08  maan
-
-       * ogg.c: avoid needless goto
-
-2004-09-17 03:30  maan
-
-       * ogg.c: new function page_out to clean up the cruft a bit
-
-2004-09-17 03:17  maan
-
-       * ogg.c: still crappy as hell, but a bit more stable. Repositioning
-         is not working yet.
-
-2004-09-17 01:27  maan
-
-       * fade.c: more verbose output
-
-2004-09-17 01:27  maan
-
-       * NEWS: [no log message]
-
-2004-09-17 01:10  maan
-
-       * gui.c: fix clipping when returning from external command
-
-2004-09-17 00:53  maan
-
-       * afs.c, dbtool.c, dbtool_template.c, gui.c: rename fut to sl
-         (score list). It did not print the future anyway, depending on
-         the particular score definition
-
-2004-09-15 22:13  maan
-
-       * afs.c, command.c, server.h: si: report supported audio formats
-
-2004-09-15 21:22  maan
-
-       * command.c: rename uptime to si (server info)
-
-2004-09-12 20:49  maan
-
-       * fade.c, fade.ggo: introduce fall asleep stream vs sleep_stream
-
-2004-09-12 20:33  maan
-
-       * mp3.c: nicer id3 tag info
-
-2004-09-12 20:33  maan
-
-       * command.c: use long unsigned for computing seconds etc. in
-         statusbar
-
-2004-09-12 20:32  maan
-
-       * ogg.c: it kinda works in some sense if you do not try to jump
-         around...
-
-2004-09-12 20:20  maan
-
-       * afs.c: cosmetics
-
-2004-09-12 20:20  maan
-
-       * INSTALL: better english
-
-2004-09-12 20:19  maan
-
-       * CREDITS: [no log message]
-
-2004-09-11 05:55  maan
-
-       * INSTALL: typo
-
-2004-09-07 21:47  maan
-
-       * server.h: function prototype changes
-
-2004-09-07 21:45  maan
-
-       * server.ggo: stream_write command may be given multiple times,
-         nuke afs_buf
-
-2004-09-07 21:44  maan
-
-       * pob-ogg.c: introduce OGG_BUFFSIZE and fill buffer halfways before
-         any output occurs
-
-2004-09-07 21:41  maan
-
-       * mp3.c: mostly rearrangement of functions and small adjustments
-
-2004-09-07 21:39  maan
-
-       * gui.c: support oggvorbis, not yet fit for more audio formats
-
-2004-09-07 21:36  maan
-
-       * command.c: adjustments due to removal of afs_buf and renaming of
-         mmd->frames_sent to mmd->chunks_sent
-
-2004-09-07 21:34  maan
-
-       * afs.c: nuke generic_write_chunk and move relevant bits  to mp3.
-         Iplement better syntax for stream_write_cmd (can be given
-         multiple times, one for each sound format). Many small changes
-
-2004-09-07 21:27  maan
-
-       * server.c: nuke afs_buf, send_chunk takes FILE* now
-
-2004-09-07 21:24  maan
-
-       * configure.ac: add checks for oggvorbis
-
-2004-09-07 21:23  maan
-
-       * Makefile.in: add targets for para_pob-ogg
-
-2004-09-04 13:51  maan
-
-       * FEATURES: [no log message]
-
-2004-09-02 20:19  maan
-
-       * server.h: remove superflous function prototypes
-
-2004-09-02 20:12  maan
-
-       * mp3.c: simplify open_stream
-
-2004-09-02 20:02  maan
-
-       * sdl_gui.c: stat: print audio format
-
-2004-09-02 19:51  maan
-
-       * command.c, gui.c: stat: print audio format, report size in KB
-         instead of bytes
-
-2004-09-02 19:26  maan
-
-       * command.c, server.c, server.h: move uptime_str() from server.c to
-         command.c, it is only used there
-
-2004-09-02 19:22  maan
-
-       * server.c: whitespace fixes
-
-2004-09-02 19:21  maan
-
-       * server.c, server.h: make more functions static
-
-2004-09-02 19:12  maan
-
-       * server.c, server.h: remove logfile from mmd
-
-2004-09-02 18:56  maan
-
-       * server.c, server.h: remove user_list from mmd
-
-2004-09-02 18:41  maan
-
-       * server.c: whitespace fixes
-
-2004-09-02 18:37  maan
-
-       * server.c, server.h: move config_file from mmd to parse_config
-
-2004-09-02 18:24  maan
-
-       * server.c: fix --config_file option
-
-2004-09-02 18:19  maan
-
-       * command.c, server.h: move dbtool_has_pic from mmd to command.c
-
-2004-09-02 18:10  maan
-
-       * command.c, server.c, server.h: move lcl_head from mmd to
-         command.c
-
-2004-09-02 18:09  maan
-
-       * afs.c: loglevel adjustment
-
-2004-09-02 18:06  maan
-
-       * gui.c: change stream_write_cmd_arg to mp3_write_cmd_arg
-
-2004-09-02 17:53  maan
-
-       * afs.c, server.c: cosmetics
-
-2004-09-02 17:41  maan
-
-       * gui.conf.sample, gui.ggo: rename stream_read_cmd to mp3_read_cmd,
-         dito for write
-
-2004-09-02 17:41  maan
-
-       * afs.c, command.c, server.h: commands stat and sb: print file type
-
-2004-09-02 17:39  maan
-
-       * 1.0: [no log message]
-
-2004-09-02 17:04  maan
-
-       * afs.c, server.c, server.h: mv alloc_afs_buf() from server to afs
-
-2004-09-02 16:41  maan
-
-       * afs.c, server.c, server.h: remove extern conf struct from afs.c.
-         Its only use was afs_buf_size which is now passed to
-         afs_send_chunk instead
-
-2004-09-02 16:38  maan
-
-       * NEWS: [no log message]
-
-2004-09-02 16:23  maan
-
-       * mp3.h: no longer needed
-
-2004-09-02 16:22  maan
-
-       * Makefile.in, afs.c, mp3.c, mp3.h, para.h, server.c, server.h:
-         move remaining mp3 specific stuff to mp3.c, introduce
-         open_stream, stop_stream function pointers for completely modular
-         audio format support. Make more functions static, get rid of
-         mp3.h
-
-2004-08-31 03:26  maan
-
-       * mp3.c: return 0 on eof instead of -1
-
-2004-08-31 02:32  maan
-
-       * afs.c, mp3.c, mp3.h, server.h: add infrastructure for dealing
-         with audio files of different format, many small cleanups
-
-2004-08-30 23:18  maan
-
-       * mp3.c, mp3.h: reduce mp3.h to bare minimum by moving everything
-         but function prototypes to mp3.c
-
-2004-08-30 22:46  maan
-
-       * Makefile.in, afs.c, mp3.c, mp3.h: move fread from afs.c to mp3.c
-         into new function mp3_read_chunk. Do some renaming also.
-
-2004-08-30 21:16  maan
-
-       * sdl_gui.ggo: kill option no_pics
-
-2004-08-30 21:15  maan
-
-       * mp3.c: print replacement texts if no id3 tag was found
-
-2004-08-30 21:14  maan
-
-       * command.c: move audio file info to status_volatile since it
-         contains bitrate which is not constant for vbr files
-
-2004-08-30 21:00  maan
-
-       * sdl_gui.c: adapt to new stat output
-
-2004-08-30 20:28  maan
-
-       * gui.c: adapt to new stat output
-
-2004-08-30 19:56  maan
-
-       * para.h: cosmetics
-
-2004-08-30 19:54  maan
-
-       * mp3.c: make functions static where possible
-
-2004-08-30 19:51  maan
-
-       * afs.c, mp3.c, mp3.h, server.h: move mp3info struct from mmd to
-         mp3.c where it belongs
-
-2004-08-30 19:21  maan
-
-       * afs.c, command.c, server.c, server.h: rename mp3_meta_data to
-         misc_meta_data
-
-2004-08-30 19:16  maan
-
-       * afs.c, command.c, mp3.c, mp3.h, server.h: move mp3 specific stuff
-         to mp3.c
-
-2004-08-30 16:52  maan
-
-       * afs.c: rename mp3_stream to audio_file
-
-2004-08-30 16:35  maan
-
-       * command.c, dbtool.c: cosmetics
-
-2004-08-30 16:25  maan
-
-       * Makefile.in: include manual.txt in tgz
-
-2004-08-30 16:19  maan
-
-       * INSTALL: [no log message]
-
-2004-08-30 15:43  maan
-
-       * Makefile.in, para.h: change mp3tech.[ch] to mp3.[ch]
-
-2004-08-30 15:40  maan
-
-       * mp3.c, mp3.h: former mp3tech.[ch]
-
-2004-08-30 15:40  maan
-
-       * mp3tech.c, mp3tech.h: renamed to mp3.[ch]
-
-2004-08-30 15:38  maan
-
-       * mp3tech.c, mp3tech.h: copyright fixes
-
-2004-08-30 15:19  maan
-
-       * Makefile.in: remove dependency on Makefile for cmdline stuff, so
-         that gengetopt is not required for build from tgz
-
-2004-08-30 05:44  maan
-
-       * Makefile.in, NEWS, afs.c, command.c, configure.ac, mp3tech.c,
-         mp3tech.h, para.h, server.c, server.h: major mp3-secific cleanup
-         and enhancements. This should fix timing issues with vbr mp3s
-
-2004-08-30 05:07  maan
-
-       * mp3info.h: most of it was never used, the rest went somewhere
-         else
-
-2004-08-30 05:05  maan
-
-       * textfunc.h: unnecessary
-
-2004-08-25 21:21  maan
-
-       * gui.c: whitespace cleanup
-
-2004-08-25 21:12  maan
-
-       * gui.c: fix memory leak in align_str, add some debugging code
-
-2004-08-23 23:59  maan
-
-       * 1.0: [no log message]
-
-2004-08-23 00:29  maan
-
-       * dbtool.c: comment out check for invalid null entries in
-         attributes as attribute columns are declared non-null anyway
-
-2004-08-21 17:18  maan
-
-       * server.c: minor main() cleanup
-
-2004-08-21 16:46  maan
-
-       * fade.ggo, server.ggo: beautify output of help option
-
-2004-08-21 15:44  maan
-
-       * client.c, dbtool.c, fade.c, gui.c, net.c, sdl_gui.c, server.c:
-         update to gengetopt 2.12.2 requires additional arg for
-         cmdline_parser_configfile
-
-2004-08-15 19:07  maan
-
-       * Makefile.in: Add ChangeLog to phony targets, cosmetics
-
-2004-08-15 19:04  maan
-
-       * dbtool.ggo: typo
-
-2004-08-15 18:35  maan
-
-       * afs.c: update_dbinfo: whitespace fixes
-
-2004-08-15 18:34  maan
-
-       * afs.c: update_dbinfo: always print three lines
-
-2004-08-15 04:01  maan
-
-       * dbtool.c: fix info: for songs not yet played, dir of song was not
-         shown
-
-2004-08-13 19:30  maan
-
-       * README.dbtool: another typo
-
-2004-08-13 19:17  maan
-
-       * README.dbtool: whitespace fixes to make grutatxt happy
-
-2004-08-13 19:13  maan
-
-       * README.dbtool: typo
-
-2004-08-13 19:08  maan
-
-       * NEWS: [no log message]
-
-2004-08-05 23:19  maan
-
-       * dbtool.c: use escaped_name also for updating numplayed
-
-2004-08-04 02:36  maan
-
-       * dbtool.c: fix skip command
-
-2004-07-29 12:50  maan
-
-       * server.c: fix log function for loglevel > VERBOSE
-
-2004-07-29 03:52  maan
-
-       * Makefile.in, NEWS: change codename
-
-2004-07-28 14:06  maan
-
-       * README: typo
-
-2004-07-25 17:41  maan
-
-       * VERSION: no longer needed
-
-2004-07-25 17:40  maan
-
-       * NEWS, configure.ac: bump version to 99
-
-2004-07-24 20:50  maan
-
-       * mp3tech.h: further simplify get_mp3_info
-
-2004-07-24 20:12  maan
-
-       * afs.c: skip song if mp3_info fails
-
-2004-07-24 19:22  maan
-
-       * mp3tech.c, mp3tech.h: further simplify get_mp3_info
-
-2004-07-24 17:51  maan
-
-       * mp3info.h, mp3tech.c: kill unneeded code
-
-2004-07-24 03:08  maan
-
-       * pob-ogg.c: simple http streamer for pogg-http
-
-2004-07-23 21:56  maan
-
-       * gui.c: simplify item placement in top.win
-
-2004-07-23 18:57  maan
-
-       * client.c, afs.c: __func__
-
-2004-07-23 18:50  maan
-
-       * client.c: whitespaces
-
-2004-07-23 18:47  maan
-
-       * net.c: __func__, whitespaces
-
-2004-07-23 18:43  maan
-
-       * server.c: typo
-
-2004-07-23 18:41  maan
-
-       * server.c: __func__
-
-2004-07-23 18:33  maan
-
-       * server.c: whitespace cleanup
-
-2004-07-23 18:31  maan
-
-       * server.c: cosmetics
-
-2004-07-23 18:26  maan
-
-       * INSTALL, Makefile.in, afs.c: cosmetics
-
-2004-07-21 23:46  maan
-
-       * Makefile.in: simplify install
-
-2004-07-21 23:45  maan
-
-       * dbtool.c, dbtool.ggo: new option: emph_np
-
-2004-07-21 23:43  maan
-
-       * README.dbtool: add section on pictures
-
-2004-07-21 23:29  maan
-
-       * README.dbtool: more details on scoring
-
-2004-07-21 20:29  maan
-
-       * afs.c: use proper types for return value of fread/write
-
-2004-07-20 20:15  maan
-
-       * gui.c: detect blocking writes by time, not by count
-
-2004-07-20 16:25  maan
-
-       * maint.mk: everything went to Makefile.in
-
-2004-07-20 16:24  maan
-
-       * INSTALL, Makefile.in, gui.c, maint.mk: INSTALL
-
-2004-07-20 15:37  maan
-
-       * FEATURES: [no log message]
-
-2004-07-20 04:34  maan
-
-       * configure.ac: cosmetics
-
-2004-07-20 03:46  maan
-
-       * dbtool.c: uncomment unused function
-
-2004-07-20 03:46  maan
-
-       * configure.ac: dbtool_template is no longer needed in extras
-         because it's always built
-
-2004-07-20 03:37  maan
-
-       * Makefile.in: introduce maintainer-clean for removing _all_
-         derived files
-
-2004-07-20 03:21  maan
-
-       * configure.ac: generated by autoscan, but heavily edited
-
-2004-07-20 02:52  maan
-
-       * gui.ggo: set default to auto-decoding
-
-2004-07-20 02:51  maan
-
-       * gui.c: reduce use of global variables
-
-2004-07-20 02:02  maan
-
-       * gui.ggo: input timeout is long gone
-
-2004-07-20 02:01  maan
-
-       * gui.c: cosmetics
-
-2004-07-20 01:20  maan
-
-       * gui.c: fix line numbering in COMMAND_MODE, use va_list for
-         print_in_bar
-
-2004-07-20 01:16  maan
-
-       * NEWS: [no log message]
-
-2004-07-20 01:16  maan
-
-       * Makefile.in: add -WAll to CCFLAGS, fix typo
-
-2004-07-19 21:21  maan
-
-       * para.h: don't include version.h
-
-2004-07-19 21:20  maan
-
-       * mp3info.h: resolve -DVERSION conflict
-
-2004-07-19 21:19  maan
-
-       * Makefile.in, maint.mk: move stuff from maint.mk to Makefile.in,
-         nuke paraslash_light
-
-2004-07-19 18:35  maan
-
-       * Makefile.in: use
-
-2004-07-19 18:07  maan
-
-       * install-sh: autoconf refuses to work without it, strange...
-
-2004-07-19 17:46  maan
-
-       * dbtool.c: include mysql/mysql.h instead of mysql.h
-
-2004-07-19 17:45  maan
-
-       * config.mk: no longer needed
-
-2004-07-19 17:44  maan
-
-       * SFont.c, SFont.h, sdl_gui.c: include SDL/SDL.h instead of SDL.h
-
-2004-07-19 17:43  maan
-
-       * Makefile: now created by autoconf from Maikefile.in
-
-2004-07-19 17:42  maan
-
-       * Makefile.in: switch to autoconf
-
-2004-07-19 12:19  maan
-
-       * gui.c: fix line numbering in command mode, cosmetics
-
-2004-07-19 12:18  maan
-
-       * afs.c: don't kill stream writer when song is finished
-
-2004-07-19 12:17  maan
-
-       * server.c: use IPC_PRIVATE, not hardcoded number for semget
-
-2004-07-15 20:57  maan
-
-       * command.c: fix com_ps
-
-2004-07-15 18:57  maan
-
-       * command.c: kill useless sleep, fix possible segfault
-
-2004-07-15 18:47  maan
-
-       * command.c: cosmetics
-
-2004-07-15 18:38  maan
-
-       * afs.c, command.c, server.c, server.h: fix play command by
-         introducing a new member in mmd: old_stream. It contains the
-         number of the stream that was selected as the song started.
-         Moreover, change mmd->stream from char[] to int. This makes the
-         patch so large.
-
-2004-07-14 02:01  maan
-
-       * dbtool_template.c, server.ggo: cosmetics
-
-2004-07-13 02:40  maan
-
-       * command.c: uptime: add afs_buf size to output
-
-2004-07-13 02:15  maan
-
-       * server.c: use PROCEED_MSG macro
-
-2004-07-13 02:03  maan
-
-       * server.c: cosmetics
-
-2004-07-13 01:57  maan
-
-       * server.c: re-allocate afs_buf on HUP, it's size might have
-         changed
-
-2004-07-13 01:56  maan
-
-       * afs.c: afs_send_chunk: rewrite on partial writes
-
-2004-07-13 00:03  maan
-
-       * fade.c: fade did not read config for silly reasons. Fix buffer
-         overflow while at it
-
-2004-07-12 22:48  maan
-
-       * dbtool.c, gui.c, sdl_gui.c: output also directory of sound file
-         in dbinfo
-
-2004-07-12 02:24  maan
-
-       * server.ggo: make help fit on 80 column terminals
-
-2004-07-12 02:23  maan
-
-       * server.c: move log message to where it belongs
-
-2004-07-12 02:23  maan
-
-       * para.h: cosmetics
-
-2004-07-12 02:19  maan
-
-       * gui.c: fix hang-when-stopped bug
-
-2004-07-12 02:18  maan
-
-       * afs.c: __func__
-
-2004-07-12 00:03  maan
-
-       * FEATURES: [no log message]
-
-2004-07-11 22:57  maan
-
-       * INSTALL, README, README.dbtool: various clarifications in
-         documentation
-
-2004-07-11 21:31  maan
-
-       * gui.c: init curses and winch cleanup
-
-2004-07-11 18:41  maan
-
-       * gui.c: hust re-order functions a bit
-
-2004-07-11 18:32  maan
-
-       * gui.c: dont close status pipe for external commands
-
-2004-07-11 17:33  maan
-
-       * gui.c: further simplify do_select logic
-
-2004-07-10 01:01  maan
-
-       * afs.c, server.c, server.ggo, server.h: make chunk buf size for
-         afs run-time configurable
-
-2004-07-09 02:39  maan
-
-       * gui.c: simplify logic in do_select
-
-2004-07-07 23:50  maan
-
-       * Makefile, command.c: output also build date, system and compiler
-         version in command 'version'
-
-2004-07-07 23:49  maan
-
-       * gui.c: cosmetics
-
-2004-07-07 22:57  maan
-
-       * fade.c: fix potential buffer overflow if /home/maan is too long
-
-2004-07-07 22:56  maan
-
-       * afs.c: cosmetics
-
-2004-07-07 22:55  maan
-
-       * gui.c: do_select: logical cleanup
-
-2004-06-30 13:26  maan
-
-       * fade.c: fix waketime in sweet_dreams
-
-2004-06-23 23:32  maan
-
-       * exec.c, server.c, server.ggo, server.h: move popeostream writer
-
-2004-06-23 23:31  maan
-
-       * afs.c: major send_chunk cleanup. Hot!
-
-2004-06-22 01:31  maan
-
-       * gui.c: cleanup dead code
-
-2004-06-20 18:13  maan
-
-       * server.ggo: kill unused option
-
-2004-06-20 18:10  maan
-
-       * FEATURES, INSTALL: some clarifications, typos
-
-2004-06-20 18:08  maan
-
-       * config.mk: cosmetics
-
-2004-06-20 18:06  maan
-
-       * fade.c: bail out if mixer cant be opened
-
-2004-06-20 17:55  maan
-
-       * fade.c: simplify sweet_dreams
-
-2004-06-20 16:28  maan
-
-       * command.c: improve play command: accepts stream as first
-         (optional) argument
-
-2004-06-20 16:25  maan
-
-       * gui.c: dont suck cpu if no server is available
-
-2004-06-12 03:10  maan
-
-       * gui.c: cosmetics
-
-2004-06-10 01:34  maan
-
-       * para.h: add prototype for exec_cmdline_pid_bg
-
-2004-06-09 03:04  maan
-
-       * gui.c: fix missing write on command exec
-
-2004-06-09 02:06  maan
-
-       * gui.c: check also stream write pipe in do_select, introduce ascii
-         logo
-
-2004-06-08 02:57  maan
-
-       * gui.c: it works fine with only 13 lines. Fix minor sigwinch bug
-         when resizing to very small windows
-
-2004-06-08 02:45  maan
-
-       * gui.c: fix color of separator
-
-2004-06-08 02:40  maan
-
-       * gui.c: kill com_exit. Leaving decoder in bg wont work anymore
-
-2004-06-08 02:36  maan
-
-       * gui.c: make it survive partial writes
-
-2004-06-08 02:08  maan
-
-       * gui.c: fix help output
-
-2004-06-08 02:05  maan
-
-       * gui.c: cosmetics
-
-2004-06-08 01:51  maan
-
-       * gui.c: retain screen content on window changes
-
-2004-06-07 23:20  maan
-
-       * gui.c: terminate decoder after 10 times EAGAIN
-
-2004-06-07 04:15  maan
-
-       * gui.c: better sigwinch handling
-
-2004-06-07 03:20  maan
-
-       * gui.c: it is pointless to have a fuction that only contains a
-         for(;;) loop
-
-2004-06-07 02:54  maan
-
-       * gui.c: avoid busy loop when there is nothing to do
-
-2004-06-07 02:12  maan
-
-       * gui.conf.sample: some more examples
-
-2004-06-07 02:02  maan
-
-       * gui.c: add some docu
-
-2004-06-07 01:44  maan
-
-       * gui.c: fix trailing whitespace
-
-2004-06-07 01:41  maan
-
-       * gui.c: no need to set nodelay every time
-
-2004-06-07 01:21  maan
-
-       * gui.ggo: short command line options
-
-2004-06-07 01:20  maan
-
-       * gui.c: simplify key_map, cosmetics
-
-2004-06-07 00:59  maan
-
-       * gui.conf.sample: update to new syntax
-
-2004-06-07 00:47  maan
-
-       * gui.c: cosmetics
-
-2004-06-07 00:43  maan
-
-       * gui.c: nuke GETSTR mode of do_select and com_decode. Many small
-         improvements
-
-2004-06-07 00:42  maan
-
-       * exec.c: two new exec functions without pipes. redirect unneded
-         fds to /dev/null
-
-2004-06-06 17:45  maan
-
-       * exec.c, gui.c, gui.ggo, para.h: implement own functions for
-         stream io
-
-2004-06-06 14:37  maan
-
-       * gui.c: new stop_decoder command
-
-2004-05-29 21:46  maan
-
-       * gui.c: declare more functions as static
-
-2004-05-29 21:43  maan
-
-       * gui.c: more cosmetics
-
-2004-05-29 21:28  maan
-
-       * gui.c: cosmetics
-
-2004-05-29 21:27  maan
-
-       * exec.c: dont mess with stderr
-
-2004-05-29 21:27  maan
-
-       * gui.c: bot window needs at least two lines
-
-2004-05-29 18:32  maan
-
-       * gui.c: color handling cleanup
-
-2004-05-29 17:36  maan
-
-       * gui.c: cosmetics
-
-2004-05-29 17:28  maan
-
-       * NEWS, gui.conf.sample: NEWS
-
-2004-05-29 17:21  maan
-
-       * fade.conf.sample: add fade options
-
-2004-05-29 17:21  maan
-
-       * gui.conf.sample: remove fade options
-
-2004-05-29 17:19  maan
-
-       * gui.c: remove dead code, small cleanups
-
-2004-05-29 17:05  maan
-
-       * exec.c, gui_common.c: move file_exists() from gui_common.c to
-         exec.c since fade also needs it
-
-2004-05-29 17:04  maan
-
-       * Makefile, config.mk: add para_fade
-
-2004-05-29 17:03  maan
-
-       * gui.c, gui.ggo: nuke soundcard stuff which was moved to fade
-
-2004-05-29 17:03  maan
-
-       * fade.c, fade.ggo: contains soundcard and linux specific stuff,
-         ripped out of gui.c, gui.ggo
-
-2004-05-29 14:12  maan
-
-       * gui.ggo: use typestr
-
-2004-05-29 13:45  maan
-
-       * README: add dbadm
-
-2004-05-27 23:48  maan
-
-       * gui_common.c, para.h: add prototypes of new exec functions
-
-2004-05-27 23:48  maan
-
-       * gui.c: use new exec functions to obtain pid of child
-
-2004-05-27 23:46  maan
-
-       * exec.c: fix up exec functions (use exec instead of return,
-         uhuhuhu), add variants of several functions that can return the
-         pid of child processes
-
-2004-05-27 23:44  maan
-
-       * dbadm.c: fix potential segfault
-
-2004-05-23 18:08  maan
-
-       * dbadm.c: fix menu in case of small window size
-
-2004-05-23 16:16  maan
-
-       * dbadm.c: use static functions
-
-2004-05-23 16:11  maan
-
-       * dbadm.c: fix filename printing for long filenames
-
-2004-05-23 15:41  maan
-
-       * Makefile, dbadm.c: use internal popen_xxx fuctions
-
-2004-05-22 16:23  maan
-
-       * Makefile, config.mk: include para_dbadm
-
-2004-05-22 16:22  maan
-
-       * client.c, server.c: increase limit for command line length
-
-2004-05-22 04:20  maan
-
-       * dbadm.c: color cleanups
-
-2004-05-22 03:38  maan
-
-       * dbadm.c: many small cleanups
-
-2004-05-22 02:44  maan
-
-       * dbadm.c: first usable version
-
-2004-05-22 01:02  maan
-
-       * dbadm.c: small tool to modify attributes
-
-2004-05-21 02:35  maan
-
-       * gui.c: new command: toggle auto decoding
-
-2004-05-21 01:54  maan
-
-       * gui.c: kill children on sigint
-
-2004-05-21 00:55  maan
-
-       * gui.c: close status pipe before executing external commands,
-         reopen afterwards
-
-2004-05-15 18:51  maan
-
-       * gui.c: typo
-
-2004-05-15 18:50  maan
-
-       * dbtool.c: free all dynamically allocated resources, static
-         functions, reduce use of exit()
-
-2004-05-12 21:23  maan
-
-       * gui.c: comment out debugging messages
-
-2004-05-12 21:18  maan
-
-       * gui.c: shutdown curses on external commands
-
-2004-05-12 20:30  maan
-
-       * NEWS: [no log message]
-
-2004-05-10 23:09  maan
-
-       * server.c: cosmetics
-
-2004-05-10 23:09  maan
-
-       * client.c: use C99 identifier __func__
-
-2004-05-10 22:12  maan
-
-       * para.h: avoid compiler warning
-
-2004-05-10 22:11  maan
-
-       * afs.c, command.c, server.c: update dbinfo only after commands
-         with perms & DB_WRITE != 0
-
-2004-05-10 04:20  maan
-
-       * gui.c: cosmetics
-
-2004-05-10 03:48  maan
-
-       * gui.c: make errmsg for unknown keys work again
-
-2004-05-10 03:39  maan
-
-       * gui.conf.sample: add standard key mappings
-
-2004-05-10 03:31  maan
-
-       * para.h: key is now a string, not a char
-
-2004-05-10 03:31  maan
-
-       * exec.c: typo
-
-2004-05-10 03:30  maan
-
-       * gui.c: make all commands runtime-configurable, make function keys
-         and control keys work in configfile, much nicer help page
-
-2004-05-09 22:12  maan
-
-       * gui.c: fix line numbering in help
-
-2004-05-09 22:08  maan
-
-       * server.c: move split_args function to exec.c
-
-2004-05-09 22:07  maan
-
-       * para.h: add new struct gui_command
-
-2004-05-09 22:06  maan
-
-       * gui.c: nicify help and improve key map handling
-
-2004-05-09 22:04  maan
-
-       * exec.c: move split_args from server.c, new function
-         popen_read_client_cmdline
-
-2004-05-09 16:29  maan
-
-       * gui.c, maint.mk: cosmetics
-
-2004-05-08 15:04  maan
-
-       * NEWS: [no log message]
-
-2004-05-08 15:01  maan
-
-       * gui.c: new command: V (print version)
-
-2004-05-08 14:31  maan
-
-       * maint.mk: set umask to 022 before creating files. Ugly
-
-2004-05-05 00:11  maan
-
-       * gui.c: cosmetics
-
-2004-05-04 23:40  maan
-
-       * gui.ggo: add new option: key_map to map keys to shell commands
-
-2004-05-04 23:26  maan
-
-       * gui.c: make reread config work again, cleanups
-
-2004-05-04 23:11  maan
-
-       * gui.c: kill key maps 0-9 (volume setting)
-
-2004-05-04 23:05  maan
-
-       * gui.conf.sample: add key_map comments
-
-2004-05-04 22:52  maan
-
-       * gui.c: implement key mappings, kill bogus transform_vol
-
-2004-05-04 02:31  maan
-
-       * client.c, dbtool.c, gui.c, gui.ggo, sdl_gui.c, server.c: update
-         to recent version of gengetopt
-
-2004-04-25 18:04  maan
-
-       * addons/gkrellm_cmd_display/para_ctrl.c: dont crash if no pic was
-         found
-
-2004-04-25 16:09  maan
-
-       * dbtool.c: get pic by identifier if name starts with '#'
-
-2004-04-25 16:08  maan
-
-       * bash_completion: add some more commands
-
-2004-04-25 16:01  maan
-
-       * README: cosmetics
-
-2004-04-25 04:52  maan
-
-       * addons/gkrellm_cmd_display/para_ctrl.c: info text, make it
-         survive theme cgange, cleanups
-
-2004-04-24 16:14  maan
-
-       * addons/gkrellm_cmd_display/para_ctrl.c: cosmetics
-
-2004-04-18 00:29  maan
-
-       * addons/gkrellm_cmd_display/: Makefile, cmd_display.c: again, too
-         much to document. Still buggy wrt opening/closing pipes
-
-2004-04-17 23:53  maan
-
-       * addons/gkrellm_cmd_display/para_ctrl.c: too much to tell
-
-2004-04-17 18:26  maan
-
-       * addons/gkrellm_cmd_display/para_ctrl.c: gkrellm plugin that
-         displays paraslash images
-
-2004-04-17 15:56  maan
-
-       * NEWS, command.c: new command: sc (song change)
-
-2004-04-10 13:10  maan
-
-       * addons/gkrellm_cmd_display/cmd_display.c: make scrolling work
-         again and make scrolling speed configurable
-
-2004-04-10 12:36  maan
-
-       * dbtool.c: cleanups
-
-2004-04-08 20:39  maan
-
-       * addons/gkrellm_cmd_display/cmd_display.c: make click left button
-         exec Mcommand
-
-2004-04-08 14:08  maan
-
-       * addons/gkrellm_cmd_display/cmd_display.c: scroll text
-
-2004-04-05 02:08  maan
-
-       * addons/gkrellm_cmd_display/cmd_display.c: cleanups
-
-2004-04-05 01:26  maan
-
-       * addons/gkrellm_cmd_display/cmd_display.c: cleanups
-
-2004-04-05 00:51  maan
-
-       * addons/gkrellm_cmd_display/: cmd_display.c: Can't crash it any
-         more
-
-2004-04-04 21:30  maan
-
-       * addons/gkrellm_cmd_display/cmd_display.c: fix memory leak, make
-         mouse button work again
-
-2004-04-04 20:21  maan
-
-       * addons/gkrellm_cmd_display/: Makefile, cmd_display.c: too much to
-         mention
-
-2004-04-04 16:15  maan
-
-       * addons/gkrellm_cmd_display/: Makefile, cmd_display.c: former
-         gkrellm-fileread-2.00
-
-2004-03-17 13:42  maan
-
-       * maint.mk: cosmetics
-
-2004-03-17 13:41  maan
-
-       * Makefile: use type -p rather than which to find poc-fec
-
-2004-03-17 13:36  maan
-
-       * 1.0: [no log message]
-
-2004-02-24 14:35  maan
-
-       * NEWS: [no log message]
-
-2004-02-20 16:27  maan
-
-       * gui.c: new command: x (quit, but leave decoder)
-
-2004-02-20 00:50  maan
-
-       * client.c: handle binary input properly
-
-2004-02-14 00:38  maan
-
-       * dbtool.c: cosmetics
-
-2004-02-02 02:33  maan
-
-       * command.c: cosmetics
-
-2004-02-02 02:27  maan
-
-       * NEWS: [no log message]
-
-2004-02-02 02:25  maan
-
-       * gui.c: new key binding: u (uptime)
-
-2004-01-25 01:05  maan
-
-       * README.dbtool, config.mk: cosmetics
-
-2004-01-25 01:05  maan
-
-       * INSTALL: streaming capabilities are no longer required for mp3
-         decoder
-
-2004-01-25 01:04  maan
-
-       * FEATURES: reformat to make it look nicer in html
-
-2004-01-24 23:52  maan
-
-       * dbtool_template.c: help must print _three_ lines
-
-2004-01-24 23:51  maan
-
-       * gui.ggo: use proper default value for decode_cmd
-
-2004-01-24 23:50  maan
-
-       * INSTALL, Makefile, README, config.mk: dbtool.sample script ->
-         dbtool_template.c
-
-2004-01-24 23:03  maan
-
-       * dbtool_template.c: C-version of former dbtool.sample shell script
-
-2004-01-24 23:03  maan
-
-       * dbtool.sample: replaced by dbtool_template.c
-
-2004-01-24 13:19  maan
-
-       * server.c: ignore sigpipe, nicify log message for sigchld
-
-2004-01-24 12:20  maan
-
-       * server.c: remove crappy and unused get_exit_status, kill sigpipe
-         handling code
-
-2004-01-24 12:11  maan
-
-       * NEWS: [no log message]
-
-2004-01-23 09:35  maan
-
-       * gui.c: new command: A (list attributes)
-
-2004-01-23 09:34  maan
-
-       * server.h: add afs_preselect
-
-2004-01-23 09:34  maan
-
-       * server.c: proper signal handling using signal pipe
-
-2004-01-19 00:05  maan
-
-       * net.c: handle partial sends properly
-
-2004-01-18 01:01  maan
-
-       * dbtool.c: new macro: PICID
-
-2004-01-18 01:01  maan
-
-       * NEWS: [no log message]
-
-2004-01-17 23:28  maan
-
-       * README.dbtool: major reorganisation/update
-
-2004-01-13 02:30  maan
-
-       * command.c, net.c, para.h: new function: send_buffer_ll. Like
-         send_buffer, but allows to specify loglevel
-
-2004-01-13 02:29  maan
-
-       * afs.c: cosmetics
-
-2004-01-13 02:00  maan
-
-       * NEWS: [no log message]
-
-2004-01-13 02:00  maan
-
-       * gui.c: add S (list streams)
-
-2004-01-13 01:59  maan
-
-       * Makefile, maint.mk: fix -V (version)
-
-2004-01-13 01:23  maan
-
-       * README.dbtool: update creation of streams
-
-2004-01-13 01:08  maan
-
-       * dbtool.c: get_query: thinko
-
-2004-01-13 01:01  maan
-
-       * dbtool.c: get_query: make an empty stream definition select all
-         songs
-
-2004-01-13 00:48  maan
-
-       * NEWS: [no log message]
-
-2004-01-13 00:48  maan
-
-       * afs.c: afs_send_chunk: either write to poc pipe or kill it
-
-2004-01-09 22:07  maan
-
-       * para.h, server.h: move CHUNK_BUFFSIZE from para.h to server.h
-
-2004-01-09 22:06  maan
-
-       * exec.c: new function: popen_write_poc. It returns pipe fd _and_
-         pid of poc-fec
-
-2004-01-09 22:00  maan
-
-       * afs.c, server.c: new functions: kill_poc/do_get_song. Move poc
-         stuff completely to afs
-
-2004-01-09 21:57  maan
-
-       * NEWS: [no log message]
-
-2004-01-06 23:21  maan
-
-       * server.h: new flag: AFS_REREAD_DB_INFO
-
-2004-01-06 23:21  maan
-
-       * server.c: check semop for return value and retry semop on error
-
-2004-01-06 23:18  maan
-
-       * gui.c: add new key-binding: Q -> strq
-
-2004-01-06 23:17  maan
-
-       * dbtool.c: nuke scan for unnecessary 'end:' fix potential buffer
-         overflow
-
-2004-01-06 23:16  maan
-
-       * command.c: set AFS_REREAD_DB_INFO after each dbtool command to
-         make dbinfo current in stat/gui
-
-2004-01-06 22:52  maan
-
-       * afs.c: single out update of db_info to call it also from server
-         when new flag AFS_REREAD_DB_INFO was set by child
-
-2004-01-05 00:51  maan
-
-       * dbtool.sample: help: output 3 columns
-
-2004-01-05 00:50  maan
-
-       * dbtool.c: piclist: order pics by id
-
-2004-01-05 00:50  maan
-
-       * command.c: uptime: print current loglevel
-
-2004-01-05 00:49  maan
-
-       * README, README.dbtool: [no log message]
-
-2004-01-04 21:55  maan
-
-       * server.h: add get_poc_pipe, change afs_send_chunk
-
-2004-01-04 21:54  maan
-
-       * maint.mk: remove html files on distclean
-
-2004-01-04 21:53  maan
-
-       * config.mk: move BINARIES from Makefile to config.mk to let the
-         user remove targets she doesn't want to build
-
-2004-01-04 21:51  maan
-
-       * afs.c, server.c: move opening/closing of poc pipe to afs, reopen
-         poc_pipe on AFS_REPOS to avoid clipping and decoder crashes
-
-2004-01-04 21:49  maan
-
-       * NEWS: [no log message]
-
-2004-01-04 21:49  maan
-
-       * Makefile: major cleanup, should compile faster on rebuilds
-
-2004-01-04 21:49  maan
-
-       * INSTALL, README.dbtool: more explanation, reordering
-
-2004-01-04 21:47  maan
-
-       * COPYING: change year to 2004
-
-2004-01-04 07:27  maan
-
-       * CREDITS, INSTALL, NEWS, README, README.dbtool, command.c,
-         dbtool.c, server.h: major documentation update
-
-2004-01-04 07:27  maan
-
-       * maint.mk: add manual.txt and web targets
-
-2004-01-04 07:26  maan
-
-       * server.c: dont exit if no streams were found on startup
-
-2004-01-04 02:18  maan
-
-       * afs.c: use POC_FEC which was located by make rather than relying
-         on
-         /home/maan/bin:/usr/local/bin:/usr/bin:/usr/X11R6/bin:/bin:/usr/local/scripts:/usr/local/mysql/bin:.:/usr/local/teTeX/bin/i586-pc-linux-gnu/:/home/maan/MIRROR/bin
-
-2004-01-04 02:17  maan
-
-       * Makefile: check also for poc-fec
-
-2004-01-04 02:07  maan
-
-       * README, afs.c, client.c, command.c, dbtool.c, gui.c, maint.mk,
-         para.h, sdl_gui.c, server.c, server.h: cosmetics
-
-2004-01-04 01:54  maan
-
-       * Makefile, config.mk, maint.mk: split Makefile into three parts
-
-2004-01-03 23:27  maan
-
-       * command.c, dbtool.c: cosmetics
-
-2004-01-03 22:38  maan
-
-       * NEWS: [no log message]
-
-2004-01-03 22:28  maan
-
-       * dbtool.c: new function: stdin2buf. make picadd accept jpeg data
-         from stdin. Change picch to only change name
-
-2004-01-03 20:00  maan
-
-       * gui.c: print key-bindings of c/C (next/previous stream) in help
-
-2004-01-03 19:59  maan
-
-       * dbtool.conf.sample: nuke streams
-
-2004-01-03 19:58  maan
-
-       * dbtool.c: strq: use memchr rather than strchr on potentially
-         binary data. stradd: properly escape stream definition
-
-2004-01-03 19:55  maan
-
-       * command.c: dbtool_cmd_handler: cleanup
-
-2004-01-03 19:54  maan
-
-       * client.c: cosmetics
-
-2004-01-03 19:53  maan
-
-       * afs.c: make get_song return -1 on errors rather than 0
-
-2004-01-03 19:52  maan
-
-       * README.dbtool: [no log message]
-
-2004-01-03 05:50  maan
-
-       * server.h: add modus to struct command
-
-2004-01-03 05:49  maan
-
-       * para.h: new #defines: AWAITING_DATA_MSG and PROCEED_MSG
-
-2004-01-03 05:49  maan
-
-       * net.c: new function: recv_bin_buffer
-
-2004-01-03 05:48  maan
-
-       * gui.c: bind ns to c again and ps to C
-
-2004-01-03 05:47  maan
-
-       * dbtool.ggo: nuke streams option
-
-2004-01-03 05:47  maan
-
-       * dbtool.c: new modus flag.  stream list is now stored inside mysql
-         db.  new commands: strq, stradd, strdel cdb: create all tables
-
-2004-01-03 05:44  maan
-
-       * command.c: new command flag: modus (read or write command). This
-         makes three command handlers: server/db_read/db_write.
-         Consequently, dbtool changed a lot.
-
-         new command: ps (reuse code of ns)
-
-2004-01-03 05:39  maan
-
-       * client.c: send stdin to server if server sends AWAITING_DATA_MSG
-
-2004-01-03 05:36  maan
-
-       * 1.0, FEATURES, NEWS, README: [no log message]
-
-2003-12-28 21:29  maan
-
-       * afs.c: reset mmd.vbr after each song. That seems to be
-         necessary..
-
-2003-12-28 04:16  maan
-
-       * Makefile, gui.c: cosmetics
-
-2003-12-28 02:35  maan
-
-       * gui.c: cosmetics
-
-2003-12-28 02:22  maan
-
-       * gui.c: hide cursor
-
-2003-12-27 21:07  maan
-
-       * FEATURES: [no log message]
-
-2003-12-27 14:49  maan
-
-       * Makefile, bash_completion, command.c, exec.c, gui.c,
-         gui_common.c, sdl_gui.c: replace remaining occurences of icc by
-         para
-
-2003-12-27 06:52  maan
-
-       * command.c, dbtool.sample, sdl_gui.c, sdl_gui.conf.sample: replace
-         more icc by para
-
-2003-12-27 06:35  maan
-
-       * Makefile, dbtool.sample, server.conf.sample: replace icc_server
-         by para_server
-
-2003-12-27 06:30  maan
-
-       * Makefile, client.c, dbtool.c, dbtool.sample, exec.c, gui.c,
-         gui_common.c, net.c, sdl_gui.c, server.h: replace icc.h by para.h
-
-2003-12-27 06:25  maan
-
-       * para.h: former icc.h
-
-2003-12-27 06:25  maan
-
-       * icc.h: renamed to para.h
-
-2003-12-27 06:21  maan
-
-       * CREDITS, INSTALL, Makefile, NEWS, README, README.dbtool,
-         client.c, client.conf.sample, client.ggo, command.c, dbtool.c,
-         dbtool.conf.sample, dbtool.ggo, gui.c, gui.ggo, icc.h, sdl_gui.c,
-         sdl_gui.ggo, server.c, server.ggo: replace icc by para
-
-2003-12-27 05:54  maan
-
-       * pics/default.jpg: no more stinky fingers as default, use
-         paraslash logo instead
-
-2003-12-27 00:12  maan
-
-       * xmms-1.2.7.titlebar_vbr_patch: no longer needed
-
-2003-12-27 00:11  maan
-
-       * NEWS: [no log message]
-
-2003-12-27 00:11  maan
-
-       * Makefile: remove dependencies on Makefile
-
-2003-12-26 21:51  maan
-
-       * VERSION: bump version number to 98
-
-2003-12-26 18:53  maan
-
-       * NEWS, README, README.dbtool, gui.c, icc.h: cosmetics
-
-2003-12-26 18:09  maan
-
-       * icc.h, server.h: move struct command from icc.h to server.h
-
-2003-12-26 18:07  maan
-
-       * icc.h, server.h: move struct user from icc.h to server.h
-
-2003-12-26 18:04  maan
-
-       * gui.c, gui_common.c, icc.h, sdl_gui.c: move open_stat_pipe to
-         gui_common.c
-
-2003-12-26 17:37  maan
-
-       * NEWS: [no log message]
-
-2003-12-26 17:37  maan
-
-       * sdl_gui.c: change placement to make all items fit on a 1024x768
-         screen. Also fix config file reading
-
-2003-12-26 17:37  maan
-
-       * afs.c, server.c: loglevel adjustments
-
-2003-12-26 17:37  maan
-
-       * gui_common.c: new function: file_exists
-
-2003-12-26 17:37  maan
-
-       * gui.c: simplify config_file exitst by using new function
-         file_exists
-
-2003-12-26 17:37  maan
-
-       * Makefile: tgz: make four tarballs
-
-2003-12-26 03:09  maan
-
-       * gui.c: base_key: return given value itsself rather that -1 if we
-         have no idea what is is
-
-2003-12-26 02:32  maan
-
-       * gui.c: print codename in Welcome message
-
-2003-12-26 02:32  maan
-
-       * Makefile: include CODENAME in version.h
-
-2003-12-26 02:10  maan
-
-       * server.h: nuke mmd->remaining since it is derived
-
-2003-12-26 02:10  maan
-
-       * gui.c: logical reordering of functions
-
-2003-12-26 02:09  maan
-
-       * server.c: cosmetics
-
-2003-12-26 02:08  maan
-
-       * afs.c, command.c: finetune former afs commands, nuke
-         mmd->remaining since it is derived
-
-2003-12-25 23:52  maan
-
-       * afs.c, server.c: send each file to separate poc process
-
-2003-12-25 21:32  maan
-
-       * gui.c: cosmetics
-
-2003-12-25 21:30  maan
-
-       * gui.c: simplify base_key function
-
-2003-12-25 20:41  maan
-
-       * gui.c: new command: CTRL+L to repaint screen
-
-2003-12-25 20:40  maan
-
-       * command.c: fix cr problem with sb
-
-2003-12-25 19:04  maan
-
-       * afs.c, command.c, server.h: move compute_sb_string from afs to
-         command.c allowing to nuke mmd->status_bar
-
-2003-12-25 18:39  maan
-
-       * afs.c, command.c, server.c, server.h: nuke mmd->afs_status, use
-         only status_flags instead
-
-2003-12-25 17:32  maan
-
-       * gui.c: new commands: F1-F10 to jmp, rename some commands
-
-2003-12-25 02:36  maan
-
-       * server.c, server.h: move gengetopt_args_info conf out of mmd
-
-2003-12-25 02:22  maan
-
-       * afs.c, server.h: get rid of file_status in mmd
-
-2003-12-25 02:06  maan
-
-       * afs.c, server.h: compute mmd->total and friends in
-         afs_send_chunk, not in update_mmd, get rid of mmd->soc
-
-2003-12-25 01:48  maan
-
-       * command.c, server.c, server.h: implement counter for currently
-         active connections
-
-2003-12-25 01:08  maan
-
-       * server.c, server.h: store semid for mmd locking in extern
-         variable, not in mmd itsself
-
-2003-12-25 01:05  maan
-
-       * command.c, server.c, server.h: move mmd lock functions from
-         command.c to server.c
-
-2003-12-25 00:54  maan
-
-       * afs.c, server.c: small logging cleanups
-
-2003-12-23 17:37  maan
-
-       * Makefile: add codename funny
-
-2003-12-23 17:11  maan
-
-       * afs.c, command.c, sdl_gui.c: stat prints wheather current mp3 has
-         vbr or not
-
-2003-12-23 05:25  maan
-
-       * server.c: init mmd->server_pid. That broke hup
-
-2003-12-23 05:23  maan
-
-       * afs.c: cosmetics
-
-2003-12-23 03:54  maan
-
-       * command.c: dont sleep after last status line has been printed
-
-2003-12-23 00:54  maan
-
-       * afs.c, server.c: add some logging
-
-2003-12-22 23:22  maan
-
-       * INSTALL, README: [no log message]
-
-2003-12-22 23:08  maan
-
-       * afs.c, client.c, command.c, net.c, server.c, server.h: change log
-         to clog to avoid compiler warnings
-
-2003-12-22 22:16  maan
-
-       * gui.conf.sample: adapt to new decode_cmd syntax
-
-2003-12-22 22:15  maan
-
-       * gui.c: introduce (and check in do_select) decoder_pipe to avoid
-         multiple instances of the decoder
-
-2003-12-22 16:08  maan
-
-       * server.h: adapt afs_send_chunk to new syntax
-
-2003-12-22 16:07  maan
-
-       * server.c: reopen poc pipe if afs_send_chunk failed
-
-2003-12-22 16:06  maan
-
-       * gui.c: ignore SIGCHLD and SIGPIPE
-
-2003-12-22 16:05  maan
-
-       * afs.c: make afs_send_chunk return negative value if write to
-         poc_pipe failed
-
-2003-12-22 04:59  maan
-
-       * server.c: fix stop command
-
-2003-12-22 04:58  maan
-
-       * command.c: fix stop command, log cleanups
-
-2003-12-22 04:57  maan
-
-       * afs.c: log cleanups
-
-2003-12-22 04:56  maan
-
-       * NEWS: aaa
-
-2003-12-22 04:56  maan
-
-       * Makefile: change THANKS to CREDITS
-
-2003-12-22 04:55  maan
-
-       * CREDITS: add Manuel Odendahl
-
-2003-12-22 02:55  maan
-
-       * CREDITS: former THANKS
-
-2003-12-22 02:55  maan
-
-       * THANKS: renamed to CREDITS
-
-2003-12-22 02:44  maan
-
-       * 1.0, INSTALL, Makefile, NEWS, README, afs.c, command.c, exec.c,
-         gui.c, gui.ggo, icc.h, server.c, server.conf.sample, server.ggo,
-         server.h: kick icecast, switch to poc
-
-2003-12-22 02:44  maan
-
-       * icecast.conf.sample, init_afs.c: no longer needed
-
-2003-12-20 15:48  maan
-
-       * server.c: kill pid_list code (was commented out)
-
-2003-12-20 15:44  maan
-
-       * gui.conf.sample: sample configuration file
-
-2003-12-20 15:43  maan
-
-       * NEWS: [no log message]
-
-2003-12-20 15:41  maan
-
-       * gui.c, gui.ggo: implement auto-decoding
-
-2003-12-20 15:39  maan
-
-       * afs.c: set status to playing _after_ the first chunk has been
-         streamed
-
-2003-12-18 01:48  maan
-
-       * command.c, server.c: fix term command which broke due to removal
-         of pid_list
-
-2003-12-17 00:54  maan
-
-       * SFont.c: include stdlib to avoid compiler warnings
-
-2003-12-17 00:28  maan
-
-       * NEWS: [no log message]
-
-2003-12-17 00:18  maan
-
-       * server.c: Pid was logged twice in debug mode. Fix it.
-
-2003-12-17 00:13  maan
-
-       * command.c, gui.c, init_afs.c, server.c: comment out racy pid_list
-         crap
-
-2003-12-04 23:22  maan
-
-       * dbtool.conf.sample: document gengetopt's strange behaviour
-         concerning backsslashes in arguments
-
-2003-12-04 01:29  maan
-
-       * dbtool.c: cosmetics
-
-2003-12-02 02:31  maan
-
-       * dbtool.c: fix help test format for verb
-
-2003-12-02 02:08  maan
-
-       * dbtool.c: print score of zero if it is undefined
-
-2003-12-02 00:37  maan
-
-       * dbtool.c: new command: verb
-
-2003-12-02 00:37  maan
-
-       * NEWS: [no log message]
-
-2003-12-01 23:20  maan
-
-       * SFont.h: Missing since ages. Reported by Thomas Forell
-
-2003-12-01 23:18  maan
-
-       * NEWS: insert release date of 0.0.97
-
-2003-11-23 21:19  maan
-
-       * gui.c: dont die on sigchld. That was silly. Instead, die on
-         sighup and change signal for rereading conf from hup to usr1
-
-2003-11-23 21:11  maan
-
-       * README.dbtool: document pic column
-
-2003-11-23 21:10  maan
-
-       * dbtool.c: test args_info.find_cmd_given, fix typo
-
-2003-11-20 00:22  maan
-
-       * gui.c: Die on sigchld. This should fix stale  processes that eat
-         up memory.
-
-2003-10-30 21:51  maan
-
-       * server.c, server.ggo: dont change stream on hup
-
-2003-10-26 14:11  maan
-
-       * VERSION: bump version number to 97
-
-2003-10-26 12:18  maan
-
-       * Makefile: add THANKS to txts
-
-2003-10-26 12:18  maan
-
-       * NEWS: cosmetics
-
-2003-10-26 00:46  maan
-
-       * NEWS: cosmetics
-
-2003-10-26 00:41  maan
-
-       * NEWS: nuke icc prefix
-
-2003-10-26 00:33  maan
-
-       * gui.c: com_sleep: change stream _after_ sleep
-
-2003-10-21 22:35  maan
-
-       * README.dbtool: some small changes
-
-2003-10-21 22:25  maan
-
-       * README: sdl_gui update
-
-2003-10-21 21:48  maan
-
-       * dbtool.ggo: gengetopt file for dbtool
-
-2003-10-21 21:46  maan
-
-       * THANKS: list of people who helped developing this project
-
-2003-10-21 21:23  maan
-
-       * gui.c: change snooze key from o to a (because it is easier to hit
-         on the keyboard when dazed and confused in the morning)
-
-2003-10-20 23:58  maan
-
-       * sdl_gui.ggo: add option w which is currently ignored but needed
-         to start sdl_gui from xscreensaver
-
-2003-10-20 23:57  maan
-
-       * gui.c: new function: outputf to print formated output. Avoid
-         sleep on startup, print message in bot window instead.
-
-2003-10-20 23:56  maan
-
-       * client.c: cosmetics
-
-2003-10-20 23:56  maan
-
-       * NEWS: [no log message]
-
-2003-10-20 22:33  maan
-
-       * gui.c: cosmetics
-
-2003-10-20 22:08  maan
-
-       * gui.c: do not cleanup in interrupt handler (that crap originally
-         came from some examples), set flag instead. This allows to omit
-         the strange sleep(1) in finish, so quiting quits immediately now.
-         Also, catch sigterm and exit gracefully.
-
-2003-10-20 21:43  maan
-
-       * gui.c: catch sighup and reread configuration on sighup
-
-2003-10-19 22:58  maan
-
-       * afs.c: cosmetics
-
-2003-10-19 17:11  maan
-
-       * gui.c: make sleep kinda work
-
-2003-10-11 18:49  maan
-
-       * dbtool.c: we only need basename of row[1]
-
-2003-10-11 18:46  maan
-
-       * command.c: help text update
-
-2003-10-11 18:46  maan
-
-       * NEWS: update
-
-2003-10-11 18:46  maan
-
-       * Makefile: Change default prefix to /usr/local
-
-2003-10-08 18:02  maan
-
-       * dbtool.c: update syntax of fut in help (reported by Thomas
-         Forell)
-
-2003-10-07 19:39  maan
-
-       * exec.c: dont dup stderr
-
-2003-10-07 19:38  maan
-
-       * gui.c, gui.ggo: add decode command
-
-2003-10-07 19:33  maan
-
-       * dbtool.c: remove useless printf
-
-2003-10-07 19:33  maan
-
-       * client.c: fix interactive mode (reported by Thomas Forell)
-
-2003-09-25 02:46  maan
-
-       * dbtool.c: minor cleanups
-
-2003-09-24 23:35  maan
-
-       * dbtool.conf.sample: put quotes around find_cmd
-
-2003-09-24 23:34  maan
-
-       * dbtool.c: switch to gengetopt
-
-2003-09-24 23:34  maan
-
-       * NEWS: update
-
-2003-09-24 23:34  maan
-
-       * Makefile: dbtool depends on dbtool.cmdline.c
-
-2003-09-23 20:46  maan
-
-       * Makefile: nuke unused TODO stuff
-
-2003-09-23 19:22  maan
-
-       * gui.ggo: gengetopt file for gui
-
-2003-09-23 19:17  maan
-
-       * command.c, icc.h, server.c: change all handlers from static int
-         com_foo(char *, int); to static int com_foo(int, int, char **);,
-         i.e. pass pointerarray instead of command line to handlers
-
-2003-09-23 19:13  maan
-
-       * afs.c: cosmetics
-
-2003-09-23 19:12  maan
-
-       * .tdldb: unused since May 2002
-
-2003-09-23 15:23  maan
-
-       * server.c: use popen_read_dbtool
-
-2003-09-23 15:23  maan
-
-       * sdl_gui.c: use popen_read_client
-
-2003-09-23 15:22  maan
-
-       * command.c, icc.h: cosmetics
-
-2003-09-22 22:04  maan
-
-       * gui.c: simplify cases (vol1 - vol9), add sleep command to help
-         text
-
-2003-09-22 21:46  maan
-
-       * gui.c: new function: configfile_exists.  do_select: change long
-         int timeout ro tong long timeout. Long timeouts didnt work
-         otherwise.  Fix thinko with select_timeout (introducing
-         default_select_timeout).  New function and command: reread
-         config.
-
-2003-09-22 20:59  maan
-
-       * afs.c: print two digits sor seconds in log info
-
-2003-09-22 17:18  maan
-
-       * gui.c: use gengetopt
-
-2003-09-22 17:18  maan
-
-       * Makefile: gui depends on gui.cmdline.c
-
-2003-09-22 02:50  maan
-
-       * command.c: cosmetics
-
-2003-09-22 02:43  maan
-
-       * dbtool.c: dokumentation update for na
-
-2003-09-22 02:30  maan
-
-       * afs.c: use mmd->size instead of equivalent
-         mmd->file_status.st_size
-
-2003-09-22 02:23  maan
-
-       * afs.c: cosmetics
-
-2003-09-22 02:08  maan
-
-       * icc.h: add popen_read_dbtool
-
-2003-09-22 02:08  maan
-
-       * command.c: use popen_read_dbtool, log correct fd in debug mode
-
-2003-09-22 02:06  maan
-
-       * afs.c: use popen_read_dbtool
-
-2003-09-22 02:06  maan
-
-       * exec.c: new function popen_read_dbtool
-
-2003-09-22 01:03  maan
-
-       * sdl_gui.c: use popen again for commands (with popoen_read,
-         commands having more than one arg doesnt work)
-
-2003-09-22 01:01  maan
-
-       * icc.h: add new function popen_read_client
-
-2003-09-22 01:01  maan
-
-       * gui.c: use new function popen_read_client
-
-2003-09-22 00:59  maan
-
-       * exec.c: new function: popen_read_client
-
-2003-09-22 00:59  maan
-
-       * command.c: adapt help text of ff to new syntax
-
-2003-09-22 00:58  maan
-
-       * Makefile: sdl_gui depends on exec.c
-
-2003-09-22 00:58  maan
-
-       * afs.c: make ff work again with negative offset
-
-2003-09-21 15:15  maan
-
-       * sdl_gui.c: use popen_read where it makes sense
-
-2003-09-19 14:19  maan
-
-       * server.conf.sample: replace never uptodate example configureation
-         by hint to read help
-
-2003-09-19 14:18  maan
-
-       * gui.c: use popen_read
-
-2003-09-19 14:17  maan
-
-       * exec.c: dont log anything, dont exit on errors, return NULL
-         instead
-
-2003-09-19 14:16  maan
-
-       * Makefile: icc_gui needs exec.c
-
-2003-09-18 03:35  maan
-
-       * gui.c: only use strlen if we really need to know the length
-
-2003-09-18 02:38  maan
-
-       * gui.c: cosmetics
-
-2003-09-18 02:24  maan
-
-       * gui.c: tidy up do_select
-
-2003-09-18 02:04  maan
-
-       * gui.c: fix output bug causing end of buffer being displayed on
-         next command
-
-2003-09-17 23:20  maan
-
-       * command.c: help: fix alphabetical ordering
-
-2003-09-17 22:53  maan
-
-       * server.c: use popen_read instead of popen
-
-2003-09-17 22:52  maan
-
-       * exec.c: dont write to stdout/stderr
-
-2003-09-17 22:52  maan
-
-       * command.c: cosmetics
-
-2003-09-17 22:38  maan
-
-       * command.c: lcl_init: use popen_read another time
-
-2003-09-17 22:35  maan
-
-       * command.c: lcl_init: use popen_read
-
-2003-09-17 22:07  maan
-
-       * server.c: always print strerror() text from exit status
-
-2003-09-17 22:07  maan
-
-       * icc.h: add prototype for popen_read_vp
-
-2003-09-17 22:06  maan
-
-       * exec.c: new function: popen_read_vp (ala execvp)
-
-2003-09-17 22:05  maan
-
-       * dbtool.c: change syntax of picass: Now ID has to be specified
-         instead of name.  escape filenames several times.
-
-2003-09-17 22:03  maan
-
-       * command.c: afs_cmd_handler: replace \n by space in args.  new
-         function: split args.  dbtool_cmd_handler: use popen_read_vp
-         instead of popen.
-
-2003-09-17 21:58  maan
-
-       * client.c: dont send addidtional space in commands
-
-2003-09-17 21:58  maan
-
-       * afs.c: dont log warnings on EINTR.
-
-2003-09-17 17:31  maan
-
-       * dbtool.c: info: dont continue if entry not found
-
-2003-09-17 17:26  maan
-
-       * dbtool.c: replace add_slashes by escape_str which calls
-         mysql_real_escape_string
-
-2003-09-17 00:49  maan
-
-       * NEWS: update
-
-2003-09-17 00:48  maan
-
-       * afs.c: replace popen by popen_read
-
-2003-09-17 00:32  maan
-
-       * icc.h: add popen_read
-
-2003-09-17 00:32  maan
-
-       * dbtool.c: modify add_slashes to return dynamically allocated
-         buffer.  use add_slashes in us and info.
-
-2003-09-17 00:30  maan
-
-       * afs.c: use popen_read instead of popen
-
-2003-09-17 00:30  maan
-
-       * Makefile: server depends on exec.c
-
-2003-09-17 00:29  maan
-
-       * exec.c: new: contains only popen_read for now
-
-2003-09-15 03:51  maan
-
-       * dbtool.c: cosmetics
-
-2003-09-15 03:16  maan
-
-       * dbtool.c: help text update
-
-2003-09-15 02:09  maan
-
-       * 1.0, command.c, server.conf.sample: print
-
-2003-09-15 02:01  maan
-
-       * dbtool.c: print mysql_error message in get_resuts, use strlen
-         only where neccessary
-
-2003-09-15 01:59  maan
-
-       * command.c: insert commands in alphabetical order into lcl
-
-2003-09-14 23:13  maan
-
-       * dbtool.c: cosmetics
-
-2003-09-14 20:15  maan
-
-       * dbtool.c: do not write to stderr
-
-2003-09-14 18:39  maan
-
-       * dbtool.c: fut: dont limit number of matches since we have to
-         consider all matches to make the magic randomizer work. That
-         hopefully fixed the bug that made output of fut appear
-         alphabetically ordered if there are many new songs.
-
-2003-09-14 17:30  maan
-
-       * server.h: nuke duplicated info in mmd.stream_name.  change pid_t
-         init_afs to void init_afs.  add pid_list_add.
-
-2003-09-14 17:28  maan
-
-       * server.ggo: use empty default value for stream
-
-2003-09-14 17:27  maan
-
-       * server.c: change static void pid_list_add(pid_t pid) to void
-         pid_list_add(pid_t pid).  exit on errors.  stream_list_init: make
-         sure that initial stream is valid.  simplify handle_sighup and
-         main.
-
-2003-09-14 17:24  maan
-
-       * init_afs.c: exit on errors.  set mmd->afs_pid
-
-2003-09-14 17:22  maan
-
-       * command.c:
-         replace mmd->stream_name by mmd->stream, handle_cmd: exit on
-         errors, new fuction: find_stream, simplify com_cs,
-
-2003-09-14 17:19  maan
-
-       * afs.c: replace mmd->stream_name by mmd->stream
-
-2003-09-13 19:50  maan
-
-       * server.c: new function: init_network
-
-2003-09-13 19:45  maan
-
-       * server.c: new function: init_network
-
-2003-09-13 19:44  maan
-
-       * icc.h, net.c: new functions: setserversockopts, do_bind
-
-2003-09-13 17:13  maan
-
-       * Makefile: make also light tarballs
-
-2003-09-13 16:47  maan
-
-       * NEWS, README, dbtool.c: small documentation update
-
-2003-09-13 16:38  maan
-
-       * Makefile: tgz include date in tarball
-
-2003-09-13 15:59  maan
-
-       * icc.h: do not include argtable.h
-
-2003-09-13 15:53  maan
-
-       * server.conf.sample: remove list of users
-
-2003-09-13 15:52  maan
-
-       * dbtool.conf.sample: change user name from maan to foo
-
-2003-09-13 15:51  maan
-
-       * INSTALL, README.dbtool: document cdb function
-
-2003-09-13 15:50  maan
-
-       * dbtool.c: new command: cdb (create database)
-
-2003-09-12 20:54  maan
-
-       * Makefile: add server.h to headers
-
-2003-09-12 20:28  maan
-
-       * net.c, server.c: logging adjustments
-
-2003-09-12 19:32  maan
-
-       * Makefile: clean: distclean: Remove also ChangLog.bak
-
-2003-09-12 19:24  maan
-
-       * dbtool.c: cosmetics
-
-2003-09-12 19:24  maan
-
-       * command.c: replace icc_server by server in help text
-
-2003-09-12 19:22  maan
-
-       * client.conf.sample: adapt name of keyfile
-
-2003-09-12 19:21  maan
-
-       * README.dbtool: typo
-
-2003-09-12 19:13  maan
-
-       * Makefile: adapt to new filenames without icc prefix
-
-2003-09-12 18:58  maan
-
-       * dbtool.sample: former icc_dbtool.sample
-
-2003-09-12 18:58  maan
-
-       * icc_dbtool.sample: rename to dbtool.sample
-
-2003-09-12 18:54  maan
-
-       * server.c: former icc_server.c
-
-2003-09-12 18:54  maan
-
-       * icc_server.c: rename to server.c
-
-2003-09-12 18:52  maan
-
-       * dbtool.c: former icc_dbtool.c
-
-2003-09-12 18:52  maan
-
-       * icc_dbtool.c: rename ro dbtool.c
-
-2003-09-12 18:49  maan
-
-       * gui.c: former icc_gui.c
-
-2003-09-12 18:49  maan
-
-       * icc_gui.c: renamed to gui.c
-
-2003-09-12 18:48  maan
-
-       * client.c: former icc_client.c
-
-2003-09-12 18:47  maan
-
-       * icc_client.c: renamed to client.c
-
-2003-09-12 18:16  maan
-
-       * afs.c, command.c, icc.h, icc_client.c, icc_dbtool.c, icc_gui.c,
-         init_afs.c, sdl_gui.c: nuke cvs keyword expansion
-
-2003-09-12 18:16  maan
-
-       * Makefile: ChangeLog: Dont show time
-
-2003-09-12 17:42  maan
-
-       * icc.h: nuke unused CONFIDENTIAL bit
-
-2003-09-12 17:41  maan
-
-       * INSTALL: update name of conf files
-
-2003-09-12 17:05  maan
-
-       * Makefile: clean: remove also HTML dir
-
-2003-09-12 17:02  maan
-
-       * Makefile, README: minor cleanups
-
-2003-09-12 16:51  maan
-
-       * dbtool.conf.sample: former icc_dbtool.conf.sample
-
-2003-09-12 16:51  maan
-
-       * icc_dbtool.conf.sample: rename to dbtool.conf.sample
-
-2003-09-12 16:50  maan
-
-       * server.conf.sample: former icc_server.conf.sample
-
-2003-09-12 16:49  maan
-
-       * icc_server.conf.sample: rename to server.conf.sample
-
-2003-09-12 16:48  maan
-
-       * icc_server.c: documentation cleanups
-
-2003-09-12 16:47  maan
-
-       * README.dbtool: comment new sa syntax
-
-2003-09-12 16:47  maan
-
-       * README: update
-
-2003-09-11 03:04  maan
-
-       * icc_server.c: use /dev/urandom to create random numbers
-
-2003-09-11 02:03  maan
-
-       * icc_server.c: cosmetics
-
-2003-09-11 01:53  maan
-
-       * command.c, icc_server.c: minor simplifyings/cleanups/log message
-         fixes
-
-2003-09-11 01:53  maan
-
-       * Makefile: change icc_bash_completion to bash_completion
-
-2003-09-11 01:25  maan
-
-       * bash_completion: former icc_bash_completion
-
-2003-09-11 01:25  maan
-
-       * icc_bash_completion: rename to bash_completion
-
-2003-09-11 01:24  maan
-
-       * icc_server.c, net.c: send_buffer: dont send nullbytes
-
-2003-09-11 01:24  maan
-
-       * icc_bash_completion: cosmetics
-
-2003-09-11 01:08  maan
-
-       * icc_server.c, net.c: modify init_sockaddr to suit needs of both
-         client and server
-
-2003-09-10 22:18  maan
-
-       * icc_bash_completion: adapt to new sa syntax
-
-2003-09-10 03:49  maan
-
-       * icc_dbtool.c: sa syntax conflixted with gengetopt. Fix that.
-
-2003-09-10 02:04  maan
-
-       * icc.h, icc_server.c, net.c: new function: do_accept
-
-2003-09-10 01:36  maan
-
-       * icc_server.c: new function handle_connect to reduce size of main
-
-2003-09-10 01:14  maan
-
-       * icc_server.c: decrease verbosity and avoid buffer overflow
-
-2003-09-10 00:39  maan
-
-       * net.c: fix silly bug
-
-2003-09-10 00:39  maan
-
-       * icc_server.c: use recv_buffer function from net.c
-
-2003-09-09 23:01  maan
-
-       * icc_server.c: daemon_init: reverse return value
-
-2003-09-09 21:48  maan
-
-       * afs.c, icc_server.c, init_afs.c, server.ggo, server.h: make hup
-         work again
-
-2003-09-09 17:17  maan
-
-       * sdl_gui.c: adapt to new syntax of check_buf_for_items
-
-2003-09-09 17:16  maan
-
-       * icc_gui.c: use check_buf_for_items whenever possible
-
-2003-09-09 17:14  maan
-
-       * icc.h: update check_buf_for_items()
-
-2003-09-09 17:13  maan
-
-       * gui_common.c: make check_buf_for_items work again...
-
-2003-09-09 17:12  maan
-
-       * command.c: afs_cmd_handler: write terminiating null byte
-
-2003-09-09 04:43  maan
-
-       * icc_gui.c, icc_server.c: some small cleanups
-
-2003-09-09 04:43  maan
-
-       * NEWS: update
-
-2003-09-09 04:04  maan
-
-       * icc_server.c: many small cleanups
-
-2003-09-09 03:27  maan
-
-       * icc_server.c: nuke unneded functions
-
-2003-09-09 03:23  maan
-
-       * server.ggo: gengetopt file for server
-
-2003-09-09 03:21  maan
-
-       * afs.c, icc_server.c, init_afs.c, server.h: switch to gengetopt
-
-2003-09-09 01:41  maan
-
-       * Makefile, afs.c, command.c, icc_server.c, init_afs.c: include
-         server.h instead of icc.h
-
-2003-09-09 01:41  maan
-
-       * icc.h: move server specific parts to server.h
-
-2003-09-09 01:40  maan
-
-       * server.h: server part of icc.h
-
-2003-09-09 01:16  maan
-
-       * Makefile: server: compile server.cmdline.c
-
-2003-09-09 00:43  maan
-
-       * Makefile: remove .c,.h files generated by gengetopt on distclean
-
-2003-09-09 00:33  maan
-
-       * client.conf.sample: former icc_client.conf.sample
-
-2003-09-09 00:33  maan
-
-       * icc_client.conf.sample: renamed to client.conf.sample
-
-2003-09-09 00:19  maan
-
-       * icc_client.c: setlinebuf is no longer needed
-
-2003-09-09 00:19  maan
-
-       * Makefile, icc.h, icc_gui.c, sdl_gui.c: use new gui_common
-
-2003-09-09 00:17  maan
-
-       * gui_common.c: common functions for sdl_gui and ncurses gui
-
-2003-09-08 23:16  maan
-
-       * icc_gui.c: make it work even when stat output contains null bytes
-
-2003-09-08 20:56  maan
-
-       * Makefile: filter out gengetopts c files from sources
-
-2003-09-08 20:42  maan
-
-       * sdl_gui.conf.sample: former icc_sdl_gui.conf.sample
-
-2003-09-08 20:41  maan
-
-       * icc_sdl_gui.conf.sample: rename to sdl_gui.conf.sample
-
-2003-09-08 20:40  maan
-
-       * Makefile, sdl_gui.c, sdl_gui.ggo: use sdl_gui.cmdline.c instead
-         of sdl_gui_cmdline.c, same for .h
-
-2003-09-08 20:35  maan
-
-       * client.ggo: gengetopt file for client
-
-2003-09-08 20:24  maan
-
-       * Makefile, command.c, icc.h: server: use net.c
-
-2003-09-08 20:17  maan
-
-       * net.c: new file, contains networking routines
-
-2003-09-08 20:16  maan
-
-       * Makefile, icc.h, icc_client.c: icc_client: use gengetopt and new
-         net.c
-
-2003-09-08 20:16  maan
-
-       * sdl_gui.c: typo
-
-2003-09-08 03:20  maan
-
-       * Makefile: remove version.h on distclean
-
-2003-09-08 03:15  maan
-
-       * icc_sdl_gui.conf.sample: sample configuration for sdl_gui
-
-2003-09-08 03:08  maan
-
-       * Makefile, sdl_gui.c: switch to gengetopts for sdl_gui
-
-2003-09-08 03:07  maan
-
-       * icc_dbtool.c: cosmetics
-
-2003-09-08 02:43  maan
-
-       * sdl_gui.ggo: gengetopt file for sdl_gui
-
-2003-09-07 21:30  maan
-
-       * NEWS: update
-
-2003-09-07 21:05  maan
-
-       * command.c, icc_server.c: cosmetics
-
-2003-09-07 20:42  maan
-
-       * command.c: cosmetics
-
-2003-09-07 20:25  maan
-
-       * command.c, icc.h, icc_server.c: nuke mmd->handler, rename
-         mmd->handler_fct to mmd->handler
-
-2003-09-07 20:10  maan
-
-       * command.c, icc.h, icc_server.c: nuke handle_cmd function since
-         all commands a now directly called via function pointers
-
-2003-09-07 18:41  maan
-
-       * command.c: use function pointers to execute internal commands
-
-2003-09-07 18:06  maan
-
-       * command.c, icc.h, icc_server.c: major lcl cleanup
-
-2003-09-07 15:43  maan
-
-       * command.c: simplify struct linked_cmd_list
-
-2003-09-07 15:16  maan
-
-       * command.c, icc.h: reordering of functions
-
-2003-09-07 14:37  maan
-
-       * icc_server.c, init_afs.c: logic was reversed in handle_sighup
-
-2003-09-07 14:34  maan
-
-       * command.c: own function for each internal command
-
-2003-09-07 05:56  maan
-
-       * afs.c, command.c, icc.h, icc_server.c, init_afs.c: major function
-         arguments cleanup
-
-2003-09-07 01:31  maan
-
-       * command.c, icc.h, icc_server.c, init_afs.c: move afs_server_pipe
-         and server_afs_pipe to mmd
-
-2003-09-07 00:59  maan
-
-       * command.c: C99 struct initializers
-
-2003-09-07 00:19  maan
-
-       * command.c: fix potential buffer overflow in compute_status
-
-2003-09-07 00:04  maan
-
-       * command.c: use static functions whenever possible
-
-2003-09-06 23:42  maan
-
-       * command.c: comment out unused lcl_log_list, cosmetics
-
-2003-09-06 23:29  maan
-
-       * command.c: change return type for lcl_del from int to void
-
-2003-09-06 23:17  maan
-
-       * command.c: fix potential buffer overflow, change return value of
-         lcl_add to void
-
-2003-09-06 23:02  maan
-
-       * command.c: cleanup crappy cmd_handler_itohuman
-
-2003-09-06 22:50  maan
-
-       * command.c: fix potential buffer overflow
-
-2003-09-06 22:43  maan
-
-       * command.c: cosmetics
-
-2003-09-06 22:40  maan
-
-       * command.c, icc.h, icc_server.c: handle_cmd doesnt need argument
-         mmd
-
-2003-09-06 22:35  maan
-
-       * afs.c: rename bear_server_pipe to afs_server_pipe
-
-2003-09-06 22:23  maan
-
-       * icc_server.c: rename cb_fd to afs_server_pipe
-
-2003-09-06 22:20  maan
-
-       * icc_server.c: cleanup crappy istrue function
-
-2003-09-06 20:37  maan
-
-       * afs.c, icc_server.c: cosmetics
-
-2003-09-06 20:32  maan
-
-       * afs.c: cosmetics
-
-2003-09-06 20:25  maan
-
-       * icc_server.c, afs.c, command.c, icc.h, init_afs.c: no need to
-         pass mmd via functions, it is an exported variable
-
-2003-09-06 20:07  maan
-
-       * icc_server.c: no need to pass mmd to handle_sighup
-
-2003-09-06 20:03  maan
-
-       * icc_server.c: use static functions whenever possible
-
-2003-09-06 19:52  maan
-
-       * icc_server.c: read_config: doesnt need return value, exit on
-         errors instead
-
-2003-09-06 19:45  maan
-
-       * icc_server.c: reverse logic after fork to have nicer idents
-
-2003-09-06 19:36  maan
-
-       * icc_server.c: minor cleanups
-
-2003-09-06 19:04  maan
-
-       * icc_server.c: handle_sighup doesnt need command line options
-
-2003-09-06 18:45  maan
-
-       * icc_server.c: read_config: close config file unconditionally
-
-2003-09-06 18:35  maan
-
-       * icc_server.c: read_config: close config file
-
-2003-09-06 18:29  maan
-
-       * icc.h: cmd_perms_itohuman doesnt need return value
-
-2003-09-06 18:25  maan
-
-       * icc_server.c, command.c: cmd_perms_itohuman doesnt need return
-         value
-
-2003-09-06 18:22  maan
-
-       * icc_server.c: fix potential buffer overflow, change challenge_nr
-         and chall_response to long unsigned
-
-2003-09-06 18:13  maan
-
-       * icc_server.c: indent main function
-
-2003-09-06 18:00  maan
-
-       * icc_server.c: C99 struct initializers
-
-2003-09-06 17:54  maan
-
-       * icc_server.c: simplify signal handling
-
-2003-09-06 16:47  maan
-
-       * icc_server.c: fix potential buffer overflow in encrypt
-
-2003-09-06 16:44  maan
-
-       * icc_server.c: fix potential buffer overflow in uptime_str
-
-2003-09-06 16:19  maan
-
-       * command.c, icc.h, icc_server.c: fix pidlist locking (I hope)
-
-2003-09-06 15:31  maan
-
-       * icc_server.c: use EXIT_FAILURE/EXIT_SUCCESS in exit()
-
-2003-09-06 15:26  maan
-
-       * icc_server.c: change int pid_list_add to void pid_list_add, same
-         with pid_list_unlock
-
-2003-09-06 15:07  maan
-
-       * icc_server.c: use size_t instead of int in set_conf()
-
-2003-09-06 15:06  maan
-
-       * afs.c: change int read_n_exec() to void read_n_exec()
-
-2003-09-06 14:45  maan
-
-       * afs.c: fix memory leak in mp3_info
-
-2003-09-06 14:00  maan
-
-       * afs.c, icc.h, icc_server.c: fix some minor bugs found by splint
-
-2003-09-06 13:11  maan
-
-       * icc.h: remove TRUE and FALSE
-
-2003-09-06 13:10  maan
-
-       * icc_gui.c: documentation update
-
-2003-09-06 13:10  maan
-
-       * icc_client.c: coding style
-
-2003-09-03 01:17  maan
-
-       * icc_client.c: still more coding style
-
-2003-09-02 23:45  maan
-
-       * icc_client.c: further coding style issues
-
-2003-09-02 23:17  maan
-
-       * icc_client.c: coding style cleanup
-
-2003-09-02 04:03  maan
-
-       * afs.c, icc_client.c: remove TRUE and FALSE
-
-2003-09-02 03:40  maan
-
-       * icc_client.c: indent main function
-
-2003-08-30 20:02  maan
-
-       * icc_gui.c: fix compile warning, change SNOOZE to 540 seconds
-
-2003-08-30 17:51  maan
-
-       * icc_dbtool.c: piclist now shows length of jpg files
-
-2003-08-30 17:18  maan
-
-       * VERSION: bump version number to 96
-
-2003-08-30 17:08  maan
-
-       * NEWS: update
-
-2003-08-30 17:06  maan
-
-       * icc_dbtool.c: vrfy/clean also checks for invalid pic pointers
-
-2003-08-30 16:13  maan
-
-       * icc_gui.c: update upper window also when fading volume
-
-2003-08-30 05:54  maan
-
-       * icc_dbtool.c: add some dokumentation
-
-2003-08-30 05:32  maan
-
-       * icc_dbtool.c: make picdel work when more than one id is given
-
-2003-08-30 05:26  maan
-
-       * icc_dbtool.c: simplify picadd
-
-2003-08-30 05:12  maan
-
-       * icc_dbtool.c: new command: picch, new function:
-         binfile2escaped_string
-
-2003-08-30 03:31  maan
-
-       * icc_dbtool.c: new command: picdel
-
-2003-08-30 01:40  maan
-
-       * sdl_gui.c: close icc pic pipes, default to pic mode, simplify
-         update_pic
-
-2003-08-30 01:37  maan
-
-       * icc_dbtool.c: new command: picass, new functions: get_very_last,
-         get_pic_id_by_name
-
-2003-08-30 01:33  maan
-
-       * command.c: simplify pic
-
-2003-08-29 22:14  maan
-
-       * icc_dbtool.c: new commands: picadd and piclist
-
-2003-08-29 17:18  maan
-
-       * Makefile: add fonts and pics to tgz
-
-2003-08-29 17:06  maan
-
-       * fonts/24P_Arial_Blue.png, fonts/24P_Arial_Metallic_Yellow.png,
-         fonts/24P_Arial_NeonBlue.png, fonts/24P_Arial_NeonYellow.png,
-         fonts/24P_Copperplate_Blue.png, pics/default.jpg,
-         pics/no_pics.jpg: initial import
-
-2003-08-29 17:04  maan
-
-       * sdl_gui.c: use icc_client pic to obtain the picture, new command
-         line option: pic
-
-2003-08-29 17:02  maan
-
-       * icc_server.c: lcl_init needs to know mmd to set dbtool_has_pic
-
-2003-08-29 17:01  maan
-
-       * icc_dbtool.sample: make it work again...
-
-2003-08-29 17:00  maan
-
-       * icc_dbtool.c: add preliminary pic command
-
-2003-08-29 16:59  maan
-
-       * icc_client.c: use write instead of printf to print output
-
-2003-08-29 16:58  maan
-
-       * icc.h: add dbtool_has_pic to mmd
-
-2003-08-29 16:58  maan
-
-       * command.c: add pic command, introduce send_bin_buffer to transfer
-         binary data
-
-2003-08-29 16:54  maan
-
-       * Makefile: install also fonts and pics
-
-2003-08-28 04:05  maan
-
-       * icc_dbtool.c: implement recursive permutation generator
-
-2003-08-28 00:20  maan
-
-       * sdl_gui.c: documentation update
-
-2003-08-25 05:01  maan
-
-       * sdl_gui.c: many small cleanups
-
-2003-08-25 00:37  maan
-
-       * sdl_gui.c: poll all events, not only one
-
-2003-08-24 23:19  maan
-
-       * sdl_gui.c: nuke shm crap
-
-2003-08-24 23:05  maan
-
-       * sdl_gui.c: use select instead of fork
-
-2003-08-24 19:42  maan
-
-       * sdl_gui.c: implement basic picture viewing
-
-2003-08-22 14:20  maan
-
-       * icc_gui.c: fix silly snooze bug
-
-2003-08-21 22:10  maan
-
-       * NEWS: add 'fix long outstanding case sensitivity bug'
-
-2003-08-21 22:09  maan
-
-       * README.dbtool: document binary format for initial creation
-
-2003-08-21 21:38  maan
-
-       * icc_dbtool.c: fix long outstanding case sensitivity bug
-
-2003-08-21 04:20  maan
-
-       * README: update
-
-2003-08-19 03:26  maan
-
-       * NEWS: update
-
-2003-08-19 03:14  maan
-
-       * icc_gui.c: small cleanups
-
-2003-08-19 03:13  maan
-
-       * icc_dbtool.c: vrfy/clean: check/replace NULL values in attributes
-
-2003-08-19 01:21  maan
-
-       * icc_dbtool.c: na: Create NOT NULL columns
-
-2003-08-18 06:02  maan
-
-       * icc_gui.c: do_select: implement getstr mode and timeout in getch
-         mode. Avoid remaining memory leaks
-
-2003-08-18 02:18  maan
-
-       * icc_gui.c: new fucntion: do_select. Fix memory leak while in
-         scroll mode
-
-2003-08-17 20:46  maan
-
-       * icc_gui.c: remove unneeded header includes
-
-2003-08-17 20:12  maan
-
-       * icc_gui.c: fix bug: some lines of stat's output could be missed
-
-2003-08-17 19:53  maan
-
-       * icc_gui.c: add new commands J, K
-
-2003-08-17 04:46  maan
-
-       * icc_gui.c: add comments on new functions
-
-2003-08-17 04:24  maan
-
-       * icc_gui.c: add past command
-
-2003-08-17 04:00  maan
-
-       * icc_gui.c: more status and error messages
-
-2003-08-17 02:06  maan
-
-       * icc_gui.c: reduce minimal top lines to 8
-
-2003-08-17 01:57  maan
-
-       * icc_gui.c: add f command, nicify help output
-
-2003-08-16 22:57  maan
-
-       * icc_gui.c: implement scrolling, fix sigint handling
-
-2003-08-16 21:34  maan
-
-       * icc_gui.c: implement '!' prefix for commands
-
-2003-08-16 21:11  maan
-
-       * icc_gui.c: add +/- to change size of top/bottom windows
-
-2003-08-16 18:14  maan
-
-       * icc_gui.c: add separator, add input window
-
-2003-08-16 17:30  maan
-
-       * icc_gui.c: kill fake shm struct, fix winch handling
-
-2003-08-16 17:08  maan
-
-       * icc_gui.c: kill shared mem crap, fix ':' command
-
-2003-08-16 16:15  maan
-
-       * icc_gui.c: major improvements, use select instead of fork, use
-         two windows
-
-2003-08-15 03:44  maan
-
-       * icc_gui.c: copy LINES and COLS to shm
-
-2003-08-15 03:25  maan
-
-       * icc_gui.c: use semaphore locking
-
-2003-08-14 23:35  maan
-
-       * icc_gui.c: fix potential buffer overflow in print_item
-
-2003-08-14 23:14  maan
-
-       * icc_gui.c: new function: handle_command
-
-2003-08-14 23:05  maan
-
-       * icc_gui.c: cleanup signal handling and shared mem init
-
-2003-08-14 22:50  maan
-
-       * icc_gui.c: new sigchld handler. Check which child has died
-
-2003-08-14 22:37  maan
-
-       * icc_gui.c: remove useless SIGTSTP handler, some small cleanups
-
-2003-08-14 22:18  maan
-
-       * icc_gui.c: exit gracefully and let the terminal intact
-
-2003-08-14 21:57  maan
-
-       * icc_gui.c:
-         use shmXXX instead of mmap to get shared memory area. Works with
-         2.2 kernels.
-
-         new variable: shm->winch to distinguish between winch and status
-         bar updates. So endwin is only called on winch events.
-
-         new function: print welcome. This is used by parent.
-
-2003-08-10 23:25  maan
-
-       * icc_dbtool.c: na: use default value 0 instead of NULL
-
-2003-07-28 04:27  maan
-
-       * icc_gui.c: fix memory leak, notice when invalid key is pressed
-
-2003-07-27 16:19  maan
-
-       * icc_gui.c: don't update status bar in interrupt handler
-
-2003-07-27 06:04  maan
-
-       * NEWS: add old news for 0.0.93 and some recent news
-
-2003-07-27 05:39  maan
-
-       * icc_gui.c: remove definition of row since this is now a comupted
-         value
-
-2003-07-27 05:13  maan
-
-       * icc_gui.c: make it work with 60x10 terminals, add dokumentation
-
-2003-07-27 04:14  maan
-
-       * icc_gui.c: modify transform vol slightly
-
-2003-07-27 04:10  maan
-
-       * icc_gui.c: kill unneeded print_help function
-
-2003-07-27 04:09  maan
-
-       * icc_gui.c: new command: help
-
-2003-07-27 03:38  maan
-
-       * icc_gui.c: adapt also lines to varying window size. Many small
-         cleanups and fixes
-
-2003-07-27 02:10  maan
-
-       * icc_gui.c: update status bar in sigwinch
-
-2003-07-27 01:52  maan
-
-       * icc_gui.c: make it respect varying window sizes
-
-2003-07-26 20:59  maan
-
-       * icc_gui.c: test window geometry and exit if too narrow
-
-2003-07-17 03:34  maan
-
-       * icc_dbtool.c: print_results: avoid trailing whitespace. Some
-         typos
-
-2003-07-13 02:35  maan
-
-       * Makefile: cleanup, introduce variables CC_FLAGS LD_FLAGS
-         SDL_INCLUDES MYSQL_INCLUDES
-
-2003-07-12 17:55  maan
-
-       * README.dbtool: add mysql commands for creating the tables data
-         and dir
-
-2003-07-09 02:28  maan
-
-       * icc_dbtool.c: more documentation, cosmetics
-
-2003-07-09 01:57  maan
-
-       * README.dbtool: replace LASTPLAYED by LASTPLAYED(). Same with
-         NUMPLAYED. Small cleanups
-
-2003-07-09 01:45  maan
-
-       * Makefile: clean: remove icc_dbtool
-
-2003-07-09 01:41  maan
-
-       * Makefile: nuke make_streams
-
-2003-07-09 01:40  maan
-
-       * make_streams: now implemented in icc_dbtool.c
-
-2003-07-08 23:12  maan
-
-       * icc_dbtool.c: fut: implement parsing functions for new
-         streams_def syntax
-
-2003-07-08 22:30  maan
-
-       * icc_dbtool.c: nuke randomize function which is no longer needed
-
-2003-07-08 22:29  maan
-
-       * icc_dbtool.c: streams: adapt to new syntax, change default
-         filename from streams to stream_defs
-
-2003-06-30 05:03  maan
-
-       * Makefile: icc_server depends on mp3info.h
-
-2003-06-30 04:57  maan
-
-       * Makefile: icc_sdl_gui depends on SFont.c
-
-2003-06-30 04:56  maan
-
-       * SFont.c: comment out unused functions
-
-2003-06-30 04:40  maan
-
-       * SFont.c: indent to kr style
-
-2003-06-30 04:34  maan
-
-       * SFont.c: add GPL header
-
-2003-06-29 22:05  maan
-
-       * INSTALL, README: change icc_dbtool.template to icc_dbtool.sample
-
-2003-06-29 22:04  maan
-
-       * Makefile: major cleanup and bugfixes
-
-2003-06-29 21:17  maan
-
-       * icc_dbtool.sample: former icc_dbtool.template
-
-2003-06-29 21:16  maan
-
-       * icc_dbtool.template: moved to icc_dbtool.sample
-
-2003-06-29 21:01  maan
-
-       * Makefile: Use cvs status to determine if local copy is up to date
-
-2003-06-29 19:44  maan
-
-       * VERSION: bump version number to 95
-
-2003-06-29 19:39  maan
-
-       * Makefile: install: also install make_streams
-
-2003-06-29 19:39  maan
-
-       * make_streams: bash script to produce the streams configuration
-         file
-
-2003-06-29 19:37  maan
-
-       * README.dbtool: document new syntax of streams.in
-
-2003-06-29 18:22  maan
-
-       * 1.0: improve change ssl text
-
-2003-06-29 18:19  maan
-
-       * Makefile: add NEWS and make_streams to sources
-
-2003-06-29 18:15  maan
-
-       * NEWS: contains release notes
-
-2003-06-29 17:53  maan
-
-       * icc_server.c: cosmetics
-
-2003-06-29 17:52  maan
-
-       * icc_bash_completion: use streams command to complete cs
-
-2003-06-28 13:58  maan
-
-       * afs.c: fix small race at end of song play
-
-2003-06-28 13:44  maan
-
-       * icc_server.c: set_conf: Use const char* variables for output of
-         messages to reduce space
-
-2003-06-28 13:12  maan
-
-       * icc_server.c: call wait directly from the sigchld interupt
-         handler to avoid zombies
-
-2003-06-28 13:10  maan
-
-       * command.c: cosmetics
-
-2003-06-22 06:58  maan
-
-       * icc_dbtool.c: fix order of rows bug
-
-2003-06-22 04:18  maan
-
-       * command.c: stat: print streamname continuously
-
-2003-06-22 04:13  maan
-
-       * 1.0, icc_dbtool.c: fix bug: fut n always prints all valid songs
-         instead of only n
-
-2003-06-22 03:51  maan
-
-       * icc_gui.c, sdl_gui.c: print score
-
-2003-06-22 03:51  maan
-
-       * icc_dbtool.template: fut: print dummy score
-
-2003-06-22 03:50  maan
-
-       * command.c: stat: print score
-
-2003-06-22 03:50  maan
-
-       * afs.c: get_song: adapt to new output of fut (contains score now)
-
-2003-06-22 03:48  maan
-
-       * icc_dbtool.c: simplify fut since ~/.icc/streams contains full
-         query now
-
-2003-06-22 03:47  maan
-
-       * icc.h: add mmd.score
-
-2003-06-19 17:18  maan
-
-       * icc_bash_completion: add ca (copy attributes)
-
-2003-06-19 17:12  maan
-
-       * icc_dbtool.c: add ca (copy attributes) command
-
-2003-06-15 20:44  maan
-
-       * sdl_gui.c: major cleanup, speed improvements and debugging
-
-2003-06-15 19:16  maan
-
-       * command.c: only send full volatile status when it has changed
-
-2003-06-15 19:02  maan
-
-       * command.c: only send full status when song has changed
-
-2003-06-15 02:42  maan
-
-       * icc_dbtool.c: com_us: use basename of given argument
-
-2003-06-15 01:47  maan
-
-       * icc_dbtool.c: fix do_update_song (introduce get_numplayed)
-
-2003-06-02 00:54  maan
-
-       * icc_dbtool.c: small cleanups
-
-2003-06-02 00:01  maan
-
-       * afs.c: flush id3 tags before updating
-
-2003-06-01 23:45  maan
-
-       * icc_dbtool.c: us: increase Numplayed, info: print Numplayed,
-         get_a: fix off by one bug
-
-2003-06-01 23:06  maan
-
-       * icc_dbtool.c: get_aa: skip first _three_ rows, since third row is
-         now reserved for number of times song has been played
-
-2003-06-01 22:43  maan
-
-       * icc_dbtool.c: return is not a function!
-
-2003-06-01 22:42  maan
-
-       * icc_dbtool.c: fix return value in get_a
-
-2003-05-18 18:33  maan
-
-       * sdl_gui.c: make non-interactive mode working. Some cleanups
-
-2003-05-18 04:11  maan
-
-       * sdl_gui.c: add command line options -w -h -f -i
-
-2003-05-05 01:47  maan
-
-       * VERSION: bump version number to 94
-
-2003-05-05 01:46  maan
-
-       * Makefile: start tag name with letter to make cvs happy
-
-2003-05-05 01:45  maan
-
-       * VERSION: decrease version to 93, since make version failed
-
-2003-05-05 01:45  maan
-
-       * Makefile: use backtick expansion rather than double dollars
-
-2003-05-05 01:42  maan
-
-       * VERSION: bump version number to 94
-
-2003-05-05 01:42  maan
-
-       * VERSION: decrease version to 93, since make version failed
-
-2003-05-05 01:41  maan
-
-       * Makefile: typo that caused cvs -q tag to fail
-
-2003-05-05 01:37  maan
-
-       * VERSION: bump version number to 94
-
-2003-05-04 00:24  maan
-
-       * icc_server.c: loglevel adjustments
-
-2003-05-04 00:09  maan
-
-       * icc_server.c: minor auth cleanup
-
-2003-05-03 23:21  maan
-
-       * icc_server.c: reduce # arguments for handle_sighup
-
-2003-05-03 21:28  maan
-
-       * icc_server.c: avoid use of TRUE and FALSE (tele-tubby)
-
-2003-05-03 21:10  maan
-
-       * icc_server.c: init mmd->num_played, mmd->num_commands and
-         mmd->stream_name early
-
-2003-05-03 21:08  maan
-
-       * icc.h: reduce number of arguments to init_afs
-
-2003-05-03 21:08  maan
-
-       * init_afs.c: reduce number of arguments to init_afs, move init of
-         some sane values of mmd where they belong, comment out silly
-         PETER_B log messages
-
-2003-05-03 20:44  maan
-
-       * icc.h: add prototype for afs_status_tohuman
-
-2003-05-03 20:44  maan
-
-       * command.c: don't duplicate afs_status_tohuman, use it
-
-2003-05-03 20:30  maan
-
-       * afs.c: insert missing function descriptors
-
-2003-05-03 20:30  maan
-
-       * icc.h: init afs returns pid_t
-
-2003-05-03 20:26  maan
-
-       * icc_server.c: fix missing exit for unknown commands. Strange...
-
-2003-05-03 20:13  maan
-
-       * init_afs.c: init afs returns pid_t
-
-2003-05-03 20:11  maan
-
-       * icc.h, icc_server.c, init_afs.c: move definition of conn to
-         init_afs
-
-2003-05-03 20:01  maan
-
-       * sdl_gui.c: unicolor, proposed by christian
-
-2003-05-03 19:58  maan
-
-       * icc_server.c: first bind socket, then fork. Avoids log flodding
-         if second instance of icc_server is started
-
-2003-05-03 19:51  maan
-
-       * icc_server.c: further cosmetics
-
-2003-05-03 19:34  maan
-
-       * icc_server.c: cosmetics
-
-2003-05-03 19:30  maan
-
-       * icc_server.c: kill dead code [send(...)]
-
-2003-05-03 19:13  maan
-
-       * icc_server.c: fix nasty bug introduced by use of send_buffer:
-         strlen(buf) might not give correct length in case of encrypted
-         data
-
-2003-05-03 00:47  maan
-
-       * icc_server.c: further small cleanups
-
-2003-05-03 00:34  maan
-
-       * icc.h: add prototype for send_buffer
-
-2003-05-03 00:23  maan
-
-       * icc_server.c: cosmetics
-
-2003-05-03 00:14  maan
-
-       * icc_server.c: use send_buffer() rather than send()
-
-2003-05-02 23:53  maan
-
-       * afs.c: compute_sb_string: use basename instead of weird strchr()
-         madness
-
-2003-05-02 23:22  maan
-
-       * afs.c: replace cleanexit by clean_n_jump
-
-2003-05-02 23:02  maan
-
-       * command.c: stat: output two digits for seconds
-
-2003-05-02 23:01  maan
-
-       * icc.h: replace BUFFSIZE by CHUNK_BUFFSIZE
-
-2003-04-30 00:39  maan
-
-       * afs.c: update meta data stream regularly (adjustable in icc.h)
-
-2003-04-29 22:54  maan
-
-       * icc_dbtool.c: Comment out noisy output in upd
-
-2003-04-20 17:40  maan
-
-       * README: nuke php description, add sdl_gui description
-
-2003-04-20 17:31  maan
-
-       * sdl_gui.c: add documentation
-
-2003-04-20 17:16  maan
-
-       * sdl_gui.c: add gpl header
-
-2003-04-20 17:14  maan
-
-       * sdl_gui.c: cut length of output lines if too long
-
-2003-04-20 16:49  maan
-
-       * afs.c, command.c, icc.h, icc_gui.c, sdl_gui.c: replace mmd.misc
-         by mmd.dbinfo
-
-2003-04-20 16:30  maan
-
-       * afs.c: enumerate Â«misc:» lines for status output
-
-2003-04-20 16:28  maan
-
-       * Makefile: also install icc_sdl_gui
-
-2003-04-20 15:57  maan
-
-       * SFont.c: needed by sdl_gui
-
-2003-04-20 15:56  maan
-
-       * sdl_gui.c: The gui of death that makes you blind
-
-2003-04-20 15:55  maan
-
-       * command.c: status: print id tags
-
-2003-04-20 15:55  maan
-
-       * afs.c: cleanups
-
-2003-04-20 15:53  maan
-
-       * Makefile: new target: sdl_gui
-
-2003-04-04 02:45  maan
-
-       * icc_gui.c: show also mp3tags
-
-2003-04-04 02:25  maan
-
-       * command.c: stat: print also id3 tags
-
-2003-04-04 02:12  maan
-
-       * Makefile, afs.c, command.c, icc.h: include mp3info struct in mmd
-         and remove duplication of information in mmd
-
-2003-04-04 01:19  maan
-
-       * mp3tech.c, mp3tech.h, mp3info.h, textfunc.h: taken from mp3info
-         package
-
-2003-04-04 01:18  maan
-
-       * afs.c: Use mp3tech instead of mp3info
-
-2003-04-04 01:18  maan
-
-       * Makefile: include mp3tech
-
-2003-04-03 04:20  maan
-
-       * icc_gui.c: add c (change stream) to status bar
-
-2003-04-03 03:53  maan
-
-       * icc_dbtool.c: further cosmetics
-
-2003-04-02 22:18  maan
-
-       * icc_dbtool.c: cosmetics
-
-2003-04-02 03:19  maan
-
-       * icc_dbtool.template: Omit streams in help's output
-
-2003-04-02 03:07  maan
-
-       * README.dbtool: Improve(?) Real life eample
-
-2003-04-02 02:40  maan
-
-       * icc_server.conf.sample: use 127.0.0.1 as default icecast ip
-
-2003-04-02 02:33  maan
-
-       * icc_dbtool.template: add nec. streams command and some more
-         comments
-
-2003-03-29 18:22  maan
-
-       * command.c, icc_gui.c: new command: ns (next stream)
-
-2003-03-29 17:37  maan
-
-       * command.c, icc_dbtool.c, icc_gui.c: info: print default text if
-         no attributes set or lastplayed=NULL
-
-2003-03-29 02:12  maan
-
-       * INSTALL, README: linguistic improvements (I hope)
-
-2003-03-29 00:43  maan
-
-       * VERSION: bump version number to 93
-
-2003-03-29 00:43  maan
-
-       * Makefile: add xmms-patch to sources
-
-2003-03-29 00:40  maan
-
-       * xmms-1.2.7.titlebar_vbr_patch: patch for xmms-1.2.7 to fix title
-         display for mp3s with vbr
-
-2003-03-29 00:32  maan
-
-       * afs.c, command.c: nicify afs status output
-
-2003-03-28 05:18  maan
-
-       * icc_gui.c: statusbar improvements
-
-2003-03-28 05:05  maan
-
-       * icc_gui.c: major optic overhowl. I like it colored
-
-2003-03-28 00:06  maan
-
-       * icc_gui.c: print also current stream
-
-2003-03-28 00:05  maan
-
-       * command.c: stat: print name of current stream
-
-2003-03-28 00:04  maan
-
-       * afs.c: cleanups
-
-2003-03-18 02:29  maan
-
-       * icc_gui.c: use linux/soundcard.h to set volume directly
-
-2003-03-17 22:29  maan
-
-       * icc_gui.c: cosmetics
-
-2003-03-17 22:22  maan
-
-       * icc_gui.c: additional delay for command '-'
-
-2003-03-17 22:18  maan
-
-       * init_afs.c: loglevel adjustments
-
-2003-03-17 22:17  maan
-
-       * icc_server.c: log: print server if mmd not yet defined
-
-2003-03-17 05:10  maan
-
-       * afs.c, icc_server.c: adjust some loglevels
-
-2003-03-17 02:16  maan
-
-       * command.c, icc.h, icc_server.c, init_afs.c: use semaphor-locking
-         to serialize access to server-afs pipes
-
-2003-03-17 01:19  maan
-
-       * init_afs.c: kill processgroup if afs dies
-
-2003-03-12 22:22  maan
-
-       * icc.h: add prototypes for pid_list_lock, pid_list_unlock
-
-2003-03-12 22:21  maan
-
-       * command.c: uptime: lock pid_list before accessing
-
-2003-03-12 21:51  maan
-
-       * icc_server.c: add semaphor locking for pid_list. Fix several bugs
-         causing corrupt pid_list
-
-2003-03-12 21:50  maan
-
-       * icc.h: add server and afs pids to mmd struct, split macro LICENSE
-
-2003-03-12 21:48  maan
-
-       * command.c: fix typo
-
-2003-03-11 00:43  maan
-
-       * afs.c, command.c, icc_server.c: forgotten cleanups
-
-2003-02-23 18:06  maan
-
-       * icc.h, icc_server.c: new loglevel: VERBOSE
-
-2003-02-23 16:54  maan
-
-       * icc_server.c: fix permission bug (commands were executed even if
-         permissions are not suff.)
-
-2003-02-23 16:46  maan
-
-       * Makefile: Change icebear.c and init_icebear.c to afs
-
-2003-02-23 16:45  maan
-
-       * init_afs.c: new, former init_icebear.c
-
-2003-02-23 16:44  maan
-
-       * init_icebear.c: renamed to init_afs.c
-
-2003-02-23 16:40  maan
-
-       * afs.c: new file, former icebear.c
-
-2003-02-23 16:39  maan
-
-       * icebear.c: will be renamed to afs.c
-
-2003-02-23 16:35  maan
-
-       * command.c, icc.h, icc_dbtool.c, icc_server.c, icebear.c: change
-         rest of occurences of icebear to afs
-
-2003-02-23 16:18  maan
-
-       * icc.h, icebear.c, init_icebear.c: change icebear function to afs
-
-2003-02-23 16:12  maan
-
-       * command.c, icc.h, icc_server.c, icebear.c, init_icebear.c: change
-         icebear_init to afs_init
-
-2003-02-23 15:57  maan
-
-       * INSTALL, command.c, icc.h, icc_server.c, icc_server.conf.sample,
-         icebear.c: change ICEBEAR to AFS
-
-2003-02-23 15:47  maan
-
-       * icc_dbtool.c, icebear.c: cosmetics
-
-2003-02-23 03:31  maan
-
-       * command.c: cosmetics
-
-2003-02-23 03:20  maan
-
-       * command.c, icc.h: change ICEBEAR_HANDLER to AFS_HANDLER
-
-2003-02-23 03:08  maan
-
-       * icc_server.c: cosmetics
-
-2003-02-23 03:00  maan
-
-       * command.c, icc.h, icc_server.c: replace icc_server: by server:
-
-2003-02-23 02:45  maan
-
-       * icebear.c: comment out unneeded signal handler code
-
-2003-02-23 02:17  maan
-
-       * icc_server.c: Fix bug: become deamon *before* we record our pid.
-
-2003-02-23 02:07  maan
-
-       * icc_server.c: make version the first line that is printed out
-
-2003-02-23 01:05  maan
-
-       * icebear.c: logical simplifications
-
-2003-02-23 00:34  maan
-
-       * icebear.c: new function: send_chunk. Many cleanups
-
-2003-02-22 23:01  maan
-
-       * icebear.c: new functions: get_song and compute_sb_string
-
-2003-02-22 22:51  maan
-
-       * icebear.c: new functions: get_song and compute_sb_string
-
-2003-02-22 21:56  maan
-
-       * icebear.c: cosmetics
-
-2003-02-22 21:46  maan
-
-       * icebear.c: only send metadata stream once
-
-2003-02-22 21:36  maan
-
-       * icebear.c: clear buffer before reading
-
-2003-02-18 01:48  maan
-
-       * icc_gui.c: thinko: add break statements
-
-2003-02-18 01:30  maan
-
-       * command.c: add comment
-
-2003-02-18 01:29  maan
-
-       * icc_gui.c: use case instead of ifs
-
-2003-02-18 00:34  maan
-
-       * command.c: comment out obsolete check for icebear_fd
-
-2003-02-18 00:32  maan
-
-       * icc_server.c: log pid of current process
-
-2003-02-17 23:43  maan
-
-       * init_icebear.c: cosmetics
-
-2003-02-17 23:30  maan
-
-       * icc_server.c: cosmetics
-
-2003-02-17 23:29  maan
-
-       * icc.h: add struct pid_list and macro FOR_EACH_PROC from server
-
-2003-02-17 23:27  maan
-
-       * command.c: uptime: add pid of chilren in output
-
-2003-02-17 03:47  maan
-
-       * icc_server.c: sigchd handler: Wait not only for one child. There
-         may be more...
-
-2003-02-17 02:36  maan
-
-       * icebear.c: make it terminate if read fails and ppid == 1
-
-2003-02-11 03:04  maan
-
-       * icc_gui.c: major cleanup. Wow, is that crappy
-
-2003-02-11 00:35  maan
-
-       * command.c, icc.h, icc_server.c, icebear.c: implement pid list to
-         keep track of children. Needed for hup since kill(0,sighup)
-         doesnt work in daemon mode
-
-2003-02-10 01:53  maan
-
-       * icc_server.c: cosmetics
-
-2003-02-10 01:51  maan
-
-       * icc_dbtool.template: add -print to find command, documentation
-         update
-
-2003-02-10 01:50  maan
-
-       * icc_dbtool.c: remove obsolete ass command
-
-2003-02-10 00:55  maan
-
-       * command.c, icc_server.c: new function send_buffer
-
-2003-02-10 00:04  maan
-
-       * command.c: new command: hup
-
-2003-02-09 23:33  maan
-
-       * icc.h, icc_server.c, icebear.c: handle sighup correctly (all
-         children have to reload log file)
-
-2003-02-09 18:30  maan
-
-       * icc.h, icc_server.c, icebear.c, init_icebear.c: reduce use of
-         global variables. Extend mmd and put info there instead
-
-2003-02-09 15:58  maan
-
-       * icc_server.c: print plural form correctly in uptime
-
-2003-02-09 15:46  maan
-
-       * icc_server.c: cosmetics
-
-2003-02-09 01:55  maan
-
-       * command.c: further cosmetics
-
-2003-02-09 01:18  maan
-
-       * command.c: cosmetics
-
-2003-02-08 23:16  maan
-
-       * icc_client.c: cosmetics
-
-2003-01-11 16:30  maan
-
-       * VERSION, icc_dbtool.c, icc_gui.c, icebear.c, init_icebear.c:
-         change 2002 to 2003
-
-2003-01-11 16:28  maan
-
-       * icc_client.c, icc_server.c: cleanup. use new macros LICENSE and
-         COPYRIGHT
-
-2003-01-11 16:27  maan
-
-       * icc.h: add macros COPYRIGHT, LICENSE
-
-2003-01-11 16:26  maan
-
-       * command.c: minor cleanups
-
-2003-01-11 16:24  maan
-
-       * README.dbtool: fix some misprints
-
-2003-01-11 16:23  maan
-
-       * README:
-         Minor clarifications
-
-2002-12-23 22:26  maan
-
-       * icebear.c: cosmetic cleanup
-
-2002-12-23 22:20  maan
-
-       * icc_server.c: cosmetic cleanups
-
-2002-12-23 22:15  maan
-
-       * icebear.c: set icc version in init_shout
-
-2002-12-15 23:11  maan
-
-       * Makefile: commit change of version number on target version
-         before calling cvs tag
-
-2002-12-15 23:04  maan
-
-       * Makefile: version now implies distclean
-
-2002-12-15 22:56  maan
-
-       * Makefile: enable cvs tagging
-
-2002-12-15 22:53  maan
-
-       * Makefile: prepare for cvs tagging
-
-2002-12-15 22:49  maan
-
-       * Makefile: fix version (no more tdl), new target: update
-
-2002-12-15 22:37  maan
-
-       * Makefile: tgz no longer implies version
-
-2002-12-15 21:20  maan
-
-       * icebear.c: minor cleanups
-
-2002-12-15 21:04  maan
-
-       * icc_server.c: remove unneeded comments
-
-2002-12-15 20:55  maan
-
-       * icc_server.c, icebear.c: move (parts of) initialization of conn
-         fromicebear to server
-
-2002-12-15 20:11  maan
-
-       * icc_server.c: minor code cleanup,  add documentation bits
-
-2002-12-15 18:05  maan
-
-       * INSTALL, icebear.c: icc_dbtool is no longer a script. Fix
-         accordingly
-
-2002-12-15 14:28  maan
-
-       * icc_server.c: cosmetic cleanup
-
-2002-12-14 21:51  maan
-
-       * icc.h, icebear.c: use new mmd.mdst (meta data stream text) to
-         display meta data
-
-2002-12-14 02:51  maan
-
-       * icebear.c: new function: update_mmd
-
-2002-12-14 02:02  maan
-
-       * 1.0, icebear.c: preparation for movement of large parts in
-         icebear to extra function
-
-2002-12-14 01:03  maan
-
-       * icebear.c: minor code cleanup
-
-2002-12-14 00:10  maan
-
-       * icebear.c: use icecast meta data streaming
-
-2002-12-13 22:53  maan
-
-       * icc_dbtool.c: remove #include <libgen.h>
-
-2002-12-13 22:50  maan
-
-       * icc.h: add documentation
-
-2002-12-12 23:23  maan
-
-       * icc_client.c: better ERROR logging
-
-2002-12-08 03:11  maan
-
-       * command.c: code cleanup
-
-2002-12-08 02:54  maan
-
-       * command.c: fix cs in case invalid stream name is given
-
-2002-12-01 01:47  maan
-
-       * icc_dbtool.c: unlink tempfile _after_ closing
-
-2002-12-01 00:55  maan
-
-       * command.c, icc.h, icc_client.c, icc_dbtool.c, icc_gui.c,
-         icc_server.c, init_icebear.c: add Keyword Expansion
-
-2002-12-01 00:48  maan
-
-       * .changelog_before_cvs: self explanatory
-
-2002-12-01 00:46  maan
-
-       * Makefile: New Changelog Format with cvs2cl
-
-2002-12-01 00:19  maan
-
-       * icebear.c: add Keyword Expansion
-
-2002-12-01 00:09  maan
-
-       * .tdldb, 1.0, COPYING, GPL, INSTALL, Makefile, README,
-         README.dbtool, VERSION, command.c, icc.h, icc_bash_completion,
-         icc_client.c, icc_client.conf.sample, icc_dbtool.c,
-         icc_dbtool.conf.sample, icc_dbtool.template, icc_gui.c,
-         icc_server.c, icc_server.conf.sample, icebear.c,
-         icecast.conf.sample, init_icebear.c: Initial revision
-
-2002-12-01 00:09  maan
-
-       * .tdldb, 1.0, COPYING, GPL, INSTALL, Makefile, README,
-         README.dbtool, VERSION, command.c, icc.h, icc_bash_completion,
-         icc_client.c, icc_client.conf.sample, icc_dbtool.c,
-         icc_dbtool.conf.sample, icc_dbtool.template, icc_gui.c,
-         icc_server.c, icc_server.conf.sample, icebear.c,
-         icecast.conf.sample, init_icebear.c: initial import into cvs
-
index 9091a9c28965ffa90a4ea588f1a767b05831eb5c..d340f2075c05f99ad6b8a3ccb85dd4f293fbcc19 100644 (file)
@@ -17,7 +17,7 @@ TODO
 *_command_list.h
 *_command_list.man
 paraslash-git.tar.bz2
-skencil/overview.pdf
+web/dia/overview.pdf
 *.swp
 error2.h
 web_sync
index 04d8f32621edd1426e2651aab711dd11516d9080..239cd2622ddb2a2db238749b4e815fae72a1e3cf 100644 (file)
--- a/Doxyfile
+++ b/Doxyfile
@@ -619,10 +619,8 @@ EXCLUDE_SYMLINKS       = NO
 # for example use the pattern */test/*
 
 EXCLUDE_PATTERNS       = *.cmdline.* \
-                         gui* \
                          gcc-compat.h \
                          fade.c \
-                         config.h \
                        *_command_list.h \
                        *_completion.h
 
@@ -1267,7 +1265,7 @@ ENABLE_PREPROCESSING   = YES
 # compilation will be performed. Macro expansion can be done in a controlled
 # way by setting EXPAND_ONLY_PREDEF to YES.
 
-MACRO_EXPANSION        = NO
+MACRO_EXPANSION        = YES
 
 # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
 # then the macro expansion is limited to the macros specified with the
@@ -1301,13 +1299,7 @@ INCLUDE_FILE_PATTERNS  =
 # undefined via #undef or recursively expanded use the := operator
 # instead of the = operator.
 
-PREDEFINED             = HAVE_MAD \
-                         HAVE_FAAD \
-                         HAVE_OGGVORBIS \
-                         __GNUC__=4 \
-                         __GNUC_MINOR__=4 \
-                         HAVE_UCRED \
-                        HAVE_CLOCK_GETTIME
+PREDEFINED             = __GNUC__=4 __GNUC_MINOR__=4
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
 # this tag can be used to specify a list of macro names that should be expanded.
index 6ad420dfe7a63800b3725f1295ec3c84cb580d5d..395d0f15bbc844cc864295a08b23b076786321e6 100644 (file)
--- a/FEATURES
+++ b/FEATURES
@@ -5,7 +5,7 @@ Features
 
        * Runs on Linux, Mac OS, FreeBSD, NetBSD, Solaris and probably other
          Unixes
-       * Mp3, ogg/vorbis, ogg/speex, aac (m4a), wma and flac support
+       * Mp3, ogg/vorbis, ogg/speex, aac (m4a), wma, flac and ogg/opus support
        * Native Alsa, OSS, CoreAudio output support
        * Support for ESD, Pulseaudio, AIX, Solaris, IRIX through libao
        * Local or remote http, dccp and udp network audio streaming
index 32802232244a6a79258f2640e7e0f7e3ddd950a2..df7ed327cb3f9b8f93ec596e629da4c08346e69a 100755 (executable)
@@ -16,7 +16,7 @@ elif [[ -d .git || -f .git ]] &&
        case "$VN" in
        *$LF*) (exit 1) ;;
        v[0-9]*)
-               git update-index -q --refresh
+               git update-index -q --refresh &>/dev/null
                test -z "$(git diff-index --name-only HEAD --)" ||
                VN="$VN-dirty" ;;
        esac
diff --git a/INSTALL b/INSTALL
index 0f4c18b647e0e6c2fc921bbded745275458d70c7..9917afb681b23fa90405f671beed0c640c957d00 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -8,6 +8,23 @@ From git:
 
        ./autogen.sh && sudo make install
 
+Example for cross-compiling:
+
+       export CROSS_COMPILE='armv6j-hardfloat-linux-gnueabi-'
+       export PATH="/usr/cross/arm/bin:$PATH"
+       export CC=${CROSS_COMPILE}gcc
+
+       export LDFLAGS='
+               -L/usr/sysroot/arm/lib
+               -L/usr/sysroot/arm/usr/lib
+               -L/usr/sysroot/arm/usr/lib/glibc/lib
+               -L/usr/sysroot/arm/usr/local/ssl/lib
+       '
+       autoconf
+       autoheader
+       ./configure --host=arm-linux-gnueabi --prefix /usr/sysroot/arm/usr/local
+       make CROSS_COMPILE=$CROSS_COMPILE
+
 For details see the user manual:
 
        http://paraslash.systemlinux.org/manual.html
index f82afd7b88f65a9ad2d75032ca401d0445025272..6762b449bed265fd2e0141e3c6bf462bf44e3a6e 100644 (file)
 prefix := @prefix@
 exec_prefix := @exec_prefix@
 
+# These two use prefix and exec_prefix
 BINDIR := @bindir@
-VARDIR := /var/paraslash
-PKGDATADIR := @datarootdir@/@PACKAGE_NAME@
-MANDIR := @datarootdir@/man/man1
+datarootdir := @datarootdir@
+
+PACKAGE_TARNAME := @PACKAGE_TARNAME@
 PACKAGE_VERSION := @PACKAGE_VERSION@
-PACKAGE_STRING := @PACKAGE_STRING@
-install_sh := @install_sh@
-executables := @executables@
-ggo_descriptions_declared := @ggo_descriptions_declared@
 
+INSTALL := @install@
 GENGETOPT := @gengetopt@
 HELP2MAN := @help2man@
-MKDIR_P := mkdir -p
-
-build_date := $(shell date)
-uname_s := $(shell uname -s 2>/dev/null || echo "UNKNOWN_OS")
-uname_rs := $(shell uname -rs)
-cc_version := $(shell $(CC) --version | head -n 1)
-
-GIT_VERSION := $(shell ./GIT-VERSION-GEN git-version.h)
-
-m4_ggo_dir := m4/gengetopt
-test_dir := t
-ifeq ("$(origin O)", "command line")
-       build_dir := $(O)
-else
-       build_dir := build
-endif
-ggo_dir := $(build_dir)/ggo
-object_dir := $(build_dir)/objects
-dep_dir := $(build_dir)/deps
-man_dir := $(build_dir)/man/man1
-cmdline_dir := $(build_dir)/cmdline
-
-DEBUG_CPPFLAGS += -g -Wunused -Wundef -W
-DEBUG_CPPFLAGS += -Wredundant-decls
-DEBUG_CPPFLAGS += -Wall -Wno-sign-compare -Wno-unknown-pragmas
-DEBUG_CPPFLAGS += -Wformat-security
-DEBUG_CPPFLAGS += -Wmissing-format-attribute
-# produces false positives
-# DEBUG_CPPFLAGS += -Wunreachable-code
-# DEBUG_CPPFLAGS += -Wwrite-strings
-
-# invalid option for gcc-3.3.3
-# DEBUG_CPPFLAGS += -Wextra
-# DEBUG_CPPFLAGS += -Wold-style-definition
-# DEBUG_CPPFLAGS += -Wdeclaration-after-statement
-# DEBUG_CPPFLAGS += -Wsuggest-attribute=const
-
-# many warnings about trivial stuff
-# CPPFLAGS += -Wconversion
-
-ifeq ($(uname_s),Linux)
-       CPPFLAGS += -fdata-sections -ffunction-sections
-       LDFLAGS += -Wl,--gc-sections
-       CPPFLAGS += -Wstrict-prototypes
-       CPPFLAGS += -Wshadow
-       # causes warnings on *BSD for the feature test macros
-       CPPFLAGS += -Wunused-macros
-endif
-CPPFLAGS += -Os
-CPPFLAGS += -Wuninitialized
-CPPFLAGS += -Wchar-subscripts
-CPPFLAGS += -DBINDIR='"$(BINDIR)"'
-CPPFLAGS += -DBUILD_DATE='"$(build_date)"'
-CPPFLAGS += -DUNAME_RS='"$(uname_rs)"'
-CPPFLAGS += -DCC_VERSION='"$(cc_version)"'
-CPPFLAGS += -Werror-implicit-function-declaration
-CPPFLAGS += -Wmissing-noreturn
-CPPFLAGS += -Wbad-function-cast
-CPPFLAGS += -fno-strict-aliasing
-CPPFLAGS += -DMAIN_INPUT_FILE_IS_$(*F)
-CPPFLAGS += @arch_cppflags@
-CPPFLAGS += -I/usr/local/include
-CPPFLAGS += -I$(cmdline_dir)
-CPPFLAGS += @osl_cppflags@
-
-LDFLAGS += @clock_gettime_ldflags@
-
-man_pages := $(patsubst %, $(man_dir)/%.1, @executables@)
-
-autocrap := config.h.in configure
-tarball_pfx := @PACKAGE_TARNAME@-$(PACKAGE_VERSION)
-tarball_delete := $(addprefix $(tarball_pfx)/,\
-       web .changelog_before_cvs .changelog_cvs .gitignore\
-       skencil)
-tarball := @PACKAGE_TARNAME@-$(PACKAGE_VERSION).tar.bz2
-
-# To put more focus on warnings, be less verbose as default
-# Use 'make V=1' to see the full commands
-ifeq ("$(origin V)", "command line")
-       Q :=
-else
-       Q := @
-endif
-
-.PHONY: dep all clean distclean maintainer-clean install man tarball
-all: dep @executables@ $(man_pages)
-dep: $(deps)
-man: $(man_pages)
-tarball: $(tarball)
-
-$(object_dir) $(man_dir) $(ggo_dir) $(cmdline_dir) $(dep_dir):
-       $(Q) $(MKDIR_P) $@
-
--include $(m4_ggo_dir)/makefile
-
-# When in doubt, use brute force (Ken Thompson)
-TOUPPER = \
-$(subst a,A,$(subst b,B,$(subst c,C,$(subst d,D,$(subst e,E,\
-$(subst f,F,$(subst g,G,$(subst h,H,$(subst i,I,$(subst j,J,\
-$(subst k,K,$(subst l,L,$(subst m,M,$(subst n,N,$(subst o,O,\
-$(subst p,P,$(subst q,Q,$(subst r,R,$(subst s,S,$(subst t,T,\
-$(subst u,U,$(subst v,V,$(subst w,W,$(subst x,X,$(subst y,Y,\
-$(subst z,Z,$1))))))))))))))))))))))))))
-
-%_command_list.h: %.cmd %.c
-       @[ -z "$(Q)" ] || echo 'GEN $@'
-       $(Q) ./command_util.sh h < $< >$@
-%_command_list.man: %.cmd %.c
-       @[ -z "$(Q)" ] || echo 'GEN $@'
-       $(Q) ./command_util.sh man < $< > $@
-%_completion.h: %.cmd %.c
-       @[ -z "$(Q)" ] || echo 'GEN $@'
-       $(Q) ./command_util.sh compl $(strip $(call TOUPPER,$(*F)))_COMPLETERS \
-               $(strip $(call TOUPPER,$(*F)))_COMMANDS < $< > $@
-
-server_command_list.h server_command_list.man server_completion.h: command.c
-afs_command_list.h afs_command_list.man afs_completion.h: afs.c aft.c attribute.c
-audiod_command_list.h audiod_command_list.man audiod_completion.h: audiod_command.c
-
-server_command_lists_man = server_command_list.man afs_command_list.man
-$(man_dir)/para_server.1: para_server $(server_command_lists_man) | $(man_dir)
-       @[ -z "$(Q)" ] || echo 'MAN $<'
-       $(Q) opts="-h --detailed-help -N `for i in $(server_command_lists_man); do printf "%s\n" "-i $$i"; done`"; \
-       $(HELP2MAN) $$opts ./para_server > $@
-
-$(man_dir)/para_audiod.1: para_audiod audiod_command_list.man | $(man_dir)
-       @[ -z "$(Q)" ] || echo 'MAN $<'
-       $(Q) $(HELP2MAN) -h --detailed-help -N -i audiod_command_list.man ./para_audiod > $@
-
-$(man_dir)/para_play.1: para_play play_command_list.man | $(man_dir)
-       @[ -z "$(Q)" ] || echo 'MAN $<'
-       $(Q) $(HELP2MAN) -h --detailed-help -N -i play_command_list.man ./para_play > $@
-
-$(man_dir)/%.1: % | $(man_dir)
-       @[ -z "$(Q)" ] || echo 'MAN $<'
-       $(Q) $(HELP2MAN) -h --detailed-help -N ./$< > $@
-
-$(object_dir)/crypt.o: crypt.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) @openssl_cppflags@ $<
-$(object_dir)/spx_common.o: spx_common.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) @ogg_cppflags@ $<
-
-$(object_dir)/spxdec_filter.o: spxdec_filter.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) @ogg_cppflags@ $<
-
-$(object_dir)/spx_afh.o: spx_afh.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) @ogg_cppflags@ $<
-
-$(object_dir)/oggdec_filter.o: oggdec_filter.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) @ogg_cppflags@ $<
-
-$(object_dir)/ogg_afh.o: ogg_afh.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) @ogg_cppflags@ $<
-
-$(object_dir)/ogg_afh_common.o: ogg_afh_common.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) @ogg_cppflags@ $<
-
-$(object_dir)/mp3dec_filter.o: mp3dec_filter.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) @mad_cppflags@ $<
 
-$(object_dir)/compress_filter.o: compress_filter.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) -O3 $<
-
-$(object_dir)/aacdec_filter.o: aacdec_filter.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) @faad_cppflags@ $<
-
-$(object_dir)/aac_common.o: aac_common.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) @faad_cppflags@ $<
-
-$(object_dir)/aac_afh.o: aac_afh.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) @faad_cppflags@ $<
-
-$(object_dir)/mp3_afh.o: mp3_afh.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) @id3tag_cppflags@ $<
-
-$(object_dir)/gui%.o: gui%.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) @curses_cppflags@ $<
-$(object_dir)/ao_write.o: ao_write.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) @ao_cppflags@ $<
-
-$(object_dir)/%.cmdline.o: $(cmdline_dir)/%.cmdline.c $(cmdline_dir)/%.cmdline.h | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c $(CPPFLAGS) -Wno-unused-function -o $@ $<
-
-$(object_dir)/%.o: %.c | $(object_dir)
-       @[ -z "$(Q)" ] || echo 'CC $<'
-       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) $<
-
-$(dep_dir)/%.cmdline.d: $(cmdline_dir)/%.cmdline.c | $(dep_dir)
-       @[ -z "$(Q)" ] || echo 'DEP $<'
-       $(Q) ./depend.sh $(dep_dir) $(object_dir) $(cmdline_dir) \
-               $(CPPFLAGS) $< > $@
-
-$(dep_dir)/%.d: %.c | $(dep_dir)
-       @[ -z "$(Q)" ] || echo 'DEP $<'
-       $(Q) ./depend.sh $(dep_dir) $(object_dir) $(cmdline_dir) \
-               $(CPPFLAGS) $< > $@
-
-all_objs := @recv_objs@ @filter_objs@ @client_objs@ @gui_objs@ \
-       @audiod_objs@ @audioc_objs@ @fade_objs@ @server_objs@ \
-       @write_objs@ @afh_objs@ @play_objs@
-deps := $(addprefix $(dep_dir)/, $(all_objs:.o=.d))
-
-recv_objs := $(addprefix $(object_dir)/, @recv_objs@)
-filter_objs := $(addprefix $(object_dir)/, @filter_objs@)
-client_objs := $(addprefix $(object_dir)/, @client_objs@)
-gui_objs := $(addprefix $(object_dir)/, @gui_objs@)
-audiod_objs := $(addprefix $(object_dir)/, @audiod_objs@)
-audioc_objs := $(addprefix $(object_dir)/, @audioc_objs@)
-fade_objs := $(addprefix $(object_dir)/, @fade_objs@)
-server_objs := $(addprefix $(object_dir)/, @server_objs@)
-write_objs := $(addprefix $(object_dir)/, @write_objs@)
-afh_objs := $(addprefix $(object_dir)/, @afh_objs@)
-play_objs := $(addprefix $(object_dir)/, @play_objs@)
-
-ifeq ($(findstring clean, $(MAKECMDGOALS)),)
--include $(deps)
-endif
-
-para_recv: $(recv_objs)
-       @[ -z "$(Q)" ] || echo 'LD $@'
-       $(Q) $(CC) $(recv_objs) -o $@ @recv_ldflags@ $(LDFLAGS)
-
-para_filter: $(filter_objs)
-       @[ -z "$(Q)" ] || echo 'LD $@'
-       $(Q) $(CC) $(filter_objs) -o $@ @filter_ldflags@ $(LDFLAGS)
-
-para_client: $(client_objs)
-       @[ -z "$(Q)" ] || echo 'LD $@'
-       $(Q) $(CC) -o $@ $(client_objs) @client_ldflags@ $(LDFLAGS)
-
-para_gui: $(gui_objs)
-       @[ -z "$(Q)" ] || echo 'LD $@'
-       $(Q) $(CC) -o $@ $(gui_objs) @gui_ldflags@ $(LDFLAGS)
-
-para_audiod: $(audiod_objs)
-       @[ -z "$(Q)" ] || echo 'LD $@'
-       $(Q) $(CC) -o $@ $(audiod_objs) @audiod_ldflags@ $(LDFLAGS)
-
-para_audioc: $(audioc_objs)
-       @[ -z "$(Q)" ] || echo 'LD $@'
-       $(Q) $(CC) -o $@ $(audioc_objs) @audioc_ldflags@ $(LDFLAGS)
-
-para_fade: $(fade_objs)
-       @[ -z "$(Q)" ] || echo 'LD $@'
-       $(Q) $(CC) -o $@ $(fade_objs) @fade_ldflags@ $(LDFLAGS)
-
-para_server: $(server_objs)
-       @[ -z "$(Q)" ] || echo 'LD $@'
-       $(Q) $(CC) -o $@ $(server_objs) @server_ldflags@ $(LDFLAGS)
-
-para_write: $(write_objs)
-       @[ -z "$(Q)" ] || echo 'LD $@'
-       $(Q) $(CC) -o $@ $(write_objs) @write_ldflags@ $(LDFLAGS)
-
-para_afh: $(afh_objs)
-       @[ -z "$(Q)" ] || echo 'LD $@'
-       $(Q) $(CC) -o $@ $(afh_objs) @afh_ldflags@ $(LDFLAGS)
-
-para_play: $(play_objs)
-       @[ -z "$(Q)" ] || echo 'LD $@'
-       $(Q) $(CC) -o $@ $(play_objs) @play_ldflags@ $(LDFLAGS)
-
-clean:
-       @[ -z "$(Q)" ] || echo 'CLEAN'
-       $(Q) rm -f @executables@
-       $(Q) rm -rf $(object_dir)
-
-clean2: clean
-       @[ -z "$(Q)" ] || echo 'CLEAN2'
-       $(Q) rm -f *_command_list.* *_completion.h
-       $(Q) rm -rf $(build_dir)
-distclean: clean2 test-clean
-       @[ -z "$(Q)" ] || echo 'DISTCLEAN'
-       $(Q) rm -f Makefile autoscan.log config.status config.log
-       $(Q) rm -rf autom4te.cache
-       $(Q) rm -f GPATH GRTAGS GSYMS GTAGS
-
-maintainer-clean: distclean
-       rm -f *.tar.bz2 \
-               config.h configure \
-               config.h.in skencil/*.pdf skencil/*.ps
-       rm -rf web_sync
-
-install: all man
-       $(MKDIR_P) $(BINDIR) $(MANDIR)
-       $(install_sh) -s -m 755 @executables@ $(BINDIR)
-       $(install_sh) -m 644 $(man_pages) $(MANDIR)
-       $(MKDIR_P) $(VARDIR) >/dev/null 2>&1 || true # not fatal, so don't complain
-
-$(tarball):
-       rm -rf $(tarball_pfx).tar.bz2 $(tarball_pfx)
-       git archive --format=tar --prefix=$(tarball_pfx)/ HEAD \
-               | tar --delete $(tarball_delete) > $(tarball_pfx).tar
-       $(MKDIR_P) $(tarball_pfx)
-       ./GIT-VERSION-GEN > $(tarball_pfx)/VERSION
-       cp -r $(autocrap) $(tarball_pfx)
-       tar rf $(tarball_pfx).tar $(tarball_pfx)/*
-       bzip2 -9 $(tarball_pfx).tar
-       ls -l $(tarball_pfx).tar.bz2
-       rm -rf $(tarball_pfx)
-%.ps: %.sk
-       sk2ps $< > $@
-%.pdf: %.ps
-       ps2pdf - - < $< > $@
+ggo_descriptions_declared := @ggo_descriptions_declared@
+object_executable_matrix := @object_executable_matrix@
 
-include $(test_dir)/makefile.test
+executables := @executables@
+receivers := @receivers@
+filters := @filters@
+writers := @writers@
+
+recv_objs := @recv_objs@
+filter_objs := @filter_objs@
+client_objs := @client_objs@
+gui_objs := @gui_objs@
+audiod_objs := @audiod_objs@
+audioc_objs := @audioc_objs@
+fade_objs := @fade_objs@
+server_objs := @server_objs@
+write_objs := @write_objs@
+afh_objs := @afh_objs@
+play_objs := @play_objs@
+
+speex_cppflags := @speex_cppflags@
+opus_cppflags := @opus_cppflags@
+arch_cppflags := @arch_cppflags@
+osl_cppflags := @osl_cppflags@
+id3tag_cppflags := @id3tag_cppflags@
+openssl_cppflags := @openssl_cppflags@
+ogg_cppflags := @ogg_cppflags@
+mad_cppflags := @mad_cppflags@
+faad_cppflags := @faad_cppflags@
+curses_cppflags := @curses_cppflags@
+ao_cppflags := @ao_cppflags@
+
+clock_gettime_ldflags := @clock_gettime_ldflags@
+id3tag_ldflags := @id3tag_ldflags@
+ogg_ldflags := @ogg_ldflags@
+vorbis_ldflags := @vorbis_ldflags@
+speex_ldflags := @speex_ldflags@
+opus_ldflags := @opus_ldflags@
+faad_ldflags := @faad_ldflags@
+mad_ldflags := @mad_ldflags@
+flac_ldflags := @flac_ldflags@
+oss_ldflags := @oss_ldflags@
+alsa_ldflags := @alsa_ldflags@
+ao_ldflags := @ao_ldflags@
+readline_ldflags := @readline_ldflags@
+samplerate_ldflags := @samplerate_ldflags@
+osl_ldflags := @osl_ldflags@
+openssl_ldflags := @openssl_ldflags@
+gcrypt_ldflags := @gcrypt_ldflags@
+socket_ldflags := @socket_ldflags@
+nsl_ldflags := @nsl_ldflags@
+curses_ldflags := @curses_ldflags@
+core_audio_ldflags := @core_audio_ldflags@
+
+include Makefile.real
diff --git a/Makefile.real b/Makefile.real
new file mode 100644 (file)
index 0000000..2973637
--- /dev/null
@@ -0,0 +1,307 @@
+VARDIR := /var/paraslash
+MANDIR := $(datarootdir)/man/man1
+STRIP := $(CROSS_COMPILE)strip
+HOSTCC ?= cc
+MKDIR_P := mkdir -p
+prefixed_executables := $(addprefix para_, $(executables))
+
+build_date := $(shell date)
+uname_s := $(shell uname -s 2>/dev/null || echo "UNKNOWN_OS")
+uname_rs := $(shell uname -rs)
+cc_version := $(shell $(CC) --version | head -n 1)
+GIT_VERSION := $(shell ./GIT-VERSION-GEN git-version.h)
+
+ifeq ("$(origin O)", "command line")
+       build_dir := $(O)
+else
+       build_dir := build
+endif
+ggo_dir := $(build_dir)/ggo
+object_dir := $(build_dir)/objects
+dep_dir := $(build_dir)/deps
+man_dir := $(build_dir)/man/man1
+cmdline_dir := $(build_dir)/cmdline
+m4depdir := $(build_dir)/m4deps
+help2man_dir := $(build_dir)/help2man
+hostbin_dir := $(build_dir)/host/bin
+m4_ggo_dir := m4/gengetopt
+test_dir := t
+
+# sort removes duplicate words, which is all we need here
+all_objs := $(sort $(recv_objs) $(filter_objs) $(client_objs) $(gui_objs) \
+       $(audiod_objs) $(audioc_objs) $(fade_objs) $(server_objs) \
+       $(write_objs) $(afh_objs) $(play_objs))
+deps := $(addprefix $(dep_dir)/, $(all_objs:.o=.d))
+m4_deps := $(addprefix $(m4depdir)/, $(addsuffix .m4d, $(executables)))
+
+# now prefix all objects with object dir
+recv_objs := $(addprefix $(object_dir)/, $(recv_objs))
+filter_objs := $(addprefix $(object_dir)/, $(filter_objs))
+client_objs := $(addprefix $(object_dir)/, $(client_objs))
+gui_objs := $(addprefix $(object_dir)/, $(gui_objs))
+audiod_objs := $(addprefix $(object_dir)/, $(audiod_objs))
+audioc_objs := $(addprefix $(object_dir)/, $(audioc_objs))
+fade_objs := $(addprefix $(object_dir)/, $(fade_objs))
+server_objs := $(addprefix $(object_dir)/, $(server_objs))
+write_objs := $(addprefix $(object_dir)/, $(write_objs))
+afh_objs := $(addprefix $(object_dir)/, $(afh_objs))
+play_objs := $(addprefix $(object_dir)/, $(play_objs))
+
+man_pages := $(patsubst %, $(man_dir)/%.1, $(prefixed_executables))
+
+autocrap := config.h.in configure
+tarball_pfx := $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)
+tarball_delete := $(addprefix $(tarball_pfx)/, web .gitignore)
+tarball := $(tarball_pfx).tar.bz2
+
+.PHONY: dep all clean clean2 distclean maintainer-clean install man tarball
+all: dep $(prefixed_executables) $(man_pages)
+dep: $(deps)
+man: $(man_pages)
+tarball: $(tarball)
+
+include $(m4_ggo_dir)/makefile
+include $(test_dir)/makefile.test
+ifeq ($(findstring clean, $(MAKECMDGOALS)),)
+-include $(deps)
+-include $(m4_deps)
+endif
+
+$(object_dir) $(man_dir) $(ggo_dir) $(cmdline_dir) $(dep_dir) $(m4depdir) \
+               $(help2man_dir) $(hostbin_dir):
+       $(Q) $(MKDIR_P) $@
+
+# When in doubt, use brute force (Ken Thompson)
+TOUPPER = \
+$(subst a,A,$(subst b,B,$(subst c,C,$(subst d,D,$(subst e,E,\
+$(subst f,F,$(subst g,G,$(subst h,H,$(subst i,I,$(subst j,J,\
+$(subst k,K,$(subst l,L,$(subst m,M,$(subst n,N,$(subst o,O,\
+$(subst p,P,$(subst q,Q,$(subst r,R,$(subst s,S,$(subst t,T,\
+$(subst u,U,$(subst v,V,$(subst w,W,$(subst x,X,$(subst y,Y,\
+$(subst z,Z,$1))))))))))))))))))))))))))
+
+
+DEBUG_CPPFLAGS += -g -Wunused -Wundef -W
+DEBUG_CPPFLAGS += -Wredundant-decls
+DEBUG_CPPFLAGS += -Wall -Wno-sign-compare -Wno-unknown-pragmas
+DEBUG_CPPFLAGS += -Wformat-security
+DEBUG_CPPFLAGS += -Wmissing-format-attribute
+
+ifeq ($(uname_s),Linux)
+       CPPFLAGS += -fdata-sections -ffunction-sections
+       LDFLAGS += -Wl,--gc-sections
+       CPPFLAGS += -Wstrict-prototypes
+       CPPFLAGS += -Wshadow
+       # causes warnings on *BSD for the feature test macros
+       CPPFLAGS += -Wunused-macros
+endif
+CPPFLAGS += -Os
+CPPFLAGS += -Wuninitialized
+CPPFLAGS += -Wchar-subscripts
+CPPFLAGS += -DBINDIR='"$(BINDIR)"'
+CPPFLAGS += -DBUILD_DATE='"$(build_date)"'
+CPPFLAGS += -DUNAME_RS='"$(uname_rs)"'
+CPPFLAGS += -DCC_VERSION='"$(cc_version)"'
+CPPFLAGS += -Werror-implicit-function-declaration
+CPPFLAGS += -Wmissing-noreturn
+CPPFLAGS += -Wbad-function-cast
+CPPFLAGS += -fno-strict-aliasing
+CPPFLAGS += -DMAIN_INPUT_FILE_IS_$(*F)
+CPPFLAGS += $(arch_cppflags)
+CPPFLAGS += -I/usr/local/include
+CPPFLAGS += -I$(cmdline_dir)
+CPPFLAGS += $(osl_cppflags)
+
+LDFLAGS += $(clock_gettime_ldflags)
+
+# To put more focus on warnings, be less verbose as default
+# Use 'make V=1' to see the full commands
+ifeq ("$(origin V)", "command line")
+       Q :=
+else
+       Q := @
+endif
+
+%_command_list.h: %.cmd %.c
+       @[ -z "$(Q)" ] || echo 'GEN $@'
+       $(Q) ./command_util.bash h < $< >$@
+%_command_list.man: %.cmd %.c
+       @[ -z "$(Q)" ] || echo 'GEN $@'
+       $(Q) ./command_util.bash man < $< > $@
+%_completion.h: %.cmd %.c
+       @[ -z "$(Q)" ] || echo 'GEN $@'
+       $(Q) ./command_util.bash compl $(strip $(call TOUPPER,$(*F)))_COMPLETERS \
+               $(strip $(call TOUPPER,$(*F)))_COMMANDS < $< > $@
+
+server_command_list.h server_command_list.man server_completion.h: command.c
+afs_command_list.h afs_command_list.man afs_completion.h: afs.c aft.c attribute.c
+audiod_command_list.h audiod_command_list.man audiod_completion.h: audiod_command.c
+
+server_command_lists := server_command_list.man afs_command_list.man
+audiod_command_lists := audiod_command_list.man
+play_command_lists := play_command_list.man
+
+$(man_dir)/para_server.1: $(server_command_lists)
+$(man_dir)/para_audiod.1: $(audiod_command_lists)
+$(man_dir)/para_play.1: $(play_command_lists)
+
+$(man_dir)/para_server.1: man_util_command_lists := $(server_command_lists)
+$(man_dir)/para_audiod.1: man_util_command_lists := $(audiod_command_lists)
+$(man_dir)/para_play.1: man_util_command_lists := $(play_command_lists)
+
+$(man_dir)/para_%.1: $(ggo_dir)/%.ggo man_util.bash | $(man_dir) $(help2man_dir)
+       @[ -z "$(Q)" ] || echo 'MAN $<'
+       $(Q) \
+               COMMAND_LISTS="$(man_util_command_lists)" \
+               FILTERS="$(filters)" \
+               GENGETOPT=$(GENGETOPT) \
+               GGO_DIR=$(ggo_dir) \
+               HELP2MAN=$(HELP2MAN) \
+               HELP2MAN_DIR=$(help2man_dir) \
+               RECEIVERS="$(receivers)" \
+               VERSION="$(GIT_VERSION)" \
+               WRITERS="$(writers)" \
+               ./man_util.bash $@
+
+$(hostbin_dir)/error2: error2.c | $(hostbin_dir)
+       @[ -z "$(Q)" ] || echo 'HCC $<'
+       $(Q) $(HOSTCC) -o $@ $<
+error2.h: $(hostbin_dir)/error2 Makefile
+       @[ -z "$(Q)" ] || echo 'ER2 $<'
+       @echo "$(object_executable_matrix)" | $< > $@
+
+$(object_dir)/%.o: %.c | $(object_dir)
+$(object_dir)/opus%.o: CPPFLAGS += $(opus_cppflags)
+$(object_dir)/gui%.o: CPPFLAGS += $(curses_cppflags)
+$(object_dir)/spx%.o: CPPFLAGS += $(speex_cppflags)
+$(object_dir)/%.cmdline.o: CPPFLAGS += -Wno-unused-function
+
+$(object_dir)/mp3_afh.o: CPPFLAGS += $(id3tag_cppflags)
+$(object_dir)/crypt.o: CPPFLAGS += $(openssl_cppflags)
+$(object_dir)/mp3dec_filter.o: CPPFLAGS += $(mad_cppflags)
+$(object_dir)/compress_filter.o: CPPFLAGS += -O3
+$(object_dir)/ao_write.o: CPPFLAGS += $(ao_cppflags)
+
+$(object_dir)/aacdec_filter.o \
+$(object_dir)/aac_common.o \
+$(object_dir)/aac_afh.o \
+: CPPFLAGS += $(faad_cppflags)
+
+$(object_dir)/spx_common.o \
+$(object_dir)/spxdec_filter.o \
+$(object_dir)/spx_afh.o \
+$(object_dir)/oggdec_filter.o \
+$(object_dir)/ogg_afh.o \
+$(object_dir)/ogg_afh_common.o \
+: CPPFLAGS += $(ogg_cppflags)
+
+$(object_dir)/%.o: %.c | $(object_dir)
+       @[ -z "$(Q)" ] || echo 'CC $<'
+       $(Q) $(CC) -c -o $@ $(CPPFLAGS) $(DEBUG_CPPFLAGS) $<
+
+$(object_dir)/%.cmdline.o: $(cmdline_dir)/%.cmdline.c $(cmdline_dir)/%.cmdline.h | $(object_dir)
+       @[ -z "$(Q)" ] || echo 'CC $<'
+       $(Q) $(CC) -c $(CPPFLAGS) -Wno-unused-function -o $@ $<
+
+$(dep_dir)/%.cmdline.d: $(cmdline_dir)/%.cmdline.c error2.h | $(dep_dir)
+       @[ -z "$(Q)" ] || echo 'DEP $<'
+       $(Q) ./depend.sh $(dep_dir) $(object_dir) $(cmdline_dir) \
+               $(CPPFLAGS) $< > $@
+
+$(dep_dir)/%.d: %.c error2.h | $(dep_dir)
+       @[ -z "$(Q)" ] || echo 'DEP $<'
+       $(Q) ./depend.sh $(dep_dir) $(object_dir) $(cmdline_dir) \
+               $(CPPFLAGS) $< > $@
+
+para_recv para_afh para_play para_server: LDFLAGS += $(id3tag_ldflags)
+para_write para_play para_audiod: LDFLAGS += $(ao_ldflags) $(core_audio_ldflags)
+para_client para_audioc para_play : LDFLAGS += $(readline_ldflags)
+para_server: LDFLAGS += $(osl_ldflags)
+para_gui: LDFLAGS += $(curses_ldflags)
+para_server \
+para_client \
+para_audiod \
+:LDFLAGS += \
+       $(openssl_ldflags) \
+       $(gcrypt_ldflags)
+
+para_audiod \
+para_filter \
+para_play \
+: LDFLAGS += \
+       $(mad_ldflags) \
+       $(samplerate_ldflags) \
+       -lm
+
+para_write \
+para_play \
+para_audiod \
+para_fade \
+: LDFLAGS += \
+       $(oss_ldflags) \
+       $(alsa_ldflags)
+
+para_server \
+para_filter \
+para_audiod \
+para_play \
+para_afh \
+para_recv \
+: LDFLAGS += \
+       $(ogg_ldflags) \
+       $(vorbis_ldflags) \
+       $(speex_ldflags) \
+       $(opus_ldflags) \
+       $(faad_ldflags) \
+       $(flac_ldflags)
+
+para_server \
+para_client \
+para_audioc \
+para_audiod \
+para_recv \
+: LDFLAGS += \
+       $(socket_ldflags) $(nsl_ldflags)
+
+$(foreach exe,$(executables),$(eval para_$(exe): $$($(exe)_objs)))
+$(prefixed_executables):
+       @[ -z "$(Q)" ] || echo 'LD $@'
+       $(Q) $(CC) $^ -o $@ $(LDFLAGS)
+
+clean:
+       @[ -z "$(Q)" ] || echo 'CLEAN'
+       $(Q) rm -f $(prefixed_executables)
+       $(Q) rm -rf $(object_dir)
+
+clean2: clean
+       @[ -z "$(Q)" ] || echo 'CLEAN2'
+       $(Q) rm -f *_command_list.* *_completion.h
+       $(Q) rm -rf $(build_dir)
+distclean: clean2 test-clean
+       @[ -z "$(Q)" ] || echo 'DISTCLEAN'
+       $(Q) rm -f Makefile autoscan.log config.status config.log error2.h
+       $(Q) rm -rf autom4te.cache
+       $(Q) rm -f GPATH GRTAGS GSYMS GTAGS
+
+maintainer-clean: distclean
+       rm -f *.tar.bz2 config.h configure config.h.in
+       rm -rf web_sync
+
+install: all man
+       $(MKDIR_P) $(BINDIR) $(MANDIR)
+       $(INSTALL) -s --strip-program $(STRIP) -m 755 \
+               $(prefixed_executables) $(BINDIR)
+       $(INSTALL) -m 644 $(man_pages) $(MANDIR)
+       $(MKDIR_P) $(VARDIR) >/dev/null 2>&1 || true # not fatal, so don't complain
+
+$(tarball):
+       rm -rf $(tarball_pfx).tar.bz2 $(tarball_pfx)
+       git archive --format=tar --prefix=$(tarball_pfx)/ HEAD \
+               | tar --delete $(tarball_delete) > $(tarball_pfx).tar
+       $(MKDIR_P) $(tarball_pfx)
+       ./GIT-VERSION-GEN > $(tarball_pfx)/VERSION
+       cp -r $(autocrap) $(tarball_pfx)
+       tar rf $(tarball_pfx).tar $(tarball_pfx)/*
+       bzip2 -9 $(tarball_pfx).tar
+       ls -l $(tarball_pfx).tar.bz2
+       rm -rf $(tarball_pfx)
diff --git a/NEWS b/NEWS
index 4127e38bcdf0434be750aed7da7fee83acad872e..311aca2b06996005eb1ce2972a5c4df5116f6a58 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,103 @@
----------------------------------------------
-0.?.? (to be announced) "invertible validity"
----------------------------------------------
+NEWS
+====
+
+-------------------------------------------------
+0.5.3 (to be released) "symbolic synchronization"
+-------------------------------------------------
+
+Not many new features, but lots of fixes and usability improvements.
+
+       - para_gui has been converted to use the paraslash scheduler.
+       - Various alsa-related fixes, mostly for the raspberry pi.
+       - Many scheduler improvements and cleanups.
+       - The test suite has been extended to include sanity checks
+         for the generated man pages.
+       - ao_writer fixes. This writer was in a quite bad shape. Many
+         serious bugs have been fixed.
+       - new audiod command: version.
+       - Minor improvements to the bitstream API.
+       - The cpsi command now prints a meaningful error message if
+         none of the given patterns matched any audio file.
+
+----------------------------------------
+0.5.2 (2014-04-11) "orthogonal interior"
+----------------------------------------
+
+The new sync filter, the AES_CTR128 stream cipher and the overhauled
+network code are the highlights of this release. It also includes a
+fair number of smaller fixes and improvements not mentioned here.
+
+       - The new sync filter synchronizes playback between multiple
+         clients.
+       - Connections between para_server and para_client are now
+         encrypted by means of AES rather than RC4 if both sides
+         support it. RC4 is still available as a fallback. This
+         feature is fully transparent, i.e. no command line options
+         are necessary, and a client linked against openssl can
+         speak with a server linked against libgcrypt and vice versa.
+       - Major cleanup of the networking subsystem.
+       - Improvements to para_fade: the new set mode, multi-channel
+         initial volumes, better error logging.
+       - The man pages of para_audiod, para_filter, para_recv, and
+         para_write contain the relevant options for receivers, filters,
+         writers. This broke in 0.5.0.
+       - ogg/vorbis latency improvements.
+       - Improved user manual.
+       - Minor fixes to avoid clang warnings.
+
+Downloads: ./releases/paraslash-0.5.2.tar.bz2 (tarball),
+./releases/paraslash-0.5.2.tar.bz2.asc (signature)
+
+------------------------------------------
+0.5.1 (2013-12-20) "temporary implication"
+------------------------------------------
+
+Lots of fixes and improvements all over the place, and a major overhaul
+of the build system.
+
+       - Audiod improvements and fixes.
+       - Buffer tree robustness improvements.
+       - Cleanup of the mood subsystem.
+       - Fixes and cleanups for the flac decoder.
+       - Latency improvements for the ogg/opus decoder.
+       - Crypto support is now optional. On systems without
+         openssl/gcrypt, the build succeeds but para_server,
+         para_audiod, para_client won't be built.
+       - The build system now works for cross-compile setups.
+       - The dependency tree has been flattened, which speeds up
+         builds and avoids to recreate the man pages on every change.
+       - The error code helper has been rewritten from perl to C,
+         which further improves build time.
+       - Many small bugs in the build system have been identified
+         and fixed.
+
+Downloads: ./releases/paraslash-0.5.1.tar.bz2 (tarball),
+./releases/paraslash-0.5.1.tar.bz2.asc (signature)
+
+----------------------------------------
+0.5.0 (2013-08-23) "invertible validity"
+----------------------------------------
+
+Some API-breaking changes, one serious bug fix, and a lot of bike-shedding.
+
+       - The sideband compatibility code has been removed, hence
+         sideband connections (introduced in 0.4.11) are now mandatory.
+       - Addblob commands can produce output.
+       - The stat command no longer sends garbage when para_server was
+         compiled against libgcrypt.
+       - Dependencies for gengetopt files are computed automatically.
+         This eliminates a constant source of build bugs.
+       - The setatt command now accepts file name patterns rather than only
+         path names.
+       - overview.pdf is now based on dia, a simple diagram creation program.
+         The new version is much more detailed and contains descriptions of
+         the various programs of the paraslash package.
+       - The separator of all multi-word options has been changed from
+         underscore to dash. For example --log_color becomes --log-color.
+       - Overhauled web pages and the new logo.
+
+Downloads: ./releases/paraslash-0.5.0.tar.bz2 (tarball),
+./releases/paraslash-0.5.0.tar.bz2.asc (signature)
 
 --------------------------------------
 0.4.13 (2013-07-29) "spectral gravity"
diff --git a/README b/README
index e991b7340e61bb2bee929fe145e39b0dee32bf8d..24b971d310d77e886f50c59cfa9a70bce4b0b179 100644 (file)
--- a/README
+++ b/README
@@ -1,26 +1,12 @@
-README
-======
+The paraslash package contains server and client software for network
+audio streaming and stand-alone utilities for decoding and playing
+audio files. See the user manual for details.
 
-----
-Paraslash is an acronym for
+Distribution of paraslash is covered by the GNU GPL, version 2 unless
+otherwise stated. See file COPYING.
 
-_Play, archive, rate and stream large audio sets happily_
+Web page:      http://paraslash.systemlinux.org/
+Git URL:       git://paraslash.systemlinux.org/git
+Email:         Andre Noll <maan@systemlinux.org>
 
-The paraslash package contains server and client software for
-network streaming as well as stand-alone utilities for decoding
-mp3, ogg, aac and wma files. See the user manual for details.
-
-
--------
-LICENSE
--------
-
-Distribution of paraslash is covered by the GNU GPL, version 2. See file
-COPYING.
-
-----------
-THE AUTHOR
-----------
-
-Andre Noll <maan@systemlinux.org>
 Comments and bug reports are welcome.
diff --git a/aac.h b/aac.h
index 08bc8b1ef6d26fdf6486b0a3becd015a3b5e9b7f..6e6c3402b303095334bd71e84d10c95d835ab47e 100644 (file)
--- a/aac.h
+++ b/aac.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 2d04695a84305972c6a4d87b1aef77457a8606ad..f354a63ce9c3c34b95d32d19bc588bd1134470eb 100644 (file)
--- a/aac_afh.c
+++ b/aac_afh.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -111,15 +111,15 @@ static void read_tags(unsigned char *buf, size_t buflen, struct afh_info *afhi)
                q = p + ret + ret2 + 8;
                if (q + size2 > buf + buflen)
                        break;
-               if (!atom_cmp(type1, "©ART"))
+               if (!atom_cmp(type1, "\xa9" "ART"))
                        afhi->tags.artist = get_tag(q, size2);
-               else if (!atom_cmp(type1, "©alb"))
+               else if (!atom_cmp(type1, "\xa9" "alb"))
                        afhi->tags.album = get_tag(q, size2);
-               else if (!atom_cmp(type1, "©nam"))
+               else if (!atom_cmp(type1, "\xa9" "nam"))
                        afhi->tags.title = get_tag(q, size2);
-               else if (!atom_cmp(type1, "©cmt"))
+               else if (!atom_cmp(type1, "\xa9" "cmt"))
                        afhi->tags.comment = get_tag(q, size2);
-               else if (!atom_cmp(type1, "©day"))
+               else if (!atom_cmp(type1, "\xa9" "day"))
                        afhi->tags.year = get_tag(q, size2);
                p += size1;
        }
index ab1fb50c259546755f23ca8838eeba1c63def529..ca29607a1753e243d8d2f627842776e57af7ce2e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 3ff90834c62bb75f179e5778ef02f6d23feb0d09..7988723bd2b3cf4194de426dcdc965937cfe29d2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -80,9 +80,9 @@ static void aacdec_close(struct filter_node *fn)
        fn->private_data = NULL;
 }
 
-static int aacdec_post_select(__a_unused struct sched *s, struct task *t)
+static int aacdec_post_select(__a_unused struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        struct btr_node *btrn = fn->btrn;
        struct private_aacdec_data *padd = fn->private_data;
        int i, ret;
diff --git a/acl.c b/acl.c
index 60f835aefc0e2c777dae34e1a0b80fb371e0268e..e1415050e6e47a1397689bbcbcdc341693834e71 100644 (file)
--- a/acl.c
+++ b/acl.c
@@ -1,18 +1,24 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 
 /** \file acl.c Access control lists for paraslash senders. */
 
+#include <netinet/in.h>
+#include <sys/socket.h>
 #include <regex.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
 
 #include "para.h"
 #include "error.h"
 #include "string.h"
 #include "list.h"
 #include "net.h"
+#include "acl.h"
 
 /**
  * Describes one entry in the blacklist/whitelist of a paraslash sender.
@@ -57,7 +63,7 @@ static int acl_lookup(int fd, struct list_head *acl)
                PARA_ERROR_LOG("Can not determine peer address: %s\n", strerror(errno));
                goto no_match;
        }
-       v4_addr = extract_v4_addr(&ss);
+       extract_v4_addr(&ss, &v4_addr);
        if (!v4_addr.s_addr)
                goto no_match;
 
diff --git a/acl.h b/acl.h
index c44f26ab21fa042ca0be1093e97262c5d325ce2d..af68e1bcef1c517b411a531ff9f6e8d03637ec9f 100644 (file)
--- a/acl.h
+++ b/acl.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2008-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/afh.c b/afh.c
index 8e70750511381b425c33f0c7cf8237dc1a47af16..15b5e6b940b17b02043b38937ff8f44fca0dc04e 100644 (file)
--- a/afh.c
+++ b/afh.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2008-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/afh.h b/afh.h
index b224b61a4bbf5f210311fe2c7573c4725e866e7a..2264cc6139501e26d1f46ba89960cf5e630308c2 100644 (file)
--- a/afh.h
+++ b/afh.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 5be43550c202b516aaedf332dbbfba341da20dcb..b3ba348526cad86c103bcff65e3765fc3b571e2a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -230,11 +230,12 @@ success:
 }
 
 /**
- * Deallocate contents of a filled-in ahi structure
+ * Deallocate the contents of an afh_info structure.
  *
  * \param afhi The structure to clear.
  *
- * The given pointer is kept, everything else is freed.
+ * This only frees the memory the various pointer fields of \a afhi point to.
+ * It does *not* free \a afhi itself.
  */
 void clear_afhi(struct afh_info *afhi)
 {
index 5c17dab7de21132cf48d50bfaf37eabba506ce6f..657a205737595f370eeb238813a7cd2c009064dc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2011-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -60,7 +60,6 @@ static int afh_execute(struct btr_node *btrn, const char *cmd, char **result)
                if (x >= pard->afhi.chunks_total)
                        return -ERRNO_TO_PARA_ERROR(EINVAL);
                pard->first_chunk = pard->current_chunk = x;
-               rn->task.error = 0;
                return 1;
        }
        return -E_BTR_NAVAIL;
@@ -151,14 +150,14 @@ static void afh_recv_close(struct receiver_node *rn)
        freep(&rn->private_data);
 }
 
-static void afh_recv_pre_select(struct sched *s, struct task *t)
+static void afh_recv_pre_select(struct sched *s, void *context)
 {
-       struct receiver_node *rn = container_of(t, struct receiver_node, task);
+       struct receiver_node *rn = context;
        struct private_afh_recv_data *pard = rn->private_data;
        struct afh_info *afhi = &pard->afhi;
        struct afh_recv_args_info *conf = rn->conf;
        struct timeval chunk_time;
-       int state = generic_recv_pre_select(s, t);
+       int state = generic_recv_pre_select(s, rn);
 
        if (state <= 0)
                return;
@@ -171,9 +170,9 @@ static void afh_recv_pre_select(struct sched *s, struct task *t)
        sched_request_barrier_or_min_delay(&chunk_time, s);
 }
 
-static int afh_recv_post_select(__a_unused struct sched *s, struct task *t)
+static int afh_recv_post_select(__a_unused struct sched *s, void *context)
 {
-       struct receiver_node *rn = container_of(t, struct receiver_node, task);
+       struct receiver_node *rn = context;
        struct afh_recv_args_info *conf = rn->conf;
        struct private_afh_recv_data *pard = rn->private_data;
        struct btr_node *btrn = rn->btrn;
diff --git a/afs.c b/afs.c
index c87fdf78fb9bf60d413503f557cac34573b50edf..a17da5b4ac82e11b88561c35e54ec624960424cd 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -1,15 +1,20 @@
 /*
- * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 
 /** \file afs.c Paraslash's audio file selector. */
 
+#include <netinet/in.h>
+#include <sys/socket.h>
 #include <regex.h>
 #include <signal.h>
 #include <fnmatch.h>
 #include <osl.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
 
 #include "server.cmdline.h"
 #include "para.h"
@@ -76,7 +81,7 @@ struct command_task {
         */
        uint32_t cookie;
        /** The associated task structure. */
-       struct task task;
+       struct task *task;
 };
 
 extern int mmd_mutex;
@@ -565,10 +570,7 @@ int afs_cb_result_handler(struct osl_object *result, uint8_t band,
        assert(cc);
        if (!result->size)
                return 1;
-       if (cc->use_sideband)
-               return send_sb(&cc->scc, result->data, result->size, band,
-                       true);
-       return sc_send_bin_buffer(&cc->scc, result->data, result->size);
+       return send_sb(&cc->scc, result->data, result->size, band, true);
 }
 
 static void com_select_callback(int fd, const struct osl_object *query)
@@ -717,13 +719,13 @@ static int open_afs_tables(void)
        return ret;
 }
 
-static void signal_pre_select(struct sched *s, struct task *t)
+static void signal_pre_select(struct sched *s, void *context)
 {
-       struct signal_task *st = container_of(t, struct signal_task, task);
+       struct signal_task *st = context;
        para_fd_set(st->fd, &s->rfds, &s->max_fileno);
 }
 
-static int afs_signal_post_select(struct sched *s, __a_unused struct task *t)
+static int afs_signal_post_select(struct sched *s, __a_unused void *context)
 {
        int signum, ret;
 
@@ -760,10 +762,13 @@ static void register_signal_task(struct sched *s)
        para_install_sighandler(SIGTERM);
        para_install_sighandler(SIGHUP);
 
-       st->task.pre_select = signal_pre_select;
-       st->task.post_select = afs_signal_post_select;
-       sprintf(st->task.status, "signal task");
-       register_task(s, &st->task);
+       st->task = task_register(&(struct task_info) {
+               .name = "signal",
+               .pre_select = signal_pre_select,
+               .post_select = afs_signal_post_select,
+               .context = st,
+
+       }, s);
 }
 
 static struct list_head afs_client_list;
@@ -778,9 +783,9 @@ struct afs_client {
        struct timeval connect_time;
 };
 
-static void command_pre_select(struct sched *s, struct task *t)
+static void command_pre_select(struct sched *s, void *context)
 {
-       struct command_task *ct = container_of(t, struct command_task, task);
+       struct command_task *ct = context;
        struct afs_client *client;
 
        para_fd_set(server_socket, &s->rfds, &s->max_fileno);
@@ -807,7 +812,7 @@ static void command_pre_select(struct sched *s, struct task *t)
  * \return Zero if \a buf is \p NULL or \a size is zero. Negative on errors,
  * and positive on success.
  */
-int pass_buffer_as_shm(int fd, uint8_t band, char *buf, size_t size)
+int pass_buffer_as_shm(int fd, uint8_t band, const char *buf, size_t size)
 {
        int ret, shmid;
        void *shm;
@@ -915,14 +920,14 @@ err:
 /** Shutdown connection if query has not arrived until this many seconds. */
 #define AFS_CLIENT_TIMEOUT 3
 
-static int command_post_select(struct sched *s, struct task *t)
+static int command_post_select(struct sched *s, void *context)
 {
-       struct command_task *ct = container_of(t, struct command_task, task);
+       struct command_task *ct = context;
        struct sockaddr_un unix_addr;
        struct afs_client *client, *tmp;
        int fd, ret;
 
-       ret = task_get_notification(t);
+       ret = task_get_notification(ct->task);
        if (ret < 0)
                return ret;
        ret = execute_server_command(&s->rfds);
@@ -970,10 +975,12 @@ static void register_command_task(uint32_t cookie, struct sched *s)
        ct->fd = setup_command_socket_or_die();
        ct->cookie = cookie;
 
-       ct->task.pre_select = command_pre_select;
-       ct->task.post_select = command_post_select;
-       sprintf(ct->task.status, "afs command task");
-       register_task(s, &ct->task);
+       ct->task = task_register(&(struct task_info) {
+               .name = "afs command",
+               .pre_select = command_pre_select,
+               .post_select = command_post_select,
+               .context = ct,
+       }, s);
 }
 
 /**
@@ -1005,6 +1012,7 @@ __noreturn void afs_init(uint32_t cookie, int socket_fd)
        s.default_timeout.tv_sec = 0;
        s.default_timeout.tv_usec = 999 * 1000;
        ret = schedule(&s);
+       sched_shutdown(&s);
 out_close:
        close_afs_tables();
 out:
@@ -1068,9 +1076,6 @@ int com_init(struct command_context *cc)
        }
        ret = send_callback_request(create_tables_callback, &query,
                afs_cb_result_handler, cc);
-       if (ret < 0 && !cc->use_sideband)
-               /* ignore return value */
-               sc_send_va_buffer(&cc->scc, "%s\n", para_strerror(-ret));
        return ret;
 }
 
diff --git a/afs.cmd b/afs.cmd
index 82b6dc485cd00683b58a4ec79bd1e69c5602690f..91da48cb4511a8b740c27f93b73812132cbf3e09 100644 (file)
--- a/afs.cmd
+++ b/afs.cmd
@@ -22,7 +22,7 @@ H:    database, skip this file.  This operation is really cheap.
 H:     Use it when adding large directories if only a few files
 H:     where added.
 H:
-H:-f   Force adding/updating. Recompute the audio format handler data
+H: -f  Force adding/updating. Recompute the audio format handler data
 H:     even if a file with the same path and the same hash value exists.
 H:
 H: -v  Verbose mode. Print what is being done.
@@ -44,17 +44,12 @@ H: Options:
 H:
 H: -l  Change listing mode. Defaults to short listing if not given.
 H:
-H:             -ls:   short listing mode
-H:
-H:             -ll:   long listing mode (equivalent to -l)
-H:
-H:             -lv:   verbose listing mode
-H:
-H:             -lp:   parser-friendly mode
-H:
-H:             -lm:   mbox listing mode
-H:
-H:             -lc:   chunk-table listing mode
+H:    -ls: short listing mode
+H:    -ll: long listing mode (equivalent to -l)
+H:    -lv: verbose listing mode
+H:    -lp: parser-friendly mode
+H:    -lm: mbox listing mode
+H:    -lc: chunk-table listing mode
 H:
 H: -p  List full path of audio file. If not specified, only the basename
 H:     of each file is printed.
@@ -68,27 +63,17 @@ H: -d       Print dates as seconds after the epoch.
 H:
 H: -s  Change sort order. Defaults to alphabetical path sort if not given.
 H:
-H:             -sp:  sort by path.
-H:
-H:             -sl:  sort by last played time.
-H:
-H:             -ss:  sort by score (implies -a).
-H:
-H:             -sn:  sort by num played count.
-H:
-H:             -sf:  sort by frequency.
-H:
-H:             -sc:  sort by number of channels.
-H:
-H:             -si:  sort by image id.
-H:
-H:             -sy:  sort by lyrics id.
-H:
-H:             -sb:  sort by bit rate.
-H:
-H:             -sd:  sort by duration.
-H:
-H:             -sa:  sort by audio format.
+H:    -sp: by path
+H:    -sl: by last played time
+H:    -ss: by score (implies -a)
+H:    -sn: by num played count
+H:    -sf: by frequency
+H:    -sc: by number of channels
+H:    -si: by image id
+H:    -sy: by lyrics id
+H:    -sb: by bit rate
+H:    -sd: by duration
+H:    -sa: by audio format
 ---
 N: lsatt
 P: AFS_READ
diff --git a/afs.h b/afs.h
index b415bfec6c2c7aa6d8fcb0f12308c7e8d30b7025..7a3f963f940e3e710e02d0dbb34e42e97a9542fd 100644 (file)
--- a/afs.h
+++ b/afs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -20,7 +20,7 @@ struct afs_info {
        uint32_t image_id;
        /** Lyrics blob associated with this file (foreign key). */
        uint32_t lyrics_id;
-       /** Mp3, ogg, aac, wma, spx. */
+       /** Mp3, ogg, ... */
        uint8_t audio_format_id;
        /** Amplification value. */
        uint8_t amp;
@@ -207,7 +207,7 @@ typedef void callback_function(int fd, const struct osl_object *);
  */
 typedef int callback_result_handler(struct osl_object *result, uint8_t band, void *private);
 int afs_cb_result_handler(struct osl_object *result, uint8_t band, void *private);
-int pass_buffer_as_shm(int fd, uint8_t band, char *buf, size_t size);
+int pass_buffer_as_shm(int fd, uint8_t band, const char *buf, size_t size);
 
 /** Structure passed to the AFS max_size handler. */
 struct afs_max_size_handler_data {
@@ -279,13 +279,9 @@ int aft_get_row_of_path(const char *path, struct osl_row **row);
 int open_and_update_audio_file(struct osl_row *aft_row, long score,
        struct audio_file_data *afd);
 int load_afd(int shmid, struct audio_file_data *afd);
-int load_afsi(struct afs_info *afsi, struct osl_object *obj);
-void save_afsi(struct afs_info *afsi, struct osl_object *obj);
 int get_afsi_of_row(const struct osl_row *row, struct afs_info *afsi);
 int get_afhi_of_row(const struct osl_row *row, struct afh_info *afhi);
-int get_afsi_of_path(const char *path, struct afs_info *afsi);
 int get_audio_file_path_of_row(const struct osl_row *row, char **path);
-int get_afsi_object_of_row(const struct osl_row *row, struct osl_object *obj);
 int audio_file_loop(void *private_data, osl_rbtree_loop_func *func);
 void aft_check_callback(int fd, __a_unused const struct osl_object *query);
 
diff --git a/aft.c b/aft.c
index a2883d4af1438ea9ab30e93a94ebc1a3ba5b1419..39f95ad2517b15979a31545e79fae13c7ec33c7e 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -163,7 +163,7 @@ enum afsi_offsets {
        AFSI_SIZE = 32
 };
 
-/**
+/*
  * Convert a struct afs_info to an osl object.
  *
  * \param afsi Pointer to the audio file info to be converted.
@@ -171,7 +171,7 @@ enum afsi_offsets {
  *
  * \sa load_afsi().
  */
-void save_afsi(struct afs_info *afsi, struct osl_object *obj)
+static void save_afsi(struct afs_info *afsi, struct osl_object *obj)
 {
        char *buf = obj->data;
 
@@ -186,17 +186,17 @@ void save_afsi(struct afs_info *afsi, struct osl_object *obj)
        memset(buf + AFSI_AUDIO_FORMAT_UNUSED_OFFSET, 0, 2);
 }
 
-/**
- *  Get the audio file selector info struct stored in an osl object.
+/*
+ * Get the audio file selector info struct stored in an osl object.
  *
  * \param afsi Points to the audio_file info structure to be filled in.
  * \param obj The osl object holding the data.
  *
- * \return Positive on success, negative on errors. Possible errors: \p E_BAD_AFS.
+ * \return Standard.
  *
  * \sa save_afsi().
  */
-int load_afsi(struct afs_info *afsi, struct osl_object *obj)
+static int load_afsi(struct afs_info *afsi, struct osl_object *obj)
 {
        char *buf = obj->data;
        if (obj->size < AFSI_SIZE)
@@ -493,15 +493,16 @@ static int aft_get_row_of_hash(unsigned char *hash, struct osl_row **row)
        return osl(osl_get_row(audio_file_table, AFTCOL_HASH, &obj, row));
 }
 
-/**
- * Get the osl object holding the audio file selector info of a row.
+/*
+ * Get the audio file selector info object of a row.
  *
  * \param row Pointer to a row in the audio file table.
  * \param obj Result pointer.
  *
  * \return Standard.
  */
-int get_afsi_object_of_row(const struct osl_row *row, struct osl_object *obj)
+static int get_afsi_object_of_row(const struct osl_row *row,
+               struct osl_object *obj)
 {
        return osl(osl_get_object(audio_file_table, row, AFTCOL_AFSI, obj));
 }
@@ -541,15 +542,15 @@ int get_afsi_of_row(const struct osl_row *row, struct afs_info *afsi)
        return load_afsi(afsi, &obj);
 }
 
-/**
+/*
  * Get the audio file selector info, given the path of an audio table.
  *
  * \param path The full path of the audio file.
  * \param afsi Result pointer.
  *
- * \return Positive on success, negative on errors.
+ * \return Standard.
  */
-int get_afsi_of_path(const char *path, struct afs_info *afsi)
+static int get_afsi_of_path(const char *path, struct afs_info *afsi)
 {
        struct osl_object obj;
        int ret = get_afsi_object_of_path(path, &obj);
@@ -1876,12 +1877,8 @@ static int add_one_audio_file(const char *path, void *private_data)
        ret = 1;
        if (pb && (pad->flags & ADD_FLAG_LAZY)) { /* lazy is really cheap */
                if (pad->flags & ADD_FLAG_VERBOSE)
-                       send_ret = pad->cc->use_sideband?
-                               send_sb_va(&pad->cc->scc, SBD_OUTPUT,
-                                       "lazy-ignore: %s\n", path)
-                       :
-                               sc_send_va_buffer(&pad->cc->scc,
-                                       "lazy-ignore: %s\n", path);
+                       send_ret = send_sb_va(&pad->cc->scc, SBD_OUTPUT,
+                               "lazy-ignore: %s\n", path);
                goto out_free;
        }
        /* We still want to add this file. Compute its hash. */
@@ -1901,12 +1898,8 @@ static int add_one_audio_file(const char *path, void *private_data)
        ret = 1;
        if (pb && hs && hs == pb && !(pad->flags & ADD_FLAG_FORCE)) {
                if (pad->flags & ADD_FLAG_VERBOSE)
-                       send_ret = pad->cc->use_sideband?
-                               send_sb_va(&pad->cc->scc, SBD_OUTPUT,
-                                       "%s exists, not forcing update\n", path)
-                       :
-                               sc_send_va_buffer(&pad->cc->scc,
-                                       "%s exists, not forcing update\n", path);
+                       send_ret = send_sb_va(&pad->cc->scc, SBD_OUTPUT,
+                               "%s exists, not forcing update\n", path);
                goto out_unmap;
        }
        /*
@@ -1923,12 +1916,8 @@ static int add_one_audio_file(const char *path, void *private_data)
        munmap(map.data, map.size);
        close(fd);
        if (pad->flags & ADD_FLAG_VERBOSE) {
-               send_ret = pad->cc->use_sideband?
-                       send_sb_va(&pad->cc->scc, SBD_OUTPUT,
-                               "adding %s\n", path)
-               :
-                       sc_send_va_buffer(&pad->cc->scc,
-                               "adding %s\n", path);
+               send_ret = send_sb_va(&pad->cc->scc, SBD_OUTPUT,
+                       "adding %s\n", path);
                if (send_ret < 0)
                        goto out_free;
        }
@@ -1943,14 +1932,8 @@ out_unmap:
        munmap(map.data, map.size);
 out_free:
        if (ret < 0 && send_ret >= 0)
-               send_ret = pad->cc->use_sideband?
-                       send_sb_va(&pad->cc->scc, SBD_ERROR_LOG,
-                               "failed to add %s (%s)\n", path,
-                               para_strerror(-ret))
-               :
-                       sc_send_va_buffer(&pad->cc->scc,
-                               "failed to add %s (%s)\n", path,
-                               para_strerror(-ret));
+               send_ret = send_sb_va(&pad->cc->scc, SBD_ERROR_LOG,
+                       "failed to add %s (%s)\n", path, para_strerror(-ret));
        free(obj.data);
        clear_afhi(afhi_ptr);
        /* Stop adding files only on send errors. */
@@ -1994,11 +1977,7 @@ int com_add(struct command_context *cc)
                char *path;
                ret = verify_path(cc->argv[i], &path);
                if (ret < 0) {
-                       ret = cc->use_sideband?
-                               send_sb_va(&cc->scc, SBD_ERROR_LOG, "%s: %s\n",
-                               cc->argv[i], para_strerror(-ret))
-                       :
-                               sc_send_va_buffer(&cc->scc, "%s: %s\n",
+                       ret = send_sb_va(&cc->scc, SBD_ERROR_LOG, "%s: %s\n",
                                cc->argv[i], para_strerror(-ret));
                        if (ret < 0)
                                return ret;
@@ -2006,14 +1985,9 @@ int com_add(struct command_context *cc)
                }
                ret = stat(path, &statbuf);
                if (ret < 0) {
-                       ret = cc->use_sideband?
-                               send_sb_va(&cc->scc, SBD_ERROR_LOG,
-                                       "failed to stat %s (%s)\n", path,
-                                       strerror(errno))
-                               :
-                               sc_send_va_buffer(&cc->scc,
-                                       "failed to stat %s (%s)\n", path,
-                                       strerror(errno));
+                       ret = send_sb_va(&cc->scc, SBD_ERROR_LOG,
+                               "failed to stat %s (%s)\n", path,
+                               strerror(errno));
                        free(path);
                        if (ret < 0)
                                return ret;
@@ -2025,12 +1999,8 @@ int com_add(struct command_context *cc)
                else
                        ret = add_one_audio_file(path, &pad);
                if (ret < 0) {
-                       if (cc->use_sideband)
-                               send_sb_va(&cc->scc, SBD_OUTPUT, "%s: %s\n", path,
-                                       para_strerror(-ret));
-                       else
-                               sc_send_va_buffer(&cc->scc, "%s: %s\n", path,
-                                       para_strerror(-ret));
+                       send_sb_va(&cc->scc, SBD_OUTPUT, "%s: %s\n", path,
+                               para_strerror(-ret));
                        free(path);
                        return ret;
                }
@@ -2439,13 +2409,12 @@ static void com_cpsi_callback(int fd, const struct osl_object *query)
 out:
        if (ret < 0)
                para_printf(&cad.pb, "%s\n", para_strerror(-ret));
-       else if (cad.flags & CPSI_FLAG_VERBOSE) {
-               if (pmd.num_matches > 0)
+       else if (pmd.num_matches > 0) {
+               if (cad.flags & CPSI_FLAG_VERBOSE)
                        para_printf(&cad.pb, "copied requested afsi from %s "
                                "to %u files\n", source_path, pmd.num_matches);
-               else
-                       para_printf(&cad.pb, "nothing copied\n");
-       }
+       } else
+               para_printf(&cad.pb, "no matches - nothing copied\n");
        if (cad.pb.offset)
                pass_buffer_as_shm(fd, SBD_OUTPUT, cad.pb.buf, cad.pb.offset);
        free(cad.pb.buf);
@@ -2502,6 +2471,108 @@ int com_cpsi(struct command_context *cc)
        return ret;
 }
 
+struct change_atts_data {
+       uint64_t add_mask, del_mask;
+       struct para_buffer pb;
+};
+
+static int change_atts(__a_unused struct osl_table *table,
+               struct osl_row *row, __a_unused const char *name, void *data)
+{
+       int ret;
+       struct osl_object obj;
+       struct afs_info old_afsi, new_afsi;
+       struct afsi_change_event_data aced = {
+               .aft_row = row,
+               .old_afsi = &old_afsi
+       };
+       struct change_atts_data *cad = data;
+
+       ret = get_afsi_object_of_row(row, &obj);
+       if (ret < 0)
+               return ret;
+       ret = load_afsi(&old_afsi, &obj);
+       if (ret < 0)
+               return ret;
+       new_afsi = old_afsi;
+       new_afsi.attributes |= cad->add_mask;
+       new_afsi.attributes &= ~cad->del_mask;
+       save_afsi(&new_afsi, &obj); /* in-place update */
+       afs_event(AFSI_CHANGE, &cad->pb, &aced);
+       return 1;
+}
+
+static void com_setatt_callback(int fd, const struct osl_object *query)
+{
+       char *p;
+       int ret;
+       size_t len;
+       struct change_atts_data cad = {
+               .pb = {
+                       .max_size = shm_get_shmmax(),
+                       .max_size_handler = afs_max_size_handler,
+                       .private_data = &(struct afs_max_size_handler_data) {
+                               .fd = fd,
+                               .band = SBD_OUTPUT
+                       }
+               }
+       };
+       struct pattern_match_data pmd = {
+               .table = audio_file_table,
+               .loop_col_num = AFTCOL_HASH,
+               .match_col_num = AFTCOL_PATH,
+               .pm_flags = PM_SKIP_EMPTY_NAME,
+               .data = &cad,
+               .action = change_atts
+       };
+
+       for (p = query->data; p < (char *)query->data + query->size; p += len + 1) {
+               char c;
+               unsigned char bitnum;
+
+               len = strlen(p);
+               ret = -E_ATTR_SYNTAX;
+               if (len == 0)
+                       goto out;
+               c = p[len - 1];
+               if (c != '+' && c != '-')
+                       break;
+               p[len - 1] = '\0';
+               ret = get_attribute_bitnum_by_name(p, &bitnum);
+               if (ret < 0)
+                       goto out;
+               if (c == '+')
+                       cad.add_mask |= (1UL << bitnum);
+               else
+                       cad.del_mask |= (1UL << bitnum);
+       }
+       ret = -E_ATTR_SYNTAX;
+       if (!cad.add_mask && !cad.del_mask)
+               goto out;
+       pmd.patterns.data = p;
+       assert(p < (char *)query->data + query->size);
+       pmd.patterns.size = (char *)query->data + query->size - p;
+       ret = for_each_matching_row(&pmd);
+       if (ret < 0)
+               goto out;
+       if (pmd.num_matches == 0)
+               para_printf(&cad.pb, "no matches\n");
+out:
+       if (ret < 0)
+               para_printf(&cad.pb, "%s\n", para_strerror(-ret));
+       if (cad.pb.offset)
+               pass_buffer_as_shm(fd, SBD_OUTPUT, cad.pb.buf, cad.pb.offset);
+       free(cad.pb.buf);
+}
+
+int com_setatt(struct command_context *cc)
+{
+       if (cc->argc < 3)
+               return -E_ATTR_SYNTAX;
+       return send_standard_callback_request(cc->argc - 1, cc->argv + 1,
+               com_setatt_callback, afs_cb_result_handler, cc);
+}
+
 static void afs_stat_callback(int fd, const struct osl_object *query)
 {
        int *parser_friendly = query->data;
index 01f1c51260a7b6753ba8b14aac0c255120b4b331..c860efc8aa34d9776f52375d87c4d9cb43ad3c27 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2012-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -141,19 +141,19 @@ static int alsa_mix_set_channel(struct mixer_handle *h,
                PARA_NOTICE_LOG("unable to find simple control '%s',%i\n",
                        snd_mixer_selem_id_get_name(sid),
                        snd_mixer_selem_id_get_index(sid));
-               return -E_ALSA_MIX_BAD_ELEM;
+               return -E_BAD_CHANNEL;
        }
        ret = snd_mixer_selem_get_playback_volume_range(h->elem,
                &h->pmin, &h->pmax);
        if (ret < 0) {
                PARA_NOTICE_LOG("unable to get %s range (%s): %s\n",
                        mixer_channel, h->card, snd_strerror(ret));
-               return -E_ALSA_MIX_BAD_ELEM;
+               return -E_ALSA_MIX_RANGE;
        }
-       if (h->pmin < 0 || h->pmax < 0 || h->pmin >= h->pmax) {
+       if (h->pmin >= h->pmax) {
                PARA_NOTICE_LOG("alsa reported %s range %ld-%ld (%s)\n",
                        mixer_channel, h->pmin, h->pmax, h->card);
-               return -E_ALSA_MIX_BAD_ELEM;
+               return -E_ALSA_MIX_RANGE;
        }
        return 1;
 }
index a3912c1165e6054b0be0bd622b17175fdad4fd8a..32d8a50e98715ec92e2c43734c44c2bc33b39098 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -34,17 +34,24 @@ struct private_alsa_write_data {
        snd_pcm_t *handle;
        /** Determined and set by alsa_init(). */
        int bytes_per_frame;
-       /**
-        * The sample rate given by command line option or the decoder
-        * of the writer node group.
+       /*
+        * If the sample rate is not given at the command line and no wav
+        * header was detected, the btr exec mechanism is employed to query the
+        * ancestor buffer tree nodes for this information. In a typical setup
+        * the decoder passes the sample rate back to the alsa writer.
+        *
+        *  \sa \ref btr_exec_up().
         */
        unsigned sample_rate;
-       snd_pcm_format_t sample_format;
-       /**
-        * The number of channels, given by command line option or the
-        * decoder of the writer node group.
+       /*
+        * The sample format (8/16 bit, signed/unsigned, little/big endian) is
+        * determined in the same way as the \a sample_rate.
         */
+       snd_pcm_format_t sample_format;
+       /* The number of channels, again determined like \a sample_rate. */
        unsigned channels;
+       /* time until buffer underrun occurs, in milliseconds */
+       unsigned buffer_time;
        struct timeval drain_barrier;
        /* File descriptor for select(). */
        int poll_fd;
@@ -72,9 +79,9 @@ static int alsa_init(struct private_alsa_write_data *pad,
        snd_pcm_uframes_t start_threshold, stop_threshold;
        snd_pcm_uframes_t buffer_size, period_size;
        snd_output_t *output_log;
-       unsigned buffer_time;
        int ret;
        const char *msg;
+       unsigned period_time;
 
        PARA_INFO_LOG("opening %s\n", conf->device_arg);
        msg = "unable to open pcm";
@@ -107,18 +114,21 @@ static int alsa_init(struct private_alsa_write_data *pad,
                &pad->sample_rate, NULL);
        if (ret < 0)
                goto fail;
-       msg = "unable to get buffer time";
-       ret = snd_pcm_hw_params_get_buffer_time_max(hwparams, &buffer_time,
-               NULL);
-       if (ret < 0 || buffer_time == 0)
-               goto fail;
-       /* buffer at most 500 milliseconds */
-       buffer_time = PARA_MIN(buffer_time, 500U * 1000U);
+       /* alsa wants microseconds */
+       pad->buffer_time = conf->buffer_time_arg * 1000;
        msg = "could not set buffer time";
        ret = snd_pcm_hw_params_set_buffer_time_near(pad->handle, hwparams,
-               &buffer_time, NULL);
+               &pad->buffer_time, NULL);
+       if (ret < 0)
+               goto fail;
+       pad->buffer_time /= 1000; /* we prefer milliseconds */
+       period_time = pad->buffer_time * 250; /* buffer time / 4 */
+       msg = "could not set period time";
+       ret = snd_pcm_hw_params_set_period_time_near(pad->handle, hwparams,
+               &period_time, 0);
        if (ret < 0)
                goto fail;
+
        msg = "unable to install hw params";
        ret = snd_pcm_hw_params(pad->handle, hwparams);
        if (ret < 0)
@@ -166,15 +176,16 @@ static int alsa_init(struct private_alsa_write_data *pad,
        if (ret == 0) {
                char *buf, *p;
                size_t sz;
-               PARA_INFO_LOG("dumping alsa configuration\n");
+               PARA_DEBUG_LOG("dumping alsa configuration\n");
                snd_pcm_dump(pad->handle, output_log);
+               snd_pcm_hw_params_dump(hwparams, output_log);
                sz = snd_output_buffer_string(output_log, &buf);
                for (p = buf; p < buf + sz;) {
                        char *q = memchr(p, '\n', buf + sz - p);
                        if (!q)
                                break;
                        *q = '\0';
-                       PARA_INFO_LOG("%s\n", p);
+                       PARA_DEBUG_LOG("%s\n", p);
                        p = q + 1;
                }
                snd_output_close(output_log);
@@ -188,10 +199,10 @@ fail:
        return -E_ALSA;
 }
 
-static void alsa_write_pre_select(struct sched *s, struct task *t)
+static void alsa_write_pre_select(struct sched *s, void *context)
 {
        struct pollfd pfd;
-       struct writer_node *wn = container_of(t, struct writer_node, task);
+       struct writer_node *wn = context;
        struct private_alsa_write_data *pad = wn->private_data;
        int ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
 
@@ -207,11 +218,12 @@ static void alsa_write_pre_select(struct sched *s, struct task *t)
                sched_request_barrier_or_min_delay(&pad->drain_barrier, s);
                return;
        }
+       /* wait at most 50% of the buffer time */
+       sched_request_timeout_ms(pad->buffer_time / 2, s);
        ret = snd_pcm_poll_descriptors(pad->handle, &pfd, 1);
        if (ret < 0) {
                PARA_ERROR_LOG("could not get alsa poll fd: %s\n",
                        snd_strerror(-ret));
-               t->error = -E_ALSA;
                return;
        }
        pad->poll_fd = pfd.fd;
@@ -236,10 +248,9 @@ static void alsa_close(struct writer_node *wn)
        free(pad);
 }
 
-static int alsa_write_post_select(__a_unused struct sched *s,
-               struct task *t)
+static int alsa_write_post_select(__a_unused struct sched *s, void *context)
 {
-       struct writer_node *wn = container_of(t, struct writer_node, task);
+       struct writer_node *wn = context;
        struct private_alsa_write_data *pad = wn->private_data;
        struct btr_node *btrn = wn->btrn;
        char *data;
@@ -247,7 +258,7 @@ static int alsa_write_post_select(__a_unused struct sched *s,
        snd_pcm_sframes_t frames;
        int ret;
 
-       ret = task_get_notification(t);
+       ret = task_get_notification(wn->task);
        if (ret < 0)
                goto err;
 again:
@@ -296,21 +307,13 @@ again:
                wn->min_iqs = pad->bytes_per_frame;
                goto again;
        }
-       if (pad->poll_fd < 0 || !FD_ISSET(pad->poll_fd, &s->rfds))
-               return 0;
        frames = bytes / pad->bytes_per_frame;
        frames = snd_pcm_writei(pad->handle, data, frames);
        if (frames == 0 || frames == -EAGAIN) {
-               /*
-                * The alsa poll fd was ready for IO but we failed to write to
-                * the alsa handle. This means another event is pending. We
-                * don't care about that but we have to dispatch the event in
-                * order to avoid a busy loop. So we simply read from the poll
-                * fd.
-                */
                char buf[100];
-               if (read(pad->poll_fd, buf, 100))
-                       do_nothing;
+               if (pad->poll_fd >= 0 && FD_ISSET(pad->poll_fd, &s->rfds))
+                       if (read(pad->poll_fd, buf, 100))
+                               do_nothing;
                return 0;
        }
        if (frames > 0) {
index f62ea8a2f50962182e158ce8da7f18fb4ec1df4f..8b8db2019c81c6712d8a587325b4153392cd571d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2009-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -58,13 +58,13 @@ static void amp_open(struct filter_node *fn)
                sscanf(stat_item_values[SI_AMPLIFICATION], "%u", &pad->amp);
        else
                pad->amp = conf->amp_arg;
-       PARA_NOTICE_LOG("amplification: %u (scaling factor: %1.2f)\n",
+       PARA_INFO_LOG("amplification: %u (scaling factor: %1.2f)\n",
                pad->amp, pad->amp / 64.0 + 1.0);
 }
 
-static int amp_post_select(__a_unused struct sched *s, struct task *t)
+static int amp_post_select(__a_unused struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        struct private_amp_data *pad = fn->private_data;
        struct btr_node *btrn = fn->btrn;
        int ret, factor = 64 + pad->amp;
@@ -73,7 +73,7 @@ static int amp_post_select(__a_unused struct sched *s, struct task *t)
        bool inplace = btr_inplace_ok(btrn);
 
        if (pad->amp == 0) { /* no amplification */
-               btr_splice_out_node(btrn);
+               btr_splice_out_node(&fn->btrn);
                return -E_AMP_ZERO_AMP;
        }
 next_buffer:
index fdae8eea542f97720f963f281bddd121cf5d0a38..4cecdfd87c10047eb8a5b646b7178401da1eac6f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2011-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -28,6 +28,7 @@ struct private_aow_data {
 
        pthread_t thread;
        pthread_attr_t attr;
+       /* The mutex and the condition variable serialize access to ->btrn */
        pthread_mutex_t mutex;
        pthread_cond_t data_available;
        struct btr_node *thread_btrn;
@@ -39,19 +40,46 @@ static void aow_close(struct writer_node *wn)
 
        if (!pawd)
                return;
+       assert(!pawd->thread_btrn);
        ao_close(pawd->dev);
        free(pawd);
        wn->private_data = NULL;
-       ao_shutdown();
 }
 
-static void aow_pre_select(struct sched *s, struct task *t)
+static void aow_pre_select(struct sched *s, void *context)
 {
-       struct writer_node *wn = container_of(t, struct writer_node, task);
-       int ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
+       struct writer_node *wn = context;
+       struct private_aow_data *pawd = wn->private_data;
+       int ret;
 
-       if (ret == 0)
-               return;
+       if (!pawd) { /* not yet started */
+               assert(wn->btrn);
+               ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
+               if (ret != 0)
+                       goto min_delay;
+               return; /* no data available */
+       }
+       if (!wn->btrn) { /* EOF */
+               if (!pawd->thread_btrn) /* ready to exit */
+                       goto min_delay;
+               /* wait for the play thread to terminate */
+               goto timeout;
+       }
+       pthread_mutex_lock(&pawd->mutex);
+       ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
+       pthread_mutex_unlock(&pawd->mutex);
+       if (ret != 0)
+               goto min_delay;
+       /*
+        * Even though the node status is zero, we might have data available,
+        * but the output buffer is full. If we don't set a timeout here, we
+        * are woken up only if new data arrives, which might be too late and
+        * result in a buffer underrun in the playing thread. To avoid this we
+        * never sleep longer than the (default) buffer time.
+        */
+timeout:
+       return sched_request_timeout_ms(20, s);
+min_delay:
        sched_min_delay(s);
 }
 
@@ -129,7 +157,6 @@ static int aow_init(struct writer_node *wn, unsigned sample_rate,
        struct private_aow_data *pawd = para_malloc(sizeof(*pawd));
        struct ao_write_args_info *conf = wn->conf;
 
-       ao_initialize();
        if (conf->driver_given) {
                ret = -E_AO_BAD_DRIVER;
                id = ao_driver_id(conf->driver_arg);
@@ -192,16 +219,12 @@ __noreturn static void *aow_play(void *priv)
        char *data;
        int ret;
 
+       pthread_mutex_lock(&pawd->mutex);
        for (;;) {
-               /*
-                * Lock mutex and wait for signal. pthread_cond_wait() will
-                * automatically and atomically unlock mutex while it waits.
-                */
-               pthread_mutex_lock(&pawd->mutex);
                for (;;) {
                        ret = btr_node_status(btrn, wn->min_iqs, BTR_NT_LEAF);
                        if (ret < 0)
-                               goto unlock;
+                               goto fail;
                        if (ret > 0) {
                                btr_merge(btrn, wn->min_iqs);
                                bytes = btr_next_buffer(btrn, &data);
@@ -210,26 +233,35 @@ __noreturn static void *aow_play(void *priv)
                                        break;
                                /* eof and less than a single frame available */
                                ret = -E_WRITE_COMMON_EOF;
-                               goto unlock;
+                               goto fail;
                        }
-                       //PARA_CRIT_LOG("waiting for data\n");
-                       //usleep(1000);
-                       //pthread_mutex_unlock(&pawd->mutex);
-                       pthread_cond_wait(&pawd->data_available, &pawd->mutex);
+                       /*
+                        * No data available, go to sleep and wait for the main
+                        * thread to wake us up. pthread_cond_wait() unlocks
+                        * the mutex while it waits and locks it again upon
+                        * return.
+                        */
+                       ret = pthread_cond_wait(&pawd->data_available,
+                               &pawd->mutex);
+                       /* pthread_cond_wait() can never fail here */
+                       assert(ret == 0);
                }
-               pthread_mutex_unlock(&pawd->mutex);
                assert(frames > 0);
                bytes = frames * pawd->bytes_per_frame;
-               ret = -E_AO_PLAY;
-               if (ao_play(pawd->dev, data, bytes) == 0) /* failure */
-                       goto out;
+               pthread_mutex_unlock(&pawd->mutex);
+               ret = ao_play(pawd->dev, data, bytes);
+               pthread_mutex_lock(&pawd->mutex);
+               if (ret == 0) { /* failure */
+                       ret = -E_AO_PLAY;
+                       goto fail;
+               }
                btr_consume(btrn, bytes);
        }
-unlock:
-       pthread_mutex_unlock(&pawd->mutex);
-out:
+fail:
+       btr_remove_node(&pawd->thread_btrn);
        assert(ret < 0);
        PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
+       pthread_mutex_unlock(&pawd->mutex);
        pthread_exit(NULL);
 }
 
@@ -276,10 +308,9 @@ fail:
        return -E_AO_PTHREAD;
 }
 
-static int aow_post_select(__a_unused struct sched *s,
-               struct task *t)
+static int aow_post_select(__a_unused struct sched *s, void *context)
 {
-       struct writer_node *wn = container_of(t, struct writer_node, task);
+       struct writer_node *wn = context;
        struct private_aow_data *pawd = wn->private_data;
        int ret;
 
@@ -314,21 +345,32 @@ static int aow_post_select(__a_unused struct sched *s,
                        goto remove_thread_btrn;
                return 0;
        }
+       if (!wn->btrn) {
+               if (!pawd->thread_btrn) {
+                       pthread_join(pawd->thread, NULL);
+                       return -E_AO_EOF;
+               }
+               PARA_INFO_LOG("waiting for play thread to terminate\n");
+               return 0;
+       }
        pthread_mutex_lock(&pawd->mutex);
        ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
        if (ret > 0) {
                btr_pushdown(wn->btrn);
-               pthread_cond_signal(&pawd->data_available);
+               if (pthread_cond_signal(&pawd->data_available) != 0) {
+                       ret = -E_AO_PTHREAD;
+                       PARA_ERROR_LOG("pthread_cond_signal() failed\n");
+                       goto remove_thread_btrn;
+               }
        }
-       pthread_mutex_unlock(&pawd->mutex);
-       if (ret >= 0)
+       if (ret >= 0) {
+               pthread_mutex_unlock(&pawd->mutex);
                goto out;
-       pthread_mutex_lock(&pawd->mutex);
+       }
        btr_remove_node(&wn->btrn);
-       PARA_INFO_LOG("waiting for thread to terminate\n");
        pthread_cond_signal(&pawd->data_available);
        pthread_mutex_unlock(&pawd->mutex);
-       pthread_join(pawd->thread, NULL);
+       return 0;
 remove_thread_btrn:
        btr_remove_node(&pawd->thread_btrn);
 remove_btrn:
@@ -410,6 +452,5 @@ void ao_write_init(struct writer *w)
        dh[num_lines] = NULL;
        w->help.detailed_help = (const char **)dh;
        ao_write_cmdline_parser_free(&dummy);
-       ao_shutdown();
 }
 
index 96b54c99080deb62b0b593e62d6470306c601886..7777a8ddc4cdf2a9a25f9a2b67f1935277d371ae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -212,85 +212,10 @@ int com_lsatt(struct command_context *cc)
        if (ret < 0)
                send_strerror(cc, -ret);
        else if (ret == 0 && cc->argc > 1)
-               ret = cc->use_sideband?
-                       send_sb_va(&cc->scc, SBD_ERROR_LOG, "no matches\n")
-               :
-                       sc_send_va_buffer(&cc->scc, "no matches\n");
+               ret = send_sb_va(&cc->scc, SBD_ERROR_LOG, "no matches\n");
        return ret;
 }
 
-static void com_setatt_callback(__a_unused int fd, const struct osl_object *query)
-{
-       char *p;
-       uint64_t add_mask = 0, del_mask = 0;
-       int ret;
-       size_t len;
-       struct osl_object obj;
-       struct osl_row *row;
-
-       for (p = query->data; p < (char *)query->data + query->size; p += len + 1) {
-               char c;
-
-               len = strlen(p);
-               ret = -E_ATTR_SYNTAX;
-               if (!*p)
-                       goto out;
-               c = p[len - 1];
-               if (c != '+' && c != '-')
-                       break;
-               p[len - 1] = '\0';
-               obj.data = p;
-               obj.size = len + 1;
-               ret = osl(osl_get_row(attribute_table, ATTCOL_NAME, &obj, &row));
-               if (ret < 0)
-                       goto out;
-               ret = osl(osl_get_object(attribute_table, row, ATTCOL_BITNUM,
-                       &obj));
-               if (ret < 0)
-                       goto out;
-               if (c == '+')
-                       add_mask |= (1UL << *(unsigned char *)obj.data);
-               else
-                       del_mask |= (1UL << *(unsigned char *)obj.data);
-       }
-       ret = -E_ATTR_SYNTAX;
-       if (!add_mask && !del_mask)
-               goto out;
-       PARA_DEBUG_LOG("masks: %llx:%llx\n",(long long unsigned)add_mask,
-               (long long unsigned)del_mask);
-       for (; p < (char *)query->data + query->size; p += len + 1) { /* TODO: fnmatch */
-               struct afs_info old_afsi, new_afsi;
-               struct afsi_change_event_data aced = {.old_afsi = &old_afsi};
-
-               len = strlen(p);
-               ret = aft_get_row_of_path(p, &aced.aft_row);
-               if (ret < 0)
-                       goto out;
-               ret = get_afsi_object_of_row(aced.aft_row, &obj);
-               if (ret < 0)
-                       goto out;
-               ret = load_afsi(&old_afsi, &obj);
-               if (ret < 0)
-                       goto out;
-               new_afsi = old_afsi;
-               new_afsi.attributes |= add_mask;
-               new_afsi.attributes &= ~del_mask;
-               save_afsi(&new_afsi, &obj); /* in-place update */
-               afs_event(AFSI_CHANGE, NULL, &aced);
-       }
-out:
-       if (ret < 0)
-               PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
-}
-
-int com_setatt(struct command_context *cc)
-{
-       if (cc->argc < 3)
-               return -E_ATTR_SYNTAX;
-       return send_standard_callback_request(cc->argc - 1, cc->argv + 1,
-               com_setatt_callback, NULL, NULL);
-}
-
 struct addatt_event_data {
        const char *name;
        unsigned char bitnum;
@@ -430,7 +355,7 @@ int com_mvatt(struct command_context *cc)
 struct remove_attribute_action_data {
        /** Message buffer. */
        struct para_buffer pb;
-       /** Numver of attributes removed. */
+       /** Number of attributes removed. */
        int num_removed;
        /** Bitwise "or" of the removed attributes. */
        uint64_t mask_of_removed_atts;
@@ -513,7 +438,7 @@ int com_rmatt(struct command_context *cc)
  * used for unset attributes.
  *
  * In practice, not all 64 attributes are defined. In this case, the function
- * only prints \a N + 1 charaters where \a N is the greatest id of a defined
+ * only prints \a N + 1 characters where \a N is the greatest id of a defined
  * attribute.
  */
 void get_attribute_bitmap(const uint64_t *atts, char *buf)
index 0edab366efe6ef6fa50f99c22b9ffa3492494640..83425a2e485fd49ea3b40a9ab60183865c14a25d 100644 (file)
--- a/audioc.c
+++ b/audioc.c
@@ -1,13 +1,18 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 
 /** \file audioc.c The client program used to connect to para_audiod. */
 
+#include <netinet/in.h>
+#include <sys/socket.h>
 #include <regex.h>
 #include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
 #include <stdbool.h>
 #include <signal.h>
 
@@ -74,7 +79,7 @@ static struct sched sched;
 struct audioc_task {
        int fd;
        struct btr_node *btrn;
-       struct task task;
+       struct task *task;
 };
 
 static struct i9e_completer audiod_completers[];
@@ -92,6 +97,15 @@ static void help_completer(struct i9e_completion_info *ci,
        result->matches = i9e_complete_commands(ci->word, audiod_completers);
 }
 
+static void version_completer(struct i9e_completion_info *ci,
+               struct i9e_completion_result *cr)
+{
+       char *opts[] = {"-v", NULL};
+
+       if (ci->word_num <= 2 && ci->word && ci->word[0] == '-')
+               i9e_complete_option(opts, ci, cr);
+}
+
 static void stat_completer(struct i9e_completion_info *ci,
                struct i9e_completion_result *cr)
 {
@@ -116,9 +130,9 @@ static struct i9e_completer audiod_completers[] = {
        {.name = NULL}
 };
 
-static void audioc_pre_select(struct sched *s, struct task *t)
+static void audioc_pre_select(struct sched *s, void *context)
 {
-       struct audioc_task *at = container_of(t, struct audioc_task, task);
+       struct audioc_task *at = context;
        int ret = btr_node_status(at->btrn, 0, BTR_NT_ROOT);
 
        if (ret < 0)
@@ -126,10 +140,10 @@ static void audioc_pre_select(struct sched *s, struct task *t)
        para_fd_set(at->fd, &s->rfds, &s->max_fileno);
 }
 
-static int audioc_post_select(struct sched *s, struct task *t)
+static int audioc_post_select(struct sched *s, void *context)
 {
        char *buf = NULL;
-       struct audioc_task *at = container_of(t, struct audioc_task, task);
+       struct audioc_task *at = context;
        int ret = btr_node_status(at->btrn, 0, BTR_NT_ROOT);
 
        if (ret < 0)
@@ -154,13 +168,7 @@ out:
        return ret;
 }
 
-static struct audioc_task audioc_task = {
-       .task = {
-               .pre_select = audioc_pre_select,
-               .post_select = audioc_post_select,
-               .status = "audioc task"
-       },
-}, *at = &audioc_task;
+static struct audioc_task audioc_task, *at = &audioc_task;
 
 static int audioc_i9e_line_handler(char *line)
 {
@@ -188,8 +196,12 @@ static int audioc_i9e_line_handler(char *line)
        args = NULL;
        at->btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.name = "audioc line handler"));
-       at->task.error = 0;
-       register_task(&sched, &at->task);
+       at->task = task_register(&(struct task_info) {
+               .name = "audioc",
+               .pre_select = audioc_pre_select,
+               .post_select = audioc_post_select,
+               .context = at,
+       }, &sched);
        i9e_attach_to_stdout(at->btrn);
        return 1;
 close:
@@ -234,6 +246,7 @@ __noreturn static void interactive_session(void)
                goto out;
        para_log = i9e_log;
        ret = schedule(&sched);
+       sched_shutdown(&sched);
        i9e_close();
        para_log = stderr_log;
 out:
index 8f2a72ac8700ee0699c19d78724cbe1d6ec61296..6fd101a093b2f7f94abe43cab0331781c8a57a3a 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -1,12 +1,18 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 
 /** \file audiod.c The paraslash's audio daemon. */
+
+#include <netinet/in.h>
+#include <sys/socket.h>
 #include <regex.h>
 #include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
 #include <signal.h>
 
 #include "para.h"
@@ -87,14 +93,10 @@ enum vss_status_flags {
  */
 struct sched sched = {.max_fileno = 0};
 
-/**
- * The task for obtaining para_server's status (para_client stat).
- *
- * \sa struct task, struct sched.
- */
+/* The task for obtaining para_server's status (para_client stat). */
 struct status_task {
        /** The associated task structure of audiod. */
-       struct task task;
+       struct task *task;
        /** Client data associated with the stat task. */
        struct client_task *ct;
        /** Do not restart client command until this time. */
@@ -162,7 +164,7 @@ struct command_task {
        /** the local listening socket */
        int fd;
        /** the associated task structure */
-       struct task task;
+       struct task *task;
 };
 
 /** iterate over all supported audio formats */
@@ -213,7 +215,7 @@ static int get_matching_audio_format_nums(const char *re)
  * from the status items received from para_server and the start time of the
  * (first) writer of the given slot.
  *
- * It has to to take into account that probably the stream was not started at
+ * It has to take into account that the stream was probably not started at
  * the beginning of the file, that the clock between the server and the client
  * host may differ and that playback of the stream was delayed, e.g. because
  * the prebuffer filter is used in the filter configuration of the given slot.
@@ -385,6 +387,7 @@ static void close_receiver(int slot_num)
                audio_formats[s->format], slot_num);
        a->receiver->close(s->receiver_node);
        btr_remove_node(&s->receiver_node->btrn);
+       task_reap(&s->receiver_node->task);
        free(s->receiver_node);
        s->receiver_node = NULL;
        tv_add(now, &(struct timeval)EMBRACE(0, 200 * 1000),
@@ -401,6 +404,7 @@ static void writer_cleanup(struct writer_node *wn)
        PARA_INFO_LOG("closing %s\n", writer_names[wn->writer_num]);
        w->close(wn);
        btr_remove_node(&wn->btrn);
+       task_reap(&wn->task);
 }
 
 static void close_writers(struct slot_info *s)
@@ -438,6 +442,7 @@ static void close_filters(struct slot_info *s)
                if (f->close)
                        f->close(fn);
                btr_remove_node(&fn->btrn);
+               task_reap(&fn->task);
        }
        free(s->fns);
        s->fns = NULL;
@@ -453,7 +458,7 @@ static void notify_receivers(int error)
                        continue;
                if (!s->receiver_node)
                        continue;
-               task_notify(&s->receiver_node->task, error);
+               task_notify(s->receiver_node->task, error);
        }
 }
 
@@ -491,22 +496,26 @@ static void open_filters(struct slot_info *s)
        s->fns = para_calloc(nf * sizeof(struct filter_node));
        parent = s->receiver_node->btrn;
        for (i = 0; i < nf; i++) {
+               char buf[20];
                struct filter *f = filters + a->filter_nums[i];
                fn = s->fns + i;
                fn->filter_num = a->filter_nums[i];
                fn->conf = a->filter_conf[i];
-               fn->task.pre_select = f->pre_select;
-               fn->task.post_select = f->post_select;
                fn->btrn = btr_new_node(&(struct btr_node_description)
                        EMBRACE(.name = f->name, .parent = parent,
                                .handler = f->execute, .context = fn));
 
                f->open(fn);
-               register_task(&sched, &fn->task);
+               sprintf(buf, "%s (slot %d)", f->name, (int)(s - slot));
+               fn->task = task_register(&(struct task_info) {
+                       .name = buf,
+                       .pre_select = f->pre_select,
+                       .post_select = f->post_select,
+                       .context = fn,
+               }, &sched);
                parent = fn->btrn;
                PARA_NOTICE_LOG("%s filter %d/%d (%s) started in slot %d\n",
                        audio_formats[s->format], i,  nf, f->name, (int)(s - slot));
-               sprintf(fn->task.status, "%s (slot %d)", f->name, (int)(s - slot));
        }
 }
 
@@ -520,12 +529,13 @@ static void open_writers(struct slot_info *s)
        assert(s->wns == NULL);
        s->wns = para_calloc(PARA_MAX(1U, a->num_writers)
                * sizeof(struct writer_node));
-       PARA_INFO_LOG("opening %s writers\n", audio_formats[s->format]);
        for (i = 0; i < a->num_writers; i++) {
                wn = s->wns + i;
                wn->conf = a->writer_conf[i];
                wn->writer_num = a->writer_nums[i];
                register_writer_node(wn, parent, &sched);
+               PARA_NOTICE_LOG("%s writer started in slot %d\n",
+                       writer_names[a->writer_nums[i]], (int)(s - slot));
        }
 }
 
@@ -559,10 +569,12 @@ static int open_receiver(int format)
        s->receiver_node = rn;
        PARA_NOTICE_LOG("started %s: %s receiver in slot %d\n",
                audio_formats[format], r->name, slot_num);
-       rn->task.pre_select = r->pre_select;
-       rn->task.post_select = r->post_select;
-       sprintf(rn->task.status, "%s receiver node", r->name);
-       register_task(&sched, &rn->task);
+       rn->task = task_register(&(struct task_info) {
+               .name = r->name,
+               .pre_select = r->pre_select,
+               .post_select = r->post_select,
+               .context = rn,
+       }, &sched);
        return slot_num;
 }
 
@@ -577,7 +589,7 @@ static bool receiver_running(void)
 
                if (!s->receiver_node)
                        continue;
-               if (s->receiver_node->task.error >= 0)
+               if (task_status(s->receiver_node->task) >= 0)
                        return true;
                if (ss1 == ss2)
                        return true;
@@ -604,7 +616,7 @@ struct btr_node *audiod_get_btr_root(void)
                struct timeval rstime;
                if (!s->receiver_node)
                        continue;
-               if (s->receiver_node->task.error < 0)
+               if (task_status(s->receiver_node->task) < 0)
                        continue;
                btr_get_node_start(s->receiver_node->btrn, &rstime);
                if (newest_slot >= 0 && tv_diff(&rstime, &newest_rstime, NULL) < 0)
@@ -640,7 +652,7 @@ static bool must_start_decoder(void)
        return true;
 }
 
-static unsigned compute_time_diff(const struct timeval *status_time)
+static void compute_time_diff(const struct timeval *status_time)
 {
        struct timeval tmp, diff;
        static unsigned count;
@@ -648,8 +660,6 @@ static unsigned compute_time_diff(const struct timeval *status_time)
        const struct timeval max_deviation = {0, 500 * 1000};
        const int time_smooth = 5;
 
-       if (!status_time)
-               return count;
        sign = tv_diff(status_time, now, &diff);
 //             PARA_NOTICE_LOG("%s: sign = %i, sa_time_diff_sign = %i\n", __func__,
 //                     sign, sa_time_diff_sign);
@@ -679,7 +689,6 @@ static unsigned compute_time_diff(const struct timeval *status_time)
        );
 out:
        stat_task->sa_time_diff_sign = sa_time_diff_sign;
-       return count;
 }
 
 static int update_item(int itemnum, char *buf)
@@ -914,7 +923,7 @@ out:
 
 static int parse_filter_args(void)
 {
-       int i, j, ret, af_mask;
+       int i, j, ret, af_mask, num_matches;
 
        for (i = 0; i < conf.filter_given; i++) {
                char *arg;
@@ -922,13 +931,18 @@ static int parse_filter_args(void)
                if (ret < 0)
                        goto out;
                af_mask = ret;
+               num_matches = 0;
                FOR_EACH_AUDIO_FORMAT(j) {
                        if ((af_mask & (1 << j)) == 0) /* no match */
                                continue;
                        ret = add_filter(j, arg);
                        if (ret < 0)
                                goto out;
+                       num_matches++;
                }
+               if (num_matches == 0)
+                       PARA_WARNING_LOG("ignoring filter spec: %s\n",
+                               conf.filter_arg[i]);
        }
        ret = init_default_filters(); /* use default values for the rest */
 out:
@@ -986,73 +1000,85 @@ err:
        exit(EXIT_FAILURE);
 }
 
-static void signal_pre_select(struct sched *s, struct task *t)
+static void signal_pre_select(struct sched *s, void *context)
 {
-       struct signal_task *st = container_of(t, struct signal_task, task);
+       struct signal_task *st = context;
        para_fd_set(st->fd, &s->rfds, &s->max_fileno);
 }
 
-static int signal_post_select(struct sched *s, __a_unused struct task *t)
+static int signal_post_select(struct sched *s, __a_unused void *context)
 {
        int signum;
-
        signum = para_next_signal(&s->rfds);
        switch (signum) {
        case SIGINT:
        case SIGTERM:
        case SIGHUP:
-               PARA_EMERG_LOG("terminating on signal %d\n", signum);
+               PARA_NOTICE_LOG("received signal %d\n", signum);
                clean_exit(EXIT_FAILURE, "caught deadly signal");
        }
        return 0;
 }
 
-static void signal_setup_default(struct signal_task *st)
+static void command_pre_select(struct sched *s, void *context)
 {
-       st->task.pre_select = signal_pre_select;
-       st->task.post_select = signal_post_select;
-       sprintf(st->task.status, "signal task");
-}
-
-static void command_pre_select(struct sched *s, struct task *t)
-{
-       struct command_task *ct = container_of(t, struct command_task, task);
+       struct command_task *ct = context;
        para_fd_set(ct->fd, &s->rfds, &s->max_fileno);
 }
 
-static int command_post_select(struct sched *s, struct task *t)
+static int command_post_select(struct sched *s, void *context)
 {
        int ret;
-       struct command_task *ct = container_of(t, struct command_task, task);
+       struct command_task *ct = context;
        static struct timeval last_status_dump;
-       struct timeval tmp, delay = {0, 500 * 1000};
-
-       tv_add(&last_status_dump, &delay, &tmp);
-       if (tv_diff(&tmp, now, NULL) < 0) {
-               audiod_status_dump();
-               last_status_dump = *now;
-       }
+       struct timeval tmp, delay;
+       bool force = true;
 
        ret = handle_connect(ct->fd, &s->rfds);
        if (ret < 0)
                PARA_ERROR_LOG("%s\n", para_strerror(-ret));
-       audiod_status_dump();
-       return 0;
+       else if (ret > 0)
+               goto dump;
+
+       /* if last status dump was less than 500ms ago, do nothing */
+       delay.tv_sec = 0;
+       delay.tv_usec = 500 * 1000;
+       tv_add(&last_status_dump, &delay, &tmp);
+       if (tv_diff(now, &tmp, NULL) < 0)
+               return 0;
+
+       /*
+        * If last status dump was more than 5s ago, force update. Otherwise,
+        * update only those items that have changed.
+        */
+       delay.tv_sec = 5;
+       delay.tv_usec = 0;
+       tv_add(&last_status_dump, &delay, &tmp);
+       if (tv_diff(now, &tmp, NULL) < 0)
+               force = false;
+dump:
+       audiod_status_dump(force);
+       last_status_dump = *now;
+       return 1;
 }
 
 static void init_command_task(struct command_task *ct)
 {
-       ct->task.pre_select = command_pre_select;
-       ct->task.post_select = command_post_select;
-       ct->task.error = 0;
        ct->fd = audiod_get_socket(); /* doesn't return on errors */
-       sprintf(ct->task.status, "command task");
+
+       ct->task = task_register(&(struct task_info) {
+               .name = "command",
+               .pre_select = command_pre_select,
+               .post_select = command_post_select,
+               .context = ct,
+       }, &sched);
 }
 
 static void close_stat_pipe(void)
 {
        if (!stat_task->ct)
                return;
+       task_reap(&stat_task->ct->task);
        client_close(stat_task->ct);
        stat_task->ct = NULL;
        clear_and_dump_items();
@@ -1060,28 +1086,7 @@ static void close_stat_pipe(void)
        stat_task->offset_seconds = 0;
        stat_task->vss_status = 0;
        stat_task->current_audio_format_num = -1;
-       audiod_status_dump();
-}
-
-/**
- * close the connection to para_server and exit
- *
- * \param status the exit status which is passed to exit(3)
- * \param msg the log message
- *
- * Log \a msg with loglevel \p EMERG, close the connection to para_server if
- * open, and call \p exit(status). \a status should be either EXIT_SUCCESS or
- * EXIT_FAILURE.
- *
- * \sa exit(3)
- */
-void __noreturn clean_exit(int status, const char *msg)
-{
-       PARA_EMERG_LOG("%s\n", msg);
-       if (socket_name)
-               unlink(socket_name);
-       close_stat_pipe();
-       exit(status);
+       audiod_status_dump(true);
 }
 
 /* avoid busy loop if server is down */
@@ -1099,36 +1104,64 @@ static bool must_close_slot(int slot_num)
 
        if (s->format < 0)
                return false;
-       if (s->receiver_node && s->receiver_node->task.error >= 0)
+       if (s->receiver_node && task_status(s->receiver_node->task) >= 0)
                return false;
        for (i = 0; i < a->num_filters; i++)
-               if (s->fns && s->fns[i].task.error >= 0)
+               if (s->fns && task_status(s->fns[i].task) >= 0)
                        return false;
        if (a->num_writers > 0) {
                for (i = 0; i < a->num_writers; i++)
-                       if (s->wns && s->wns[i].task.error >= 0)
+                       if (s->wns && task_status(s->wns[i].task) >= 0)
                                return false;
        } else {
-               if (s->wns && s->wns[0].task.error >= 0)
+               if (s->wns && task_status(s->wns[0].task) >= 0)
                        return false;
        }
        return true;
 }
 
+static void close_slot(int slot_num)
+{
+       struct slot_info *s = slot + slot_num;
+
+       PARA_INFO_LOG("closing slot %d\n", slot_num);
+       close_writers(s);
+       close_filters(s);
+       close_receiver(slot_num);
+       clear_slot(slot_num);
+}
+
 static void close_unused_slots(void)
 {
        int i;
 
-       FOR_EACH_SLOT(i) {
-               struct slot_info *s = slot + i;
-               if (!must_close_slot(i))
-                       continue;
-               PARA_INFO_LOG("closing slot %d\n", i);
-               close_writers(s);
-               close_filters(s);
-               close_receiver(i);
-               clear_slot(i);
-       }
+       FOR_EACH_SLOT(i)
+               if (must_close_slot(i))
+                       close_slot(i);
+}
+
+/**
+ * Close the connection to para_server and exit.
+ *
+ * \param status The exit status which is passed to exit(3).
+ * \param msg The log message
+ *
+ * Log \a msg with loglevel \p EMERG, close the connection to para_server and
+ * all slots, and call \p exit(status). \a status should be either EXIT_SUCCESS
+ * or EXIT_FAILURE.
+ *
+ * \sa exit(3).
+ */
+void __noreturn clean_exit(int status, const char *msg)
+{
+       if (socket_name)
+               unlink(socket_name);
+       close_stat_pipe();
+       close_unused_slots();
+       audiod_cmdline_parser_free(&conf);
+       close_stat_clients();
+       PARA_EMERG_LOG("%s\n", msg);
+       exit(status);
 }
 
 /*
@@ -1139,7 +1172,6 @@ static void start_stop_decoders(void)
 {
        int ret;
        struct slot_info *sl;
-       struct audio_format_info *a;
 
        close_unused_slots();
        if (audiod_status != AUDIOD_ON ||
@@ -1153,17 +1185,15 @@ static void start_stop_decoders(void)
                return;
        }
        sl = slot + ret;
-       a = afi + sl->format;
-       if (a->num_filters)
-               open_filters(sl);
+       open_filters(sl);
        open_writers(sl);
        activate_grab_clients(&sched);
        btr_log_tree(sl->receiver_node->btrn, LL_NOTICE);
 }
 
-static void status_pre_select(struct sched *s, struct task *t)
+static void status_pre_select(struct sched *s, void *context)
 {
-       struct status_task *st = container_of(t, struct status_task, task);
+       struct status_task *st = context;
        int i, ret, cafn = stat_task->current_audio_format_num;
 
        if (must_start_decoder())
@@ -1193,15 +1223,15 @@ min_delay:
 }
 
 /* restart the client task if necessary */
-static int status_post_select(struct sched *s, struct task *t)
+static int status_post_select(struct sched *s, void *context)
 {
-       struct status_task *st = container_of(t, struct status_task, task);
+       struct status_task *st = context;
 
        if (audiod_status == AUDIOD_OFF) {
                if (!st->ct)
                        goto out;
-               if (st->ct->task.error >= 0) {
-                       task_notify(&st->ct->task, E_AUDIOD_OFF);
+               if (task_status(st->ct->task) >= 0) {
+                       task_notify(st->ct->task, E_AUDIOD_OFF);
                        goto out;
                }
                close_stat_pipe();
@@ -1212,25 +1242,26 @@ static int status_post_select(struct sched *s, struct task *t)
                char *buf;
                size_t sz;
                int ret;
-               if (st->ct->task.error < 0) {
+
+               ret = btr_node_status(st->btrn, st->min_iqs, BTR_NT_LEAF);
+               if (ret < 0) {
                        close_stat_pipe();
                        goto out;
                }
-               if (st->ct->status != CL_RECEIVING)
+               if (st->ct->status != CL_EXECUTING)
                        goto out;
-               ret = btr_node_status(st->btrn, st->min_iqs, BTR_NT_LEAF);
-               if (ret <= 0) {
+               if (ret == 0) {
                        struct timeval diff;
                        tv_diff(now, &st->last_status_read, &diff);
                        if (diff.tv_sec > 61)
-                               task_notify(&st->ct->task, E_AUDIOD_OFF);
+                               task_notify(st->ct->task, E_STATUS_TIMEOUT);
                        goto out;
                }
                btr_merge(st->btrn, st->min_iqs);
                sz = btr_next_buffer(st->btrn, &buf);
                ret = for_each_stat_item(buf, sz, update_item);
                if (ret < 0) {
-                       task_notify(&st->ct->task, E_AUDIOD_OFF);
+                       task_notify(st->ct->task, -ret);
                        goto out;
                }
                if (sz != ret) {
@@ -1272,14 +1303,18 @@ out:
 static void init_status_task(struct status_task *st)
 {
        memset(st, 0, sizeof(struct status_task));
-       st->task.pre_select = status_pre_select;
-       st->task.post_select = status_post_select;
        st->sa_time_diff_sign = 1;
        st->clock_diff_count = conf.clock_diff_count_arg;
        st->current_audio_format_num = -1;
-       sprintf(st->task.status, "stat");
        st->btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.name = "stat"));
+
+       stat_task->task = task_register(&(struct task_info) {
+               .name = "stat",
+               .pre_select = status_pre_select,
+               .post_select = status_post_select,
+               .context = stat_task,
+       }, &sched);
 }
 
 static void set_initial_status(void)
@@ -1383,7 +1418,6 @@ int main(int argc, char *argv[])
        FOR_EACH_SLOT(i)
                clear_slot(i);
        setup_signal_handling();
-       signal_setup_default(sig_task);
 
        init_status_task(stat_task);
        init_command_task(cmd_task);
@@ -1391,12 +1425,17 @@ int main(int argc, char *argv[])
        if (conf.daemon_given)
                daemonize(false /* parent exits immediately */);
 
-       register_task(&sched, &sig_task->task);
-       register_task(&sched, &cmd_task->task);
-       register_task(&sched, &stat_task->task);
+       sig_task->task = task_register(&(struct task_info) {
+               .name = "signal",
+               .pre_select = signal_pre_select,
+               .post_select = signal_post_select,
+               .context = sig_task,
+       }, &sched);
+
        sched.default_timeout.tv_sec = 2;
        sched.default_timeout.tv_usec = 999 * 1000;
        ret = schedule(&sched);
+       sched_shutdown(&sched);
 
        PARA_EMERG_LOG("%s\n", para_strerror(-ret));
        return EXIT_FAILURE;
index 6c99d4c7d272e73e686bc8a9cd1d5832b3bdf9de..18c802de8857788449cb6dfbfa53823c7ef0da0e 100644 (file)
@@ -19,17 +19,13 @@ H: Options:
 H:
 H: -m  Change grab mode. Defaults to sloppy grab if not given.
 H:
-H:             -ms: sloppy grab
+H:    -ms: sloppy grab
+H:    -mp: pedantic grab
+H:    -ma: aggressive grab
 H:
-H:             -mp: pedantic grab
-H:
-H:             -ma: aggressive grab
-H:
-H:     The various grab modes only differ in what happens if the
-H:     file descriptor to write the grabbed audio data to is not
-H:     ready for writing (i.e. would block). Sloppy mode ignores
-H:     the write, pedantic mode aborts and aggressive mode tries
-H:     to write anyway.
+H: The various grab modes only differ in what happens if an attempt to
+H: write the grabbed audio data would block. Sloppy mode ignores the
+H: write, pedantic mode aborts and aggressive mode tries to write anyway.
 H:
 H: -p  Grab output of node PARENT of the buffer tree.
 H:
@@ -70,9 +66,14 @@ H: parser-friendly mode.
 N: tasks
 D: list current tasks
 U: tasks
-H: print the list of task ids together with the status of each task
+H: Print the list of task ids together with the status of each task.
 ---
 N: term
 D: terminate audiod
 U: term
 H: Stop all decoders, shut down connection to para_server and exit.
+---
+N: version
+D: print the version of para_audiod
+U: version [-v]
+H: If the -v option is given, a more detailed version text is printed.
index e54a8576dfe5da24d7496e4de39e9f0044573321..aa98001c3d34906775ce6cf7c135dfb22c060ac1 100644 (file)
--- a/audiod.h
+++ b/audiod.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -68,12 +68,13 @@ extern int audiod_status;
 
 void __noreturn clean_exit(int status, const char *msg);
 int handle_connect(int accept_fd, fd_set *rfds);
-void audiod_status_dump(void);
+void audiod_status_dump(bool force);
 char *get_time_string(int slot_num);
 struct btr_node *audiod_get_btr_root(void);
 
 void stat_client_write_item(int item_num);
 void clear_and_dump_items(void);
+void close_stat_clients(void);
 
 /** iterate over all slots */
 #define FOR_EACH_SLOT(_slot) for (_slot = 0; _slot < MAX_STREAM_SLOTS; _slot++)
index b49d659e0ac0bd784b2002b941b3471540ee5ac9..56d922e6681e66d0d9c4f65df86569806a38ca80 100644 (file)
@@ -1,13 +1,18 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 
 /** \file audiod_command.c Commands for para_audiod. */
 
+#include <netinet/in.h>
+#include <sys/socket.h>
 #include <regex.h>
 #include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
 
 #include "para.h"
 #include "audiod.cmdline.h"
 #include "string.h"
 #include "write.h"
 #include "fd.h"
+#include "version.h"
 #include "audiod_command_list.h"
 
 extern struct sched sched;
 extern char *stat_item_values[NUM_STAT_ITEMS];
 
 
-struct audiod_command audiod_cmds[] = {DEFINE_AUDIOD_CMD_ARRAY};
+static struct audiod_command audiod_cmds[] = {DEFINE_AUDIOD_CMD_ARRAY};
 
 /** Iterate over the array of all audiod commands. */
 #define FOR_EACH_COMMAND(c) for (c = 0; audiod_cmds[c].name; c++)
@@ -109,6 +115,31 @@ static int stat_client_add(int fd, uint64_t mask, int parser_friendly)
        num_clients++;
        return 1;
 }
+
+static void close_stat_client(struct stat_client *sc)
+{
+       PARA_INFO_LOG("closing client fd %d\n", sc->fd);
+       close(sc->fd);
+       list_del(&sc->node);
+       free(sc);
+       num_clients--;
+}
+
+/**
+ * Empty the status clients list.
+ *
+ * This iterates over the list of connected status clients, closes each client
+ * file descriptor and frees the resources.
+ */
+void close_stat_clients(void)
+{
+       struct stat_client *sc, *tmp;
+
+       list_for_each_entry_safe(sc, tmp, &client_list, node)
+               close_stat_client(sc);
+       assert(num_clients == 0);
+}
+
 /**
  * Write a message to all connected status clients.
  *
@@ -127,7 +158,7 @@ void stat_client_write_item(int item_num)
        struct para_buffer *b;
 
        list_for_each_entry_safe(sc, tmp, &client_list, node) {
-               int fd = sc->fd, ret;
+               int ret;
 
                if (!((one << item_num) & sc->item_mask))
                        continue;
@@ -135,15 +166,11 @@ void stat_client_write_item(int item_num)
                if (!b->buf)
                        (void)WRITE_STATUS_ITEM(b, item_num, "%s\n",
                                msg? msg : "");
-               ret = write(fd, b->buf, b->offset);
+               ret = write(sc->fd, b->buf, b->offset);
                if (ret == b->offset)
                        continue;
                /* write error or short write */
-               close(fd);
-               num_clients--;
-               PARA_INFO_LOG("deleting client on fd %d\n", fd);
-               list_del(&sc->node);
-               free(sc);
+               close_stat_client(sc);
                dump_stat_client_list();
        }
        free(pb.buf);
@@ -320,7 +347,6 @@ static int com_stat(int fd, int argc, char **argv)
                if (!strncmp(arg, "-p", 2)) {
                        parser_friendly = 1;
                        b.flags = PBF_SIZE_PREFIX;
-                       continue;
                }
        }
        if (i >= argc)
@@ -394,6 +420,22 @@ static int com_cycle(int fd, int argc, char **argv)
        return 1;
 }
 
+static int com_version(int fd, int argc, char **argv)
+{
+       int ret;
+       char *msg;
+
+       if (argc > 1 && strcmp(argv[1], "-v") == 0)
+               msg = make_message("%s", version_text("audiod"));
+       else
+               msg = make_message("%s\n", version_single_line("audiod"));
+       ret = client_write(fd, msg);
+       free(msg);
+       if (ret >= 0)
+               close(fd);
+       return ret;
+}
+
 static int check_perms(uid_t uid)
 {
        int i;
@@ -466,8 +508,10 @@ out:
 
 /**
  * Send the current audiod status to all connected stat clients.
+ *
+ * \param force Whether to write unchanged items.
  */
-void audiod_status_dump(void)
+void audiod_status_dump(bool force)
 {
        int slot_num = get_play_time_slot_num();
        char *old, *new;
@@ -475,7 +519,7 @@ void audiod_status_dump(void)
        old = stat_item_values[SI_PLAY_TIME];
        new = get_time_string(slot_num);
        if (new) {
-               if (!old || strcmp(old, new)) {
+               if (force || !old || strcmp(old, new)) {
                        free(old);
                        stat_item_values[SI_PLAY_TIME] = new;
                        stat_client_write_item(SI_PLAY_TIME);
@@ -485,7 +529,7 @@ void audiod_status_dump(void)
 
        new = get_server_uptime_str(now);
        old = stat_item_values[SI_AUDIOD_UPTIME];
-       if (!old || strcmp(old, new)) {
+       if (force || !old || strcmp(old, new)) {
                free(old);
                stat_item_values[SI_AUDIOD_UPTIME] = new;
                stat_client_write_item(SI_AUDIOD_UPTIME);
@@ -494,7 +538,7 @@ void audiod_status_dump(void)
 
        old = stat_item_values[SI_AUDIOD_STATUS];
        new = audiod_status_string();
-       if (!old || strcmp(old, new)) {
+       if (force || !old || strcmp(old, new)) {
                free(old);
                stat_item_values[SI_AUDIOD_STATUS] = new;
                stat_client_write_item(SI_AUDIOD_STATUS);
@@ -503,7 +547,7 @@ void audiod_status_dump(void)
 
        old = stat_item_values[SI_DECODER_FLAGS];
        new = decoder_flags();
-       if (!old || strcmp(old, new)) {
+       if (force || !old || strcmp(old, new)) {
                free(old);
                stat_item_values[SI_DECODER_FLAGS] = new;
                stat_client_write_item(SI_DECODER_FLAGS);
index d35247eb7d47d4d739a61973949f8c564d67bb2f..33bf64f6f4e68790e04ae1edff8d9c613b8c0ec5 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+# Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
 #
 # Licensed under the GPL v2. For licencing details see COPYING.
 
index ddad67bb177211b3909f88d3be9dcb3d5c381238..fb638d0a83317568c89e00a56d6bd375e6326a41 100644 (file)
@@ -11,9 +11,7 @@
  * For licencing details see COPYING.LIB.
  */
 
-/**
- * \file bitstream.c Bitstream API.
- */
+/** \file bitstream.c Bitstream API for the wma decoder. */
 
 #include <stdlib.h>
 #include <inttypes.h>
@@ -58,8 +56,7 @@ static int build_table(struct vlc *vlc, int table_nb_bits, int nb_codes,
                const void *bits, const void *codes, int codes_size,
                uint32_t code_prefix, int n_prefix)
 {
-       int i, j, k, n, table_size, table_index, nb, n1, idx, code_prefix2,
-               symbol;
+       int i, j, k, n, table_size, table_index, nb, n1, idx;
        uint32_t code;
        VLC_TYPE(*table)[2];
 
@@ -69,62 +66,57 @@ static int build_table(struct vlc *vlc, int table_nb_bits, int nb_codes,
        table = &vlc->table[table_index];
 
        for (i = 0; i < table_size; i++) {
-               table[i][1] = 0;        //bits
-               table[i][0] = -1;       //codes
+               table[i][1] = 0; /* bits */
+               table[i][0] = -1; /* codes */
        }
 
-       /* map codes and compute auxillary table sizes */
+       /* map codes and compute auxiliary table sizes */
        for (i = 0; i < nb_codes; i++) {
                GET_DATA(n, bits, i, 1);
-               GET_DATA(code, codes, i, codes_size);
                /* we accept tables with holes */
+               n -= n_prefix;
                if (n <= 0)
                        continue;
-               symbol = i;
+               GET_DATA(code, codes, i, codes_size);
                /* if code matches the prefix, it is in the table */
-               n -= n_prefix;
-               code_prefix2 = code >> n;
-               if (n <= 0 || code_prefix2 != code_prefix)
+               if ((code >> n) != code_prefix)
                        continue;
                if (n <= table_nb_bits) {
                        /* no need to add another table */
                        j = (code << (table_nb_bits - n)) & (table_size - 1);
                        nb = 1 << (table_nb_bits - n);
                        for (k = 0; k < nb; k++) {
-                               if (table[j][1] /* bits */ != 0) {
-                                       PARA_EMERG_LOG("incorrect code\n");
-                                       exit(EXIT_FAILURE);
-                               }
-                               table[j][1] = n;        //bits
-                               table[j][0] = symbol;
+                               assert(table[j][1] == 0); /* incorrect code */
+                               table[j][1] = n; /* bits */
+                               table[j][0] = i;
                                j++;
                        }
                } else {
                        n -= table_nb_bits;
                        j = (code >> n) & ((1 << table_nb_bits) - 1);
                        /* compute table size */
-                       n1 = -table[j][1];      //bits
+                       n1 = -table[j][1]; /* bits */
                        if (n > n1)
                                n1 = n;
-                       table[j][1] = -n1;      //bits
+                       table[j][1] = -n1; /* bits */
                }
        }
 
-       /* fill auxillary tables recursively */
+       /* fill auxiliary tables recursively */
        for (i = 0; i < table_size; i++) {
-               n = table[i][1];        //bits
+               n = table[i][1]; /* bits */
                if (n < 0) {
                        n = -n;
                        if (n > table_nb_bits) {
                                n = table_nb_bits;
-                               table[i][1] = -n;       //bits
+                               table[i][1] = -n; /* bits */
                        }
                        idx = build_table(vlc, n, nb_codes, bits, codes,
                                codes_size, (code_prefix << table_nb_bits) | i,
                                n_prefix + table_nb_bits);
                        /* vlc->table might have changed */
                        table = &vlc->table[table_index];
-                       table[i][0] = idx;      //code
+                       table[i][0] = idx; /* code */
                }
        }
        return table_index;
@@ -134,19 +126,15 @@ static int build_table(struct vlc *vlc, int table_nb_bits, int nb_codes,
  * Build VLC decoding tables suitable for use with get_vlc().
  *
  * \param vlc The structure to be initialized.
- *
- * \param nb_bits Set the decoding table size (2^nb_bits) entries. The bigger
- * it is, the faster is the decoding. But it should not be too big to save
- * memory and L1 cache. '9' is a good compromise.
- *
- * \param nb_codes Number of vlcs codes.
- *
+ * \param nb_bits Set the decoding table size (2^nb_bits) entries.
+ * \param nb_codes Number of vlc codes.
  * \param bits Table which gives the size (in bits) of each vlc code.
- *
  * \param codes Table which gives the bit pattern of of each vlc code.
- *
  * \param codes_size The number of bytes of each entry of the \a codes tables.
  *
+ * The bigger \a nb_bits is, the faster is the decoding. But it should not be
+ * too big to save memory and L1 cache. '9' is a good compromise.
+ *
  * The wrap and size parameters allow to use any memory configuration and
  * types (byte/word/long) to store the bits and codes tables.
  */
@@ -178,15 +166,14 @@ void free_vlc(struct vlc *vlc)
  * Parse a vlc code.
  *
  * \param gbc The getbit context structure.
- *
  * \param table The vlc tables to use.
- *
- * \param bits The number of bits which will be read at once, must be
- * identical to nb_bits in init_vlc().
- *
- * \param max_depth The number of times bits bits must be read to completely
+ * \param bits The number of bits which will be read at once.
+ * \param max_depth The number of times \a bits bits must be read to completely
  * read the longest vlc code = (max_vlc_length + bits - 1) / bits.
  *
+ * The \a bits parameter must be identical to the \a nb_bits value supplied to
+ * \ref init_vlc().
+ *
  * \return The vlc code.
  */
 int get_vlc(struct getbit_context *gbc, VLC_TYPE(*table)[2], int bits,
index a3393380e5e02801a4312c6f904c1ea25527aad9..5890d08c89d4033f7fefb9a19be525860a701d77 100644 (file)
@@ -69,11 +69,13 @@ static inline unsigned int get_bit(struct getbit_context *gbc)
 /**
  * Initialize a getbit_context structure.
  *
- * \param buffer The bitstream buffer. It must be 4 bytes larger then the
- * actual read bits because the bitstream reader might read 32 bits at once and
- * could read over the end.
+ * \param gbc The structure to initialize.
+ * \param buffer The bitstream buffer.
+ * \param size The size of the buffer in bytes.
  *
- * \param bit_size The size of the buffer in bytes.
+ * The bitstream buffer must be 4 bytes larger then the actual read bits
+ * because the bitstream reader might read 32 bits at once and could read over
+ * the end.
  */
 static inline void init_get_bits(struct getbit_context *gbc,
                const uint8_t *buffer, int size)
@@ -88,4 +90,3 @@ void init_vlc(struct vlc *vlc, int nb_bits, int nb_codes, const void *bits,
 void free_vlc(struct vlc *vlc);
 int get_vlc(struct getbit_context *gbc, VLC_TYPE(*table)[2], int bits,
                int max_depth);
-
diff --git a/blob.c b/blob.c
index cd571d74e5d40f71286ef8dc19aca635778f9429..dc71b8e3feb61323279b770effbab33b7c6d4978 100644 (file)
--- a/blob.c
+++ b/blob.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -311,12 +311,12 @@ static int com_rmblob(callback_function *f, struct command_context *cc)
                afs_cb_result_handler, cc);
 }
 
-static void com_addblob_callback(struct osl_table *table, __a_unused int fd,
+static void com_addblob_callback(struct osl_table *table, int fd,
                const struct osl_object *query)
 {
        struct osl_object objs[NUM_BLOB_COLUMNS];
-       char *name = query->data;
-       size_t name_len = strlen(name) + 1;
+       char *name = query->data, *msg;
+       size_t name_len = strlen(name) + 1, msg_len;
        uint32_t id;
        unsigned num_rows;
        int ret;
@@ -344,6 +344,10 @@ static void com_addblob_callback(struct osl_table *table, __a_unused int fd,
                if (ret < 0 && ret != -OSL_ERRNO_TO_PARA_ERROR(E_OSL_RB_KEY_NOT_FOUND))
                        goto out;
                if (ret >= 0) { /* we already have a blob with this name */
+                       ret = osl(osl_get_object(table, row, BLOBCOL_ID, &obj));
+                       if (ret < 0)
+                               goto out;
+                       id = *(uint32_t *)obj.data;
                        obj.data = name + name_len;
                        obj.size = query->size - name_len;
                        ret = osl(osl_update_object(table, row, BLOBCOL_DEF, &obj));
@@ -377,81 +381,88 @@ static void com_addblob_callback(struct osl_table *table, __a_unused int fd,
        afs_event(BLOB_ADD, NULL, table);
 out:
        if (ret < 0)
-               PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
+               msg_len = xasprintf(&msg, "could not add %s: %s\n", name,
+                       para_strerror(-ret));
+       else
+               msg_len = xasprintf(&msg, "added %s as id %u\n", name, id);
+       pass_buffer_as_shm(fd, SBD_OUTPUT, msg, msg_len);
+       free(msg);
 }
 
-/*
- * write input from fd to dynamically allocated buffer,
- * but maximal max_size byte.
- */
-static int fd2buf(struct stream_cipher_context *scc, unsigned max_size, struct osl_object *obj)
+/* Write input from fd to dynamically allocated buffer, but maximal 10M. */
+static int fd2buf(struct stream_cipher_context *scc, struct osl_object *obj)
 {
-       const size_t chunk_size = 1024;
-       size_t size = 2048, received = 0;
+       size_t max_size = 10 * 1024 * 1024;
        int ret;
-       char *buf = para_malloc(size);
+       struct iovec iov;
 
-       for (;;) {
-               ret = sc_recv_bin_buffer(scc, buf + received, chunk_size);
-               if (ret <= 0)
-                       break;
-               received += ret;
-               if (received + chunk_size >= size) {
-                       size *= 2;
-                       ret = -E_INPUT_TOO_LARGE;
-                       if (size > max_size)
-                               break;
-                       buf = para_realloc(buf, size);
-               }
+       obj->data = NULL;
+       obj->size = 0;
+again:
+       do {
+               ret = recv_sb(scc, SBD_BLOB_DATA, max_size, &iov);
+       } while (ret == 0);
+
+       if (ret < 0) {
+               free(obj->data);
+               obj->data = NULL;
+               obj->size = 0;
+               return ret;
        }
-       obj->data = buf;
-       obj->size = received;
-       if (ret < 0)
-               free(buf);
-       return ret;
+       if (iov.iov_len == 0) /* end of blob */
+               return 1;
+       if (!obj->data) {
+               obj->data = iov.iov_base;
+               obj->size = iov.iov_len;
+       } else {
+               obj->data = para_realloc(obj->data, obj->size + iov.iov_len);
+               memcpy(obj->data + obj->size, iov.iov_base, iov.iov_len);
+               obj->size += iov.iov_len;
+               free(iov.iov_base);
+               max_size -= iov.iov_len;
+       }
+       goto again;
+       return 1;
 }
 
 /*
  * Read data from a file descriptor, and send it to the afs process.
  *
- * \param scc crypt context containing the file descriptor to read data from.
+ * \param cc Contains the file descriptor to read data from.
  * \param arg_obj Pointer to the arguments to \a f.
  * \param f The callback function.
- * \param max_len Don't read more than that many bytes from stdin.
  * \param result_handler See \ref send_callback_request.
  * \param private_result_data See \ref send_callback_request.
  *
- * This function is used by commands that wish to let para_server store
- * arbitrary data specified by the user (for instance the add_blob family of
- * commands). First, at most \a max_len bytes are read and decrypted from the
- * file descriptor given by \a scc. The result is concatenated with the buffer
- * given by \a arg_obj, and the combined buffer is made available to the afs
- * process via the callback method. See \ref send_callback_request for details.
+ * This function is used by the addblob commands that instruct para_server to
+ * store arbitrary data in a blob table. Input data is read and decrypted from
+ * the file descriptor given by \a cc. This data is concatenated with the
+ * buffer given by \a arg_obj, and the combined buffer is made available to the
+ * afs process via the callback method. See \ref send_callback_request for
+ * details.
  *
  * \return Negative on errors, the return value of the underlying call to
  * send_callback_request() otherwise.
  */
 static int stdin_command(struct command_context *cc, struct osl_object *arg_obj,
-               callback_function *f, unsigned max_len,
-               callback_result_handler *result_handler,
+               callback_function *f, callback_result_handler *result_handler,
                void *private_result_data)
 {
        struct osl_object query, stdin_obj;
        int ret;
 
-       if (cc->use_sideband)
-               ret = send_sb(&cc->scc, NULL, 0, SBD_AWAITING_DATA, false);
-       else
-               ret = sc_send_buffer(&cc->scc, AWAITING_DATA_MSG);
+       ret = send_sb(&cc->scc, NULL, 0, SBD_AWAITING_DATA, false);
        if (ret < 0)
                return ret;
-       ret = fd2buf(&cc->scc, max_len, &stdin_obj);
+       ret = fd2buf(&cc->scc, &stdin_obj);
        if (ret < 0)
                return ret;
        query.size = arg_obj->size + stdin_obj.size;
        query.data = para_malloc(query.size);
        memcpy(query.data, arg_obj->data, arg_obj->size);
-       memcpy((char *)query.data + arg_obj->size, stdin_obj.data, stdin_obj.size);
+       if (stdin_obj.size > 0)
+               memcpy((char *)query.data + arg_obj->size, stdin_obj.data,
+                       stdin_obj.size);
        free(stdin_obj.data);
        ret = send_callback_request(f, &query, result_handler, private_result_data);
        free(query.data);
@@ -468,7 +479,7 @@ static int com_addblob(callback_function *f, struct command_context *cc)
                return -E_BLOB_SYNTAX;
        arg_obj.size = strlen(cc->argv[1]) + 1;
        arg_obj.data = (char *)cc->argv[1];
-       return stdin_command(cc, &arg_obj, f, 10 * 1024 * 1024, NULL, NULL);
+       return stdin_command(cc, &arg_obj, f, afs_cb_result_handler, cc);
 }
 
 /* FIXME: Print output to client, not to log file */
index aa9f1cdb0c95b77635981cea0e6bb1588bbcdc03..44b73c946d1fc6127aba2b1e9e31c206b67ba18c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2009-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -544,14 +544,16 @@ static bool btr_no_children(struct btr_node *btrn)
 }
 
 /**
- * Find out whether a node is an orphan node.
+ * Find out whether a node is an orphan.
  *
  * \param btrn The buffer tree node.
  *
  * \return True if \a btrn has no parent.
  *
- * This function will always return true for the root node.  However in case
- * nodes have been removed from the tree, other nodes may become orphans too.
+ * This function returns true for the root node and false for any other node.
+ *
+ * After a (non-leaf) node was removed removed from the tree, the function
+ * returns true for all child nodes.
  */
 bool btr_no_parent(struct btr_node *btrn)
 {
@@ -769,6 +771,12 @@ void btr_drain(struct btr_node *btrn)
                btr_drop_buffer_reference(br);
 }
 
+static void btr_free_node(struct btr_node *btrn)
+{
+       free(btrn->name);
+       free(btrn);
+}
+
 /**
  * Remove a node from a buffer tree.
  *
@@ -796,8 +804,7 @@ void btr_remove_node(struct btr_node **btrnp)
        btr_drain(btrn);
        if (btrn->parent)
                list_del(&btrn->node);
-       free(btrn->name);
-       free(btrn);
+       btr_free_node(btrn);
 out:
        *btrnp = NULL;
 }
@@ -833,7 +840,7 @@ size_t btr_get_input_queue_size(struct btr_node *btrn)
 /**
  * Remove a node from the buffer tree, reconnecting parent and children.
  *
- * \param btrn The node to splice out.
+ * \param btrnp The node to splice out.
  *
  * This function is used by buffer tree nodes that do not exist during the
  * whole lifetime of the buffer tree. Unlike btr_remove_node(), calling
@@ -841,9 +848,9 @@ size_t btr_get_input_queue_size(struct btr_node *btrn)
  * but reconnects the buffer tree by making all child nodes of \a btrn children
  * of the parent of \a btrn.
  */
-void btr_splice_out_node(struct btr_node *btrn)
+void btr_splice_out_node(struct btr_node **btrnp)
 {
-       struct btr_node *ch, *tmp;
+       struct btr_node *btrn = *btrnp, *ch, *tmp;
 
        assert(btrn);
        PARA_NOTICE_LOG("splicing out %s\n", btrn->name);
@@ -860,7 +867,8 @@ void btr_splice_out_node(struct btr_node *btrn)
                        list_del(&ch->node);
        }
        assert(list_empty(&btrn->children));
-       btrn->parent = NULL;
+       btr_free_node(btrn);
+       *btrnp = NULL;
 }
 
 /**
@@ -1201,21 +1209,20 @@ int btr_node_status(struct btr_node *btrn, size_t min_iqs,
        size_t iqs;
 
        assert(btrn);
-       if (type != BTR_NT_LEAF) {
-               if (btr_no_children(btrn))
-                       return -E_BTR_NO_CHILD;
-               if (btr_get_output_queue_size(btrn) > BTRN_MAX_PENDING)
-                       return 0;
-       }
-       if (type != BTR_NT_ROOT) {
-               if (btr_eof(btrn))
-                       return -E_BTR_EOF;
-               iqs = btr_get_input_queue_size(btrn);
-               if (iqs == 0) /* we have a parent, because not eof */
-                       return 0;
-               if (iqs < min_iqs && !btr_no_parent(btrn))
-                       return 0;
-       }
+       if (type != BTR_NT_LEAF && btr_no_children(btrn))
+               return -E_BTR_NO_CHILD;
+       if (type != BTR_NT_ROOT && btr_eof(btrn))
+               return -E_BTR_EOF;
+
+       if (btr_get_output_queue_size(btrn) > BTRN_MAX_PENDING)
+               return 0;
+       if (type == BTR_NT_ROOT)
+               return 1;
+       iqs = btr_get_input_queue_size(btrn);
+       if (iqs == 0) /* we have a parent, because not eof */
+               return 0;
+       if (iqs < min_iqs && !btr_no_parent(btrn))
+               return 0;
        return 1;
 }
 
index 20dcd62dda5a531fdf10fe4a01b3669dad39e2ca..e01cb90609b6acf89109a21b0279dc446e150ac3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2009-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -192,7 +192,7 @@ size_t btr_next_buffer(struct btr_node *btrn, char **bufp);
 size_t btr_next_buffer_omit(struct btr_node *btrn, size_t omit, char **bufp);
 void btr_consume(struct btr_node *btrn, size_t numbytes);
 int btr_exec_up(struct btr_node *btrn, const char *command, char **value_result);
-void btr_splice_out_node(struct btr_node *btrn);
+void btr_splice_out_node(struct btr_node **btrnp);
 void btr_pushdown(struct btr_node *btrn);
 void *btr_context(struct btr_node *btrn);
 void btr_merge(struct btr_node *btrn, size_t dest_size);
index 11459e08c375c62285664637125c599f0e5b02be..a36cea9ab34fb319bf7070eaa43e8bb65dcfcd24 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index ba1a8eca48f2bf9407c7f3efbbdbd74e7414b2c7..5310d170735c24cef72bfe2443e104310947e14e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2012-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index c870d4d2a0d397d17777f09fe3f94ff527cfc86a..5328c1132f51ff9b85c2c448f740233732c76a10 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -13,6 +13,7 @@
 #include "afh.h"
 #include "string.h"
 #include "error.h"
+#include "chunk_queue.h"
 
 /**
  * Senders may use the chunk queue facility to deal with laggy connections.  It
index 7514682464b787295863119b90a03ae5b9eb8439..946cacda31749437a575cecc0e319aac92864dd8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 2d6ef31f590bca1736d458cc61c4fbe67459641b..987a637fa2301b22beea8795fbe7ee063b46787b 100644 (file)
--- a/client.c
+++ b/client.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -39,24 +39,24 @@ __printf_2_3 void (*para_log)(int, const char*, ...) = stderr_log;
 #include "afs_completion.h"
 
 struct exec_task {
-       struct task task;
+       struct task *task;
        struct btr_node *btrn;
        char *result_buf;
        size_t result_size;
 };
 
-static void exec_pre_select(struct sched *s, struct task *t)
+static void exec_pre_select(struct sched *s, void *context)
 {
-       struct exec_task *et = container_of(t, struct exec_task, task);
+       struct exec_task *et = context;
        int ret = btr_node_status(et->btrn, 0, BTR_NT_LEAF);
 
        if (ret != 0)
                sched_min_delay(s);
 }
 
-static int exec_post_select(__a_unused struct sched *s, struct task *t)
+static int exec_post_select(__a_unused struct sched *s, void *context)
 {
-       struct exec_task *et = container_of(t, struct exec_task, task);
+       struct exec_task *et = context;
        struct btr_node *btrn = et->btrn;
        char *buf;
        size_t sz;
@@ -93,11 +93,6 @@ static int execute_client_command(const char *cmd, char **result)
        int ret;
        struct sched command_sched = {.default_timeout = {.tv_sec = 1}};
        struct exec_task exec_task = {
-               .task = {
-                       .pre_select = exec_pre_select,
-                       .post_select = exec_post_select,
-                       .status = "client exec task",
-               },
                .result_buf = para_strdup(""),
                .result_size = 1,
        };
@@ -107,14 +102,19 @@ static int execute_client_command(const char *cmd, char **result)
                goto out;
        exec_task.btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.name = "exec_collect"));
-       register_task(&command_sched, &exec_task.task);
+       exec_task.task = task_register(&(struct task_info) {
+               .name = "client exec",
+               .pre_select = exec_pre_select,
+               .post_select = exec_post_select,
+               .context = &exec_task,
+       }, &command_sched);
        ret = client_connect(ct, &command_sched, NULL, exec_task.btrn);
        if (ret < 0)
                goto out;
        schedule(&command_sched);
+       sched_shutdown(&command_sched);
        *result = exec_task.result_buf;
        btr_remove_node(&exec_task.btrn);
-       client_disconnect(ct);
        ret = 1;
 out:
        btr_remove_node(&exec_task.btrn);
@@ -444,7 +444,6 @@ static int client_i9e_line_handler(char *line)
 {
        int ret;
 
-       client_disconnect(ct);
        PARA_DEBUG_LOG("line: %s\n", line);
        ret = make_client_argv(line);
        if (ret <= 0)
@@ -452,7 +451,7 @@ static int client_i9e_line_handler(char *line)
        ret = client_connect(ct, &sched, NULL, NULL);
        if (ret < 0)
                return ret;
-       i9e_attach_to_stdout(ct->btrn);
+       i9e_attach_to_stdout(ct->btrn[0]);
        return 1;
 }
 
@@ -497,6 +496,7 @@ __noreturn static void interactive_session(void)
                goto out;
        para_log = i9e_log;
        ret = schedule(&sched);
+       sched_shutdown(&sched);
        i9e_close();
        para_log = stderr_log;
 out:
@@ -528,27 +528,31 @@ __noreturn static void print_completions(void)
 
 #endif /* HAVE_READLINE */
 
-static int supervisor_post_select(struct sched *s, __a_unused struct task *t)
+struct supervisor_task {
+       bool stdout_task_started;
+       struct task *task;
+};
+
+static int supervisor_post_select(struct sched *s, void *context)
 {
-       if (ct->task.error < 0)
-               return ct->task.error;
-       if (ct->status == CL_SENDING) {
-               stdin_set_defaults(&sit);
-               register_task(s, &sit.task);
-               return -E_TASK_STARTED;
+       struct supervisor_task *svt = context;
+       int ret = task_status(ct->task);
+
+       if (ret < 0)
+               return ret;
+       if (!svt->stdout_task_started && ct->status == CL_EXECUTING) {
+               stdout_task_register(&sot, s);
+               svt->stdout_task_started = true;
+               return 1;
        }
-       if (ct->status == CL_RECEIVING) {
-               stdout_set_defaults(&sot);
-               register_task(s, &sot.task);
+       if (ct->status == CL_SENDING) {
+               stdin_task_register(&sit, s);
                return -E_TASK_STARTED;
        }
        return 0;
 }
 
-static struct task svt = {
-       .post_select = supervisor_post_select,
-       .status = "supervisor task"
-};
+static struct supervisor_task supervisor_task;
 
 /**
  * The client program to connect to para_server.
@@ -595,21 +599,30 @@ int main(int argc, char *argv[])
        if (ret < 0)
                goto out;
        sot.btrn = btr_new_node(&(struct btr_node_description)
-               EMBRACE(.name = "stdout", .parent = ct->btrn));
-       register_task(&sched, &svt);
+               EMBRACE(.name = "stdout", .parent = ct->btrn[0]));
+       supervisor_task.task = task_register(&(struct task_info) {
+               .name = "supervisor",
+               .post_select = supervisor_post_select,
+               .context = &supervisor_task,
+       }, &sched);
+
        ret = schedule(&sched);
-       if (ret >= 0 && ct->task.error < 0) {
-               switch(ct->task.error) {
-               /* these are not errors */
-               case -E_SERVER_CMD_SUCCESS:
-               case -E_EOF:
-               case -E_SERVER_EOF:
-               case -E_BTR_EOF:
-                       ret = 0;
-                       break;
-               default: ret = -E_SERVER_CMD_FAILURE;
+       if (ret >= 0) {
+               ret = task_status(ct->task);
+               if (ret < 0) {
+                       switch (ret) {
+                       /* these are not errors */
+                       case -E_SERVER_CMD_SUCCESS:
+                       case -E_EOF:
+                       case -E_SERVER_EOF:
+                       case -E_BTR_EOF:
+                               ret = 0;
+                               break;
+                       default: ret = -E_SERVER_CMD_FAILURE;
+                       }
                }
        }
+       sched_shutdown(&sched);
 out:
        if (ret < 0)
                PARA_ERROR_LOG("%s\n", para_strerror(-ret));
index 92e14b15eabc686b95a077d0097598f99b3f97a6..0a0c55cba0077cecaeb665b86542dc5a038e7d7d 100644 (file)
--- a/client.h
+++ b/client.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -20,12 +20,10 @@ enum {
        CL_SENT_CH_RESPONSE,
        /** Server accepts this authentication. */
        CL_RECEIVED_PROCEED,
-       /** Client sends the command. */
-       CL_SENT_COMMAND,
-       /** Server expects data. */
+       /** Command is executing. */
+       CL_EXECUTING,
+       /** Server is expecting data (addblob commands only). */
        CL_SENDING,
-       /** Client expects data. */
-       CL_RECEIVING,
 };
 
 /** Data specific to a client task. */
@@ -34,10 +32,10 @@ struct client_task {
        int status;
        /** The file descriptor and the session keys. */
        struct stream_cipher_context scc;
-       /** True if this connections uses the sideband API. */
-       bool use_sideband;
-       /** The sideband context, ignored if \a use_sideband is false. */
-       struct sb_context *sbc;
+       /** The sideband contexts for receiving/sending. */
+       struct sb_context *sbc[2];
+       /** The buffer tree nodes for receiving/sending. */
+       struct btr_node *btrn[2];
        /** The hash value of the decrypted challenge. */
        unsigned char *challenge_hash;
        /** The configuration (including the command). */
@@ -49,14 +47,11 @@ struct client_task {
        /** Paraslash user name. */
        char *user;
        /** The client task structure. */
-       struct task task;
-       /** The buffer tree node of the client task. */
-       struct btr_node *btrn;
+       struct task *task;
        /** List of features supported by the server. */
        char **features;
 };
 
-void client_disconnect(struct client_task *ct);
 void client_close(struct client_task *ct);
 int client_parse_config(int argc, char *argv[], struct client_task **ct_ptr,
                int *loglevel);
index 1ecba73068f04c4dbf43480f5ccf32a932e01279..c111e351ba50dc54ca48a2dae851d2f8f72dcae7 100644 (file)
@@ -1,13 +1,18 @@
 /*
- * Copyright (C) 1997-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 
 /** \file client_common.c Common functions of para_client and para_audiod. */
 
+#include <netinet/in.h>
+#include <sys/socket.h>
 #include <regex.h>
 #include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
 
 #include "para.h"
 #include "error.h"
 /** The size of the receiving buffer. */
 #define CLIENT_BUFSIZE 4000
 
-/**
- * Close the connection to para_server and deallocate per-command resources.
- *
- * \param ct The client task.
- *
- * This frees all resources of the current command but keeps the configuration
- * in \p ct->conf.
- *
- * \sa \ref client_close().
- */
-void client_disconnect(struct client_task *ct)
-{
-       if (!ct)
-               return;
-       if (ct->scc.fd >= 0)
-               close(ct->scc.fd);
-       free_argv(ct->features);
-       ct->features = NULL;
-       sc_free(ct->scc.recv);
-       ct->scc.recv = NULL;
-       sc_free(ct->scc.send);
-       ct->scc.send = NULL;
-       btr_remove_node(&ct->btrn);
-}
-
 /**
  * Close the connection to para_server and free all resources.
  *
  * \param ct Pointer to the client data.
  *
- * \sa \ref client_open(), \ref client_disconnect().
+ * \sa \ref client_open().
  */
 void client_close(struct client_task *ct)
 {
        if (!ct)
                return;
-       client_disconnect(ct);
        free(ct->user);
        free(ct->config_file);
        free(ct->key_file);
        client_cmdline_parser_free(&ct->conf);
        free(ct->challenge_hash);
-       sb_free(ct->sbc);
+       sb_free(ct->sbc[0]);
+       sb_free(ct->sbc[1]);
        free(ct);
 }
 
-/**
+/*
  * The preselect hook for server commands.
  *
- * \param s Pointer to the scheduler.
- * \param t Pointer to the task struct for this command.
- *
  * The task pointer must contain a pointer to the initialized client data
  * structure as it is returned by client_open().
  *
  * This function checks the state of the connection and adds the file descriptor
- * of the connection to the read or write fd set of \a s accordingly.
- *
- * \sa register_task() client_open(), struct sched, struct task.
+ * of the connection to the read or write fd set of s accordingly.
  */
-static void client_pre_select(struct sched *s, struct task *t)
+static void client_pre_select(struct sched *s, void *context)
 {
        int ret;
-       struct client_task *ct = container_of(t, struct client_task, task);
-       struct btr_node *btrn = ct->btrn;
+       struct client_task *ct = context;
 
        if (ct->scc.fd < 0)
                return;
@@ -99,7 +73,6 @@ static void client_pre_select(struct sched *s, struct task *t)
        case CL_CONNECTED:
        case CL_SENT_AUTH:
        case CL_SENT_CH_RESPONSE:
-       case CL_SENT_COMMAND:
                para_fd_set(ct->scc.fd, &s->rfds, &s->max_fileno);
                return;
 
@@ -109,76 +82,49 @@ static void client_pre_select(struct sched *s, struct task *t)
                para_fd_set(ct->scc.fd, &s->wfds, &s->max_fileno);
                return;
 
-       case CL_RECEIVING:
-               ret = btr_node_status(btrn, 0, BTR_NT_ROOT);
-               if (ret != 0) {
+       case CL_SENDING:
+               if (ct->btrn[1]) {
+                       ret = btr_node_status(ct->btrn[1], 0, BTR_NT_LEAF);
                        if (ret < 0)
                                sched_min_delay(s);
-                       else
-                               para_fd_set(ct->scc.fd, &s->rfds,
-                                       &s->max_fileno);
+                       else if (ret > 0)
+                               para_fd_set(ct->scc.fd, &s->wfds, &s->max_fileno);
                }
-               return;
-       case CL_SENDING:
-               ret = btr_node_status(btrn, 0, BTR_NT_LEAF);
-               if (ret != 0) {
+               /* fall though */
+       case CL_EXECUTING:
+               if (ct->btrn[0]) {
+                       ret = btr_node_status(ct->btrn[0], 0, BTR_NT_ROOT);
                        if (ret < 0)
                                sched_min_delay(s);
-                       else
-                               para_fd_set(ct->scc.fd, &s->wfds,
-                                       &s->max_fileno);
+                       else if (ret > 0)
+                               para_fd_set(ct->scc.fd, &s->rfds, &s->max_fileno);
                }
                return;
        }
 }
 
-static int client_recv_buffer(struct client_task *ct, fd_set *rfds,
-               char *buf, size_t sz, size_t *n)
-{
-       int ret;
-
-       if (ct->status < CL_SENT_CH_RESPONSE)
-               return read_nonblock(ct->scc.fd, buf, sz, rfds, n);
-
-       *n = 0;
-       ret = sc_recv_buffer(&ct->scc, buf, sz);
-       /*
-        * sc_recv_buffer is used with blocking fds elsewhere, so it
-        * does not use the nonblock-API. Therefore we need to
-        * check for EOF and EAGAIN.
-        */
-       if (ret == 0)
-               return -E_SERVER_EOF;
-       if (ret == -ERRNO_TO_PARA_ERROR(EAGAIN))
-               return 0;
-       if (ret < 0)
-               return ret;
-       *n = ret;
-       return 0;
-}
-
-static int send_sb(struct client_task *ct, void *buf, size_t numbytes,
+static int send_sb(struct client_task *ct, int channel, void *buf, size_t numbytes,
                enum sb_designator band, bool dont_free)
 {
        int ret, fd = ct->scc.fd;
        struct iovec iov[2];
 
-       if (!ct->sbc) {
+       if (!ct->sbc[channel]) {
                struct sb_buffer sbb;
                sb_transformation trafo = ct->status < CL_RECEIVED_PROCEED?
                        NULL : sc_trafo;
                sbb = (typeof(sbb))SBB_INIT(band, buf, numbytes);
-               ct->sbc = sb_new_send(&sbb, dont_free, trafo, ct->scc.send);
+               ct->sbc[channel] = sb_new_send(&sbb, dont_free, trafo, ct->scc.send);
        }
-       ret = sb_get_send_buffers(ct->sbc, iov);
+       ret = sb_get_send_buffers(ct->sbc[channel], iov);
        ret = xwritev(fd, iov, ret);
        if (ret < 0) {
-               sb_free(ct->sbc);
-               ct->sbc = NULL;
+               sb_free(ct->sbc[channel]);
+               ct->sbc[channel] = NULL;
                return ret;
        }
-       if (sb_sent(ct->sbc, ret)) {
-               ct->sbc = NULL;
+       if (sb_sent(ct->sbc[channel], ret)) {
+               ct->sbc[channel] = NULL;
                return 1;
        }
        return 0;
@@ -201,21 +147,21 @@ static int recv_sb(struct client_task *ct, fd_set *rfds,
                trafo = sc_trafo;
                trafo_context = ct->scc.recv;
        }
-       if (!ct->sbc)
-               ct->sbc = sb_new_recv(0, trafo, trafo_context);
+       if (!ct->sbc[0])
+               ct->sbc[0] = sb_new_recv(0, trafo, trafo_context);
 again:
-       sb_get_recv_buffer(ct->sbc, &iov);
+       sb_get_recv_buffer(ct->sbc[0], &iov);
        ret = read_nonblock(ct->scc.fd, iov.iov_base, iov.iov_len, rfds, &n);
        if (ret < 0) {
-               sb_free(ct->sbc);
-               ct->sbc = NULL;
+               sb_free(ct->sbc[0]);
+               ct->sbc[0] = NULL;
                return ret;
        }
        if (n == 0)
                return 0;
-       if (!sb_received(ct->sbc, n, result))
+       if (!sb_received(ct->sbc[0], n, result))
                goto again;
-       ct->sbc = NULL;
+       ct->sbc[0] = NULL;
        return 1;
 }
 
@@ -251,10 +197,14 @@ static int dispatch_sbb(struct client_task *ct, struct sb_buffer *sbb)
                PARA_DEBUG_LOG("band: %s\n", designator[sbb->band]);
 
        switch (sbb->band) {
+       case SBD_AWAITING_DATA:
+               ct->status = CL_SENDING;
+               ret = 1;
+               goto out;
        case SBD_OUTPUT:
                if (iov_valid(&sbb->iov))
                        btr_add_output(sbb->iov.iov_base, sbb->iov.iov_len,
-                               ct->btrn);
+                               ct->btrn[0]);
                ret = 1;
                goto out;
        case SBD_DEBUG_LOG:
@@ -299,8 +249,8 @@ static int send_sb_command(struct client_task *ct)
        char *command, *p;
        size_t len = 0;
 
-       if (ct->sbc)
-               return send_sb(ct, NULL, 0, 0, false);
+       if (ct->sbc[1])
+               return send_sb(ct, 0, NULL, 0, 0, false);
 
        for (i = 0; i < ct->conf.inputs_num; i++)
                len += strlen(ct->conf.inputs[i]) + 1;
@@ -310,51 +260,47 @@ static int send_sb_command(struct client_task *ct)
                p += strlen(ct->conf.inputs[i]) + 1;
        }
        PARA_DEBUG_LOG("--> %s\n", command);
-       return send_sb(ct, command, len, SBD_COMMAND, false);
+       return send_sb(ct, 0, command, len, SBD_COMMAND, false);
 }
 
-/**
+/*
  * The post select hook for client commands.
  *
- * \param s Pointer to the scheduler.
- * \param t Pointer to the task struct for this command.
- *
  * Depending on the current state of the connection and the status of the read
- * and write fd sets of \a s, this function performs the necessary steps to
- * authenticate the connection, to send the command given by \a t->private_data
+ * and write fd sets of s, this function performs the necessary steps to
+ * authenticate the connection, to send the command given by t->private_data
  * and to receive para_server's output, if any.
- *
- * \sa struct sched, struct task.
  */
-static int client_post_select(struct sched *s, struct task *t)
+static int client_post_select(struct sched *s, void *context)
 {
-       struct client_task *ct = container_of(t, struct client_task, task);
-       struct btr_node *btrn = ct->btrn;
+       struct client_task *ct = context;
        int ret = 0;
        size_t n;
        char buf[CLIENT_BUFSIZE];
 
-       ret = task_get_notification(t);
+       ret = task_get_notification(ct->task);
        if (ret < 0)
                goto out;
        if (ct->scc.fd < 0)
                return 0;
        switch (ct->status) {
        case CL_CONNECTED: /* receive welcome message */
-               ret = client_recv_buffer(ct, &s->rfds, buf, sizeof(buf), &n);
+               ret = read_nonblock(ct->scc.fd, buf, sizeof(buf), &s->rfds, &n);
                if (ret < 0 || n == 0)
                        goto out;
                ct->features = parse_features(buf);
+               if (!has_feature("sideband", ct)) {
+                       PARA_ERROR_LOG("server has no sideband support\n");
+                       ret = -E_INCOMPAT_FEAT;
+                       goto out;
+               }
                ct->status = CL_RECEIVED_WELCOME;
                return 0;
        case CL_RECEIVED_WELCOME: /* send auth command */
                if (!FD_ISSET(ct->scc.fd, &s->wfds))
                        return 0;
-               if (has_feature("sideband", ct)) {
-                       ct->use_sideband = true;
-                       sprintf(buf, AUTH_REQUEST_MSG "%s sideband", ct->user);
-               } else
-                       sprintf(buf, AUTH_REQUEST_MSG "%s", ct->user);
+               sprintf(buf, AUTH_REQUEST_MSG "%s sideband%s", ct->user,
+                       has_feature("aes_ctr128", ct)? ",aes_ctr128" : "");
                PARA_INFO_LOG("--> %s\n", buf);
                ret = write_buffer(ct->scc.fd, buf);
                if (ret < 0)
@@ -369,202 +315,140 @@ static int client_post_select(struct sched *s, struct task *t)
                {
                /* decrypted challenge/session key buffer */
                unsigned char crypt_buf[1024];
-               /* the SHA1 of the decrypted challenge */
+               struct sb_buffer sbb;
+               bool use_aes;
 
-               if (ct->use_sideband) {
-                       struct sb_buffer sbb;
-                       ret = recv_sb(ct, &s->rfds, &sbb);
-                       if (ret <= 0)
-                               goto out;
-                       if (sbb.band != SBD_CHALLENGE) {
-                               ret = -E_BAD_BAND;
-                               free(sbb.iov.iov_base);
-                                       goto out;
-                       }
-                       n = sbb.iov.iov_len;
-                       PARA_INFO_LOG("<-- [challenge] (%zu bytes)\n", n);
-                       ret = priv_decrypt(ct->key_file, crypt_buf,
-                               sbb.iov.iov_base, n);
+               ret = recv_sb(ct, &s->rfds, &sbb);
+               if (ret <= 0)
+                       goto out;
+               if (sbb.band != SBD_CHALLENGE) {
+                       ret = -E_BAD_BAND;
                        free(sbb.iov.iov_base);
-                       if (ret < 0)
-                               goto out;
-               } else {
-                       ret = client_recv_buffer(ct, &s->rfds, buf, sizeof(buf), &n);
-                       if (ret < 0 || n == 0)
-                               goto out;
-                       PARA_INFO_LOG("<-- [challenge] (%zu bytes)\n", n);
-                       ret = priv_decrypt(ct->key_file, crypt_buf,
-                               (unsigned char *)buf, n);
-                       if (ret < 0)
                                goto out;
                }
+               n = sbb.iov.iov_len;
+               PARA_INFO_LOG("<-- [challenge] (%zu bytes)\n", n);
+               ret = priv_decrypt(ct->key_file, crypt_buf,
+                       sbb.iov.iov_base, n);
+               free(sbb.iov.iov_base);
+               if (ret < 0)
+                       goto out;
                ct->challenge_hash = para_malloc(HASH_SIZE);
                hash_function((char *)crypt_buf, CHALLENGE_SIZE, ct->challenge_hash);
-               ct->scc.send = sc_new(crypt_buf + CHALLENGE_SIZE, SESSION_KEY_LEN);
+               use_aes = has_feature("aes_ctr128", ct);
+               ct->scc.send = sc_new(crypt_buf + CHALLENGE_SIZE, SESSION_KEY_LEN, use_aes);
                ct->scc.recv = sc_new(crypt_buf + CHALLENGE_SIZE + SESSION_KEY_LEN,
-                       SESSION_KEY_LEN);
+                       SESSION_KEY_LEN, use_aes);
                hash_to_asc(ct->challenge_hash, buf);
                PARA_INFO_LOG("--> %s\n", buf);
                ct->status = CL_RECEIVED_CHALLENGE;
                return 0;
                }
        case CL_RECEIVED_CHALLENGE:
-               if (ct->use_sideband) {
-                       ret = send_sb(ct, ct->challenge_hash, HASH_SIZE,
-                               SBD_CHALLENGE_RESPONSE, false);
-                       if (ret != 0)
-                               ct->challenge_hash = NULL;
-                       if (ret <= 0)
-                               goto out;
-               } else {
-                       ret = write_all(ct->scc.fd, (char *)ct->challenge_hash, HASH_SIZE);
-                       if (ret < 0)
-                               goto out;
-               }
+               ret = send_sb(ct, 0, ct->challenge_hash, HASH_SIZE,
+                       SBD_CHALLENGE_RESPONSE, false);
+               if (ret != 0)
+                       ct->challenge_hash = NULL;
+               if (ret <= 0)
+                       goto out;
                ct->status = CL_SENT_CH_RESPONSE;
                goto out;
        case CL_SENT_CH_RESPONSE: /* read server response */
                {
-               if (ct->use_sideband) {
-                       struct sb_buffer sbb;
-                       ret = recv_sb(ct, &s->rfds, &sbb);
-                       if (ret <= 0)
-                               goto out;
-                       free(sbb.iov.iov_base);
-                       if (sbb.band != SBD_PROCEED)
-                               ret = -E_BAD_BAND;
-                       else
-                               ct->status = CL_RECEIVED_PROCEED;
-                       goto out;
-               }
-               ret = client_recv_buffer(ct, &s->rfds, buf, sizeof(buf), &n);
-               if (ret < 0 || n == 0)
-                       goto out;
-               /* check if server has sent "Proceed" message */
-               ret = -E_CLIENT_AUTH;
-               if (n < PROCEED_MSG_LEN)
-                       goto out;
-               if (!strstr(buf, PROCEED_MSG))
+               struct sb_buffer sbb;
+               ret = recv_sb(ct, &s->rfds, &sbb);
+               if (ret <= 0)
                        goto out;
-               ct->status = CL_RECEIVED_PROCEED;
-               return 0;
+               free(sbb.iov.iov_base);
+               if (sbb.band != SBD_PROCEED)
+                       ret = -E_BAD_BAND;
+               else
+                       ct->status = CL_RECEIVED_PROCEED;
+               goto out;
                }
        case CL_RECEIVED_PROCEED: /* concat args and send command */
                {
-               int i;
-               char *command = NULL;
                if (!FD_ISSET(ct->scc.fd, &s->wfds))
                        return 0;
-               if (ct->use_sideband) {
-                       ret = send_sb_command(ct);
-                       if (ret <= 0)
-                               goto out;
-                       ct->status = CL_SENT_COMMAND;
-                       return 0;
-               }
-               for (i = 0; i < ct->conf.inputs_num; i++) {
-                       char *tmp = command;
-                       command = make_message("%s\n%s", command?
-                               command : "", ct->conf.inputs[i]);
-                       free(tmp);
-               }
-               command = para_strcat(command, EOC_MSG "\n");
-               PARA_DEBUG_LOG("--> %s\n", command);
-               ret = sc_send_buffer(&ct->scc, command);
-               free(command);
-               if (ret < 0)
+               ret = send_sb_command(ct);
+               if (ret <= 0)
                        goto out;
-               ct->status = CL_SENT_COMMAND;
+               ct->status = CL_EXECUTING;
                return 0;
                }
-       case CL_SENT_COMMAND:
-               {
-               char *buf2;
-               if (ct->use_sideband) {
-                       struct sb_buffer sbb;
-                       ret = recv_sb(ct, &s->rfds, &sbb);
-                       if (ret <= 0)
-                               goto out;
-                       if (sbb.band == SBD_AWAITING_DATA) {
-                               ct->status = CL_SENDING;
-                               free(sbb.iov.iov_base);
-                               goto out;
+       case CL_SENDING:
+               if (ct->btrn[1]) {
+                       char *buf2;
+                       size_t sz;
+                       ret = btr_node_status(ct->btrn[1], 0, BTR_NT_LEAF);
+                       if (ret == -E_BTR_EOF) {
+                               /* empty blob data packet indicates EOF */
+                               PARA_INFO_LOG("blob sent\n");
+                               ret = send_sb(ct, 1, NULL, 0, SBD_BLOB_DATA, true);
+                               if (ret >= 0)
+                                       ret = -E_BTR_EOF;
                        }
-                       ct->status = CL_RECEIVING;
-                       ret = dispatch_sbb(ct, &sbb);
-                       goto out;
-               }
-               /* can not use "buf" here because we need a malloced buffer */
-               buf2 = para_malloc(CLIENT_BUFSIZE);
-               ret = client_recv_buffer(ct, &s->rfds, buf2, CLIENT_BUFSIZE, &n);
-               if (n > 0) {
-                       if (strstr(buf2, AWAITING_DATA_MSG)) {
-                               free(buf2);
-                               ct->status = CL_SENDING;
-                               return 0;
+                       if (ret < 0)
+                               goto close1;
+                       if (ret > 0 && FD_ISSET(ct->scc.fd, &s->wfds)) {
+                               sz = btr_next_buffer(ct->btrn[1], &buf2);
+                               assert(sz);
+                               ret = send_sb(ct, 1, buf2, sz, SBD_BLOB_DATA, true);
+                               if (ret < 0)
+                                       goto close1;
+                               if (ret > 0)
+                                       btr_consume(ct->btrn[1], sz);
                        }
-                       ct->status = CL_RECEIVING;
-                       btr_add_output(buf2, n, btrn);
-               } else
-                       free(buf2);
-               goto out;
                }
-       case CL_SENDING:
-               {
-               char *buf2;
-               size_t sz;
-               ret = btr_node_status(btrn, 0, BTR_NT_LEAF);
-               if (ret < 0)
-                       goto out;
-               if (ret == 0)
-                       return 0;
-               if (!FD_ISSET(ct->scc.fd, &s->wfds))
-                       return 0;
-               sz = btr_next_buffer(btrn, &buf2);
-               ret = sc_send_bin_buffer(&ct->scc, buf2, sz);
-               if (ret < 0)
-                       goto out;
-               btr_consume(btrn, sz);
-               return 0;
-               }
-       case CL_RECEIVING:
-               {
-               char *buf2;
-               ret = btr_node_status(btrn, 0, BTR_NT_ROOT);
-               if (ret < 0)
-                       goto out;
-               if (ret == 0)
-                       return 0;
-               /*
-                * The FD_ISSET() is not strictly necessary, but is allows us
-                * to skip the malloc below if there is nothing to read anyway.
-                */
-               if (!FD_ISSET(ct->scc.fd, &s->rfds))
-                       return 0;
-               if (ct->use_sideband) {
-                       struct sb_buffer sbb;
-                       ret = recv_sb(ct, &s->rfds, &sbb);
-                       if (ret > 0)
-                               ret = dispatch_sbb(ct, &sbb);
-                       goto out;
+               /* fall though */
+       case CL_EXECUTING:
+               if (ct->btrn[0]) {
+                       ret = btr_node_status(ct->btrn[0], 0, BTR_NT_ROOT);
+                       if (ret < 0)
+                               goto close0;
+                       if (ret > 0 && FD_ISSET(ct->scc.fd, &s->rfds)) {
+                               struct sb_buffer sbb;
+                               ret = recv_sb(ct, &s->rfds, &sbb);
+                               if (ret < 0)
+                                       goto close0;
+                               if (ret > 0) {
+                                       ret = dispatch_sbb(ct, &sbb);
+                                       if (ret < 0)
+                                               goto close0;
+                               }
+                       }
                }
-               buf2 = para_malloc(CLIENT_BUFSIZE);
-               ret = client_recv_buffer(ct, &s->rfds, buf2, CLIENT_BUFSIZE, &n);
-               if (n > 0) {
-                       buf2 = para_realloc(buf2, n);
-                       btr_add_output(buf2, n, btrn);
-               } else
-                       free(buf2);
+               ret = 0;
                goto out;
-               }
        }
+close1:
+       PARA_INFO_LOG("channel 1: %s\n", para_strerror(-ret));
+       btr_remove_node(&ct->btrn[1]);
+       if (ct->btrn[0])
+               return 0;
+       goto out;
+close0:
+       PARA_INFO_LOG("channel 0: %s\n", para_strerror(-ret));
+       btr_remove_node(&ct->btrn[0]);
+       if (ct->btrn[1] && ct->status == CL_SENDING)
+               return 0;
 out:
-       if (ret < 0) {
-               if (!ct->use_sideband && ret != -E_SERVER_EOF &&
-                               ret != -E_BTR_EOF && ret != -E_EOF)
-                       PARA_ERROR_LOG("%s\n", para_strerror(-ret));
-               btr_remove_node(&ct->btrn);
+       if (ret >= 0)
+               return 0;
+       btr_remove_node(&ct->btrn[0]);
+       btr_remove_node(&ct->btrn[1]);
+       if (ret != -E_SERVER_CMD_SUCCESS && ret != -E_SERVER_CMD_FAILURE)
+               PARA_ERROR_LOG("%s\n", para_strerror(-ret));
+       if (ct->scc.fd >= 0) {
+               close(ct->scc.fd);
+               ct->scc.fd = -1;
        }
+       free_argv(ct->features);
+       ct->features = NULL;
+       sc_free(ct->scc.recv);
+       ct->scc.recv = NULL;
+       sc_free(ct->scc.send);
+       ct->scc.send = NULL;
        return ret;
 }
 
@@ -598,13 +482,17 @@ int client_connect(struct client_task *ct, struct sched *s,
        if (ret < 0)
                goto err_out;
        ct->status = CL_CONNECTED;
-       ct->btrn = btr_new_node(&(struct btr_node_description)
-               EMBRACE(.name = "client", .parent = parent, .child = child));
-       ct->task.pre_select = client_pre_select;
-       ct->task.post_select = client_post_select;
-       ct->task.error = 0;
-       sprintf(ct->task.status, "client");
-       register_task(s, &ct->task);
+       ct->btrn[0] = btr_new_node(&(struct btr_node_description)
+               EMBRACE(.name = "client recv", .parent = NULL, .child = child));
+       ct->btrn[1] = btr_new_node(&(struct btr_node_description)
+               EMBRACE(.name = "client send", .parent = parent, .child = NULL));
+
+       ct->task = task_register(&(struct task_info) {
+               .name = "client",
+               .pre_select = client_pre_select,
+               .post_select = client_post_select,
+               .context = ct,
+       }, s);
        return 1;
 err_out:
        close(ct->scc.fd);
index 37f727e278c6b61cedede8e6a84e77db3ba4c74b..eb470cf6066b16d78a9154a85124b88e6045ad11 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -11,6 +11,7 @@
 #include "para.h"
 #include "list.h"
 #include "string.h"
+#include "close_on_fork.h"
 
 static struct list_head close_on_fork_list;
 static int initialized;
index 41a58eac0517e15e44c964250578173708289e60..eb15875c36b8affba5a3defdce8f787ad73026ba 100644 (file)
--- a/command.c
+++ b/command.c
@@ -1,15 +1,20 @@
 /*
- * Copyright (C) 1997-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 
 /** \file command.c Client authentication and server commands. */
 
+#include <netinet/in.h>
+#include <sys/socket.h>
 #include <regex.h>
 #include <signal.h>
 #include <sys/types.h>
 #include <osl.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
 
 #include "para.h"
 #include "error.h"
@@ -35,8 +40,8 @@
 #include "signal.h"
 #include "version.h"
 
-struct server_command afs_cmds[] = {DEFINE_AFS_CMD_ARRAY};
-struct server_command server_cmds[] = {DEFINE_SERVER_CMD_ARRAY};
+static struct server_command afs_cmds[] = {DEFINE_AFS_CMD_ARRAY};
+static struct server_command server_cmds[] = {DEFINE_SERVER_CMD_ARRAY};
 
 /** Commands including options must be shorter than this. */
 #define MAX_COMMAND_LEN 32768
@@ -110,7 +115,6 @@ static unsigned get_status(struct misc_meta_data *nmmd, int parser_friendly,
        char mtime[30] = "";
        char *status, *flags; /* vss status info */
        /* nobody updates our version of "now" */
-       char *ut = get_server_uptime_str(NULL);
        long offset = (nmmd->offset + 500) / 1000;
        struct timeval current_time;
        struct tm mtime_tm;
@@ -144,7 +148,6 @@ static unsigned get_status(struct misc_meta_data *nmmd, int parser_friendly,
                (long unsigned)current_time.tv_usec);
        free(flags);
        free(status);
-       free(ut);
        *result = b.buf;
        return b.offset;
 }
@@ -220,8 +223,8 @@ int send_sb(struct stream_cipher_context *scc, void *buf, size_t numbytes,
        int ret;
        struct sb_context *sbc;
        struct iovec iov[2];
-       struct sb_buffer sbb = SBB_INIT(band, buf, numbytes);
        sb_transformation trafo = band < SBD_PROCEED? NULL : sc_trafo;
+       struct sb_buffer sbb = SBB_INIT(band, buf, numbytes);
 
        sbc = sb_new_send(&sbb, dont_free, trafo, scc->send);
        do {
@@ -268,10 +271,7 @@ __printf_3_4 int send_sb_va(struct stream_cipher_context *scc, int band,
  */
 int send_strerror(struct command_context *cc, int err)
 {
-       return cc->use_sideband?
-               send_sb_va(&cc->scc, SBD_ERROR_LOG, "%s\n", para_strerror(err))
-       :
-               sc_send_va_buffer(&cc->scc, "%s\n", para_strerror(err));
+       return send_sb_va(&cc->scc, SBD_ERROR_LOG, "%s\n", para_strerror(err));
 }
 
 /**
@@ -338,23 +338,14 @@ static int com_sender(struct command_context *cc)
                        free(msg);
                        msg = tmp;
                }
-               if (cc->use_sideband)
-                       return send_sb(&cc->scc, msg, ret, SBD_OUTPUT, false);
-               ret = sc_send_buffer(&cc->scc, msg);
-               free(msg);
-               return ret;
+               return send_sb(&cc->scc, msg, ret, SBD_OUTPUT, false);
        }
        ret = check_sender_args(cc->argc, cc->argv, &scd);
        if (ret < 0) {
                if (scd.sender_num < 0)
                        return ret;
                msg = senders[scd.sender_num].help();
-               if (cc->use_sideband)
-                       return send_sb(&cc->scc, msg, strlen(msg), SBD_OUTPUT,
-                               false);
-               ret = sc_send_buffer(&cc->scc, msg);
-               free(msg);
-               return ret;
+               return send_sb(&cc->scc, msg, strlen(msg), SBD_OUTPUT, false);
        }
 
        switch (scd.cmd_num) {
@@ -418,11 +409,7 @@ static int com_si(struct command_context *cc)
        mutex_unlock(mmd_mutex);
        free(ut);
        free(sender_info);
-       if (cc->use_sideband)
-               return send_sb(&cc->scc, msg, ret, SBD_OUTPUT, false);
-       ret = sc_send_bin_buffer(&cc->scc, msg, ret);
-       free(msg);
-       return ret;
+       return send_sb(&cc->scc, msg, ret, SBD_OUTPUT, false);
 }
 
 /* version */
@@ -434,9 +421,7 @@ static int com_version(struct command_context *cc)
        if (cc->argc != 1)
                return -E_COMMAND_SYNTAX;
        len = xasprintf(&msg, "%s", version_text("server"));
-       if (cc->use_sideband)
-               return send_sb(&cc->scc, msg, len, SBD_OUTPUT, false);
-       return sc_send_bin_buffer(&cc->scc, msg, len);
+       return send_sb(&cc->scc, msg, len, SBD_OUTPUT, false);
 }
 
 #define EMPTY_STATUS_ITEMS \
@@ -536,24 +521,13 @@ static int com_stat(struct command_context *cc)
        for (;;) {
                mmd_dup(nmmd);
                ret = get_status(nmmd, parser_friendly, &s);
-               if (cc->use_sideband)
-                       ret = send_sb(&cc->scc, s, ret, SBD_OUTPUT, false);
-               else {
-                       ret = sc_send_bin_buffer(&cc->scc, s, ret);
-                       free(s);
-               }
+               ret = send_sb(&cc->scc, s, ret, SBD_OUTPUT, false);
                if (ret < 0)
                        goto out;
                if (nmmd->vss_status_flags & VSS_NEXT) {
                        char *esi;
                        ret = empty_status_items(parser_friendly, &esi);
-                       if (cc->use_sideband)
-                               ret = send_sb(&cc->scc, esi, ret, SBD_OUTPUT,
-                                       false);
-                       else {
-                               ret = sc_send_bin_buffer(&cc->scc, esi, ret);
-                               free(esi);
-                       }
+                       ret = send_sb(&cc->scc, esi, ret, SBD_OUTPUT, false);
                        if (ret < 0)
                                goto out;
                } else
@@ -573,7 +547,6 @@ out:
 static int send_list_of_commands(struct command_context *cc, struct server_command *cmd,
                const char *handler)
 {
-       int ret;
        char *msg = NULL;
 
        for (; cmd->name; cmd++) {
@@ -584,11 +557,8 @@ static int send_list_of_commands(struct command_context *cc, struct server_comma
                msg = para_strcat(msg, tmp);
                free(tmp);
        }
-       if (cc->use_sideband)
-               return send_sb(&cc->scc, msg, strlen(msg), SBD_OUTPUT, false);
-       ret = sc_send_buffer(&cc->scc, msg);
-       free(msg);
-       return ret;
+       assert(msg);
+       return send_sb(&cc->scc, msg, strlen(msg), SBD_OUTPUT, false);
 }
 
 /* returns string that must be freed by the caller */
@@ -644,11 +614,7 @@ static int com_help(struct command_context *cc)
        );
        free(perms);
        free(handler);
-       if (cc->use_sideband)
-               return send_sb(&cc->scc, buf, ret, SBD_OUTPUT, false);
-       ret = sc_send_buffer(&cc->scc, buf);
-       free(buf);
-       return ret;
+       return send_sb(&cc->scc, buf, ret, SBD_OUTPUT, false);
 }
 
 /* hup */
@@ -810,58 +776,6 @@ static int check_perms(unsigned int perms, struct server_command *cmd_ptr)
        return (cmd_ptr->perms & perms) < cmd_ptr->perms ? -E_PERM : 0;
 }
 
-/*
- * Parse first string from *cmd and lookup in table of valid commands.
- * On error, NULL is returned.
- */
-static struct server_command *parse_cmd(const char *cmdstr)
-{
-       char buf[255];
-       int n = 0;
-
-       sscanf(cmdstr, "%200s%n", buf, &n);
-       if (!n)
-               return NULL;
-       buf[n] = '\0';
-       return get_cmd_ptr(buf, NULL);
-}
-
-static int read_command(struct stream_cipher_context *scc, char **result)
-{
-       int ret;
-       char buf[4096];
-       char *command = NULL;
-
-       for (;;) {
-               size_t numbytes;
-               char *p;
-
-               ret = sc_recv_buffer(scc, buf, sizeof(buf));
-               if (ret < 0)
-                       goto out;
-               if (!ret)
-                       break;
-               numbytes = ret;
-               ret = -E_COMMAND_SYNTAX;
-               if (command && numbytes + strlen(command) > MAX_COMMAND_LEN) /* DOS */
-                       goto out;
-               command = para_strcat(command, buf);
-               p = strstr(command, EOC_MSG);
-               if (p) {
-                       *p = '\0';
-                       break;
-               }
-       }
-       ret = command? 1 : -E_COMMAND_SYNTAX;
-out:
-       if (ret < 0)
-               free(command);
-       else
-               *result = command;
-       return ret;
-
-}
-
 static void reset_signals(void)
 {
        para_sigaction(SIGCHLD, SIG_IGN);
@@ -870,15 +784,20 @@ static void reset_signals(void)
        para_sigaction(SIGHUP, SIG_DFL);
 }
 
+struct connection_features {
+       bool sideband_requested;
+       bool aes_ctr128_requested;
+};
+
 static int parse_auth_request(char *buf, int len, struct user **u,
-               bool *use_sideband)
+               struct connection_features *cf)
 {
        int ret;
        char *p, *username, **features = NULL;
        size_t auth_rq_len = strlen(AUTH_REQUEST_MSG);
 
        *u = NULL;
-       *use_sideband = false;
+       memset(cf, 0, sizeof(*cf));
        if (len < auth_rq_len + 2)
                return -E_AUTH_REQUEST;
        if (strncmp(buf, AUTH_REQUEST_MSG, auth_rq_len) != 0)
@@ -894,15 +813,16 @@ static int parse_auth_request(char *buf, int len, struct user **u,
                create_argv(p, ",", &features);
                for (i = 0; features[i]; i++) {
                        if (strcmp(features[i], "sideband") == 0)
-                               *use_sideband = true;
+                               cf->sideband_requested = true;
+                       else if (strcmp(features[i], "aes_ctr128") == 0)
+                               cf->aes_ctr128_requested = true;
                        else {
                                ret = -E_BAD_FEATURE;
                                goto out;
                        }
                }
        }
-       PARA_DEBUG_LOG("received auth request for user %s (sideband = %s)\n",
-               username, *use_sideband? "true" : "false");
+       PARA_DEBUG_LOG("received auth request for user %s\n", username);
        *u = lookup_user(username);
        ret = 1;
 out:
@@ -929,7 +849,7 @@ static int parse_sb_command(struct command_context *cc, struct iovec *iov)
        if (ret < 0)
                goto out;
        end = iov->iov_base + iov->iov_len;
-       for (i = 0, p = iov->iov_base; p < end; i++)
+       for (i = 0; p < end; i++)
                p += strlen(p) + 1;
        cc->argc = i;
        cc->argv = para_malloc((cc->argc + 1) * sizeof(char *));
@@ -976,9 +896,11 @@ __noreturn void handle_connect(int fd, const char *peername)
        int ret;
        unsigned char rand_buf[CHALLENGE_SIZE + 2 * SESSION_KEY_LEN];
        unsigned char challenge_hash[HASH_SIZE];
-       char *p, *command = NULL, *buf = para_malloc(HANDSHAKE_BUFSIZE) /* must be on the heap */;
+       char *command = NULL, *buf = para_malloc(HANDSHAKE_BUFSIZE) /* must be on the heap */;
        size_t numbytes;
        struct command_context cc_struct = {.peer = peername}, *cc = &cc_struct;
+       struct iovec iov;
+       struct connection_features cf;
 
        cc->scc.fd = fd;
        reset_signals();
@@ -989,7 +911,7 @@ __noreturn void handle_connect(int fd, const char *peername)
        /* send Welcome message */
        ret = write_va_buffer(fd, "This is para_server, version "
                PACKAGE_VERSION  ".\n"
-               "Features: sideband\n"
+               "Features: sideband,aes_ctr128\n"
        );
        if (ret < 0)
                goto net_err;
@@ -997,12 +919,14 @@ __noreturn void handle_connect(int fd, const char *peername)
        ret = recv_buffer(fd, buf, HANDSHAKE_BUFSIZE);
        if (ret < 0)
                goto net_err;
-       ret = parse_auth_request(buf, ret, &cc->u, &cc->use_sideband);
+       ret = parse_auth_request(buf, ret, &cc->u, &cf);
        if (ret < 0)
                goto net_err;
-       p = buf + strlen(AUTH_REQUEST_MSG);
-       PARA_DEBUG_LOG("received auth request for user %s\n", p);
-       cc->u = lookup_user(p);
+       if (!cf.sideband_requested) { /* sideband is mandatory */
+               PARA_ERROR_LOG("client did not request sideband\n");
+               ret = -E_BAD_FEATURE;
+               goto net_err;
+       }
        if (cc->u) {
                get_random_bytes_or_die(rand_buf, sizeof(rand_buf));
                ret = pub_encrypt(cc->u->pubkey, rand_buf, sizeof(rand_buf),
@@ -1019,30 +943,18 @@ __noreturn void handle_connect(int fd, const char *peername)
                numbytes = 256;
                get_random_bytes_or_die((unsigned char *)buf, numbytes);
        }
-       PARA_DEBUG_LOG("sending %u byte challenge + rc4 keys (%zu bytes)\n",
+       PARA_DEBUG_LOG("sending %u byte challenge + session key (%zu bytes)\n",
                CHALLENGE_SIZE, numbytes);
-       if (cc->use_sideband) {
-               struct iovec iov;
-               ret = send_sb(&cc->scc, buf, numbytes, SBD_CHALLENGE, false);
-               buf = NULL;
-               if (ret < 0)
-                       goto net_err;
-               ret = recv_sb(&cc->scc, SBD_CHALLENGE_RESPONSE,
-                       HANDSHAKE_BUFSIZE, &iov);
-               if (ret < 0)
-                       goto net_err;
-               buf = iov.iov_base;
-               numbytes = iov.iov_len;
-       } else {
-               ret = write_all(fd, buf, numbytes);
-               if (ret < 0)
-                       goto net_err;
-               /* recv challenge response */
-               ret = recv_bin_buffer(fd, buf, HASH_SIZE);
-               if (ret < 0)
-                       goto net_err;
-               numbytes = ret;
-       }
+       ret = send_sb(&cc->scc, buf, numbytes, SBD_CHALLENGE, false);
+       buf = NULL;
+       if (ret < 0)
+               goto net_err;
+       ret = recv_sb(&cc->scc, SBD_CHALLENGE_RESPONSE,
+               HANDSHAKE_BUFSIZE, &iov);
+       if (ret < 0)
+               goto net_err;
+       buf = iov.iov_base;
+       numbytes = iov.iov_len;
        PARA_DEBUG_LOG("received %zu bytes challenge response\n", numbytes);
        ret = -E_BAD_USER;
        if (!cc->u)
@@ -1061,43 +973,20 @@ __noreturn void handle_connect(int fd, const char *peername)
        alarm(0);
        PARA_INFO_LOG("good auth for %s\n", cc->u->name);
        /* init stream cipher keys with the second part of the random buffer */
-       cc->scc.recv = sc_new(rand_buf + CHALLENGE_SIZE, SESSION_KEY_LEN);
-       cc->scc.send = sc_new(rand_buf + CHALLENGE_SIZE + SESSION_KEY_LEN, SESSION_KEY_LEN);
-       if (cc->use_sideband)
-               ret = send_sb(&cc->scc, NULL, 0, SBD_PROCEED, false);
-       else
-               ret = sc_send_buffer(&cc->scc, PROCEED_MSG);
+       cc->scc.recv = sc_new(rand_buf + CHALLENGE_SIZE, SESSION_KEY_LEN,
+               cf.aes_ctr128_requested);
+       cc->scc.send = sc_new(rand_buf + CHALLENGE_SIZE + SESSION_KEY_LEN,
+               SESSION_KEY_LEN, cf.aes_ctr128_requested);
+       ret = send_sb(&cc->scc, NULL, 0, SBD_PROCEED, false);
        if (ret < 0)
                goto net_err;
-       if (cc->use_sideband) {
-               struct iovec iov;
-               ret = recv_sb(&cc->scc, SBD_COMMAND, MAX_COMMAND_LEN, &iov);
-               if (ret < 0)
-                       goto net_err;
-               ret = parse_sb_command(cc, &iov);
-               if (ret < 0)
-                       goto err_out;
-               cc->argc = ret;
-       } else {
-               ret = read_command(&cc->scc, &command);
-               if (ret == -E_COMMAND_SYNTAX)
-                       goto err_out;
-               if (ret < 0)
-                       goto net_err;
-               ret = -E_BAD_CMD;
-               cc->cmd = parse_cmd(command);
-               if (!cc->cmd)
-                       goto err_out;
-               /* valid command, check permissions */
-               ret = check_perms(cc->u->perms, cc->cmd);
-               if (ret < 0)
-                       goto err_out;
-               /* valid command and sufficient perms */
-               ret = create_argv(command, "\n", &cc->argv);
-               if (ret < 0)
-                       goto err_out;
-               cc->argc = ret;
-       }
+       ret = recv_sb(&cc->scc, SBD_COMMAND, MAX_COMMAND_LEN, &iov);
+       if (ret < 0)
+               goto net_err;
+       ret = parse_sb_command(cc, &iov);
+       if (ret < 0)
+               goto err_out;
+       cc->argc = ret;
        PARA_NOTICE_LOG("calling com_%s() for %s@%s\n", cc->cmd->name,
                cc->u->name, peername);
        ret = cc->cmd->handler(cc);
@@ -1108,7 +997,7 @@ __noreturn void handle_connect(int fd, const char *peername)
        if (ret >= 0)
                goto out;
 err_out:
-       if (send_strerror(cc, -ret) >= 0 && cc->use_sideband)
+       if (send_strerror(cc, -ret) >= 0)
                send_sb(&cc->scc, NULL, 0, SBD_EXIT__FAILURE, true);
 net_err:
        PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
@@ -1120,7 +1009,7 @@ out:
                mmd->events++;
        mmd->active_connections--;
        mutex_unlock(mmd_mutex);
-       if (ret >= 0 && cc->use_sideband) {
+       if (ret >= 0) {
                ret = send_sb(&cc->scc, NULL, 0, SBD_EXIT__SUCCESS, true);
                if (ret < 0)
                        PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
index e4159e6bda00131bf4a1ef6b5a46627c9f7d88b1..6d2202071c6b849fe37a9a69c30c21d09ff80ef0 100644 (file)
--- a/command.h
+++ b/command.h
@@ -14,8 +14,6 @@ struct command_context {
        struct server_command *cmd;
        /** File descriptor and crypto keys. */
        struct stream_cipher_context scc;
-       /** Whether to use the sideband API for this command. */
-       bool use_sideband;
 };
 
 /**
diff --git a/command_util.bash b/command_util.bash
new file mode 100755 (executable)
index 0000000..e33e076
--- /dev/null
@@ -0,0 +1,305 @@
+#!/usr/bin/env bash
+
+read_header()
+{
+       local key value i
+
+       while read key value; do
+               case "$key" in
+               ---)
+                       break
+                       ;;
+               BN:)
+                       base_name="$value"
+                       ;;
+               SF:)
+                       source_files="$value"
+                       ;;
+               SN:)
+                       section_name="$value"
+                       ;;
+               TM:)
+                       template_members="$value"
+               esac
+       done
+}
+
+read_one_command()
+{
+       local line
+
+       name_txt=""
+       desc_txt=""
+       usage_txt=""
+       help_txt=""
+       perms_txt=""
+       template=0
+       template_name=""
+       template_prototype=""
+       while read key value; do
+               case "$key" in
+               ---)
+                       break
+                       ;;
+               N:)
+                       name_txt="$value"
+                       ;;
+               T:)
+                       template_name="$value"
+                       template=1
+                       ;;
+               O:)
+                       template_prototype="$value"
+                       template=1
+                       ;;
+               P:)
+                       perms_txt="$value"
+                       ;;
+               D:)
+                       desc_txt="$value"
+                       ;;
+               U:)
+                       usage_txt="$value"
+                       ;;
+               H:)
+                       help_txt="${value}"
+                       while read line; do
+                               if test "$line" = "---"; then
+                                       break;
+                               fi
+                               line=${line#H:}
+                               help_txt="$help_txt
+${line# }"
+                       done
+                       break
+                       ;;
+               esac
+       done
+       if test $template -eq 0; then
+               if test -n "$name_txt" -a -n "$desc_txt" -a -n "$usage_txt" \
+                               -a -n "$help_txt"; then
+                       ret=1
+                       return
+               fi
+       else
+               if test -n "$template_name" -a -n "$template_prototype" \
+                               -a -n "$name_txt " -a -n "$template_members" \
+                               -a -n "$desc_txt" -a -n "$usage_txt" \
+                               -a -n "$help_txt"; then
+                       ret=1
+                       return
+               fi
+       fi
+       if test -z "$name_txt" -a -z "$desc_txt" -a -z "$usage_txt" \
+                       -a -z "$help_txt"; then
+               ret=0
+               return
+       fi
+       ret=-1
+       #return
+       echo "!ERROR!"
+       echo "N: $name_txt"
+       echo "D: $desc_txt"
+       echo "S: $usage_txt"
+       echo "P: $perms_txt"
+       echo "H: $help_txt"
+       echo "O: $template_prototype"
+}
+
+dump_man()
+{
+       if test $template -eq 0; then
+               echo ".SS \"$name_txt\""
+               echo "$desc_txt"
+               echo
+               echo "\\fBUsage: \\fP$usage_txt"
+       else
+               for member in $template_members; do
+                       local sed_cmd="sed -e s/@member@/$member/g"
+                       local t_name_txt=$(echo $name_txt | $sed_cmd)
+                       echo ".SS \"$t_name_txt\""
+               done
+               echo "$desc_txt" | sed -e "s/@member@/{$(echo $template_members | sed -e 's/ / | /g')}/g"
+               echo
+               echo "\\fBUsage: \\fP"
+               echo
+               echo ".nf"
+               for member in $template_members; do
+                       local sed_cmd="sed -e s/@member@/$member/g"
+                       local t_usage_txt=$(echo $usage_txt | $sed_cmd)
+                       printf "\t$t_usage_txt\n"
+               done
+               echo ".fi"
+       fi
+       echo
+       echo "$help_txt" | sed -e 's/^  //'
+       echo
+       if test -n "$perms_txt"; then
+               echo -n "\\fBpermissions:\\fP "
+               if test "$perms_txt" = "0"; then
+                       echo "(none)"
+               else
+                       echo "$perms_txt"
+               fi
+       fi
+       echo
+}
+
+
+com_man()
+{
+       echo "[$section_name]"
+       echo
+       while : ; do
+               read_one_command
+               if test $ret -lt 0; then
+                       exit 1
+               fi
+               if test $ret -eq 0; then
+                       break
+               fi
+               dump_man
+       done
+}
+
+make_proto()
+{
+       local regex='\(__noreturn \)*\(static \)*int com_'
+       local source_file match="" all_commands CR='
+'
+       if test -n "$prototype"; then
+               result="$prototype$CR"
+               return
+       fi
+       all_commands="$(cat $source_files | grep "$regex")"
+       result=
+       for source_file in $source_files; do
+               match=$(grep "$regex$name_txt(" <<< "$all_commands" | head -n 1 | sed -e 's/$/;/1')
+               if test -n "$match"; then
+                       result="$result$match$CR"
+                       break
+               fi
+       done
+}
+
+make_array_member()
+{
+       local TAB='     ' CR='
+'
+       local tmp
+
+       result="{.name = \"$name_txt\", .handler = com_$name_txt, "
+       if test -n "$perms_txt"; then
+               result="$result .perms = $perms_txt,"
+       fi
+       result="$result.description = \"$desc_txt\", .usage = \"$usage_txt\", \\$CR .help = "
+       tmp="$(printf "%s\n" "$help_txt" | sed -e 's/^/\"/g' -e 's/$/\\n\"/g' \
+               -e "s/$TAB/\\\t/g" -e's/$/\\/g')"
+       result="$result$tmp$CR}, \\$CR"
+}
+
+make_completion()
+{
+       local CR='
+'
+       result="  {.name = \"$name_txt\", .completer = ${name_txt}_completer}, \\$CR"
+}
+
+template_loop()
+{
+       local loop_result=
+
+       local t_name="$name_txt"
+       local t_perms="$perms_txt"
+       local t_desc="$desc_txt"
+       local t_usage="$usage_txt"
+       local t_help="$help_txt"
+       local t_source_files="$source_files"
+       local member
+       for member in $template_members; do
+               name_txt="${t_name//@member@/$member}"
+               perms_txt="${t_perms//@member@/$member}"
+               desc_txt="${t_desc//@member@/$member}"
+               usage_txt="${t_usage//@member@/$member}"
+               help_txt="${t_help//@member@/$member}"
+               prototype="${template_prototype//@member@/$member}"
+               result=
+               $1
+               loop_result="$loop_result$result"
+       done
+       result="$loop_result"
+       # reset global variables
+       name_txt="$t_name"
+       perms_txt="$t_perms"
+       desc_txt="$t_desc"
+       usage_txt="$t_usage"
+       help_txt="$t_help"
+       source_files="$t_source_files"
+}
+
+com_header()
+{
+       local array_members CR='
+'
+
+       while : ; do
+               read_one_command
+               if test $ret -lt 0; then
+                       exit 1
+               fi
+               if test $ret -eq 0; then
+                       break
+               fi
+               if test $template -eq 0; then
+                       make_proto
+                       printf "%s" "$result"
+                       make_array_member
+                       array_members="$array_members$result"
+                       continue
+               fi
+               template_loop make_proto
+               printf "%s" "$result"
+               template_loop make_array_member
+               array_members="$array_members$result"
+       done
+       array_members="$array_members{.name = NULL} \\$CR"
+       echo "#define DEFINE_$(tr 'a-z' 'A-Z' <<< "$base_name")_CMD_ARRAY $array_members"
+}
+
+com_completion()
+{
+
+       echo "#define $1 \\"
+       while : ; do
+               read_one_command
+               if test $ret -lt 0; then
+                       exit 1
+               fi
+               if test $ret -eq 0; then
+                       break
+               fi
+               if test $template -eq 0; then
+                       make_completion
+                       printf "%s" "$result"
+                       continue
+               fi
+               template_loop make_completion
+               printf "%s" "$result"
+       done
+       echo
+}
+
+read_header
+arg="$1"
+shift
+case "$arg" in
+       "h")
+               com_header
+               ;;
+       "man")
+               com_man $*
+               ;;
+       "compl")
+               com_completion $*
+               ;;
+esac
diff --git a/command_util.sh b/command_util.sh
deleted file mode 100755 (executable)
index e33e076..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-#!/usr/bin/env bash
-
-read_header()
-{
-       local key value i
-
-       while read key value; do
-               case "$key" in
-               ---)
-                       break
-                       ;;
-               BN:)
-                       base_name="$value"
-                       ;;
-               SF:)
-                       source_files="$value"
-                       ;;
-               SN:)
-                       section_name="$value"
-                       ;;
-               TM:)
-                       template_members="$value"
-               esac
-       done
-}
-
-read_one_command()
-{
-       local line
-
-       name_txt=""
-       desc_txt=""
-       usage_txt=""
-       help_txt=""
-       perms_txt=""
-       template=0
-       template_name=""
-       template_prototype=""
-       while read key value; do
-               case "$key" in
-               ---)
-                       break
-                       ;;
-               N:)
-                       name_txt="$value"
-                       ;;
-               T:)
-                       template_name="$value"
-                       template=1
-                       ;;
-               O:)
-                       template_prototype="$value"
-                       template=1
-                       ;;
-               P:)
-                       perms_txt="$value"
-                       ;;
-               D:)
-                       desc_txt="$value"
-                       ;;
-               U:)
-                       usage_txt="$value"
-                       ;;
-               H:)
-                       help_txt="${value}"
-                       while read line; do
-                               if test "$line" = "---"; then
-                                       break;
-                               fi
-                               line=${line#H:}
-                               help_txt="$help_txt
-${line# }"
-                       done
-                       break
-                       ;;
-               esac
-       done
-       if test $template -eq 0; then
-               if test -n "$name_txt" -a -n "$desc_txt" -a -n "$usage_txt" \
-                               -a -n "$help_txt"; then
-                       ret=1
-                       return
-               fi
-       else
-               if test -n "$template_name" -a -n "$template_prototype" \
-                               -a -n "$name_txt " -a -n "$template_members" \
-                               -a -n "$desc_txt" -a -n "$usage_txt" \
-                               -a -n "$help_txt"; then
-                       ret=1
-                       return
-               fi
-       fi
-       if test -z "$name_txt" -a -z "$desc_txt" -a -z "$usage_txt" \
-                       -a -z "$help_txt"; then
-               ret=0
-               return
-       fi
-       ret=-1
-       #return
-       echo "!ERROR!"
-       echo "N: $name_txt"
-       echo "D: $desc_txt"
-       echo "S: $usage_txt"
-       echo "P: $perms_txt"
-       echo "H: $help_txt"
-       echo "O: $template_prototype"
-}
-
-dump_man()
-{
-       if test $template -eq 0; then
-               echo ".SS \"$name_txt\""
-               echo "$desc_txt"
-               echo
-               echo "\\fBUsage: \\fP$usage_txt"
-       else
-               for member in $template_members; do
-                       local sed_cmd="sed -e s/@member@/$member/g"
-                       local t_name_txt=$(echo $name_txt | $sed_cmd)
-                       echo ".SS \"$t_name_txt\""
-               done
-               echo "$desc_txt" | sed -e "s/@member@/{$(echo $template_members | sed -e 's/ / | /g')}/g"
-               echo
-               echo "\\fBUsage: \\fP"
-               echo
-               echo ".nf"
-               for member in $template_members; do
-                       local sed_cmd="sed -e s/@member@/$member/g"
-                       local t_usage_txt=$(echo $usage_txt | $sed_cmd)
-                       printf "\t$t_usage_txt\n"
-               done
-               echo ".fi"
-       fi
-       echo
-       echo "$help_txt" | sed -e 's/^  //'
-       echo
-       if test -n "$perms_txt"; then
-               echo -n "\\fBpermissions:\\fP "
-               if test "$perms_txt" = "0"; then
-                       echo "(none)"
-               else
-                       echo "$perms_txt"
-               fi
-       fi
-       echo
-}
-
-
-com_man()
-{
-       echo "[$section_name]"
-       echo
-       while : ; do
-               read_one_command
-               if test $ret -lt 0; then
-                       exit 1
-               fi
-               if test $ret -eq 0; then
-                       break
-               fi
-               dump_man
-       done
-}
-
-make_proto()
-{
-       local regex='\(__noreturn \)*\(static \)*int com_'
-       local source_file match="" all_commands CR='
-'
-       if test -n "$prototype"; then
-               result="$prototype$CR"
-               return
-       fi
-       all_commands="$(cat $source_files | grep "$regex")"
-       result=
-       for source_file in $source_files; do
-               match=$(grep "$regex$name_txt(" <<< "$all_commands" | head -n 1 | sed -e 's/$/;/1')
-               if test -n "$match"; then
-                       result="$result$match$CR"
-                       break
-               fi
-       done
-}
-
-make_array_member()
-{
-       local TAB='     ' CR='
-'
-       local tmp
-
-       result="{.name = \"$name_txt\", .handler = com_$name_txt, "
-       if test -n "$perms_txt"; then
-               result="$result .perms = $perms_txt,"
-       fi
-       result="$result.description = \"$desc_txt\", .usage = \"$usage_txt\", \\$CR .help = "
-       tmp="$(printf "%s\n" "$help_txt" | sed -e 's/^/\"/g' -e 's/$/\\n\"/g' \
-               -e "s/$TAB/\\\t/g" -e's/$/\\/g')"
-       result="$result$tmp$CR}, \\$CR"
-}
-
-make_completion()
-{
-       local CR='
-'
-       result="  {.name = \"$name_txt\", .completer = ${name_txt}_completer}, \\$CR"
-}
-
-template_loop()
-{
-       local loop_result=
-
-       local t_name="$name_txt"
-       local t_perms="$perms_txt"
-       local t_desc="$desc_txt"
-       local t_usage="$usage_txt"
-       local t_help="$help_txt"
-       local t_source_files="$source_files"
-       local member
-       for member in $template_members; do
-               name_txt="${t_name//@member@/$member}"
-               perms_txt="${t_perms//@member@/$member}"
-               desc_txt="${t_desc//@member@/$member}"
-               usage_txt="${t_usage//@member@/$member}"
-               help_txt="${t_help//@member@/$member}"
-               prototype="${template_prototype//@member@/$member}"
-               result=
-               $1
-               loop_result="$loop_result$result"
-       done
-       result="$loop_result"
-       # reset global variables
-       name_txt="$t_name"
-       perms_txt="$t_perms"
-       desc_txt="$t_desc"
-       usage_txt="$t_usage"
-       help_txt="$t_help"
-       source_files="$t_source_files"
-}
-
-com_header()
-{
-       local array_members CR='
-'
-
-       while : ; do
-               read_one_command
-               if test $ret -lt 0; then
-                       exit 1
-               fi
-               if test $ret -eq 0; then
-                       break
-               fi
-               if test $template -eq 0; then
-                       make_proto
-                       printf "%s" "$result"
-                       make_array_member
-                       array_members="$array_members$result"
-                       continue
-               fi
-               template_loop make_proto
-               printf "%s" "$result"
-               template_loop make_array_member
-               array_members="$array_members$result"
-       done
-       array_members="$array_members{.name = NULL} \\$CR"
-       echo "#define DEFINE_$(tr 'a-z' 'A-Z' <<< "$base_name")_CMD_ARRAY $array_members"
-}
-
-com_completion()
-{
-
-       echo "#define $1 \\"
-       while : ; do
-               read_one_command
-               if test $ret -lt 0; then
-                       exit 1
-               fi
-               if test $ret -eq 0; then
-                       break
-               fi
-               if test $template -eq 0; then
-                       make_completion
-                       printf "%s" "$result"
-                       continue
-               fi
-               template_loop make_completion
-               printf "%s" "$result"
-       done
-       echo
-}
-
-read_header
-arg="$1"
-shift
-case "$arg" in
-       "h")
-               com_header
-               ;;
-       "man")
-               com_man $*
-               ;;
-       "compl")
-               com_completion $*
-               ;;
-esac
index 0c0200e7e3b522af5aad7bb0a9f86f7e32024218..119e01693a9accf7fcc788d3433c8edce4979a5e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -41,9 +41,9 @@ static void compress_close(struct filter_node *fn)
        free(fn->private_data);
 }
 
-static int compress_post_select(__a_unused struct sched *s, struct task *t)
+static int compress_post_select(__a_unused struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        struct private_compress_data *pcd = fn->private_data;
        struct btr_node *btrn = fn->btrn;
        bool inplace = btr_inplace_ok(btrn);
index 1d1d6e3c079a16fc73c20685929cd8799f4a8c45..639da81fbc05c51aa3f6d56bbe53a165e64cb9b1 100644 (file)
@@ -3,14 +3,27 @@
 
 AC_PREREQ([2.61])
 
-
 AC_INIT([paraslash],[git],[maan@systemlinux.org])
 AC_CONFIG_HEADER([config.h])
 
 AC_CONFIG_FILES([Makefile])
 AC_DEFUN([add_dot_o],[$(for i in $@; do printf "$i.o "; done)])
-AC_DEFUN([add_para],[$(for i in $@; do printf "para_$i "; done)])
-AC_DEFUN([objlist_to_errlist],[$(for i in $@; do printf "DEFINE_ERRLIST($(echo $i| tr 'a-z' 'A-Z'));"; done) [const char **para_errlist[[]]] = {$(for i in $@; do printf "PARA_ERRLIST($(echo $i | tr 'a-z' 'A-Z')), "; done) }])
+AC_DEFUN([add_cmdline],[$(for i in $@; do printf "${i}.cmdline "; done)])
+AC_DEFUN([make_errlist_defines], \
+       $(for i in $@; do \
+               printf "DEFINE_ERRLIST($(echo $i | tr 'a-z' 'A-Z'));"; \
+       done) \
+)
+AC_DEFUN([make_para_errlists], \
+       $(for i in $@; do \
+               printf "PARA_ERRLIST($(echo $i | tr 'a-z' 'A-Z')), "; \
+       done) \
+)
+AC_DEFUN([objlist_to_errlist],[ \
+       make_errlist_defines($@) \
+       [const char **para_errlist[[]]] = {make_para_errlists($@)} \
+])
+
 AC_PATH_PROG(UNAMEPATH, uname, no)
 if test "$UNAMEPATH" = "no"; then
        AC_MSG_ERROR(unable to determine system type)
@@ -35,11 +48,12 @@ AC_PATH_PROG([help2man], [help2man])
 test -z "$help2man" && AC_MSG_ERROR(
        [help2man is required to build this package])
 
+AC_PATH_PROG([install], [install])
+test -z "$install" && AC_MSG_ERROR(
+       [The install program is required to build this package])
+
 AC_PROG_CC
 AC_PROG_CPP
-AC_PROG_INSTALL
-AC_SUBST(install_sh, [$INSTALL])
-AC_REPLACE_FNMATCH
 
 AC_HEADER_DIRENT
 AC_HEADER_STDC
@@ -73,11 +87,9 @@ AC_TYPE_UINT64_T
 # Checks for library functions.
 AC_FUNC_FORK
 AC_PROG_GCC_TRADITIONAL
-AC_FUNC_MALLOC
 AC_FUNC_MEMCMP
 AC_FUNC_MKTIME
 AC_FUNC_MMAP
-AC_FUNC_REALLOC
 AC_FUNC_SELECT_ARGTYPES
 AC_FUNC_STAT
 AC_FUNC_STRFTIME
@@ -91,197 +103,7 @@ AC_CHECK_FUNCS([atexit dup2 memchr memmove memset \
        strncasecmp strrchr strspn alarm mkdir inet_ntoa socket], [],
        [AC_MSG_ERROR([function not found, cannot live without it])])
 
-AC_DEFUN([add_cmdline],[$(for i in $@; do printf "${i}.cmdline "; done)])
-
-
-all_errlist_objs="mp3_afh afh_common net string signal time daemon
-       stat afh amp_filter fd ringbuffer 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
-       exec send_common ggo udp_recv color fec fecdec_filter
-       prebuffer_filter bitstream imdct check_wav
-       wma_afh wma_common wmadec_filter buffer_tree crypt_common
-       gui gui_theme sideband afh_recv play version"
-
-executables="recv filter audioc write client afh audiod play"
-
-recv_cmdline_objs="add_cmdline(recv http_recv dccp_recv udp_recv afh_recv)"
-
-recv_errlist_objs="
-       http_recv recv_common recv time string net dccp_recv fd
-       sched stdout ggo udp_recv buffer_tree afh_recv afh_common
-       wma_afh wma_common mp3_afh version
-"
-
-recv_ldflags=""
-
-filter_cmdline_objs="add_cmdline(filter compress_filter amp_filter prebuffer_filter)"
-filter_errlist_objs="filter_common wav_filter compress_filter filter string
-       stdin stdout sched fd amp_filter ggo fecdec_filter fec version
-       prebuffer_filter time bitstream imdct wma_common wmadec_filter buffer_tree"
-filter_ldflags="-lm"
-filters=" compress wav amp fecdec wmadec prebuffer"
-
-audioc_cmdline_objs="add_cmdline(audioc)"
-audioc_errlist_objs="
-       audioc
-       string
-       net
-       fd
-       version
-       ggo
-"
-audioc_ldflags=""
-
-audiod_cmdline_objs="add_cmdline(audiod compress_filter http_recv dccp_recv file_write client amp_filter udp_recv prebuffer_filter)"
-audiod_errlist_objs="audiod signal string daemon stat net crypt_common sideband
-       time grab_client filter_common wav_filter compress_filter amp_filter http_recv dccp_recv
-       recv_common fd sched write_common file_write audiod_command fecdec_filter
-       client_common ggo udp_recv color fec prebuffer_filter version
-       bitstream imdct wma_common wmadec_filter buffer_tree"
-audiod_ldflags="-lm"
-audiod_audio_formats="wma"
-
-afh_cmdline_objs="add_cmdline(afh)"
-afh_errlist_objs="afh string fd mp3_afh afh_common time wma_afh wma_common
-       version ggo"
-afh_ldflags=""
-
-write_cmdline_objs="add_cmdline(write file_write)"
-write_errlist_objs="write write_common file_write time fd string sched stdin
-       buffer_tree ggo check_wav version"
-write_ldflags=""
-writers=" file"
-default_writer="FILE_WRITE"
-
-client_cmdline_objs="add_cmdline(client)"
-client_errlist_objs="
-       client
-       net
-       string
-       fd
-       sched
-       stdin
-       stdout
-       time
-       sideband
-       client_common
-       buffer_tree
-       crypt_common
-       version
-       ggo
-"
-client_ldflags=""
-
-gui_cmdline_objs="add_cmdline(gui)"
-gui_errlist_objs="
-       exec
-       signal
-       string
-       stat
-       ringbuffer
-       fd
-       gui
-       gui_theme
-       time
-       version
-       ggo
-"
-gui_objs="$gui_cmdline_objs $gui_errlist_objs"
-play_errlist_objs="play fd sched ggo buffer_tree time string net
-       afh_recv afh_common
-       wma_afh wma_common mp3_afh
-       recv_common udp_recv http_recv dccp_recv
-       filter_common fec bitstream imdct
-       wav_filter compress_filter amp_filter prebuffer_filter fecdec_filter
-               wmadec_filter
-       write_common file_write
-       version
-"
-play_cmdline_objs="add_cmdline(http_recv dccp_recv udp_recv afh_recv compress_filter amp_filter prebuffer_filter file_write play)"
-play_ldflags="-lm"
-########################################################################### snprintf
-# ===========================================================================
-#        http://www.nongnu.org/autoconf-archive/ax_func_snprintf.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-#   AX_FUNC_SNPRINTF
-#
-# DESCRIPTION
-#
-#   Checks for a fully C99 compliant snprintf, in particular checks whether
-#   it does bounds checking and returns the correct string length; does the
-#   same check for vsnprintf. If no working snprintf or vsnprintf is found,
-#   it prints an error message and aborts.
-#
-# LICENSE
-#
-#   Copyright (c) 2008 Ruediger Kuhlmann <info@ruediger-kuhlmann.de>
-#
-#   Copying and distribution of this file, with or without modification, are
-#   permitted in any medium without royalty provided the copyright notice
-#   and this notice are preserved.
-
-AU_ALIAS([AC_FUNC_SNPRINTF], [AX_FUNC_SNPRINTF])
-AC_DEFUN([AX_FUNC_SNPRINTF],
-[AC_CHECK_FUNCS(snprintf vsnprintf)
-AC_MSG_CHECKING(for working snprintf)
-AC_CACHE_VAL(ac_cv_have_working_snprintf,
-[AC_RUN_IFELSE([AC_LANG_SOURCE([[
-#include <stdio.h>
-
-int main(void)
-{
-    char bufs[5] = { 'x', 'x', 'x', '\0', '\0' };
-    char bufd[5] = { 'x', 'x', 'x', '\0', '\0' };
-    int i;
-    i = snprintf (bufs, 2, "%s", "111");
-    if (strcmp (bufs, "1")) exit (1);
-    if (i != 3) exit (1);
-    i = snprintf (bufd, 2, "%d", 111);
-    if (strcmp (bufd, "1")) exit (1);
-    if (i != 3) exit (1);
-    exit(0);
-}]])],[ac_cv_have_working_snprintf=yes],
-[ac_cv_have_working_snprintf=no],[ac_cv_have_working_snprintf=cross])])
-AC_MSG_RESULT([$ac_cv_have_working_snprintf])
-AC_MSG_CHECKING(for working vsnprintf)
-AC_CACHE_VAL(ac_cv_have_working_vsnprintf,
-[AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <stdio.h>
-#include <stdarg.h>
-
-int my_vsnprintf (char *buf, const char *tmpl, ...)
-{
-    int i;
-    va_list args;
-    va_start (args, tmpl);
-    i = vsnprintf (buf, 2, tmpl, args);
-    va_end (args);
-    return i;
-}
-
-int main(void)
-{
-    char bufs[5] = { 'x', 'x', 'x', '\0', '\0' };
-    char bufd[5] = { 'x', 'x', 'x', '\0', '\0' };
-    int i;
-    i = my_vsnprintf (bufs, "%s", "111");
-    if (strcmp (bufs, "1")) exit (1);
-    if (i != 3) exit (1);
-    i = my_vsnprintf (bufd, "%d", 111);
-    if (strcmp (bufd, "1")) exit (1);
-    if (i != 3) exit (1);
-    exit(0);
-}]])],[ac_cv_have_working_vsnprintf=yes],
-[ac_cv_have_working_vsnprintf=no],[ac_cv_have_working_vsnprintf=cross])])
-AC_MSG_RESULT([$ac_cv_have_working_vsnprintf])
-if test x$ac_cv_have_working_snprintf$ac_cv_have_working_vsnprintf != "xyesyes"; then
-AC_MSG_ERROR([fatal: buggy snprintf() detected])
-fi])
-AX_FUNC_SNPRINTF()
+executables="recv filter audioc write afh play"
 ################################################################## clock_gettime
 clock_gettime_lib=
 AC_CHECK_LIB([c], [clock_gettime], [clock_gettime_lib=c], [
@@ -314,63 +136,17 @@ fi
 
 AC_CHECK_HEADER(osl.h, [], have_osl=no)
 AC_CHECK_LIB([osl], [osl_open_table], [], have_osl=no)
-if test "$have_osl" = "no"; then
+if test "$have_osl" = "yes"; then
+       AC_SUBST(osl_cppflags)
+       osl_ldflags="$osl_libs -losl"
+       AC_SUBST(osl_ldflags)
+else
        AC_MSG_WARN([libosl not found, can not build para_server.
 Download libosl at
        http://systemlinux.org/~maan/osl
 or execute
        git clone git://git.tuebingen.mpg.de/osl
        ])
-else
-       extras="$extras server"
-       executables="$executables server"
-       server_cmdline_objs="add_cmdline(server)"
-       server_errlist_objs="
-               server
-               afh_common
-               mp3_afh
-               vss command
-               net
-               string
-               signal
-               time
-               daemon
-               http_send
-               close_on_fork
-               mm
-               crypt_common
-               ipc dccp_send
-               fd
-               user_list
-               chunk_queue
-               afs
-               aft
-               mood
-               score
-               attribute
-               blob
-               playlist
-               sched
-               acl
-               send_common
-               udp_send
-               color
-               fec
-               wma_afh
-               wma_common
-               sideband
-               version
-               ggo
-       "
-       all_errlist_objs="$all_errlist_objs server vss command
-               http_send close_on_fork mm ipc dccp_send user_list
-               chunk_queue afs aft mood score attribute blob playlist
-               acl udp_send"
-
-       server_ldflags=""
-       audio_format_handlers="mp3 wma"
-       AC_SUBST(osl_cppflags)
-       server_ldflags="$server_ldflags $osl_libs -losl"
 fi
 CPPFLAGS="$OLD_CPPFLAGS"
 LDFLAGS="$OLD_LDFLAGS"
@@ -426,15 +202,8 @@ if test "$check_openssl" = "yes"; then
        if test "$have_openssl" = "yes"; then
                AC_DEFINE(HAVE_OPENSSL, 1, [define to 1 to turn on openssl support])
                AC_SUBST(openssl_cppflags)
-               openssl_libs="$openssl_libs -lssl -lcrypto"
-               server_ldflags="$server_ldflags $openssl_libs"
-               client_ldflags="$client_ldflags $openssl_libs"
-               audiod_ldflags="$audiod_ldflags $openssl_libs"
-
-               all_errlist_objs="$all_errlist_objs crypt"
-               server_errlist_objs="$server_errlist_objs crypt"
-               client_errlist_objs="$client_errlist_objs crypt"
-               audiod_errlist_objs="$audiod_errlist_objs crypt"
+               openssl_ldflags="$openssl_libs -lssl -lcrypto"
+               AC_SUBST(openssl_ldflags)
 
                check_gcrypt="no"
        else
@@ -469,15 +238,8 @@ if test "$check_gcrypt" = "yes"; then
        if test "$have_gcrypt" = "yes"; then
                AC_DEFINE(HAVE_GCRYPT, 1, [define to 1 to turn on gcrypt support])
                AC_SUBST(gcrypt_cppflags)
-               gcrypt_libs="$gcrypt_libs -lgcrypt"
-               server_ldflags="$server_ldflags $gcrypt_libs"
-               client_ldflags="$client_ldflags $gcrypt_libs"
-               audiod_ldflags="$audiod_ldflags $gcrypt_libs"
-
-               all_errlist_objs="$all_errlist_objs gcrypt"
-               server_errlist_objs="$server_errlist_objs gcrypt"
-               client_errlist_objs="$client_errlist_objs gcrypt"
-               audiod_errlist_objs="$audiod_errlist_objs gcrypt"
+               gcrypt_ldflags="$gcrypt_libs -lgcrypt"
+               AC_SUBST(gcrypt_ldflags)
        else
                AC_MSG_WARN([gcrypt library not found])
        fi
@@ -487,35 +249,18 @@ if test "$check_gcrypt" = "yes"; then
 else
        have_gcrypt="no"
 fi
-###########################################################################
-if test "$have_openssl" = "no" -a "$have_gcrypt" = "no"; then
-       AC_MSG_ERROR([neither openssl nor gcrypt usable])
-fi
 ########################################################################### libsocket
 AC_CHECK_LIB([c], [socket],
-       [socket_lib=],
-       [socket_lib="-lsocket"]
+       [socket_ldlflags=],
+       [socket_ldflags="-lsocket"]
 )
-server_ldflags="$server_ldflags $socket_lib"
-client_ldflags="$client_ldflags $socket_lib"
-audioc_ldflags="$audioc_ldflags $socket_lib"
-audiod_ldflags="$audiod_ldflags $socket_lib"
-recv_ldflags="$recv_ldflags $socket_lib"
-AC_SEARCH_LIBS([connect],[socket],[],[
-       AC_MSG_ERROR([Fatal: Did not find connect().])
-],[])
+AC_SUBST(socket_ldflags)
 ########################################################################### libnsl
 AC_CHECK_LIB([c], [gethostbyname],
-       [nsl_lib=],
-       [nsl_lib="-lnsl"]
+       [nsl_ldflags=],
+       [nsl_ldflags="-lnsl"]
 )
-server_ldflags="$server_ldflags $nsl_lib"
-client_ldflags="$client_ldflags $nsl_lib"
-audioc_ldflags="$audioc_ldflags $nsl_lib"
-recv_ldflags="$recv_ldflags $nsl_lib"
-AC_SEARCH_LIBS([inet_ntoa],[nsl],[],[
-       AC_MSG_ERROR([Fatal: Did not find inet_ntoa().])
-],[])
+AC_SUBST(nsl_ldflags)
 ########################################################################### ucred
 AC_MSG_CHECKING(for struct ucred)
 AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@@ -558,26 +303,20 @@ fi
 AC_CHECK_HEADER(curses.h, [], [
        have_curses="no"
 ])
-gui_ldflags="$curses_libs"
+curses_ldflags="$curses_libs"
 AC_CHECK_LIB([ncursesw], [initscr],
-       [gui_ldflags="$curses_libs -lncursesw"], [
+       [curses_ldflags="$curses_libs -lncursesw"], [
                AC_CHECK_LIB([curses], [initscr],
-                       [gui_ldflags="$curses_libs -lcurses"],
+                       [curses_ldflags="$curses_libs -lcurses"],
                        [have_curses="no"]
                )
        ]
 )
-if test "$have_curses" = "yes"; then
-       AC_SUBST(curses_cppflags)
-       extras="$extras gui"
-       executables="$executables gui"
-else
-       AC_MSG_WARN([no curses lib, cannot build para_gui])
-fi
+AC_SUBST(curses_cppflags)
+AC_SUBST(curses_ldflags)
 CPPFLAGS="$OLD_CPPFLAGS"
 LDFLAGS="$OLD_LDFLAGS"
 LIBS="$OLD_LIBS"
-
 ########################################################################### ip_mreqn
 AC_MSG_CHECKING(for struct ip_mreqn (UDPv4 multicast))
 AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@@ -605,28 +344,8 @@ if test ${have_core_audio} = yes; then
        f2="-framework AudioToolbox"
        f3="-framework AudioUnit"
        f4="-framework CoreServices"
-       f="$f1 $f2 $f3 $f4"
-
-       all_errlist_objs="$all_errlist_objs osx_write"
-       # ipc is linked into para_server server and into the osx writer. If osl
-       # was not found, para_server will not be built and ipc has not yet been
-       # added to the list of all objects, so we must add it here.
-       if test "$have_osl" = "no"; then
-               all_errlist_objs="$all_errlist_objs ipc"
-       fi
-       audiod_errlist_objs="$audiod_errlist_objs osx_write ipc"
-       audiod_cmdline_objs="$audiod_cmdline_objs osx_write.cmdline"
-       audiod_ldflags="$audiod_ldflags $f"
-
-       play_errlist_objs="$play_errlist_objs osx_write ipc"
-       play_cmdline_objs="$play_cmdline_objs osx_write.cmdline"
-       play_ldflags="$play_ldflags $f"
-
-       write_errlist_objs="$write_errlist_objs osx_write ipc"
-       write_cmdline_objs="$write_cmdline_objs osx_write.cmdline"
-       write_ldflags="$write_ldflags $f"
-       writers="$writers osx"
-       default_writer="OSX_WRITE"
+       core_audio_ldflags="$f1 $f2 $f3 $f4"
+       AC_SUBST(core_audio_ldflags)
        AC_DEFINE(HAVE_CORE_AUDIO, 1, define to 1 on Mac Os X)
 fi
 ####################################################### ogg/vorbis/speex/opus
@@ -713,90 +432,30 @@ if test "$have_vorbis" = "yes" || \
                test "$have_speex" = "yes" || \
                test "$have_opus" = "yes"; then
        AC_SUBST(ogg_cppflags)
-       ogg_libs="$ogg_libs -logg"
+       ogg_ldflags="$ogg_libs -logg"
        if test "$OSTYPE" = "Darwin"; then
-               ogg_libs="-Wl,-bind_at_load $ogg_libs"
+               ogg_ldflags="-Wl,-bind_at_load $ogg_ldflags"
        fi
-       server_ldflags="$server_ldflags $ogg_libs"
-       filter_ldflags="$filter_ldflags $ogg_libs"
-       audiod_ldflags="$audiod_ldflags $ogg_libs"
-       play_ldflags="$play_ldflags $ogg_libs"
-       afh_ldflags="$afh_ldflags $ogg_libs"
-       recv_ldflags="$recv_ldflags $ogg_libs"
-       all_errlist_objs="$all_errlist_objs ogg_afh_common"
-       afh_errlist_objs="$afh_errlist_objs ogg_afh_common"
-       recv_errlist_objs="$recv_errlist_objs ogg_afh_common"
-       server_errlist_objs="$server_errlist_objs ogg_afh_common"
-       play_errlist_objs="$play_errlist_objs ogg_afh_common"
+       AC_SUBST(ogg_ldflags)
 fi
 if test "$have_vorbis" = "yes"; then
-       all_errlist_objs="$all_errlist_objs oggdec_filter ogg_afh"
        AC_DEFINE(HAVE_OGGVORBIS, 1, define to 1 to turn on ogg/vorbis support)
-       filters="$filters oggdec"
-       vorbis_libs="-lvorbis -lvorbisfile"
-       server_ldflags="$server_ldflags $vorbis_libs"
-       filter_ldflags="$filter_ldflags $vorbis_libs"
-       audiod_ldflags="$audiod_ldflags $vorbis_libs"
-       play_ldflags="$play_ldflags $vorbis_libs"
-       afh_ldflags="$afh_ldflags $vorbis_libs"
-       recv_ldflags="$recv_ldflags $vorbis_libs"
-
-       server_errlist_objs="$server_errlist_objs ogg_afh"
-       filter_errlist_objs="$filter_errlist_objs oggdec_filter"
-       audiod_errlist_objs="$audiod_errlist_objs oggdec_filter"
-       play_errlist_objs="$play_errlist_objs oggdec_filter ogg_afh"
-       afh_errlist_objs="$afh_errlist_objs ogg_afh"
-       recv_errlist_objs="$recv_errlist_objs ogg_afh"
-
-       audiod_audio_formats="$audiod_audio_formats ogg"
-       audio_format_handlers="$audio_format_handlers ogg"
-else
-       AC_MSG_WARN([no ogg/vorbis $msg])
+       vorbis_ldflags="$vorbis_libs -lvorbis -lvorbisfile"
+       AC_SUBST(vorbis_ldflags)
 fi
 if test "$have_speex" = "yes"; then
-       all_errlist_objs="$all_errlist_objs spxdec_filter spx_afh spx_common"
        AC_DEFINE(HAVE_SPEEX, 1, define to 1 to turn on ogg/speex support)
-       filters="$filters spxdec"
-       speex_libs="-lspeex"
-       server_ldflags="$server_ldflags $speex_libs"
-       filter_ldflags="$filter_ldflags $speex_libs"
-       audiod_ldflags="$audiod_ldflags $speex_libs"
-       play_ldflags="$play_ldflags $speex_libs"
-       afh_ldflags="$afh_ldflags $speex_libs"
-       recv_ldflags="$recv_ldflags $speex_libs"
-
-       server_errlist_objs="$server_errlist_objs spx_afh spx_common"
-       filter_errlist_objs="$filter_errlist_objs spxdec_filter spx_common"
-       audiod_errlist_objs="$audiod_errlist_objs spxdec_filter spx_common"
-       play_errlist_objs="$play_errlist_objs spxdec_filter spx_afh spx_common"
-       afh_errlist_objs="$afh_errlist_objs spx_afh spx_common"
-       recv_errlist_objs="$recv_errlist_objs spx_afh spx_common"
-
-       audiod_audio_formats="$audiod_audio_formats spx"
-       audio_format_handlers="$audio_format_handlers spx"
+       AC_SUBST(speex_cppflags)
+       speex_ldflags="$speex_libs -lspeex"
+       AC_SUBST(speex_ldflags)
 else
        AC_MSG_WARN([no ogg/speex $msg])
 fi
 if test "$have_opus" = "yes"; then
-       all_errlist_objs="$all_errlist_objs opusdec_filter opus_afh opus_common"
        AC_DEFINE(HAVE_OPUS, 1, define to 1 to turn on ogg/opus support)
-       filters="$filters opusdec"
-       opus_libs="-lopus"
-       server_ldflags="$server_ldflags $opus_libs"
-       filter_ldflags="$filter_ldflags $opus_libs"
-       audiod_ldflags="$audiod_ldflags $opus_libs"
-       afh_ldflags="$afh_ldflags $opus_libs"
-       play_ldflags="$play_ldflags $opus_libs"
-       recv_ldflags="$recv_ldflags $opus_libs"
-
-       server_errlist_objs="$server_errlist_objs opus_afh opus_common"
-       filter_errlist_objs="$filter_errlist_objs opusdec_filter opus_common"
-       audiod_errlist_objs="$audiod_errlist_objs opusdec_filter opus_common"
-       afh_errlist_objs="$afh_errlist_objs opus_afh opus_common"
-       play_errlist_objs="$play_errlist_objs opusdec_filter opus_afh opus_common"
-       recv_errlist_objs="$recv_errlist_objs opus_afh opus_common"
-
-       audiod_audio_formats="$audiod_audio_formats opus"
+       AC_SUBST(opus_cppflags)
+       opus_ldflags="$opus_libs -lopus"
+       AC_SUBST(opus_ldflags)
        audio_format_handlers="$audio_format_handlers opus"
 else
        AC_MSG_WARN([no ogg/opus $msg])
@@ -825,27 +484,9 @@ AC_CHECK_HEADER(neaacdec.h, [], have_faad=no)
 AC_CHECK_LIB([faad], [NeAACDecOpen], [], have_faad=no)
 if test "$have_faad" = "yes"; then
        AC_DEFINE(HAVE_FAAD, 1, define to 1 if you want to build the aacdec filter)
-       all_errlist_objs="$all_errlist_objs aac_common aacdec_filter aac_afh"
-       filter_errlist_objs="$filter_errlist_objs aacdec_filter aac_common"
-       afh_errlist_objs="$afh_errlist_objs aac_common aac_afh"
-       audiod_errlist_objs="$audiod_errlist_objs aacdec_filter aac_common"
-       play_errlist_objs="$play_errlist_objs aacdec_filter aac_afh aac_common"
-       server_errlist_objs="$server_errlist_objs aac_afh aac_common"
-       recv_errlist_objs="$recv_errlist_objs aac_afh aac_common"
-
-       server_ldflags="$server_ldflags $faad_libs -lfaad"
-       filter_ldflags="$filter_ldflags $faad_libs -lfaad"
-       audiod_ldflags="$audiod_ldflags $faad_libs -lfaad"
-       play_ldflags="$play_ldflags $faad_libs -lfaad"
-       afh_ldflags="$afh_ldflags $faad_libs -lfaad"
-       recv_ldflags="$afh_ldflags $faad_libs -lfaad"
-
-       audiod_audio_formats="$audiod_audio_formats aac"
-       audio_format_handlers="$audio_format_handlers aac"
-       filters="$filters aacdec"
        AC_SUBST(faad_cppflags)
-else
-       AC_MSG_WARN([no aac support in para_audiod/para_filter])
+       faad_ldflags="$faad_libs -lfaad"
+       AC_SUBST(faad_ldflags)
 fi
 CPPFLAGS="$OLD_CPPFLAGS"
 LDFLAGS="$OLD_LDFLAGS"
@@ -876,19 +517,9 @@ AC_CHECK_LIB([mad], [mad_stream_init], [], [
 ])
 if test "$have_mad" = "yes"; then
        AC_DEFINE(HAVE_MAD, 1, define to 1 if you want to build the mp3dec filter)
-       filter_cmdline_objs="$filter_cmdline_objs add_cmdline(mp3dec_filter)"
-       audiod_cmdline_objs="$audiod_cmdline_objs add_cmdline(mp3dec_filter)"
-       play_cmdline_objs="$play_cmdline_objs add_cmdline(mp3dec_filter)"
-       all_errlist_objs="$all_errlist_objs mp3dec_filter"
-       filter_errlist_objs="$filter_errlist_objs mp3dec_filter"
-       audiod_errlist_objs="$audiod_errlist_objs mp3dec_filter"
-       play_errlist_objs="$play_errlist_objs mp3dec_filter"
-       filter_ldflags="$filter_ldflags $mad_libs -lmad"
-       audiod_ldflags="$audiod_ldflags $mad_libs -lmad"
-       play_ldflags="$play_ldflags $mad_libs -lmad"
-       audiod_audio_formats="$audiod_audio_formats mp3"
-       filters="$filters mp3dec"
        AC_SUBST(mad_cppflags)
+       mad_ldflags="$mad_libs -lmad"
+       AC_SUBST(mad_ldflags)
 else
        AC_MSG_WARN([no mp3dec support in para_audiod/para_filter])
 fi
@@ -924,14 +555,8 @@ AC_MSG_RESULT($have_libid3tag)
 
 if test ${have_libid3tag} = yes; then
        AC_DEFINE(HAVE_LIBID3TAG, 1, define to 1 you have libid3tag)
-       server_ldflags="$server_ldflags $id3tag_libs -lid3tag -lz"
-       afh_ldflags="$afh_ldflags $id3tag_libs -lid3tag -lz"
-       play_ldflags="$play_ldflags -lz"
-       recv_ldflags="$recv_ldflags $id3tag_libs -lid3tag"
-       play_ldflags="$play_ldflags $id3tag_libs -lid3tag"
        AC_SUBST(id3tag_cppflags)
-else
-       AC_MSG_WARN([no support for id3v2 tags])
+       AC_SUBST(id3tag_ldflags, "$id3tag_libs -lid3tag -lz")
 fi
 CPPFLAGS="$OLD_CPPFLAGS"
 LDFLAGS="$OLD_LDFLAGS"
@@ -955,26 +580,16 @@ if test -n "$with_flac_libs"; then
        LDFLAGS="$LDFLAGS $flac_libs"
 fi
 AC_CHECK_HEADER(FLAC/stream_decoder.h, [], have_flac=no)
-AC_CHECK_LIB([FLAC], [FLAC__stream_decoder_init_file], [], have_flac=no, -logg -lm)
+AC_CHECK_LIB([FLAC], [FLAC__stream_decoder_init_file], [], [
+       # nope, try again with -logg
+       AC_CHECK_LIB([FLAC], [FLAC__stream_decoder_init_file], [],
+               have_flac=no, -lm -logg)
+       ], -lm)
 if test "$have_flac" = "yes"; then
        AC_DEFINE(HAVE_FLAC, 1, define to 1 if you want to build the flacdec filter)
-       all_errlist_objs="$all_errlist_objs flacdec_filter flac_afh"
-       filter_errlist_objs="$filter_errlist_objs flacdec_filter"
-       audiod_errlist_objs="$audiod_errlist_objs flacdec_filter"
-       play_errlist_objs="$play_errlist_objs flacdec_filter flac_afh"
-       afh_errlist_objs="$afh_errlist_objs flac_afh"
-       server_errlist_objs="$server_errlist_objs flac_afh"
-       recv_errlist_objs="$recv_errlist_objs flac_afh"
-       filter_ldflags="$filter_ldflags $flac_libs -lFLAC"
-       audiod_ldflags="$audiod_ldflags $flac_libs -lFLAC"
-       play_ldflags="$play_ldflags $flac_libs -lFLAC"
-       server_ldflags="$server_ldflags $flac_libs -lFLAC"
-       afh_ldflags="$afh_ldflags $flac_libs -lFLAC"
-       recv_ldflags="$recv_ldflags $flac_libs -lFLAC"
-       filters="$filters flacdec"
-       audio_format_handlers="$audio_format_handlers flac"
-       audiod_audio_formats="$audiod_audio_formats flac"
        AC_SUBST(flac_cppflags)
+       flac_ldflags="$flac_libs -lFLAC"
+       AC_SUBST(flac_ldflags)
 else
        AC_MSG_WARN([no flac support in para_audiod/para_filter/para_afh/para_server])
 fi
@@ -990,26 +605,9 @@ have_oss="yes"
 msg="=> will not build oss writer"
 
 AC_CHECK_HEADER(sys/soundcard.h, [
-       audiod_errlist_objs="$audiod_errlist_objs oss_write"
-       play_errlist_objs="$play_errlist_objs oss_write"
-       audiod_cmdline_objs="$audiod_cmdline_objs add_cmdline(oss_write)"
-       play_cmdline_objs="$play_cmdline_objs add_cmdline(oss_write)"
-
-       write_errlist_objs="$write_errlist_objs oss_write"
-       write_cmdline_objs="$write_cmdline_objs add_cmdline(oss_write)"
-       fade_errlist_objs="$fade_errlist_objs oss_mix"
-       all_errlist_objs="$all_errlist_objs oss_write oss_mix"
-
-       writers="$writers oss"
-       default_writer="OSS_WRITE"
-       mixers="${mixers}oss "
-       default_mixer="OSS_MIX"
-
        AC_CHECK_LIB(ossaudio, _oss_ioctl, [
-                       audiod_ldflags="$audiod_ldflags -lossaudio"
-                       play_ldflags="$play_ldflags -lossaudio"
-                       write_ldflags="$write_ldflags -lossaudio"
-                       fade_ldflags="$fade_ldflags -lossaudio"
+                       oss_ldflags="-lossaudio"
+                       AC_SUBST(oss_ldflags)
                ]
        )
        ],
@@ -1048,67 +646,13 @@ if test "$have_alsa" = "yes"; then
 fi
 
 if test "$have_alsa" = "yes"; then
-       audiod_errlist_objs="$audiod_errlist_objs alsa_write"
-       audiod_cmdline_objs="$audiod_cmdline_objs add_cmdline(alsa_write)"
-       audiod_ldflags="$audiod_ldflags -lasound"
-       play_errlist_objs="$play_errlist_objs alsa_write"
-       play_cmdline_objs="$play_cmdline_objs add_cmdline(alsa_write)"
-       play_ldflags="$play_ldflags -lasound"
-
-       write_errlist_objs="$write_errlist_objs alsa_write"
-       write_cmdline_objs="$write_cmdline_objs add_cmdline(alsa_write)"
-       write_ldflags="$write_ldflags -lasound"
-       fade_errlist_objs="$fade_errlist_objs alsa_mix"
-       fade_ldflags="$fade_ldflags -lasound"
-       all_errlist_objs="$all_errlist_objs alsa_write alsa_mix"
-
-       writers="$writers alsa"
-       default_writer="ALSA_WRITE"
-       mixers="${mixers}alsa "
-       default_mixer="ALSA_MIX"
+       alsa_ldflags="-lasound"
+       AC_SUBST(alsa_ldflags)
 fi
 
 CPPFLAGS="$OLD_CPPFLAGS"
 LDFLAGS="$OLD_LDFLAGS"
 LIBS="$OLD_LIBS"
-########################################################################### fade
-if test -n "$mixers"; then
-       extras="$extras fade"
-       executables="$executables fade"
-       all_errlist_objs="$all_errlist_objs fade"
-       fade_errlist_objs="$fade_errlist_objs fade exec string fd version ggo"
-       fade_cmdline_objs="add_cmdline(fade)"
-       fade_objs="$fade_cmdline_objs $fade_errlist_objs"
-       AC_SUBST(fade_objs, add_dot_o($fade_objs))
-       AC_SUBST(fade_ldflags, $fade_ldflags)
-       AC_DEFINE_UNQUOTED(INIT_FADE_ERRLISTS,
-               objlist_to_errlist($fade_errlist_objs),
-               errors used by para_fade)
-       enum="$(
-               for i in $mixers; do
-                       printf "${i}_MIX, " | tr '[a-z]' '[A-Z]'
-               done
-       )"
-       AC_DEFINE_UNQUOTED(MIXER_ENUM, $enum NUM_SUPPORTED_MIXERS,
-               enum of supported mixers)
-       AC_DEFINE_UNQUOTED(DEFAULT_MIXER, $default_mixer,
-               use this mixer if none was specified)
-       names="$(for i in $mixers; do printf \"$i\",' ' ; done)"
-       AC_DEFINE_UNQUOTED(MIXER_NAMES, $names, supported mixer names)
-       inits="$(
-               for i in $mixers; do
-                       printf 'extern void '$i'_mix_init(struct mixer *); '
-               done
-       )"
-       AC_DEFINE_UNQUOTED(DECLARE_MIXER_INITS, $inits,
-               init functions of the supported mixers)
-       array="$(for i in $mixers; do printf '{.init = '$i'_mix_init},'; done)"
-       AC_DEFINE_UNQUOTED(MIXER_ARRAY, $array, array of supported mixers)
-       mixer_summary="supported mixers:: $mixers, default: $default_mixer"
-else
-       AC_MSG_WARN([no mixer support])
-       mixer_summary="para_fade: no"
-fi
 ########################################################################### libao
 OLD_CPPFLAGS="$CPPFLAGS"
 OLD_LDFLAGS="$LDFLAGS"
@@ -1153,20 +697,9 @@ if test "$have_ao" = "yes"; then
        ])
 fi
 if test "$have_ao" = "yes"; then
-       all_errlist_objs="$all_errlist_objs ao_write"
-       audiod_errlist_objs="$audiod_errlist_objs ao_write"
-       audiod_cmdline_objs="$audiod_cmdline_objs add_cmdline(ao_write)"
-       audiod_ldflags="$audiod_ldflags -lao -lpthread"
-
-       play_errlist_objs="$play_errlist_objs ao_write"
-       play_cmdline_objs="$play_cmdline_objs add_cmdline(ao_write)"
-       play_ldflags="$play_ldflags -lao -lpthread"
-
-       write_errlist_objs="$write_errlist_objs ao_write"
-       write_cmdline_objs="$write_cmdline_objs add_cmdline(ao_write)"
-       write_ldflags="$write_ldflags $ao_libs -lao -lpthread"
-       writers="$writers ao"
        AC_SUBST(ao_cppflags)
+       ao_ldflags="$ao_libs -lao -lpthread"
+       AC_SUBST(ao_ldflags)
 fi
 
 CPPFLAGS="$OLD_CPPFLAGS"
@@ -1198,22 +731,18 @@ AC_CHECK_HEADERS([readline/readline.h], [
        AC_MSG_WARN([readline/readline.h not found, $msg])
 ])
 
-if test "$have_curses" != "yes"; then
-       have_readline="no"
-       AC_MSG_WARN([interactive cli support depends on curses,])
-       AC_MSG_WARN([but no curses lib was detected, $msg])
-fi
-
 if test "$have_readline" = "yes"; then
-       readline_libs="$readline_libs -lreadline"
-       AC_SEARCH_LIBS([rl_free_keymap], [readline], [], [have_readline="no"])
+       readline_ldflags="$readline_libs"
+       AC_SEARCH_LIBS([rl_free_keymap], [readline], [
+               readline_ldflags="$readline_ldflags -lreadline"
+       ], [have_readline="no"])
        if test "$have_readline" = "no"; then # try with -lcurses
                 # clear cache
                AC_MSG_NOTICE([trying again with -lcurses])
                 unset ac_cv_search_rl_free_keymap 2> /dev/null
                AC_SEARCH_LIBS([rl_free_keymap], [readline], [
                        have_readline=yes
-                       readline_libs="$readline_libs -lcurses"
+                       readline_ldflags="$readline_ldflags -lreadline -lcurses"
                ], [], [-lcurses])
        fi
        if test "$have_readline" = "no"; then # try with -ltermcap
@@ -1222,20 +751,23 @@ if test "$have_readline" = "yes"; then
                 unset ac_cv_search_rl_free_keymap 2> /dev/null
                AC_SEARCH_LIBS([rl_free_keymap], [readline], [
                        have_readline=yes
-                       readline_libs="$readline_libs -ltermcap"
+                       readline_ldflags="$readline_ldflags -lreadline -ltermcap"
                ], [], [-ltermcap])
        fi
 fi
 
 if test "$have_readline" = "yes"; then
-       all_errlist_objs="$all_errlist_objs interactive"
-       client_errlist_objs="$client_errlist_objs interactive"
-       client_ldflags="$client_ldflags $readline_libs"
-       audioc_errlist_objs="$audioc_errlist_objs buffer_tree interactive sched time"
-       audioc_ldflags="$audioc_ldflags $readline_libs"
-       play_errlist_objs="$play_errlist_objs interactive"
-       play_ldflags="$play_ldflags $readline_libs"
+       AC_CHECK_DECL(
+               [rl_free_keymap],
+               [AC_DEFINE(RL_FREE_KEYMAP_DECLARED, 1, readline >= 6.3)],
+               [],
+               [
+                       #include <stdio.h>
+                       #include <readline/readline.h>
+               ]
+       )
        AC_SUBST(readline_cppflags)
+       AC_SUBST(readline_ldflags)
        AC_DEFINE(HAVE_READLINE, 1, define to 1 to turn on readline support)
 else
        AC_MSG_WARN([libreadline not found or unusable])
@@ -1266,136 +798,660 @@ AC_CHECK_HEADER(samplerate.h, [], have_samplerate=no)
 AC_CHECK_LIB([samplerate], [src_process], [], have_samplerate=no, [])
 
 if test "$have_samplerate" = "yes"; then
-       all_errlist_objs="$all_errlist_objs resample_filter"
-       filter_errlist_objs="$filter_errlist_objs resample_filter check_wav"
-       filter_cmdline_objs="$filter_cmdline_objs add_cmdline(resample_filter)"
-       audiod_errlist_objs="$audiod_errlist_objs resample_filter check_wav"
-       audiod_cmdline_objs="$audiod_cmdline_objs add_cmdline(resample_filter)"
-       play_errlist_objs="$play_errlist_objs resample_filter check_wav"
-       play_cmdline_objs="$play_cmdline_objs add_cmdline(resample_filter)"
-       filter_ldflags="$filter_ldflags $samplerate_libs -lsamplerate"
-       audiod_ldflags="$audiod_ldflags $samplerate_libs -lsamplerate"
-       play_ldflags="$play_ldflags $samplerate_libs -lsamplerate"
-       filters="$filters resample"
        AC_SUBST(samplerate_cppflags)
+       samplerate_ldflags="$samplerate_libs -lsamplerate"
+       AC_SUBST(samplerate_ldflags)
 else
        AC_MSG_WARN([no resample support in para_audiod/para_filter])
 fi
 CPPFLAGS="$OLD_CPPFLAGS"
 LDFLAGS="$OLD_LDFLAGS"
 LIBS="$OLD_LIBS"
-############################################################# error2.h
-AC_MSG_NOTICE(creating error2.h)
-for i in $executables; do
-       echo "$i: "
-       eval echo \$${i}_errlist_objs
-done | ./error2.pl > error2.h
-for obj in $all_errlist_objs; do
-       SS="$SS SS_$(echo $obj | tr 'a-z' 'A-Z'),"
-done
-AC_DEFINE_UNQUOTED(DEFINE_ERRLIST_OBJECT_ENUM,
-       [enum {$SS NUM_SS}],
-       [list of all objects that use the paraslash error facility]
-)
-
-################################################################## status items
-
-status_items="basename status num_played mtime bitrate frequency file_size
-status_flags format score techinfo afs_mode
-attributes_txt decoder_flags audiod_status play_time attributes_bitmap
-offset seconds_total stream_start current_time audiod_uptime image_id
-lyrics_id duration directory lyrics_name image_name path hash channels
-last_played num_chunks chunk_time amplification artist title year album
-comment"
-
-result=
-for i in $status_items; do
-       result="$result SI_$(echo $i | tr 'a-z' 'A-Z'), "
-done
-AC_DEFINE_UNQUOTED(STATUS_ITEM_ENUM, [$result],
-       [enum of all status items])
-
-result=
-for i in $status_items; do
-       result="$result \"$i\", "
-done
-AC_DEFINE_UNQUOTED(STATUS_ITEM_ARRAY, [$result],
-       [char * array of all status items])
-
-AC_DEFINE_UNQUOTED(AUDIO_FORMAT_HANDLERS, "$audio_format_handlers",
-       [formats supported by para_server and para_afh])
-
-AC_SUBST(executables, add_para($executables))
+######################################################################### server
+if test \( "$have_openssl" = "yes" -o "$have_gcrypt" = "yes" \) \
+       -a "$have_osl" = "yes" ; then
 
-recv_objs="$recv_cmdline_objs $recv_errlist_objs"
-filter_objs="$filter_cmdline_objs $filter_errlist_objs"
-audiod_objs="$audiod_cmdline_objs $audiod_errlist_objs"
-server_objs="$server_cmdline_objs $server_errlist_objs"
-write_objs="$write_cmdline_objs $write_errlist_objs"
-client_objs="$client_cmdline_objs $client_errlist_objs"
-audioc_objs="$audioc_cmdline_objs $audioc_errlist_objs"
-afh_objs="$afh_cmdline_objs $afh_errlist_objs"
-play_objs="$play_cmdline_objs $play_errlist_objs"
-
-
-AC_SUBST(recv_objs, add_dot_o($recv_objs))
-AC_SUBST(recv_ldflags, $recv_ldflags)
-AC_DEFINE_UNQUOTED(INIT_RECV_ERRLISTS, objlist_to_errlist($recv_errlist_objs),
-       errors used by para_recv)
-
-AC_SUBST(filter_objs, add_dot_o($filter_objs))
-AC_SUBST(filter_ldflags, $filter_ldflags)
-AC_DEFINE_UNQUOTED(INIT_FILTER_ERRLISTS,
+       build_server="yes"
+       executables="$executables server"
+       server_cmdline_objs="server"
+       server_errlist_objs="
+               server
+               afh_common
+               mp3_afh
+               vss
+               command
+               net
+               string
+               signal
+               time
+               daemon
+               http_send
+               close_on_fork
+               mm
+               crypt_common
+               ipc
+               dccp_send
+               fd
+               user_list
+               chunk_queue
+               afs
+               aft
+               mood
+               score
+               attribute
+               blob
+               playlist
+               sched
+               acl
+               send_common
+               udp_send
+               color
+               fec
+               wma_afh
+               wma_common
+               sideband
+               version
+               ggo
+       "
+       if test "$have_openssl" = "yes"; then
+               server_errlist_objs="$server_errlist_objs crypt"
+       fi
+       if test "$have_gcrypt" = "yes"; then
+               server_errlist_objs="$server_errlist_objs gcrypt"
+       fi
+       if test "$have_vorbis" = "yes" || \
+                       test "$have_speex" = "yes" || \
+                       test "$have_opus" = "yes"; then
+               server_errlist_objs="$server_errlist_objs ogg_afh_common"
+       fi
+       if test "$have_vorbis" = "yes"; then
+               server_errlist_objs="$server_errlist_objs ogg_afh"
+       fi
+       if test "$have_speex" = "yes"; then
+               server_errlist_objs="$server_errlist_objs spx_afh spx_common"
+       fi
+       if test "$have_opus" = "yes"; then
+               server_errlist_objs="$server_errlist_objs opus_afh opus_common"
+       fi
+       if test "$have_faad" = "yes"; then
+               server_errlist_objs="$server_errlist_objs aac_afh aac_common"
+       fi
+       if test "$have_flac" = "yes"; then
+               server_errlist_objs="$server_errlist_objs flac_afh"
+       fi
+       server_objs="add_cmdline($server_cmdline_objs) $server_errlist_objs"
+       AC_SUBST(server_objs, add_dot_o($server_objs))
+       AC_DEFINE_UNQUOTED(INIT_SERVER_ERRLISTS,
+               objlist_to_errlist($server_errlist_objs), errors used by para_server)
+else
+       build_server="no"
+fi
+############################################################# client
+if test "$have_openssl" = "yes" -o "$have_gcrypt" = "yes"; then
+       build_client="yes"
+       executables="$executables client"
+       client_cmdline_objs="client"
+       client_errlist_objs="
+               client
+               net
+               string
+               fd
+               sched
+               stdin
+               stdout
+               time
+               sideband
+               client_common
+               buffer_tree
+               crypt_common
+               version
+               ggo
+       "
+       if test "$have_openssl" = "yes"; then
+               client_errlist_objs="$client_errlist_objs crypt"
+       fi
+       if test "$have_gcrypt" = "yes"; then
+               client_errlist_objs="$client_errlist_objs gcrypt"
+       fi
+       if test "$have_readline" = "yes"; then
+               client_errlist_objs="$client_errlist_objs interactive"
+       fi
+       client_objs="add_cmdline($client_cmdline_objs) $client_errlist_objs"
+       AC_SUBST(client_objs, add_dot_o($client_objs))
+       AC_DEFINE_UNQUOTED(INIT_CLIENT_ERRLISTS,
+               objlist_to_errlist($client_errlist_objs), errors used by para_client)
+else
+       build_client="no"
+fi
+############################################################# audiod
+if test "$have_openssl" = "yes" -o "$have_gcrypt" = "yes"; then
+       build_audiod="yes"
+       executables="$executables audiod"
+       audiod_audio_formats="wma"
+       audiod_cmdline_objs="$audiod_cmdline_objs
+               audiod
+               compress_filter
+               http_recv
+               dccp_recv
+               file_write
+               client
+               amp_filter
+               udp_recv
+               prebuffer_filter
+               sync_filter
+       "
+       audiod_errlist_objs="$audiod_errlist_objs
+               audiod
+               signal
+               string
+               daemon
+               stat
+               net
+               crypt_common
+               sideband
+               time
+               grab_client
+               filter_common
+               wav_filter
+               compress_filter
+               amp_filter
+               http_recv
+               dccp_recv
+               recv_common
+               fd
+               sched
+               write_common
+               file_write
+               audiod_command
+               fecdec_filter
+               client_common
+               ggo
+               udp_recv
+               color
+               fec
+               prebuffer_filter
+               version
+               bitstream
+               imdct
+               wma_common
+               wmadec_filter
+               buffer_tree
+               sync_filter
+       "
+       if test "$have_openssl" = "yes"; then
+               audiod_errlist_objs="$audiod_errlist_objs crypt"
+       fi
+       if test "$have_gcrypt" = "yes"; then
+               audiod_errlist_objs="$audiod_errlist_objs gcrypt"
+       fi
+       if test "$have_core_audio" = "yes"; then
+               audiod_errlist_objs="$audiod_errlist_objs osx_write ipc"
+               audiod_cmdline_objs="$audiod_cmdline_objs osx_write"
+       fi
+       if test "$have_vorbis" = "yes"; then
+               audiod_errlist_objs="$audiod_errlist_objs oggdec_filter"
+               audiod_audio_formats="$audiod_audio_formats ogg"
+       fi
+       if test "$have_speex" = "yes"; then
+               audiod_errlist_objs="$audiod_errlist_objs spxdec_filter spx_common"
+               audiod_audio_formats="$audiod_audio_formats spx"
+       fi
+       if test "$have_opus" = "yes"; then
+               audiod_errlist_objs="$audiod_errlist_objs opusdec_filter opus_common"
+               audiod_audio_formats="$audiod_audio_formats opus"
+       fi
+       if test "$have_faad" = "yes"; then
+               audiod_errlist_objs="$audiod_errlist_objs aacdec_filter aac_common"
+               audiod_audio_formats="$audiod_audio_formats aac"
+       fi
+       if test "$have_mad" = "yes"; then
+               audiod_audio_formats="$audiod_audio_formats mp3"
+               audiod_cmdline_objs="$audiod_cmdline_objs mp3dec_filter"
+               audiod_errlist_objs="$audiod_errlist_objs mp3dec_filter"
+       fi
+       if test "$have_flac" = "yes"; then
+               audiod_errlist_objs="$audiod_errlist_objs flacdec_filter"
+               audiod_audio_formats="$audiod_audio_formats flac"
+       fi
+       if test "$have_oss" = "yes"; then
+               audiod_errlist_objs="$audiod_errlist_objs oss_write"
+               audiod_cmdline_objs="$audiod_cmdline_objs oss_write"
+       fi
+       if test "$have_alsa" = "yes"; then
+               audiod_errlist_objs="$audiod_errlist_objs alsa_write"
+               audiod_cmdline_objs="$audiod_cmdline_objs alsa_write"
+       fi
+       if test "$have_ao" = "yes"; then
+               audiod_errlist_objs="$audiod_errlist_objs ao_write"
+               audiod_cmdline_objs="$audiod_cmdline_objs ao_write"
+       fi
+       if test "$have_samplerate" = "yes"; then
+               audiod_errlist_objs="$audiod_errlist_objs resample_filter check_wav"
+               audiod_cmdline_objs="$audiod_cmdline_objs resample_filter"
+       fi
+       audiod_objs="add_cmdline($audiod_cmdline_objs) $audiod_errlist_objs"
+       AC_SUBST(audiod_objs, add_dot_o($audiod_objs))
+       AC_DEFINE_UNQUOTED(INIT_AUDIOD_ERRLISTS, objlist_to_errlist($audiod_errlist_objs),
+               errors used by para_audiod)
+
+       enum="$(for i in $audiod_audio_formats; do printf "AUDIO_FORMAT_${i}, " | tr '[a-z]' '[A-Z]'; done)"
+       AC_DEFINE_UNQUOTED(AUDIOD_AUDIO_FORMATS_ENUM, $enum NUM_AUDIO_FORMATS,
+               enum of audio formats supported by audiod)
+       names="$(for i in $audiod_audio_formats; do printf \"$i\",' ' ; done)"
+       AC_DEFINE_UNQUOTED(AUDIOD_AUDIO_FORMAT_ARRAY, $names, array of audio formats supported by audiod)
+else
+       build_audiod="no"
+fi
+########################################################################### fade
+if test "$have_oss" = "yes" -o "$have_alsa" = "yes"; then
+       build_fade="yes"
+       executables="$executables fade"
+       fade_cmdline_objs="fade"
+       fade_errlist_objs="fade exec string fd version ggo"
+       if test "$have_oss" = "yes"; then
+               fade_errlist_objs="$fade_errlist_objs oss_mix"
+               mixers="${mixers}oss "
+               default_mixer="OSS_MIX"
+       fi
+       if test "$have_alsa" = "yes"; then
+               fade_errlist_objs="$fade_errlist_objs alsa_mix"
+               mixers="${mixers}alsa "
+               default_mixer="ALSA_MIX"
+       fi
+       fade_objs="add_cmdline($fade_cmdline_objs) $fade_errlist_objs"
+       AC_SUBST(fade_objs, add_dot_o($fade_objs))
+       AC_DEFINE_UNQUOTED(INIT_FADE_ERRLISTS,
+               objlist_to_errlist($fade_errlist_objs),
+               errors used by para_fade)
+       enum="$(
+               for i in $mixers; do
+                       printf "${i}_MIX, " | tr '[a-z]' '[A-Z]'
+               done
+       )"
+       AC_DEFINE_UNQUOTED(MIXER_ENUM, $enum NUM_SUPPORTED_MIXERS,
+               enum of supported mixers)
+       AC_DEFINE_UNQUOTED(DEFAULT_MIXER, $default_mixer,
+               use this mixer if none was specified)
+       names="$(for i in $mixers; do printf \"$i\",' ' ; done)"
+       AC_DEFINE_UNQUOTED(MIXER_NAMES, $names, supported mixer names)
+       inits="$(
+               for i in $mixers; do
+                       printf 'extern void '$i'_mix_init(struct mixer *); '
+               done
+       )"
+       AC_DEFINE_UNQUOTED(DECLARE_MIXER_INITS, $inits,
+               init functions of the supported mixers)
+       array="$(for i in $mixers; do printf '{.init = '$i'_mix_init},'; done)"
+       AC_DEFINE_UNQUOTED(MIXER_ARRAY, $array, array of supported mixers)
+else
+       build_fade="no"
+       AC_MSG_WARN([no mixer support])
+fi
+########################################################################### gui
+if test "$have_curses" = "yes"; then
+       build_gui="yes"
+       executables="$executables gui"
+       gui_cmdline_objs="gui"
+       gui_errlist_objs="
+               exec
+               signal
+               string
+               stat
+               ringbuffer
+               fd
+               gui
+               gui_theme
+               time
+               sched
+               version
+               ggo
+       "
+       gui_objs="add_cmdline($gui_cmdline_objs) $gui_errlist_objs"
+       AC_SUBST(gui_objs, add_dot_o($gui_objs))
+       AC_DEFINE_UNQUOTED(INIT_GUI_ERRLISTS,
+               objlist_to_errlist($gui_errlist_objs), errors used by para_gui)
+else
+       build_gui="no"
+       AC_MSG_WARN([no curses lib, cannot build para_gui])
+fi
+######################################################################## filter
+filters="
+       compress
+       wav
+       amp
+       fecdec
+       wmadec
+       prebuffer
+       sync
+"
+filter_errlist_objs="
+       filter_common
+       wav_filter
+       compress_filter
+       filter
+       string
+       stdin
+       stdout
+       sched
+       fd
+       amp_filter
+       ggo
+       fecdec_filter
+       fec
+       version
+       prebuffer_filter
+       time
+       bitstream
+       imdct
+       wma_common
+       wmadec_filter
+       buffer_tree
+       net
+       sync_filter
+"
+filter_cmdline_objs="
+       filter
+       compress_filter
+       amp_filter
+       prebuffer_filter
+       sync_filter
+"
+
+if test "$have_vorbis" = "yes"; then
+       filters="$filters oggdec"
+       filter_errlist_objs="$filter_errlist_objs oggdec_filter"
+fi
+if test "$have_speex" = "yes"; then
+       filters="$filters spxdec"
+       filter_errlist_objs="$filter_errlist_objs spxdec_filter spx_common"
+fi
+if test "$have_opus" = "yes"; then
+       filters="$filters opusdec"
+       filter_errlist_objs="$filter_errlist_objs opusdec_filter opus_common"
+fi
+if test "$have_faad" = "yes"; then
+       filter_errlist_objs="$filter_errlist_objs aacdec_filter aac_common"
+       filters="$filters aacdec"
+fi
+if test "$have_mad" = "yes"; then
+       filter_cmdline_objs="$filter_cmdline_objs mp3dec_filter"
+       filter_errlist_objs="$filter_errlist_objs mp3dec_filter"
+       filters="$filters mp3dec"
+fi
+if test "$have_flac" = "yes"; then
+       filter_errlist_objs="$filter_errlist_objs flacdec_filter"
+       filters="$filters flacdec"
+fi
+if test "$have_samplerate" = "yes"; then
+       filter_errlist_objs="$filter_errlist_objs resample_filter check_wav"
+       filter_cmdline_objs="$filter_cmdline_objs resample_filter"
+       filters="$filters resample"
+fi
+filters="$(echo $filters)"
+AC_SUBST(filters)
+filter_objs="add_cmdline($filter_cmdline_objs) $filter_errlist_objs"
+
+AC_SUBST(filter_objs, add_dot_o($filter_objs))
+AC_DEFINE_UNQUOTED(INIT_FILTER_ERRLISTS,
        objlist_to_errlist($filter_errlist_objs), errors used by para_filter)
 
-AC_SUBST(audiod_objs, add_dot_o($audiod_objs))
-AC_SUBST(audiod_ldflags, $audiod_ldflags)
-AC_DEFINE_UNQUOTED(INIT_AUDIOD_ERRLISTS, objlist_to_errlist($audiod_errlist_objs),
-       errors used by para_audiod)
+enum="$(for i in $filters; do printf "${i}_FILTER, " | tr '[a-z]' '[A-Z]'; done)"
+AC_DEFINE_UNQUOTED(FILTER_ENUM, $enum NUM_SUPPORTED_FILTERS,
+       enum of supported filters)
+inits="$(for i in $filters; do printf 'extern void '$i'_filter_init(struct filter *f); '; done)"
+AC_DEFINE_UNQUOTED(DECLARE_FILTER_INITS, $inits, init functions of the supported filters)
+array="$(for i in $filters; do printf '{.name = "'$i'", .init = '$i'_filter_init},'; done)"
+AC_DEFINE_UNQUOTED(FILTER_ARRAY, $array, array of supported filters)
+########################################################################## recv
+recv_cmdline_objs="
+       recv
+       http_recv
+       dccp_recv
+       udp_recv
+       afh_recv
+"
 
-AC_SUBST(server_objs, add_dot_o($server_objs))
-AC_SUBST(server_ldflags, $server_ldflags)
-AC_DEFINE_UNQUOTED(INIT_SERVER_ERRLISTS,
-       objlist_to_errlist($server_errlist_objs), errors used by para_server)
+recv_errlist_objs="
+       http_recv
+       recv_common
+       recv
+       time
+       string
+       net
+       dccp_recv
+       fd
+       sched
+       stdout
+       ggo
+       udp_recv
+       buffer_tree
+       afh_recv
+       afh_common
+       wma_afh
+       wma_common
+       mp3_afh
+       version
+"
+if test "$have_vorbis" = "yes" || \
+               test "$have_speex" = "yes" || \
+               test "$have_opus" = "yes"; then
+       recv_errlist_objs="$recv_errlist_objs ogg_afh_common"
+fi
+if test "$have_vorbis" = "yes"; then
+       recv_errlist_objs="$recv_errlist_objs ogg_afh"
+fi
+if test "$have_speex" = "yes"; then
+       recv_errlist_objs="$recv_errlist_objs spx_afh spx_common"
+fi
+if test "$have_opus" = "yes"; then
+       recv_errlist_objs="$recv_errlist_objs opus_afh opus_common"
+fi
+if test "$have_faad" = "yes"; then
+       recv_errlist_objs="$recv_errlist_objs aac_afh aac_common"
+fi
+if test "$have_flac" = "yes"; then
+       recv_errlist_objs="$recv_errlist_objs flac_afh"
+fi
+recv_objs="add_cmdline($recv_cmdline_objs) $recv_errlist_objs"
+AC_SUBST(receivers, "http dccp udp afh")
+AC_SUBST(recv_objs, add_dot_o($recv_objs))
+AC_DEFINE_UNQUOTED(INIT_RECV_ERRLISTS, objlist_to_errlist($recv_errlist_objs),
+       errors used by para_recv)
+########################################################################### afh
+audio_format_handlers="mp3 wma"
+afh_cmdline_objs="afh"
+afh_errlist_objs="
+       afh
+       string
+       fd
+       mp3_afh
+       afh_common
+       time
+       wma_afh
+       wma_common
+       version
+       ggo
+"
+if test "$have_vorbis" = "yes" || \
+               test "$have_speex" = "yes" || \
+               test "$have_opus" = "yes"; then
+       afh_errlist_objs="$afh_errlist_objs ogg_afh_common"
+fi
+if test "$have_vorbis" = "yes"; then
+       afh_errlist_objs="$afh_errlist_objs ogg_afh"
+       audio_format_handlers="$audio_format_handlers ogg"
+fi
+if test "$have_speex" = "yes"; then
+       afh_errlist_objs="$afh_errlist_objs spx_afh spx_common"
+       audio_format_handlers="$audio_format_handlers spx"
+fi
+if test "$have_opus" = "yes"; then
+       afh_errlist_objs="$afh_errlist_objs opus_afh opus_common"
+       audio_format_handlers="$audio_format_handlers opus"
+fi
+if test "$have_faad" = "yes"; then
+       afh_errlist_objs="$afh_errlist_objs aac_common aac_afh"
+       audio_format_handlers="$audio_format_handlers aac"
+fi
+if test "$have_flac" = "yes"; then
+       afh_errlist_objs="$afh_errlist_objs flac_afh"
+       audio_format_handlers="$audio_format_handlers flac"
+fi
+
+afh_objs="add_cmdline($afh_cmdline_objs) $afh_errlist_objs"
 
 AC_SUBST(afh_objs, add_dot_o($afh_objs))
-AC_SUBST(afh_ldflags, $afh_ldflags)
 AC_DEFINE_UNQUOTED(INIT_AFH_ERRLISTS,
        objlist_to_errlist($afh_errlist_objs), errors used by para_afh)
+########################################################################## play
+play_errlist_objs="
+       play
+       fd
+       sched
+       ggo
+       buffer_tree
+       time
+       string
+       net
+       afh_recv
+       afh_common
+       wma_afh
+       wma_common
+       mp3_afh
+       recv_common
+       udp_recv
+       http_recv
+       dccp_recv
+       filter_common
+       fec
+       bitstream
+       imdct
+       wav_filter
+       compress_filter
+       amp_filter
+       prebuffer_filter
+       fecdec_filter
+       wmadec_filter
+       write_common
+       file_write
+       version
+       sync_filter
+"
+play_cmdline_objs="
+       http_recv
+       dccp_recv
+       udp_recv
+       afh_recv
+       compress_filter
+       amp_filter
+       prebuffer_filter
+       file_write
+       play
+       sync_filter
+"
+if test "$have_core_audio" = "yes"; then
+       play_errlist_objs="$play_errlist_objs osx_write ipc"
+       play_cmdline_objs="$play_cmdline_objs osx_write"
+fi
+if test "$have_vorbis" = "yes" || \
+               test "$have_speex" = "yes" || \
+               test "$have_opus" = "yes"; then
+       play_errlist_objs="$play_errlist_objs ogg_afh_common"
+fi
+if test "$have_vorbis" = "yes"; then
+       play_errlist_objs="$play_errlist_objs oggdec_filter ogg_afh"
+fi
+if test "$have_speex" = "yes"; then
+       play_errlist_objs="$play_errlist_objs spxdec_filter spx_afh spx_common"
+fi
+if test "$have_opus" = "yes"; then
+       play_errlist_objs="$play_errlist_objs opusdec_filter opus_afh opus_common"
+fi
+if test "$have_faad" = "yes"; then
+       play_errlist_objs="$play_errlist_objs aacdec_filter aac_afh aac_common"
+fi
+if test "$have_mad" = "yes"; then
+       play_cmdline_objs="$play_cmdline_objs mp3dec_filter"
+       play_errlist_objs="$play_errlist_objs mp3dec_filter"
+fi
+if test "$have_flac" = "yes"; then
+       play_errlist_objs="$play_errlist_objs flacdec_filter flac_afh"
+fi
+if test "$have_oss" = "yes"; then
+       play_errlist_objs="$play_errlist_objs oss_write"
+       play_cmdline_objs="$play_cmdline_objs oss_write"
+fi
+if test "$have_alsa" = "yes"; then
+       play_errlist_objs="$play_errlist_objs alsa_write"
+       play_cmdline_objs="$play_cmdline_objs alsa_write"
+fi
+if test "$have_ao" = "yes"; then
+       play_errlist_objs="$play_errlist_objs ao_write"
+       play_cmdline_objs="$play_cmdline_objs ao_write"
+fi
+if test "$have_readline" = "yes"; then
+       play_errlist_objs="$play_errlist_objs interactive"
+fi
+if test "$have_samplerate" = "yes"; then
+       play_errlist_objs="$play_errlist_objs resample_filter check_wav"
+       play_cmdline_objs="$play_cmdline_objs resample_filter"
+fi
 
-AC_SUBST(write_objs, add_dot_o($write_objs))
-AC_SUBST(write_ldflags, $write_ldflags)
-AC_DEFINE_UNQUOTED(INIT_WRITE_ERRLISTS,
-       objlist_to_errlist($write_errlist_objs), errors used by para_write)
-
-AC_SUBST(client_objs, add_dot_o($client_objs))
-AC_SUBST(client_ldflags, $client_ldflags)
-AC_DEFINE_UNQUOTED(INIT_CLIENT_ERRLISTS,
-       objlist_to_errlist($client_errlist_objs), errors used by para_client)
-
-AC_SUBST(audioc_objs, add_dot_o($audioc_objs))
-AC_SUBST(audioc_ldflags, $audioc_ldflags)
-AC_DEFINE_UNQUOTED(INIT_AUDIOC_ERRLISTS,
-       objlist_to_errlist($audioc_errlist_objs), errors used by para_audioc)
-
-AC_SUBST(gui_objs, add_dot_o($gui_objs))
-AC_SUBST(gui_ldflags, $gui_ldflags)
-AC_DEFINE_UNQUOTED(INIT_GUI_ERRLISTS,
-       objlist_to_errlist($gui_errlist_objs), errors used by para_gui)
-
+play_objs="add_cmdline($play_cmdline_objs) $play_errlist_objs"
 AC_SUBST(play_objs, add_dot_o($play_objs))
-AC_SUBST(play_ldflags, $play_ldflags)
 AC_DEFINE_UNQUOTED(INIT_PLAY_ERRLISTS,
        objlist_to_errlist($play_errlist_objs), errors used by para_play)
+######################################################################### write
+write_cmdline_objs="
+       write
+       file_write
+"
+write_errlist_objs="
+       write
+       write_common
+       file_write
+       time
+       fd
+       string
+       sched
+       stdin
+       buffer_tree
+       ggo
+       check_wav
+       version
+"
+writers="file"
+default_writer="FILE_WRITE"
 
-enum="$(for i in $filters; do printf "${i}_FILTER, " | tr '[a-z]' '[A-Z]'; done)"
-AC_DEFINE_UNQUOTED(FILTER_ENUM, $enum NUM_SUPPORTED_FILTERS,
-       enum of supported filters)
-inits="$(for i in $filters; do printf 'extern void '$i'_filter_init(struct filter *f); '; done)"
-AC_DEFINE_UNQUOTED(DECLARE_FILTER_INITS, $inits, init functions of the supported filters)
-array="$(for i in $filters; do printf '{.name = "'$i'", .init = '$i'_filter_init},'; done)"
-AC_DEFINE_UNQUOTED(FILTER_ARRAY, $array, array of supported filters)
-
+if test "$have_core_audio" = "yes"; then
+       write_errlist_objs="$write_errlist_objs osx_write ipc"
+       write_cmdline_objs="$write_cmdline_objs osx_write"
+       writers="$writers osx"
+       default_writer="OSX_WRITE"
+fi
+if test "$have_ao" = "yes"; then
+       write_errlist_objs="$write_errlist_objs ao_write"
+       write_cmdline_objs="$write_cmdline_objs ao_write"
+       writers="$writers ao"
+       default_writer="AO_WRITE"
+fi
+if test "$have_oss" = "yes"; then
+       write_errlist_objs="$write_errlist_objs oss_write"
+       write_cmdline_objs="$write_cmdline_objs oss_write"
+       writers="$writers oss"
+       default_writer="OSS_WRITE"
+fi
+if test "$have_alsa" = "yes"; then
+       write_errlist_objs="$write_errlist_objs alsa_write"
+       write_cmdline_objs="$write_cmdline_objs alsa_write"
+       writers="$writers alsa"
+       default_writer="ALSA_WRITE"
+fi
+AC_SUBST(writers)
+write_objs="add_cmdline($write_cmdline_objs) $write_errlist_objs"
+AC_SUBST(write_objs, add_dot_o($write_objs))
+AC_DEFINE_UNQUOTED(INIT_WRITE_ERRLISTS,
+       objlist_to_errlist($write_errlist_objs), errors used by para_write)
 enum="$(for i in $writers; do printf "${i}_WRITE, " | tr '[a-z]' '[A-Z]'; done)"
 AC_DEFINE_UNQUOTED(WRITER_ENUM, $enum NUM_SUPPORTED_WRITERS,
        enum of supported writers)
@@ -1406,12 +1462,101 @@ inits="$(for i in $writers; do printf 'extern void '$i'_write_init(struct writer
 AC_DEFINE_UNQUOTED(DECLARE_WRITER_INITS, $inits, init functions of the supported writers)
 array="$(for i in $writers; do printf '{.init = '$i'_write_init},'; done)"
 AC_DEFINE_UNQUOTED(WRITER_ARRAY, $array, array of supported writers)
+######################################################################## audioc
+audioc_cmdline_objs="audioc"
+audioc_errlist_objs="
+       audioc
+       string
+       net
+       fd
+       version
+       ggo
+"
+if test "$have_readline" = "yes"; then
+       audioc_errlist_objs="$audioc_errlist_objs
+               buffer_tree
+               interactive
+               sched
+               time
+       "
+fi
+audioc_objs="add_cmdline($audioc_cmdline_objs) $audioc_errlist_objs"
+AC_SUBST(audioc_objs, add_dot_o($audioc_objs))
+AC_DEFINE_UNQUOTED(INIT_AUDIOC_ERRLISTS,
+       objlist_to_errlist($audioc_errlist_objs), errors used by para_audioc)
+############################################################# error2.h
+# these are always built
+all_errlist_objs="
+       $recv_errlist_objs
+       $filter_errlist_objs
+       $audioc_errlist_objs
+       $write_errlist_objs
+       $afh_errlist_objs
+       $play_errlist_objs
+"
+
+# optional executables
+if test "$build_server" = "yes"; then
+       all_errlist_objs="$all_errlist_objs $server_errlist_objs"
+fi
+if test "$build_gui" = "yes"; then
+       all_errlist_objs="$all_errlist_objs $gui_errlist_objs"
+fi
+if test "$build_fade" = "yes"; then
+       all_errlist_objs="$all_errlist_objs $fade_errlist_objs"
+fi
+if test "$build_client" = "yes"; then
+       all_errlist_objs="$all_errlist_objs $client_errlist_objs"
+fi
+if test "$build_audiod" = "yes"; then
+       all_errlist_objs="$all_errlist_objs $audiod_errlist_objs"
+fi
 
-enum="$(for i in $audiod_audio_formats; do printf "AUDIO_FORMAT_${i}, " | tr '[a-z]' '[A-Z]'; done)"
-AC_DEFINE_UNQUOTED(AUDIOD_AUDIO_FORMATS_ENUM, $enum NUM_AUDIO_FORMATS,
-       enum of audio formats supported by audiod)
-names="$(for i in $audiod_audio_formats; do printf \"$i\",' ' ; done)"
-AC_DEFINE_UNQUOTED(AUDIOD_AUDIO_FORMAT_ARRAY, $names, array of audio formats supported by audiod)
+all_errlist_objs="$(echo $all_errlist_objs | tr ' ' '\n' | sort | uniq)"
+
+object_executable_matrix=
+for i in $executables; do
+       eval objs=\$${i}_errlist_objs
+       object_executable_matrix="$object_executable_matrix $i: $objs"
+done
+# use echo to replace newlines by space
+AC_SUBST(object_executable_matrix, $(echo $object_executable_matrix))
+
+for obj in $all_errlist_objs; do
+       SS="$SS SS_$(echo $obj | tr 'a-z' 'A-Z'),"
+done
+AC_DEFINE_UNQUOTED(DEFINE_ERRLIST_OBJECT_ENUM,
+       [enum {$SS NUM_SS}],
+       [list of all objects that use the paraslash error facility]
+)
+################################################################## status items
+
+status_items="basename status num_played mtime bitrate frequency file_size
+status_flags format score techinfo afs_mode
+attributes_txt decoder_flags audiod_status play_time attributes_bitmap
+offset seconds_total stream_start current_time audiod_uptime image_id
+lyrics_id duration directory lyrics_name image_name path hash channels
+last_played num_chunks chunk_time amplification artist title year album
+comment"
+
+result=
+for i in $status_items; do
+       result="$result SI_$(echo $i | tr 'a-z' 'A-Z'), "
+done
+AC_DEFINE_UNQUOTED(STATUS_ITEM_ENUM, [$result],
+       [enum of all status items])
+
+result=
+for i in $status_items; do
+       result="$result \"$i\", "
+done
+AC_DEFINE_UNQUOTED(STATUS_ITEM_ARRAY, [$result],
+       [char * array of all status items])
+
+AC_DEFINE_UNQUOTED(AUDIO_FORMAT_HANDLERS, "$audio_format_handlers",
+       [formats supported by para_server and para_afh])
+
+AC_SUBST(executables)
 
 AC_OUTPUT
 AC_MSG_NOTICE([
@@ -1423,6 +1568,11 @@ audio formats handlers: $audio_format_handlers
 id3 version2 support: $have_libid3tag
 filters: $filters
 writers: $writers
-optional executables: $extras
-$mixer_summary
+
+para_fade: $build_fade
+para_server: $build_server
+para_gui: $build_gui
+para_fade: $build_fade
+para_client: $build_client
+para_audiod: $build_audiod
 ])
diff --git a/convert_0.3-0.4.sh b/convert_0.3-0.4.sh
deleted file mode 100755 (executable)
index aa0b239..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-#!/usr/bin/env bash
-
-#-------------------------------------------------------------------------------
-## Script to convert the database of paraslash 0.3.5 to version 0.4.x.
-##
-## Assumptions:
-##     - para_server 0.3.5 is running
-##     - "para_client check" reports no errors
-##     - para_server 0.4.x is running, listens on another port and uses a
-##       different afs database and a different afs socket
-##     - The database of paraslash 0.4.x has been initialized (i.e.
-##       para_client init has successfully been executed)
-##     - All audio files in the 0.3.x database have already been added to
-##       the 0.4.x database (execute para_client add /my/audio/file/dir to
-##       do that)
-##
-#-------------------------------------------------------------------------------
-
-# Call this script without arguments to see usage info
-
-# How to connect to para_server 0.3.x.
-client03=/usr/local/bin/para_client
-port03=2991
-host03=localhost
-database03=$HOME/.paraslash/afs_database
-
-# How to connect to para_server 0.4.x.
-client04=$(pwd)/para_client
-port04=2990
-host04=localhost
-database04=$HOME/.paraslash/afs_database-0.4
-
-# Any character that does not occur in any filename of an audio file
-sep='|'
-
-
-client03_cmd="$client03 -p $port03 -i $host03"
-client04_cmd="$client04 -p $port04 -i $host04"
-
-exec_client03_cmd()
-{
-       result="$($client03_cmd -- "$@")"
-}
-
-exec_client04_cmd()
-{
-       result="$($client04_cmd -- "$@")"
-}
-
-convert_attribute_table()
-{
-       local atts
-
-       echo "converting attribute table"
-       exec_client03_cmd lsatt
-       atts="$result"
-       exec_client04_cmd addatt $atts
-}
-
-convert_attributes()
-{
-       local OIFS="$IFS" a p att atts
-
-       printf "converting attributes: "
-       $client03_cmd -- ls -p -lv \
-               | grep '^path:\|^attributes_txt:' \
-               | sed -e "/^path:/N;s/\n/$sep/1" \
-               | {
-                       IFS="$sep"
-                       while read p a; do
-                               p=${p#path: }
-                               a=${a#attributes_txt:}
-                               IFS=" "
-                               atts=
-                               for att in $a; do
-                                       atts="$atts $att+"
-                               done
-                               IFS="$OIFS"
-                               [[ -n "$atts" ]] && $client04_cmd -- setatt $atts "$p"
-                               IFS="$sep"
-                               printf "."
-                       done
-                       echo done
-               }
-               IFS="$OIFS"
-}
-
-convert_lna()
-{
-       local OIFS="$IFS" p l n a
-
-       printf "converting last_played, num_played, amplification values: "
-       $client03_cmd -- ls -p -d -lv \
-               | grep '^path:\|^last_played: \|^num_played: \|^amplification: ' \
-               | sed -e "/^path:/N;N;N;s/\n/$sep/g" \
-               | {
-                       IFS="$sep"
-                       while read p l n a; do
-                               #echo "p: $p, l:$l, n:$n a:$a"
-                               p=${p#path: }
-                               l=${l#last_played: }
-                               n=${n#num_played: }
-                               a=${a#amplification: }
-                               IFS="$OIFS"
-                               $client04_cmd -- touch "-l$l" "-n$n" "-a$a" "$p"
-                               IFS="$sep"
-                               printf "."
-                       done
-                       echo done
-               }
-               IFS="$OIFS"
-}
-
-convert_blobs()
-{
-       local blob name
-
-       for blob in img lyr mood pl; do
-               printf "converting $blob table: "
-               exec_client03_cmd ls$blob
-               echo "$result" | while read name; do
-                       $client03_cmd -- cat$blob "$name" | $client04_cmd -- add$blob "$name"
-                       printf "."
-               done
-               echo done
-       done
-}
-
-convert_ids()
-{
-       local OIFS="$IFS" p i y iopts yopts
-
-       printf "converting image and lyrics ids: "
-       $client03_cmd -- ls -p -lv \
-               | grep '^path:\|^image_name: \|^lyrics_name: ' \
-               | sed -e "/^path:/N;N;s/\n/$sep/g" \
-               | {
-                       IFS="$sep"
-                       while read p i l; do
-                               IFS="$OIFS"
-                               iopts=
-                               yopts=
-                               p=${p#path: }
-                               i=${i#image_name: }
-                               l=${l#lyrics_name: }
-                               if [[ "$i" != '(none)' ]]; then
-                                       exec_client04_cmd lsimg -l "$i"
-                                       iopts="-i${result%%     *}"
-                               fi
-                               if [[ "$l" != '(none)' ]]; then
-                                       exec_client04_cmd lslyr -l "$l"
-                                       yopts="-y${result%%     *}"
-                               fi
-                               if [[ -n "$iopts" && -n "$yopts" ]]; then
-                                       $client04_cmd -- touch "$iopts" "$yopts" "$p"
-                               elif [[ -n "$iopts" ]]; then
-                                       $client04_cmd -- touch "$iopts" "$p"
-                               elif [[ -n "$yopts" ]]; then
-                                       $client04_cmd -- touch "$yopts" "$p"
-                               fi
-                               printf "."
-                               IFS="$sep"
-                       done
-                       echo done
-               }
-               IFS="$OIFS"
-}
-
-
-usage()
-{
-       grep '^##' $0 | sed -e 's/^## *//'
-       echo '
-Usage: $0 command
-
-command is one of the following:
-
-       attribute_table: create attributes
-       attributes: convert attributes for each audio file
-       lna: convert the last_played/num_played/amplification values
-       blobs: convert the image/lyrics/moods/playlists tables
-       ids: convert image and the lyrics id of each audio file.
-       all: Do all of the above.
-
-Edit the top of the script to customize some options.
-'
-}
-
-if test $# -ne 1; then
-       usage
-       exit 1
-fi
-
-case "$1" in
-attribute_table)
-       convert_attribute_table
-       ;;
-attributes)
-       convert_attributes
-       ;;
-lna)
-       convert_lna
-       ;;
-blobs)
-       convert_blobs
-       ;;
-ids)
-       convert_ids
-       ;;
-all)
-       convert_attribute_table
-       convert_attributes
-       convert_lna
-       convert_blobs
-       convert_ids
-       ;;
-*)
-       usage
-       exit 1
-       ;;
-esac
diff --git a/crypt.c b/crypt.c
index 5c5333a9a15a43d2cecf5d3ed1774141c58b90cf..0137e004cbb2b0e121373c1ffe1d5ee6e5f75b6e 100644 (file)
--- a/crypt.c
+++ b/crypt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -15,6 +15,7 @@
 #include <openssl/pem.h>
 #include <openssl/sha.h>
 #include <openssl/bn.h>
+#include <openssl/aes.h>
 
 #include "para.h"
 #include "error.h"
@@ -147,8 +148,7 @@ static int read_rsa_bignums(const unsigned char *blob, int blen, RSA **result)
        *result = rsa;
        return 1;
 fail:
-       if (rsa)
-               RSA_free(rsa);
+       RSA_free(rsa);
        return ret;
 }
 
@@ -260,14 +260,40 @@ int pub_encrypt(struct asymmetric_key *pub, unsigned char *inbuf,
        return ret < 0? -E_ENCRYPT : ret;
 }
 
+struct aes_ctr_128_context {
+       AES_KEY key;
+       unsigned char ivec[AES_CRT128_BLOCK_SIZE];
+       unsigned char ecount[AES_CRT128_BLOCK_SIZE];
+       unsigned int num;
+};
+
 struct stream_cipher {
-       RC4_KEY key;
+       bool use_aes;
+       union {
+               RC4_KEY rc4_key;
+               struct aes_ctr_128_context aes;
+       } context;
 };
 
-struct stream_cipher *sc_new(const unsigned char *data, int len)
+struct stream_cipher *sc_new(const unsigned char *data, int len,
+               bool use_aes)
 {
+       int ret;
        struct stream_cipher *sc = para_malloc(sizeof(*sc));
-       RC4_set_key(&sc->key, len, data);
+       struct aes_ctr_128_context *aes;
+
+       sc->use_aes = use_aes;
+       if (!use_aes) {
+               RC4_set_key(&sc->context.rc4_key, len, data);
+               return sc;
+       }
+       assert(len >= 2 * AES_CRT128_BLOCK_SIZE);
+       aes = &sc->context.aes;
+       ret = AES_set_encrypt_key(data, AES_CRT128_BLOCK_SIZE * 8 /* bits */,
+               &aes->key);
+       assert(ret == 0);
+       memcpy(aes->ivec, data + AES_CRT128_BLOCK_SIZE, AES_CRT128_BLOCK_SIZE);
+       aes->num = 0;
        return sc;
 }
 
@@ -283,44 +309,9 @@ void sc_free(struct stream_cipher *sc)
  */
 #define RC4_ALIGN 8
 
-int sc_send_bin_buffer(struct stream_cipher_context *scc, char *buf,
-               size_t len)
-{
-       int ret;
-       unsigned char *tmp;
-       static unsigned char remainder[RC4_ALIGN];
-       size_t l1 = ROUND_DOWN(len, RC4_ALIGN), l2 = ROUND_UP(len, RC4_ALIGN);
-
-       assert(len);
-       tmp = para_malloc(l2);
-       RC4(&scc->send->key, l1, (const unsigned char *)buf, tmp);
-       if (len > l1) {
-               memcpy(remainder, buf + l1, len - l1);
-               RC4(&scc->send->key, len - l1, remainder, tmp + l1);
-       }
-       ret = xwrite(scc->fd, (char *)tmp, len);
-       free(tmp);
-       return ret;
-}
-
-int sc_recv_bin_buffer(struct stream_cipher_context *scc, char *buf,
-               size_t size)
-{
-       unsigned char *tmp = para_malloc(ROUND_UP(size, RC4_ALIGN));
-       ssize_t ret = recv(scc->fd, tmp, size, 0);
-
-       if (ret > 0)
-               RC4(&scc->recv->key, ret, tmp, (unsigned char *)buf);
-       else if (ret < 0)
-               ret = -ERRNO_TO_PARA_ERROR(errno);
-       free(tmp);
-       return ret;
-}
-
-void sc_crypt(struct stream_cipher *sc, struct iovec *src, struct iovec *dst)
+static void rc4_crypt(RC4_KEY *key, struct iovec *src, struct iovec *dst)
 {
        size_t len = src->iov_len, l1, l2;
-       RC4_KEY *key = &sc->key;
 
        assert(len > 0);
        assert(len < ((typeof(src->iov_len))-1) / 2);
@@ -341,6 +332,28 @@ void sc_crypt(struct stream_cipher *sc, struct iovec *src, struct iovec *dst)
        ((char *)dst->iov_base)[len] = '\0';
 }
 
+static void aes_ctr128_crypt(struct aes_ctr_128_context *aes, struct iovec *src,
+               struct iovec *dst)
+{
+       size_t len = src->iov_len;
+
+       *dst = (typeof(*dst)) {
+               /* Add one for the terminating zero byte. */
+               .iov_base = para_malloc(len + 1),
+               .iov_len = len
+       };
+       AES_ctr128_encrypt(src->iov_base, dst->iov_base, len,
+               &aes->key, aes->ivec, aes->ecount, &aes->num);
+       ((char *)dst->iov_base)[len] = '\0';
+}
+
+void sc_crypt(struct stream_cipher *sc, struct iovec *src, struct iovec *dst)
+{
+       if (sc->use_aes)
+               return aes_ctr128_crypt(&sc->context.aes, src, dst);
+       return rc4_crypt(&sc->context.rc4_key, src, dst);
+}
+
 void hash_function(const char *data, unsigned long len, unsigned char *hash)
 {
        SHA_CTX c;
diff --git a/crypt.h b/crypt.h
index 77806af6983895c13f3120f4f65c1c1d46b9b11d..324a87b349a5b9f69443e47c44e242ffb0be04df 100644 (file)
--- a/crypt.h
+++ b/crypt.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -123,10 +123,12 @@ struct stream_cipher_context {
  *
  * \param data The key.
  * \param len The size of the key.
+ * \param use_aes True: Use the aes_ctr128 stream cipher, false: Use RC4.
  *
  * \return A new stream cipher structure.
  */
-struct stream_cipher *sc_new(const unsigned char *data, int len);
+struct stream_cipher *sc_new(const unsigned char *data, int len,
+               bool use_aes);
 
 /**
  * Encrypt or decrypt a buffer using a stream cipher.
@@ -165,75 +167,9 @@ _static_inline_ void sc_trafo(struct iovec *src, struct iovec *dst,
  */
 void sc_free(struct stream_cipher *sc);
 
-/**
- * Encrypt and send a buffer.
- *
- * \param scc The context.
- * \param buf The buffer to send.
- * \param len The size of \a buf in bytes.
- *
- * \return The return value of the underyling call to write_all().
- *
- * \sa \ref write_all(), RC4(3).
- */
-int sc_send_bin_buffer(struct stream_cipher_context *scc, char *buf,
-               size_t len);
-
-/**
- * Encrypt and send a \p NULL-terminated buffer.
- *
- * \param scc The context.
- * \param buf The buffer to send.
- *
- * \return The return value of the underyling call to sc_send_bin_buffer().
- */
-int sc_send_buffer(struct stream_cipher_context *scc, char *buf);
-
-/**
- * Format, encrypt and send a buffer.
- *
- * \param scc The context.
- * \param fmt A format string.
- *
- * \return The return value of the underyling call to sc_send_buffer().
- */
-__printf_2_3 int sc_send_va_buffer(struct stream_cipher_context *scc,
-               const char *fmt, ...);
-
-/**
- * Receive a buffer and decrypt it.
- *
- * \param scc The context.
- * \param buf The buffer to write the decrypted data to.
- * \param size The size of \a buf.
- *
- * \return The number of bytes received on success, negative on errors, zero if
- * the peer has performed an orderly shutdown.
- *
- * \sa recv(2), RC4(3).
- */
-int sc_recv_bin_buffer(struct stream_cipher_context *scc, char *buf,
-               size_t size);
-
-/**
- * Receive a buffer, decrypt it and write terminating NULL byte.
- *
- * \param scc The context.
- * \param buf The buffer to write the decrypted data to.
- * \param size The size of \a buf.
- *
- * Read at most \a size - 1 bytes from file descriptor given by \a scc, decrypt
- * the received data and write a NULL byte at the end of the decrypted data.
- *
- * \return The return value of the underlying call to \ref
- * sc_recv_bin_buffer().
- */
-int sc_recv_buffer(struct stream_cipher_context *scc, char *buf, size_t size);
-
 /** Size of the hash value in bytes. */
 #define HASH_SIZE 20
 
-
 /**
  * Compute the hash of the given input data.
  *
index 481a215fb24bc4257c1faebde329c07fa1d7ff1e..ddebe62e16e547e243d808cf9155261698fecbec 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2011-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -8,6 +8,9 @@
 
 /* This should only be incuded from files which provide crypto functions. */
 
+/** AES block size in bytes. */
+#define AES_CRT128_BLOCK_SIZE 16
+
 size_t is_ssh_rsa_key(char *data, size_t size);
 uint32_t read_ssh_u32(const void *vp);
 int uudecode(const char *src, unsigned char *target, size_t targsize);
index cd9500ab39f3a89cd4ee70da64d0d7e72ff7c84f..fb6e1ef4174931a9201ea571b7ea33ecd09bf54c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -90,41 +90,31 @@ int base64_decode(char const *src, unsigned char *target, size_t targsize)
 
                switch (state) {
                case 0:
-                       if (target) {
-                               if (tarindex >= targsize)
-                                       return -E_BASE64;
-                               target[tarindex] = (pos - Base64) << 2;
-                       }
+                       if (tarindex >= targsize)
+                               return -E_BASE64;
+                       target[tarindex] = (pos - Base64) << 2;
                        state = 1;
                        break;
                case 1:
-                       if (target) {
-                               if (tarindex + 1 >= targsize)
-                                       return -E_BASE64;
-                               target[tarindex]   |=  (pos - Base64) >> 4;
-                               target[tarindex+1]  = ((pos - Base64) & 0x0f)
-                                                       << 4 ;
-                       }
+                       if (tarindex + 1 >= targsize)
+                               return -E_BASE64;
+                       target[tarindex] |= (pos - Base64) >> 4;
+                       target[tarindex + 1] = ((pos - Base64) & 0x0f) << 4;
                        tarindex++;
                        state = 2;
                        break;
                case 2:
-                       if (target) {
-                               if (tarindex + 1 >= targsize)
-                                       return -E_BASE64;
-                               target[tarindex]   |=  (pos - Base64) >> 2;
-                               target[tarindex+1]  = ((pos - Base64) & 0x03)
-                                                       << 6;
-                       }
+                       if (tarindex + 1 >= targsize)
+                               return -E_BASE64;
+                       target[tarindex] |= (pos - Base64) >> 2;
+                       target[tarindex + 1] = ((pos - Base64) & 0x03) << 6;
                        tarindex++;
                        state = 3;
                        break;
                case 3:
-                       if (target) {
-                               if (tarindex >= targsize)
-                                       return -E_BASE64;
-                               target[tarindex] |= (pos - Base64);
-                       }
+                       if (tarindex >= targsize)
+                               return -E_BASE64;
+                       target[tarindex] |= pos - Base64;
                        tarindex++;
                        state = 0;
                        break;
@@ -170,7 +160,7 @@ int base64_decode(char const *src, unsigned char *target, size_t targsize)
                         * zeros.  If we don't check them, they become a
                         * subliminal channel.
                         */
-                       if (target && target[tarindex] != 0)
+                       if (target[tarindex] != 0)
                                return -E_BASE64;
                }
        } else {
@@ -321,41 +311,3 @@ int hash_compare(unsigned char *h1, unsigned char *h2)
        }
        return 0;
 }
-
-int sc_recv_buffer(struct stream_cipher_context *scc, char *buf, size_t size)
-{
-       int n;
-
-       assert(size);
-       n = sc_recv_bin_buffer(scc, buf, size - 1);
-       if (n >= 0)
-               buf[n] = '\0';
-       else
-               *buf = '\0';
-       return n;
-}
-
-int sc_send_buffer(struct stream_cipher_context *scc, char *buf)
-{
-       size_t len = strlen(buf);
-       int ret = sc_send_bin_buffer(scc, buf, len);
-
-       if (ret < 0 || ret == len)
-               return ret;
-       return -E_SHORT_WRITE;
-}
-
-__printf_2_3 int sc_send_va_buffer(struct stream_cipher_context *scc,
-               const char *fmt, ...)
-{
-       char *msg;
-       int ret;
-       va_list ap;
-
-       va_start(ap, fmt);
-       ret = xvasprintf(&msg, fmt, ap);
-       va_end(ap);
-       ret = sc_send_bin_buffer(scc, msg, ret);
-       free(msg);
-       return ret;
-}
index 18ad1568fbb5074bbddd60bc99835bb49967d24e..05002f4eff228e0200d5d6cdce9be0c697ed3bc3 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index c751f2f7ce5d85464d506c8c6582556bb424aa7d..a45b572d9a322f72f76e54ab323e1859144ee8d1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
  * (C) 2005 Ian McDonald <imcdnzl@gmail.com>
  */
 
+#include <netinet/in.h>
+#include <sys/socket.h>
 #include <regex.h>
 #include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
 
 #include "para.h"
 #include "error.h"
@@ -53,6 +58,7 @@ static int dccp_recv_open(struct receiver_node *rn)
        }
 
        fd = makesock(IPPROTO_DCCP, 0, conf->host_arg, conf->port_arg, fo);
+       flowopt_cleanup(fo);
        free(ccids);
        if (fd < 0)
                return fd;
@@ -113,25 +119,24 @@ static void *dccp_recv_parse_config(int argc, char **argv)
        return tmp;
 }
 
-static void dccp_recv_pre_select(struct sched *s, struct task *t)
+static void dccp_recv_pre_select(struct sched *s, void *context)
 {
-       struct receiver_node *rn = container_of(t, struct receiver_node, task);
+       struct receiver_node *rn = context;
 
-       t->error = 0;
-       if (generic_recv_pre_select(s, t) <= 0)
+       if (generic_recv_pre_select(s, rn) <= 0)
                return;
        para_fd_set(rn->fd, &s->rfds, &s->max_fileno);
 }
 
-static int dccp_recv_post_select(struct sched *s, struct task *t)
+static int dccp_recv_post_select(struct sched *s, void *context)
 {
-       struct receiver_node *rn = container_of(t, struct receiver_node, task);
+       struct receiver_node *rn = context;
        struct btr_node *btrn = rn->btrn;
        struct iovec iov[2];
        int ret, iovcnt;
        size_t num_bytes;
 
-       ret = task_get_notification(t);
+       ret = task_get_notification(rn->task);
        if (ret < 0)
                goto out;
        ret = btr_node_status(btrn, 0, BTR_NT_ROOT);
index 3979982c725da1b6e83966b6ac6887cb2cfae2a6..1e95aac6401cf43cf7368a0ad61a2c37e6428587 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
  * (C) 2005 Ian McDonald <imcdnzl@gmail.com>
  */
 
+#include <netinet/in.h>
+#include <sys/socket.h>
 #include <regex.h>
 #include <sys/types.h>
 #include <osl.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
 
 #include "para.h"
 #include "error.h"
diff --git a/error.h b/error.h
index ef54ef27707e262a09c7b638c8264cec549b2c1e..e91f49b4bdc1c0f37909d22bd71642798e145b63 100644 (file)
--- a/error.h
+++ b/error.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -16,11 +16,9 @@ DEFINE_ERRLIST_OBJECT_ENUM;
 #define TIME_ERRORS
 #define CLOSE_ON_FORK_ERRORS
 #define DAEMON_ERRORS
-#define GUI_ERRORS
 #define GUI_THEME_ERRORS
 #define RINGBUFFER_ERRORS
 #define SCORE_ERRORS
-#define RBTREE_ERRORS
 #define RECV_ERRORS
 #define IPC_ERRORS
 #define DCCP_SEND_ERRORS
@@ -28,7 +26,7 @@ DEFINE_ERRLIST_OBJECT_ENUM;
 #define GGO_ERRORS
 #define COLOR_ERRORS
 #define SIGNAL_ERRORS
-#define FADE_ERRORS
+#define OSS_MIX_ERRORS
 #define STDOUT_ERRORS
 #define FILE_WRITE_ERRORS
 #define STDIN_ERRORS
@@ -37,17 +35,18 @@ DEFINE_ERRLIST_OBJECT_ENUM;
 #define VERSION_ERRORS
 #define SCHED_ERRORS
 
-extern const char **para_errlist[];
 
-#define OSS_MIX_ERRORS \
-       PARA_ERROR(OSS_MIXER_CHANNEL, "invalid mixer channel"), \
+extern const char **para_errlist[];
 
+#define SYNC_FILTER_ERRORS\
+       PARA_ERROR(SYNC_COMPLETE, "all buddies in sync"), \
+       PARA_ERROR(SYNC_LISTEN_FD, "no fd to listen on"), \
 
 #define ALSA_MIX_ERRORS \
        PARA_ERROR(ALSA_MIX_OPEN, "could not open mixer"), \
-       PARA_ERROR(ALSA_MIX_BAD_ELEM, "invalid/unsupported control element"), \
        PARA_ERROR(ALSA_MIX_GET_VAL, "could not read control element state"), \
        PARA_ERROR(ALSA_MIX_SET_VAL, "could not set control element state"), \
+       PARA_ERROR(ALSA_MIX_RANGE, "value control element out of range"), \
 
 
 #define RESAMPLE_FILTER_ERRORS \
@@ -78,12 +77,16 @@ extern const char **para_errlist[];
        PARA_ERROR(NO_VALID_FILES, "no valid file found in playlist"), \
        PARA_ERROR(BAD_PLAY_CMD, "invalid command"), \
 
+#define FADE_ERRORS \
+       PARA_ERROR(BAD_CHANNEL, "invalid channel"), \
 
 #define FLACDEC_FILTER_ERRORS \
        PARA_ERROR(FLACDEC_DECODER_ALLOC, "could not allocate stream decoder"), \
        PARA_ERROR(FLACDEC_DECODER_INIT, "could not init stream decoder"), \
        PARA_ERROR(FLACDEC_EOF, "flacdec encountered end of file condition"), \
 
+#define GUI_ERRORS \
+       PARA_ERROR(GUI_SIGCHLD, "received SIGCHLD"), \
 
 #define FLAC_AFH_ERRORS \
        PARA_ERROR(FLAC_CHAIN_ALLOC, "could not create metadata chain"), \
@@ -178,6 +181,7 @@ extern const char **para_errlist[];
        PARA_ERROR(AO_PLAY, "ao_play() failed"), \
        PARA_ERROR(AO_BAD_SAMPLE_FORMAT, "ao: unsigned sample formats not supported"), \
        PARA_ERROR(AO_PTHREAD, "pthread error"), \
+       PARA_ERROR(AO_EOF, "ao: end of file"), \
 
 
 #define COMPRESS_FILTER_ERRORS \
@@ -301,6 +305,7 @@ extern const char **para_errlist[];
        PARA_ERROR(SERVER_EOF, "connection closed by para_server"), \
        PARA_ERROR(SERVER_CMD_SUCCESS, "command terminated successfully"), \
        PARA_ERROR(SERVER_CMD_FAILURE, "command failed"), \
+       PARA_ERROR(INCOMPAT_FEAT, "client/server incompatibility"), \
 
 
 #define NET_ERRORS \
@@ -337,6 +342,7 @@ extern const char **para_errlist[];
        PARA_ERROR(UNSUPPORTED_AUDIO_FORMAT, "given audio format not supported"), \
        PARA_ERROR(NOT_PLAYING, "not playing"), \
        PARA_ERROR(AUDIOD_OFF, "audiod switched off"), \
+       PARA_ERROR(STATUS_TIMEOUT, "status item timeout"), \
 
 
 #define AUDIOD_COMMAND_ERRORS \
@@ -464,7 +470,7 @@ extern const char **para_errlist[];
        PARA_ERROR(SENDER_CMD, "command not supported by this sender"), \
        PARA_ERROR(SERVER_CRASH, "para_server crashed -- can not live without it"), \
        PARA_ERROR(BAD_USER, "auth request for invalid user"), \
-       PARA_ERROR(BAD_FEATURE, "request for unknown or invalid feature"), \
+       PARA_ERROR(BAD_FEATURE, "invalid feature request"), \
        PARA_ERROR(BAD_AUTH, "authentication failure"), \
 
 
@@ -607,7 +613,7 @@ _static_inline_ const char *para_strerror(int num)
  *
  * This should be used for all calls to osl functions that return an osl error
  * code. It changes the return value appropriately so that it can be used for
- * printing the correct error message vi para_strerror().
+ * printing the correct error message with para_strerror().
  *
  * \return \a ret if \a ret >= 0, a paraslash error code otherwise.
  */
diff --git a/error2.c b/error2.c
new file mode 100644 (file)
index 0000000..9271dad
--- /dev/null
+++ b/error2.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2013-2014 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file error2.c Simple program to create error2.h. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <ctype.h>
+
+// #define DEBUG
+#ifdef DEBUG
+       #define log(fmt, ...) fprintf(stderr, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)
+#else
+       #define log(...) do {;} while (0)
+#endif /* DEBUG*/
+
+#define HASH_TABLE_BITS 8
+#define HASH_TABLE_SIZE (1 << HASH_TABLE_BITS)
+
+/* number of executables seen so far */
+static int num_exe;
+
+struct hash_table_entry {
+       char *key;
+       /* only used for objecs, not for executables */
+       unsigned exe_bitmask;
+};
+
+static struct hash_table_entry exe_table[HASH_TABLE_SIZE];
+static struct hash_table_entry obj_table[HASH_TABLE_SIZE];
+
+/* no need for anything sophisticated here */
+static int hash_token(const char *tok)
+{
+       uint32_t tmp = 31415927;
+       const uint8_t *src = (typeof(src))tok;
+
+       for (; *src; src++) {
+               tmp *= 27182817;
+               tmp += *tok;
+       }
+       return tmp % HASH_TABLE_SIZE;
+}
+
+static inline bool slot_empty(int idx, struct hash_table_entry *table)
+{
+       return table[idx].key == NULL;
+}
+
+static char *safe_strdup(const char *str)
+{
+       char *result = strdup(str);
+       if (result)
+               return result;
+       errno = ENOMEM;
+       perror("strdup");
+       exit(EXIT_FAILURE);
+}
+
+static bool lookup(const char *tok, struct hash_table_entry *table, int *idx)
+{
+       int i, h = hash_token(tok);
+
+       for (i = 0; i < HASH_TABLE_SIZE; i++) {
+               *idx = (h + i) % HASH_TABLE_SIZE;
+               if (slot_empty(*idx, table))
+                       return false;
+               if (!strcmp(table[*idx].key, tok))
+                       return true;
+       }
+       log ("hash table full !?\n");
+       exit(EXIT_FAILURE);
+}
+
+static bool insert(const char *tok, struct hash_table_entry *table, int *idx)
+{
+       if (lookup(tok, table, idx))
+               return false; /* not inserted */
+       table[*idx].key = safe_strdup(tok);
+       return true;
+}
+
+static void process_token(char *tok)
+{
+       int idx;
+       size_t len = strlen(tok);
+
+       assert(len > 0);
+       if (tok[len - 1] == ':') {
+               tok[len - 1] = '\0';
+               if (insert(tok, exe_table, &idx)) { /* new exe */
+                       log("exe #%d: '%s', idx: %d\n", num_exe, tok, idx);
+                       num_exe++;
+               }
+       } else {
+               if (num_exe == 0) {
+                       log("invalid input\n");
+                       exit(EXIT_FAILURE);
+               }
+               insert(tok, obj_table, &idx);
+               obj_table[idx].exe_bitmask |= (1 << (num_exe - 1));
+       }
+}
+
+static void print_ss_enum(int idx)
+{
+       char *s = obj_table[idx].key;
+
+       printf("SS_ENUM(");
+       for (; *s; s++)
+               printf("%c", toupper(*s));
+       printf(");\n");
+}
+
+static void dump_bipolar(void)
+{
+       int i, j;
+
+       for (i = 0; i < HASH_TABLE_SIZE; i++) {
+               if (slot_empty(i, obj_table))
+                       continue;
+               printf("#ifdef MAIN_INPUT_FILE_IS_%s\n", obj_table[i].key);
+               for (j = 0; j < HASH_TABLE_SIZE; j++) {
+                       unsigned mi, mj;
+                       if (slot_empty(j, obj_table))
+                               continue;
+                       mi = obj_table[i].exe_bitmask;
+                       mj = obj_table[j].exe_bitmask;
+                       if ((mi & mj) == mi)
+                               print_ss_enum(j);
+               }
+               printf("#endif\n");
+       }
+}
+
+/**
+ * The main function of error2.c.
+ *
+ * The purpose of this program is to create the error2.h file which defines the
+ * enumerations of all error codes which may be used by any given .c file. This
+ * header is included by most .c files of the paraslash suite.
+ *
+ * Since this program is executed on the build system, it must be compiled with
+ * the host compiler.
+ *
+ * \return \p EXIT_SUCCESS or \p EXIT_FAILURE.
+ */
+int main(void)
+{
+       int ret;
+
+       for (;;) {
+               char tok[100];
+               ret = scanf("%96s", tok);
+               if (ret != 1)
+                       break;
+               process_token(tok);
+       }
+       dump_bipolar();
+       return 0;
+}
diff --git a/error2.pl b/error2.pl
deleted file mode 100755 (executable)
index 78ff2c5..0000000
--- a/error2.pl
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env perl
-
-use warnings;
-use strict;
-
-my %matrix;
-my @executables;
-my %objects;
-
-sub make_matrix
-{
-       my ($line, $e, @fields, $field);
-
-       while (defined($line = <>)) {
-               chomp($line);
-               if ($line =~ "^ *\$") {
-                       next;
-               }
-               @fields = split(" ", $line);
-               while (defined(($field = shift(@fields)))) {
-                       if ($field =~ ":\$") {
-                               $field =~ s/://;
-                               $e = $field;
-                               push(@executables, $e);
-                               next;
-                       }
-                       $matrix{$e . ">" . $field} = 1;
-                       $objects{$field} = 1;
-               }
-       }
-}
-
-sub print_safe_objects
-{
-       my @objs = keys(%objects);
-       my ($o1, $o2, $e);
-
-       foreach $o1 (@objs) {
-               print("#ifdef MAIN_INPUT_FILE_IS_$o1\n");
-               O2: foreach $o2 (@objs) {
-                       foreach $e (@executables) {
-                               if (!defined($matrix{$e . ">" . $o1})) {
-                                       next;
-                               }
-                               if (defined($matrix{$e . ">" . $o2})) {
-                                       next;
-                               }
-                               next O2;
-                       }
-                       $_ = $o2;
-                       tr/a-z/A-Z/;
-                       printf("SS_ENUM(%s);\n", $_);
-               }
-               print("#endif\n");
-       }
-}
-make_matrix;
-print_safe_objects;
diff --git a/exec.c b/exec.c
index 66065d374e4e0a19b9410e00c05ec1c0a35225cf..5f48436d2b2fe8ff29cdb88a49971acdd5b32acd 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2003-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/fade.c b/fade.c
index 878b83a17e26f40da9c33c6035dba345353257d4..543a666dd0e32fbf106d263d3cf96e1bb11ce136 100644 (file)
--- a/fade.c
+++ b/fade.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1998-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1998-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -27,7 +27,7 @@ static struct mixer supported_mixer[] = {MIXER_ARRAY};
 #define FOR_EACH_MIXER(i) for ((i) = 0; (i) < NUM_SUPPORTED_MIXERS; (i)++)
 
 static int loglevel;
-__printf_2_3 void date_log(int ll, const char *fmt, ...)
+static __printf_2_3 void date_log(int ll, const char *fmt, ...)
 {
        va_list argp;
        time_t t1;
@@ -37,13 +37,21 @@ __printf_2_3 void date_log(int ll, const char *fmt, ...)
                return;
        time(&t1);
        tm = localtime(&t1);
-       printf("%d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec);
+       fprintf(stderr, "%d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec);
        va_start(argp, fmt);
        vprintf(fmt, argp);
        va_end(argp);
 }
 __printf_2_3 void (*para_log)(int, const char*, ...) = date_log;
 
+static int set_channel(struct mixer *m, struct mixer_handle *h, const char *channel)
+{
+
+       PARA_NOTICE_LOG("using %s mixer channel\n", channel?
+               channel : "default");
+       return m->set_channel(h, channel);
+}
+
 /* Fade to new volume in fade_time seconds. */
 static int fade(struct mixer *m, struct mixer_handle *h, int new_vol, int fade_time)
 {
@@ -55,11 +63,12 @@ static int fade(struct mixer *m, struct mixer_handle *h, int new_vol, int fade_t
        if (fade_time <= 0)
                return m->set(h, new_vol);
        secs = fade_time;
-       PARA_NOTICE_LOG("fading to %d in %d seconds\n", new_vol, secs);
        ret = m->get(h);
        if (ret < 0)
                goto out;
        vol = ret;
+       PARA_NOTICE_LOG("fading %s from %d to %d in %d seconds\n",
+               conf.mixer_channel_arg, vol, new_vol, secs);
        diff = new_vol - vol;
        if (!diff) {
                sleep(secs);
@@ -112,7 +121,7 @@ fail:
        exit(EXIT_FAILURE);
 }
 
-static void change_afs_mode_and_play(char *afs_mode)
+static void change_afs_mode(char *afs_mode)
 {
        char *cmd;
 
@@ -122,7 +131,44 @@ static void change_afs_mode_and_play(char *afs_mode)
        cmd = make_message("select %s", afs_mode);
        client_cmd(cmd);
        free(cmd);
-       client_cmd("play");
+}
+
+static int set_initial_volume(struct mixer *m, struct mixer_handle *h)
+{
+       int i, ret;
+
+       for (i = 0; i < conf.ivol_given; i++) {
+               char *p, *ch, *arg = para_strdup(conf.ivol_arg[i]);
+               int32_t iv;
+               p = strchr(arg, ':');
+               if (p) {
+                       *p = '\0';
+                       p++;
+                       ch = arg;
+               } else {
+                       p = arg;
+                       ch = NULL;
+               }
+               ret = para_atoi32(p, &iv);
+               if (ret < 0) {
+                       free(arg);
+                       return ret;
+               }
+               ret = set_channel(m, h, ch);
+               if (!ch)
+                       ch = "default";
+               if (ret < 0) {
+                       PARA_WARNING_LOG("ignoring channel %s\n", ch);
+                       ret = 0;
+               } else {
+                       PARA_INFO_LOG("initial volume %s: %d\n", ch, iv);
+                       ret = m->set(h, iv);
+               }
+               free(arg);
+               if (ret < 0)
+                       return ret;
+       }
+       return 1;
 }
 
 static int sweet_dreams(struct mixer *m, struct mixer_handle *h)
@@ -138,7 +184,6 @@ static int sweet_dreams(struct mixer *m, struct mixer_handle *h)
        int fot = conf.fo_time_arg;
        int fiv = conf.fi_vol_arg;
        int fov = conf.fo_vol_arg;
-       int iv = conf.ivol_arg;
 
        /* calculate wake time */
        time(&t1);
@@ -162,11 +207,14 @@ static int sweet_dreams(struct mixer *m, struct mixer_handle *h)
        client_cmd("stop");
        sleep(1);
        if (fot) {
-               PARA_INFO_LOG("initial volume: %d\n", iv);
-               ret = m->set(h, iv);
+               ret = set_initial_volume(m, h);
+               if (ret < 0)
+                       return ret;
+               change_afs_mode(fo_mood);
+               client_cmd("play");
+               ret = set_channel(m, h, conf.mixer_channel_arg);
                if (ret < 0)
                        return ret;
-               change_afs_mode_and_play(fo_mood);
                ret = fade(m, h, fov, fot);
                if (ret < 0)
                        return ret;
@@ -175,12 +223,14 @@ static int sweet_dreams(struct mixer *m, struct mixer_handle *h)
                if (ret < 0)
                        return ret;
        }
-       if (conf.sleep_mood_given)
-               change_afs_mode_and_play(sleep_mood);
-       else
+       if (conf.sleep_mood_given) {
+               change_afs_mode(sleep_mood);
+               client_cmd("play");
+       } else
                client_cmd("stop");
        if (!fit)
                return 1;
+       change_afs_mode(fi_mood);
        for (;;) {
                time(&t1);
                if (wake_time_epoch <= t1 + fit)
@@ -191,7 +241,7 @@ static int sweet_dreams(struct mixer *m, struct mixer_handle *h)
                        (delay % 3600) / 60);
                sleep(delay);
        }
-       change_afs_mode_and_play(fi_mood);
+       client_cmd("play");
        ret = fade(m, h, fiv, fit);
        PARA_INFO_LOG("fade complete, returning\n");
        return ret;
@@ -246,22 +296,9 @@ static void init_mixers(void)
        }
 }
 
-static int set_channel(struct mixer *m, struct mixer_handle *h)
+static int set_val(struct mixer *m, struct mixer_handle *h)
 {
-       char *channels;
-       int ret;
-
-       ret = m->set_channel(h, conf.mixer_channel_arg);
-       if (ret >= 0) {
-               PARA_NOTICE_LOG("using %s mixer channel\n",
-                       conf.mixer_channel_arg?  conf.mixer_channel_arg
-                               : "default");
-               return ret;
-       }
-       channels = m->get_channels(h);
-       printf("Available channels: %s\n", channels);
-       free(channels);
-       return ret;
+       return m->set(h, conf.val_arg);
 }
 
 static struct mixer *get_mixer_or_die(void)
@@ -330,7 +367,12 @@ int main(int argc, char *argv[])
        ret = m->open(conf.mixer_device_arg, &h);
        if (ret < 0)
                goto out;
-       ret = set_channel(m, h);
+       ret = set_channel(m, h, conf.mixer_channel_arg);
+       if (ret == -E_BAD_CHANNEL) {
+               char *channels = m->get_channels(h);
+               printf("Available channels: %s\n", channels);
+               free(channels);
+       }
        if (ret < 0)
                goto out;
        switch (conf.mode_arg) {
@@ -340,6 +382,9 @@ int main(int argc, char *argv[])
        case mode_arg_snooze:
                ret = snooze(m, h);
                break;
+       case mode_arg_set:
+               ret = set_val(m, h);
+               break;
        default: /* sleep mode */
                ret = sweet_dreams(m, h);
                break;
diff --git a/fd.c b/fd.c
index 3ab5cad06d1c2980b758062701b681f7761f4664..b8d0d77c3ba94091d753714d54b8181ce7c395ac 100644 (file)
--- a/fd.c
+++ b/fd.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -168,7 +168,7 @@ __printf_2_3 int write_va_buffer(int fd, const char *fmt, ...)
  *
  * \return Zero or a negative error code. If the underlying call to readv(2)
  * returned zero (indicating an end of file condition) or failed for some
- * reason other than \p EAGAIN, a negative return value is returned.
+ * reason other than \p EAGAIN, a negative error code is returned.
  *
  * In any case, \a num_bytes contains the number of bytes that have been
  * successfully read from \a fd (zero if the first readv() call failed with
@@ -526,6 +526,7 @@ static int para_opendir(const char *dirname, DIR **dir, int *cwd)
 {
        int ret;
 
+       *dir = NULL;
        if (cwd) {
                ret = para_open(".", O_RDONLY, 0);
                if (ret < 0)
diff --git a/fd.h b/fd.h
index 3cd2638bbef079f2546aeb13c6dbc0ec4fa89634..c8127a4a5a19547c8b54cab8db2d1bb34a9bc6d8 100644 (file)
--- a/fd.h
+++ b/fd.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 691d696af6e3972ac9f2becf68c0712873fe9624..0909007a48a1b6962f17a0754724b75c0d2e3e37 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2009-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -436,9 +436,9 @@ static void fecdec_close(struct filter_node *fn)
        fn->private_data = NULL;
 }
 
-static int fecdec_post_select(__a_unused struct sched *s, struct task *t)
+static int fecdec_post_select(__a_unused struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        struct btr_node *btrn = fn->btrn;
        int ret;
        struct fec_header h;
index f7b2b30792881e6146a4e2af1d12373f14b8a53f..5d43fe7d1cc8e748f16fd874f668b50bd883891d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -74,9 +74,9 @@ out:
        return ret;
 }
 
-static void file_write_pre_select(struct sched *s, struct task *t)
+static void file_write_pre_select(struct sched *s, void *context)
 {
-       struct writer_node *wn = container_of(t, struct writer_node, task);
+       struct writer_node *wn = context;
        struct private_file_write_data *pfwd = wn->private_data;
        int ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
 
@@ -97,17 +97,16 @@ static void file_write_close(struct writer_node *wn)
        free(pfwd);
 }
 
-static int file_write_post_select(__a_unused struct sched *s,
-               struct task *t)
+static int file_write_post_select(__a_unused struct sched *s, void *context)
 {
-       struct writer_node *wn = container_of(t, struct writer_node, task);
+       struct writer_node *wn = context;
        struct private_file_write_data *pfwd = wn->private_data;
        struct btr_node *btrn = wn->btrn;
        int ret;
        char *buf;
        size_t bytes;
 
-       ret = task_get_notification(t);
+       ret = task_get_notification(wn->task);
        if (ret < 0)
                goto out;
        ret = btr_node_status(btrn, wn->min_iqs, BTR_NT_LEAF);
index 3b68857328b230877e2f8cd9061fb07ee789902c..55afbd3225ff84a74ad20d57b5cfc27c8c7f71cc 100644 (file)
--- a/filter.c
+++ b/filter.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -112,13 +112,13 @@ int main(int argc, char *argv[])
                goto out;
        sit->btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.name = "stdin"));
-       stdin_set_defaults(sit);
-       register_task(&s, &sit->task);
+       stdin_task_register(sit, &s);
 
        fns = para_malloc(conf.filter_given * sizeof(*fns));
        for (i = 0, parent = sit->btrn; i < conf.filter_given; i++) {
                char *fa = conf.filter_arg[i];
                struct filter_node *fn;
+               struct task_info ti;
 
                fn = fns[i] = para_calloc(sizeof(*fn));
                ret = check_filter_arg(fa, &fn->conf);
@@ -128,26 +128,27 @@ int main(int argc, char *argv[])
                }
                fn->filter_num = ret;
                f = filters + fn->filter_num;
-               sprintf(fn->task.status, "%s", f->name);
                PARA_DEBUG_LOG("filter #%d: %s\n", i, f->name);
                fn->btrn = btr_new_node(&(struct btr_node_description)
                        EMBRACE(.name = f->name, .parent = parent,
                        .handler = f->execute, .context = fn));
-               fn->task.pre_select = f->pre_select;
-               fn->task.post_select = f->post_select;
+               ti.name = f->name;
+               ti.pre_select = f->pre_select;
+               ti.post_select = f->post_select;
+               ti.context = fn;
                f->open(fn);
-               register_task(&s, &fn->task);
+               fn->task = task_register(&ti, &s);
                parent = fn->btrn;
        }
        sot->btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.name = "stdout", .parent = parent));
-       stdout_set_defaults(sot);
-       register_task(&s, &sot->task);
+       stdout_task_register(sot, &s);
 
        s.default_timeout.tv_sec = 1;
        s.default_timeout.tv_usec = 0;
        btr_log_tree(sit->btrn, LL_INFO);
        ret = schedule(&s);
+       sched_shutdown(&s);
 out_cleanup:
        for (i--; i >= 0; i--) {
                struct filter_node *fn = fns[i];
index 80bc896be87612d869da1610366333fced5660a3..7af0fbbb2a67421984953ef75660344cfc2c93fa 100644 (file)
--- a/filter.h
+++ b/filter.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -27,7 +27,7 @@ struct filter_node {
        /** The buffer tree node. */
        struct btr_node *btrn;
        /** The task corresponding to this filter node. */
-       struct task task;
+       struct task *task;
        /** The minimal input queue size, see \ref btr_node_status(). */
        size_t min_iqs;
 };
@@ -101,14 +101,14 @@ struct filter {
         * this function is to set file descriptors to be watched by the
         * subsequent select call to the two fd sets.
         */
-       void (*pre_select)(struct sched *s, struct task *t);
+       void (*pre_select)(struct sched *s, void *context);
        /**
         * Convert (filter) the given data.
         *
         * Pointer to the converting function of the filter. On errors, the
         * post_select function is supposed to return a negative error code.
         */
-       int (*post_select)(struct sched *s, struct task *t);
+       int (*post_select)(struct sched *s, void *context);
        /**
         * Answer a buffer tree query.
         *
@@ -121,7 +121,7 @@ struct filter {
 void filter_init(void);
 int check_filter_arg(char *filter_arg, void **conf);
 void print_filter_helps(unsigned flags);
-void generic_filter_pre_select(struct sched *s, struct task *t);
+void generic_filter_pre_select(struct sched *s, void *context);
 int decoder_execute(const char *cmd, unsigned sample_rate, unsigned channels,
                char **result);
 
index 2616c9bdfc940a3415ef6e5abd3a446d4e859b7e..616a7601a76e30db8ccfaeca408cf60f5dc36fab 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -132,18 +132,17 @@ void print_filter_helps(unsigned flags)
  * Set select timeout of the scheduler.
  *
  * \param s The scheduler.
- * \param t The task struct of this filter.
+ * \param context Pointer to the filter node (task context).
  *
  * This looks at the status of the btr node of the filter. If data is available
  * in the input queue of the filter, or if an error occurred, a minimal timeout
  * for the next select call is requested from the scheduler. Otherwise the
  * scheduler timeout is left unchanged.
  */
-void generic_filter_pre_select(struct sched *s, struct task *t)
+void generic_filter_pre_select(struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
 
-       t->error = 0;
        if (btr_node_status(fn->btrn, fn->min_iqs, BTR_NT_INTERNAL) != 0)
                sched_min_delay(s);
 }
index d2f256dc152a8e9547968b5f30ece5cff381754c..eeb0e86c32ac558cc483fe1fc4ce1270c8f0d2f8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2011-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -80,7 +80,7 @@ static FLAC__int64 meta_tell_cb(FLAC__IOHandle handle)
 static int meta_eof_cb(FLAC__IOHandle handle)
 {
        struct private_flac_afh_data *pfad = handle;
-       return pfad->fpos == pfad->map_bytes - 1;
+       return pfad->fpos == pfad->map_bytes;
 }
 
 static int meta_close_cb(FLAC__IOHandle __a_unused handle)
index 09b319a029a5c392a2d1616eb4fc5602be97d1cc..b741f6b2a13c787d3a635db7566c2036cdd08e2f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2011-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -25,7 +25,7 @@ struct private_flacdec_data {
         * We can not consume directly what was copied by the read callback
         * because we might need to feed unconsumend bytes to the decoder again
         * after the read callback ran out of data and returned ABORT. So we
-        * track how many bytes are unconsumed so far.
+        * track how many bytes have been fed to libflac but are unconsumed so far.
         */
        size_t unconsumed;
 };
@@ -63,6 +63,16 @@ static FLAC__StreamDecoderReadStatus read_cb(
        }
        if (*bytes > 0)
                return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+       /**
+       * Nothing was copied. If the input queue of the btrn is smaller than
+       * the minimal input queue size, our parent must have been gone, so
+       * we're not going to get more input. Since our remaining data is not
+       * sufficient do decode a single frame, we have an EOF condition.
+       */
+       if (btr_get_input_queue_size(btrn) < fn->min_iqs) {
+               assert(btr_no_parent(btrn));
+               return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+       }
        /*
         * We are kind of screwed here. Returning CONTINUE with a byte count of
         * zero leads to an endless loop, so we must return either EOF or
@@ -144,7 +154,7 @@ static FLAC__StreamDecoderWriteStatus write_cb(
                        write_int16_host_endian(outbuffer + 4 * k + 2, right);
                }
        }
-       btr_add_output(outbuffer, n * 4, btrn);
+       btr_add_output(outbuffer, n * channels * 2, btrn);
        flac_consume(fn);
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
 }
@@ -200,9 +210,9 @@ static bool output_queue_full(struct btr_node *btrn)
        return btr_get_output_queue_size(btrn) > FLACDEC_MAX_OUTPUT_SIZE;
 }
 
-static void flacdec_pre_select(struct sched *s, struct task *t)
+static void flacdec_pre_select(struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        struct private_flacdec_data *pfd = fn->private_data;
        struct btr_node *btrn = fn->btrn;
        int ret;
@@ -216,12 +226,13 @@ static void flacdec_pre_select(struct sched *s, struct task *t)
                return sched_min_delay(s);
 }
 
-static int flacdec_post_select(__a_unused struct sched *s, struct task *t)
+static int flacdec_post_select(__a_unused struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        struct private_flacdec_data *pfd = fn->private_data;
        struct btr_node *btrn = fn->btrn;
        int ret;
+       FLAC__StreamDecoderState state;
 
        if (output_queue_full(btrn))
                return 0;
@@ -240,7 +251,6 @@ static int flacdec_post_select(__a_unused struct sched *s, struct task *t)
                goto out;
        }
        pfd->have_more = false;
-       FLAC__StreamDecoderState state;
        FLAC__stream_decoder_process_single(pfd->decoder);
        state = FLAC__stream_decoder_get_state(pfd->decoder);
        ret = -E_FLACDEC_EOF;
@@ -248,10 +258,12 @@ static int flacdec_post_select(__a_unused struct sched *s, struct task *t)
                goto out;
        if (state == FLAC__STREAM_DECODER_ABORTED) {
                FLAC__stream_decoder_flush(pfd->decoder);
-               fn->min_iqs = pfd->unconsumed + 1;
+               pfd->unconsumed = 0; /* feed unconsumed bytes again */
+               fn->min_iqs = btr_get_input_queue_size(btrn) + 1;
                ret = 1;
                goto out;
        }
+       pfd->have_more = true;
        fn->min_iqs = 0;
        ret = 1;
 out:
index b4718ec0f8c7910dbdbb3c451adeaa790e24e0d2..751c1a4a65d4d0b3b9e5a90242462a83d3fc6cf1 100644 (file)
--- a/gcrypt.c
+++ b/gcrypt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2011-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -97,7 +97,7 @@ static void mgf1(unsigned char *seed, size_t seed_len, unsigned result_len,
 {
        gcry_error_t gret;
        gcry_md_hd_t handle;
-       size_t n;;
+       size_t n;
        unsigned char *md;
        unsigned char octet_string[4], *rp = result, *end = rp + result_len;
 
@@ -912,11 +912,25 @@ struct stream_cipher {
        gcry_cipher_hd_t handle;
 };
 
-struct stream_cipher *sc_new(const unsigned char *data, int len)
+struct stream_cipher *sc_new(const unsigned char *data, int len,
+               bool use_aes)
 {
        gcry_error_t gret;
-
        struct stream_cipher *sc = para_malloc(sizeof(*sc));
+
+       if (use_aes) {
+               assert(len >= 2 * AES_CRT128_BLOCK_SIZE);
+               gret = gcry_cipher_open(&sc->handle, GCRY_CIPHER_AES128,
+                       GCRY_CIPHER_MODE_CTR, 0);
+               assert(gret == 0);
+               gret = gcry_cipher_setkey(sc->handle, data,
+                       AES_CRT128_BLOCK_SIZE);
+               assert(gret == 0);
+               gret = gcry_cipher_setctr(sc->handle,
+                       data + AES_CRT128_BLOCK_SIZE, AES_CRT128_BLOCK_SIZE);
+               assert(gret == 0);
+               return sc;
+       }
        gret = gcry_cipher_open(&sc->handle, GCRY_CIPHER_ARCFOUR,
                GCRY_CIPHER_MODE_STREAM, 0);
        if (gret) {
@@ -937,39 +951,6 @@ void sc_free(struct stream_cipher *sc)
        free(sc);
 }
 
-int sc_send_bin_buffer(struct stream_cipher_context *scc, char *buf,
-               size_t size)
-{
-       gcry_error_t gret;
-       int ret;
-       unsigned char *tmp = para_malloc(size);
-
-       assert(size);
-       gret = gcry_cipher_encrypt(scc->send->handle, tmp, size,
-               (unsigned char *)buf, size);
-       assert(gret == 0);
-       ret = xwrite(scc->fd, (char *)tmp, size);
-       free(tmp);
-       return ret;
-}
-
-int sc_recv_bin_buffer(struct stream_cipher_context *scc, char *buf,
-               size_t size)
-{
-       gcry_error_t gret;
-       ssize_t ret = recv(scc->fd, buf, size, 0);
-
-       if (ret < 0)
-               ret = -ERRNO_TO_PARA_ERROR(errno);
-       if (ret <= 0)
-               return ret;
-       /* perform in-place encryption */
-       gret = gcry_cipher_encrypt(scc->recv->handle, (unsigned char *)buf, ret,
-               NULL, 0);
-       assert(gret == 0);
-       return ret;
-}
-
 void sc_crypt(struct stream_cipher *sc, struct iovec *src, struct iovec *dst)
 {
        gcry_cipher_hd_t handle = sc->handle;
diff --git a/ggo.c b/ggo.c
index 99171c73457d150cb2f4b193f5fe20df0025e662..deea00bbb1ac46074af5f87ec1fc7787922b0138 100644 (file)
--- a/ggo.c
+++ b/ggo.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2008-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/ggo.h b/ggo.h
index 81565e7c24b50d130afd36560c4f5973973f1090..9d9c5044db9a8c0fa4061bcd579f861c353d54ea 100644 (file)
--- a/ggo.h
+++ b/ggo.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2008-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index ecc16fc89bd66d6a71b351b9e468d125bc8a1775..7948c44957cdf7f8d28e40c7d3253b385969adf6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -54,7 +54,7 @@ struct grab_client {
        /** The point of the grab client's node in the buffer tree. */
        struct btr_node *btrn;
        /* The task of this grab client. */
-       struct task task;
+       struct task *task;
        /** Belongs to either the active or the inactive list. */
        struct list_head node;
 };
@@ -92,9 +92,9 @@ err:
        return -E_GC_WRITE;
 }
 
-static void gc_pre_select(struct sched *s, struct task *t)
+static void gc_pre_select(struct sched *s, void *context)
 {
-       struct grab_client *gc = container_of(t, struct grab_client, task);
+       struct grab_client *gc = context;
        int ret = btr_node_status(gc->btrn, 0, BTR_NT_LEAF);
 
        if (ret == 0)
@@ -108,7 +108,7 @@ static void gc_pre_select(struct sched *s, struct task *t)
  * We need this forward declaration as post_select() needs
  * activate_grab_client and vice versa.
  */
-static int gc_post_select(struct sched *s, struct task *t);
+static int gc_post_select(struct sched *s, void *context);
 
 /**
  * Move a grab client to the active list and start it.
@@ -129,12 +129,13 @@ static void gc_activate(struct grab_client *gc, struct sched *s)
        list_move(&gc->node, &active_grab_client_list);
        gc->btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.name = name, .parent = parent));
-       gc->task.pre_select = gc_pre_select;
-       gc->task.post_select = gc_post_select;
-       snprintf(gc->task.status, sizeof(gc->task.status) - 1, "%s", name);
-       gc->task.status[sizeof(gc->task.status) - 1] = '\0';
-       gc->task.error = 0;
-       register_task(s, &gc->task);
+
+       gc->task = task_register(&(struct task_info) {
+               .name = name,
+               .pre_select = gc_pre_select,
+               .post_select = gc_post_select,
+               .context = gc,
+       }, s);
 }
 
 /**
@@ -184,9 +185,9 @@ static int gc_close(struct grab_client *gc, int err)
        return 0;
 }
 
-static int gc_post_select(__a_unused struct sched *s, struct task *t)
+static int gc_post_select(__a_unused struct sched *s, void *context)
 {
-       struct grab_client *gc = container_of(t, struct grab_client, task);
+       struct grab_client *gc = context;
        struct btr_node *btrn = gc->btrn;
        int ret;
        size_t sz;
index a4e81ced7283144e65db596898b2637196ded577..91adf2eaaadf67870cdee678019de7701f0f9850 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/gui.c b/gui.c
index c20bb7ac98c5d05a9c63c9103a69873b257f0dad..92b7f7cfa0a7826ab5ca95ded4d4a8ca340f46d9 100644 (file)
--- a/gui.c
+++ b/gui.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1998-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1998-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 INIT_GUI_ERRLISTS;
 static char *stat_content[NUM_STAT_ITEMS];
 
-#define STANDARD_STATUS_BAR "para_gui " PACKAGE_VERSION " (hit ? for help)"
-
-static int signal_pipe;
-
-static struct win_data {
+static struct gui_window {
        WINDOW *win;
-       size_t begx;
-       size_t begy;
-       size_t cols;
-       size_t lines;
+       bool needs_update;
 } top, bot, sb, in, sep;
 
+/** How many lines of output to remember. */
 #define RINGBUFFER_SIZE 512
+
 struct rb_entry {
        char *msg;
        size_t len;
        int color;
 };
 static struct ringbuffer *bot_win_rb;
-#define NUM_LINES(len) (1 + (len) / bot.cols)
 
 static unsigned scroll_position;
 
-static int curses_active;
-static pid_t cmd_pid;
+static pid_t exec_pid;
 
-static int command_fds[2];
-static int stat_pipe = -1;
+static int exec_fds[2] = {-1, -1};
 static struct gui_args_info conf;
+static int loglevel;
 
-enum {GETCH_MODE, COMMAND_MODE, EXTERNAL_MODE};
-
+/** Type of the process currently being executed. */
+enum exec_status {
+       EXEC_IDLE, /**< No process running. */
+       EXEC_DCMD, /**< para or display process running. */
+       EXEC_XCMD, /**< External process running. */
+};
 
-#define COLOR_STATUSBAR 52
-#define COLOR_COMMAND 53
-#define COLOR_OUTPUT 54
-#define COLOR_MSG 55
-#define COLOR_ERRMSG 56
-#define COLOR_WELCOME 57
-#define COLOR_SEPARATOR 58
-#define COLOR_TOP 59
-#define COLOR_BOT 60
+/**
+ * Codes for various colors.
+ *
+ * Each status item has its own color pair. The ones defined here start at a
+ * higher number so that they do not overlap with these.
+ */
+enum gui_color_pair {
+       COLOR_STATUSBAR = NUM_STAT_ITEMS + 1,
+       COLOR_COMMAND,
+       COLOR_OUTPUT,
+       COLOR_MSG,
+       COLOR_ERRMSG,
+       COLOR_SEPARATOR,
+       COLOR_TOP,
+       COLOR_BOT,
+};
 
 struct gui_command {
        const char *key;
@@ -80,130 +84,66 @@ struct gui_command {
        void (*handler)(void);
 };
 
-struct stat_item {
-       char name[MAXLINE];
-       char prefix[MAXLINE];
-       char postfix[MAXLINE];
-       unsigned y;
-       unsigned x;
-       unsigned len;
-       int fg, bg;
-       int align;
-       char content[MAXLINE];
+static struct gui_theme theme;
+
+#define GUI_COMMANDS \
+       GUI_COMMAND(help, "?", "print help") \
+       GUI_COMMAND(enlarge_top_win, "+", "enlarge the top window") \
+       GUI_COMMAND(shrink_top_win, "-", "shrink the top window") \
+       GUI_COMMAND(reread_conf, "r", "reread configuration file") \
+       GUI_COMMAND(quit, "q", "exit para_gui") \
+       GUI_COMMAND(refresh, "^L", "redraw the screen") \
+       GUI_COMMAND(next_theme, ".", "switch to next theme") \
+       GUI_COMMAND(prev_theme, ",", "switch to previous theme") \
+       GUI_COMMAND(ll_incr, ">", "increase loglevel (decreases verbosity)") \
+       GUI_COMMAND(ll_decr, "<", "decrease loglevel (increases verbosity)") \
+       GUI_COMMAND(version, "V", "show the para_gui version") \
+       GUI_COMMAND(scroll_up, "<up>", "scroll up one line") \
+       GUI_COMMAND(scroll_down, "<down>", "scroll_down") \
+       GUI_COMMAND(page_up, "<ppage>", "scroll up one page") \
+       GUI_COMMAND(page_down, "<npage>", "scroll down one page") \
+       GUI_COMMAND(scroll_top, "<home>", "scroll to top of buffer") \
+       GUI_COMMAND(cancel_scroll, "<end>", "deactivate scroll mode") \
+
+/* declare command handlers */
+#define GUI_COMMAND(_c, _k, _d) \
+       static void com_ ## _c(void);
+GUI_COMMANDS
+
+#undef GUI_COMMAND
+
+/* define command array */
+#define GUI_COMMAND(_c, _k, _d) \
+       { \
+               .key = _k, \
+               .name = #_c, \
+               .description = _d, \
+               .handler = com_ ## _c \
+       },
+
+static struct gui_command command_list[] = {GUI_COMMANDS {.name = NULL}};
+
+struct input_task {
+       struct task *task;
 };
 
-static struct gui_theme theme;
+struct status_task {
+       struct task *task;
+       pid_t pid;
+       char *buf;
+       int bufsize, loaded;
+       struct timeval next_exec;
+       int fd;
+};
 
-static int _argc;
-static char **_argv;
-
-static void com_help(void);
-static void com_reread_conf(void);
-static void com_enlarge_top_win(void);
-static void com_shrink_top_win(void);
-static void com_version(void);
-__noreturn static void com_quit(void);
-static void com_refresh(void);
-static void com_ll_incr(void);
-static void com_ll_decr(void);
-static void com_prev_theme(void);
-static void com_next_theme(void);
-static void com_scroll_up(void);
-static void com_scroll_down(void);
-static void com_page_up(void);
-static void com_page_down(void);
-static void com_cancel_scrolling(void);
-static void com_scroll_top(void);
-
-static struct gui_command command_list[] = {
-       {
-               .key = "?",
-               .name = "help",
-               .description = "print help",
-               .handler = com_help
-       }, {
-               .key = "+",
-               .name = "enlarge_win",
-               .description = "enlarge the top window",
-               .handler = com_enlarge_top_win
-       }, {
-               .key = "-",
-               .name = "shrink_win",
-               .description = "shrink the top window",
-               .handler = com_shrink_top_win
-       }, {
-               .key = "r",
-               .name = "reread_conf",
-               .description = "reread configuration file",
-               .handler = com_reread_conf
-       }, {
-               .key = "q",
-               .name = "quit",
-               .description = "exit para_gui",
-               .handler = com_quit
-       }, {
-               .key = "^L",
-               .name = "refresh",
-               .description = "redraw the screen",
-               .handler = com_refresh
-       }, {
-               .key = ".",
-               .name = "next_theme",
-               .description = "switch to next theme",
-               .handler = com_next_theme
-       }, {
-               .key = ",",
-               .name = "prev_theme",
-               .description = "switch to previous stream",
-               .handler = com_prev_theme
-       }, {
-               .key = ">",
-               .name = "ll_incr",
-               .description = "increase loglevel (decreases verbosity)",
-               .handler = com_ll_incr
-       }, {
-               .key = "<",
-               .name = "ll_decr",
-               .description = "decrease loglevel (increases verbosity)",
-               .handler = com_ll_decr
-       }, {
-               .key = "V",
-               .name = "version",
-               .description = "show the para_gui version",
-               .handler = com_version
-       }, {
-               .key = "<up>",
-               .name = "scroll_up",
-               .description = "scroll up one line",
-               .handler = com_scroll_up
-       }, {
-               .key = "<down>",
-               .name = "scroll_down",
-               .description = "scroll down one line",
-               .handler = com_scroll_down
-       }, {
-               .key = "<ppage>",
-               .name = "page_up",
-               .description = "scroll up one page",
-               .handler = com_page_up
-       }, {
-               .key = "<npage>",
-               .name = "page_down",
-               .description = "scroll down one page",
-               .handler = com_page_down
-       }, {
-               .key = "<home>",
-               .name = "scroll_top",
-               .description = "scroll to top of buffer",
-               .handler = com_scroll_top
-       }, {
-               .key = "<end>",
-               .name = "cancel_scroll",
-               .description = "deactivate scroll mode",
-               .handler = com_cancel_scrolling
-       }, {
-               .handler = NULL
-       }
+/** Stdout/stderr of the executing process is read in chunks of this size. */
+#define COMMAND_BUF_SIZE 32768
+
+struct exec_task {
+       struct task *task;
+       char command_buf[2][COMMAND_BUF_SIZE]; /* stdout/stderr of command */
+       int cbo[2]; /* command buf offsets */
+       unsigned flags[2]; /* passed to for_each_line() */
 };
 
 static int find_cmd_byname(char *name)
@@ -216,6 +156,37 @@ static int find_cmd_byname(char *name)
        return -1;
 }
 
+/*
+ * Even though ncurses provides getmaxx and getmaxy, these functions/macros are
+ * not described in the XSI Curses standard.
+ */
+static int get_num_lines(struct gui_window *w)
+{
+       int lines;
+       __a_unused int cols; /* avoid "set but not used" warnings */
+
+       getmaxyx(w->win, lines, cols);
+       return lines;
+}
+
+static int get_num_cols(struct gui_window *w)
+{
+       __a_unused int lines; /* avoid "set but not used" warnings */
+       int cols;
+
+       getmaxyx(w->win, lines, cols);
+       return cols;
+}
+
+/** Number of lines of the window are occupied by an output line. */
+#define NUM_LINES(len) (1 + (len) / get_num_cols(&bot))
+
+/* isendwin() returns false before initscr() was called */
+static bool curses_active(void)
+{
+       return top.win && !isendwin();
+}
+
 /* taken from mutt */
 static char *km_keyname(int c)
 {
@@ -272,24 +243,6 @@ static char *km_keyname(int c)
        return buf;
 }
 
-static char *configfile_exists(void)
-{
-       static char *config_file;
-       char *tmp;
-
-       if (!conf.config_file_given) {
-               if (!config_file) {
-                       char *home = para_homedir();
-                       config_file = make_message("%s/.paraslash/gui.conf",
-                               home);
-                       free(home);
-               }
-               tmp = config_file;
-       } else
-               tmp = conf.config_file_arg;
-       return file_exists(tmp)? tmp: NULL;
-}
-
 /* Print given number of spaces to curses window. */
 static void add_spaces(WINDOW* win, unsigned int num)
 {
@@ -349,59 +302,64 @@ static int align_str(WINDOW* win, char *str, unsigned int len,
        return 1;
 }
 
+static void refresh_window(struct gui_window *gw)
+{
+       gw->needs_update = true;
+}
+
+static bool window_update_needed(void)
+{
+       return top.needs_update || bot.needs_update || sb.needs_update ||
+               in.needs_update || sep.needs_update;
+}
+
 __printf_2_3 static void print_in_bar(int color, const char *fmt,...)
 {
        char *msg;
        va_list ap;
 
-       if (!curses_active)
+       if (!curses_active())
                return;
        wattron(in.win, COLOR_PAIR(color));
        va_start(ap, fmt);
        xvasprintf(&msg, fmt, ap);
        va_end(ap);
        wmove(in.win, 0, 0);
-       align_str(in.win, msg, sb.cols, LEFT);
+       align_str(in.win, msg, get_num_cols(&in), LEFT);
        free(msg);
-       wrefresh(in.win);
+       refresh_window(&in);
 }
 
-/*
- * update the status bar
- */
 static void print_status_bar(void)
 {
        char *tmp;
 
-       if (!curses_active)
-               return;
-       tmp = para_strdup(STANDARD_STATUS_BAR);
+       tmp = para_strdup("para_gui " PACKAGE_VERSION " (hit ? for help)");
        wmove(sb.win, 0, 0);
-       align_str(sb.win, tmp, sb.cols, CENTER);
+       align_str(sb.win, tmp, get_num_cols(&sb), CENTER);
        free(tmp);
-       wrefresh(sb.win);
 }
 
 /*
  * get the number of the oldest rbe that is (partially) visible. On return,
- * lines contains the sum of the number of lines of all visable entries. If the
+ * lines contains the sum of the number of lines of all visible entries. If the
  * first one is only partially visible, lines is greater than bot.lines.
  */
 static int first_visible_rbe(unsigned *lines)
 {
-       int i;
+       int i, bot_lines = get_num_lines(&bot);
+
        *lines = 0;
        for (i = scroll_position; i < RINGBUFFER_SIZE; i++) {
                struct rb_entry *rbe = ringbuffer_get(bot_win_rb, i);
                int rbe_lines;
                if (!rbe)
                        return i - 1;
-//             fprintf(stderr, "found: %s\n", rbe->msg);
                rbe_lines = NUM_LINES(rbe->len);
-               if (rbe_lines > bot.lines)
+               if (rbe_lines > bot_lines)
                        return -1;
                *lines += rbe_lines;
-               if (*lines >= bot.lines)
+               if (*lines >= bot_lines)
                        return i;
        }
        return RINGBUFFER_SIZE - 1;
@@ -412,7 +370,7 @@ returns number of first visible rbe, *lines is the number of lines drawn.
  */
 static int draw_top_rbe(unsigned *lines)
 {
-       int ret, fvr = first_visible_rbe(lines);
+       int bot_cols, bot_lines, ret, fvr = first_visible_rbe(lines);
        struct rb_entry *rbe;
        size_t bytes_to_skip, cells_to_skip, width;
 
@@ -422,9 +380,10 @@ static int draw_top_rbe(unsigned *lines)
        rbe = ringbuffer_get(bot_win_rb, fvr);
        if (!rbe)
                return -1;
-       if (*lines > bot.lines) {
+       getmaxyx(bot.win, bot_lines, bot_cols);
+       if (*lines > bot_lines) {
                /* rbe is partially visible multi-line */
-               cells_to_skip = (*lines - bot.lines) * bot.cols;
+               cells_to_skip = (*lines - bot_lines) * bot_cols;
                ret = skip_cells(rbe->msg, cells_to_skip, &bytes_to_skip);
                if (ret < 0)
                        return ret;
@@ -444,14 +403,14 @@ static int draw_top_rbe(unsigned *lines)
 static void redraw_bot_win(void)
 {
        unsigned lines;
-       int i;
+       int i, bot_lines = get_num_lines(&bot);
 
        wmove(bot.win, 0, 0);
        wclear(bot.win);
        i = draw_top_rbe(&lines);
        if (i <= 0)
                goto out;
-       while (i > 0 && lines < bot.lines) {
+       while (i > 0 && lines < bot_lines) {
                struct rb_entry *rbe = ringbuffer_get(bot_win_rb, --i);
                if (!rbe) {
                        lines++;
@@ -464,7 +423,7 @@ static void redraw_bot_win(void)
                waddstr(bot.win, rbe->msg);
        }
 out:
-       wrefresh(bot.win);
+       refresh_window(&bot);
 }
 
 static void rb_add_entry(int color, char *msg)
@@ -480,7 +439,6 @@ static void rb_add_entry(int color, char *msg)
        new->len = len;
        new->msg = msg;
        old = ringbuffer_add(bot_win_rb, new);
-//     fprintf(stderr, "added: %s\n", new->msg);
        if (old) {
                free(old->msg);
                free(old);
@@ -506,196 +464,66 @@ __printf_2_3 static void outputf(int color, const char* fmt,...)
        char *msg;
        va_list ap;
 
-       if (!curses_active)
+       if (!curses_active())
                return;
        va_start(ap, fmt);
        xvasprintf(&msg, fmt, ap);
        va_end(ap);
        rb_add_entry(color, msg);
-       wrefresh(bot.win);
+       refresh_window(&bot);
 }
 
 static int add_output_line(char *line, void *data)
 {
        int color = *(int *)data? COLOR_ERRMSG : COLOR_OUTPUT;
-       if (!curses_active)
+
+       if (!curses_active())
                return 1;
        rb_add_entry(color, para_strdup(line));
        return 1;
 }
 
-static int loglevel;
-
-__printf_2_3 void curses_log(int ll, const char *fmt,...)
+static __printf_2_3 void curses_log(int ll, const char *fmt,...)
 {
-       int color;
-       char *msg;
        va_list ap;
 
-       if (ll < loglevel || !curses_active)
+       if (ll < loglevel)
                return;
-       switch (ll) {
-               case LL_DEBUG:
-               case LL_INFO:
-               case LL_NOTICE:
-                       color = COLOR_MSG;
-                       break;
-               default:
-                       color = COLOR_ERRMSG;
-       }
        va_start(ap, fmt);
-       xvasprintf(&msg, fmt, ap);
+       if (curses_active()) {
+               int color = ll <= LL_NOTICE? COLOR_MSG : COLOR_ERRMSG;
+               char *msg;
+               unsigned bytes = xvasprintf(&msg, fmt, ap);
+               if (bytes > 0 && msg[bytes - 1] == '\n')
+                       msg[bytes - 1] = '\0'; /* cut trailing newline */
+               rb_add_entry(color, msg);
+               refresh_window(&bot);
+       } else if (exec_pid <= 0) /* no external command running */
+               vfprintf(stderr, fmt, ap);
        va_end(ap);
-       chop(msg);
-       rb_add_entry(color, msg);
-       wrefresh(bot.win);
 }
+/** The log function of para_gui, always set to curses_log(). */
 __printf_2_3 void (*para_log)(int, const char*, ...) = curses_log;
 
-static void setup_signal_handling(void)
-{
-       signal_pipe = para_signal_init();
-       para_install_sighandler(SIGINT);
-       para_install_sighandler(SIGTERM);
-       para_install_sighandler(SIGCHLD);
-       para_install_sighandler(SIGWINCH);
-       para_install_sighandler(SIGUSR1);
-}
-
-/* kill every process in the process group and exit */
-__noreturn static void kill_pg_and_die(int ret)
-{
-       para_sigaction(SIGTERM, SIG_IGN);
-       kill(0, SIGTERM);
-       exit(ret);
-}
-
 static void shutdown_curses(void)
 {
-       if (!curses_active)
-               return;
        def_prog_mode();
-       curses_active = 0;
        endwin();
 }
 
-__noreturn static void finish(int ret)
-{
-       shutdown_curses();
-       kill_pg_and_die(ret);
-}
-
-/*
- * exit curses and print given message to stdout/stderr
- */
-__noreturn __printf_2_3 static void msg_n_exit(int ret, const char* fmt, ...)
+/* disable curses, print a message, kill running processes and exit */
+__noreturn __printf_2_3 static void die(int exit_code, const char* fmt, ...)
 {
        va_list argp;
-       FILE *outfd = ret? stderr: stdout;
 
        shutdown_curses();
        va_start(argp, fmt);
-       vfprintf(outfd, fmt, argp);
+       vfprintf(stderr, fmt, argp);
        va_end(argp);
-       kill_pg_and_die(ret);
-}
-
-static void print_welcome(void)
-{
-       if (loglevel > LL_NOTICE)
-               return;
-       outputf(COLOR_WELCOME, "Welcome to %s. Theme: %s",
-               version_single_line("gui"), theme.name);
-       wclrtoeol(bot.win);
-}
-
-/*
- * init all windows
- */
-static void init_wins(int top_lines)
-{
-       int i;
-
-       top.lines = top_lines;
-       top.cols = COLS;
-       top.begy = 0;
-       top.begx = 0;
-
-       bot.lines = LINES - top.lines - 3;
-       bot.cols = COLS;
-       bot.begy = top.lines + 1;
-       bot.begx = 0;
-
-       sb.lines = 1;
-       sb.cols = COLS;
-       sb.begy = LINES - 2;
-       sb.begx = 0;
-
-       in.lines = 1;
-       in.cols = COLS;
-       in.begy = LINES - 1;
-       in.begx = 0;
-
-       sep.lines = 1;
-       sep.cols = COLS;
-       sep.begy = top.lines;
-       sep.begx = 0;
-
-       assume_default_colors(theme.default_fg, theme.default_bg);
-       if (top.win) {
-               mvwin(top.win, top.begy, top.begx);
-               wresize(top.win, top.lines, top.cols);
-
-               mvwin(sb.win, sb.begy, sb.begx);
-               wresize(sb.win, sb.lines, sb.cols);
-
-               mvwin(sep.win, sep.begy, sep.begx);
-               wresize(sep.win, sep.lines, sep.cols);
-
-               mvwin(bot.win, bot.begy, bot.begx);
-               wresize(bot.win, bot.lines, bot.cols);
-
-               mvwin(in.win, in.begy, in.begx);
-               wresize(in.win, in.lines, in.cols);
-       } else {
-               sep.win = newwin(sep.lines, sep.cols, sep.begy, sep.begx);
-               top.win = newwin(top.lines, top.cols, top.begy, top.begx);
-               bot.win = newwin(bot.lines, bot.cols, bot.begy, bot.begx);
-               sb.win = newwin(sb.lines, sb.cols, sb.begy, sb.begx);
-               in.win = newwin(in.lines, in.cols, in.begy, in.begx);
-               if (!top.win || !bot.win || !sb.win || !in.win || !sep.win)
-                       msg_n_exit(1, "Error: Cannot create curses windows\n");
-               wclear(bot.win);
-               wclear(sb.win);
-               wclear(in.win);
-               scrollok(bot.win, 1);
-               wattron(sb.win, COLOR_PAIR(COLOR_STATUSBAR));
-               wattron(sep.win, COLOR_PAIR(COLOR_SEPARATOR));
-               wattron(bot.win, COLOR_PAIR(COLOR_BOT));
-               wattron(top.win, COLOR_PAIR(COLOR_TOP));
-               nodelay(top.win, 1);
-               nodelay(bot.win, 1);
-               nodelay(sb.win, 1);
-               nodelay(in.win, 0);
-
-               keypad(top.win, 1);
-               keypad(bot.win, 1);
-               keypad(sb.win, 1);
-               keypad(in.win, 1);
-               print_status_bar();
-       }
-       wmove(sep.win, 0, 0);
-       for (i = 1; i <= COLS; i++)
-               waddstr(sep.win, theme.sep_str);
-       wclear(top.win);
-       //wclear(bot.win);
-       wnoutrefresh(top.win);
-       wnoutrefresh(bot.win);
-       //wnoutrefresh(sb.win);
-       print_status_bar();
-       wnoutrefresh(in.win);
-       wnoutrefresh(sep.win);
-       doupdate();
+       /* kill every process in the process group and exit */
+       para_sigaction(SIGTERM, SIG_IGN);
+       kill(0, SIGTERM);
+       exit(exit_code);
 }
 
 /*
@@ -706,16 +534,16 @@ static void print_stat_item(int i)
        char *tmp;
        struct stat_item_data d = theme.data[i];
        char *c = stat_content[i];
+       int top_lines = get_num_lines(&top);
 
-       if (!curses_active || !d.len || !c)
+       if (!curses_active() || !d.len || !c)
                return;
        tmp = make_message("%s%s%s", d.prefix, c, d.postfix);
-       wmove(top.win, d.y * top.lines / 100, d.x * COLS / 100);
-       wrefresh(top.win);
+       wmove(top.win, d.y * top_lines / 100, d.x * COLS / 100);
        wattron(top.win, COLOR_PAIR(i + 1));
        align_str(top.win, tmp, d.len * COLS / 100, d.align);
        free(tmp);
-       wrefresh(top.win);
+       refresh_window(&top);
 }
 
 static int update_item(int item_num, char *buf)
@@ -749,44 +577,11 @@ print:
        return 1;
 }
 
-static int read_stat_pipe(fd_set *rfds)
-{
-       static char *buf;
-       static int bufsize, loaded;
-       int ret, ret2;
-       size_t sz;
-
-       if (stat_pipe < 0)
-               return 0;
-       if (loaded >= bufsize) {
-               if (bufsize > 1000 * 1000) {
-                       loaded = 0;
-                       return 0;
-               }
-               bufsize += bufsize + 1000;
-               buf = para_realloc(buf, bufsize);
-       }
-       assert(loaded < bufsize);
-       ret = read_nonblock(stat_pipe, buf + loaded, bufsize - loaded,
-               rfds, &sz);
-       loaded += sz;
-       ret2 = for_each_stat_item(buf, loaded, update_item);
-       if (ret < 0 || ret2 < 0) {
-               loaded = 0;
-               return ret2 < 0? ret2 : ret;
-       }
-       sz = ret2; /* what is left */
-       if (sz > 0 && sz < loaded)
-               memmove(buf, buf + loaded - sz, sz);
-       loaded = sz;
-       return 1;
-}
-
 static void print_all_items(void)
 {
        int i;
 
-       if (!curses_active)
+       if (!curses_active())
                return;
        FOR_EACH_STATUS_ITEM(i)
                print_stat_item(i);
@@ -802,10 +597,155 @@ static void clear_all_items(void)
        }
 }
 
+static void status_pre_select(struct sched *s, void *context)
+{
+       struct status_task *st = context;
+
+       if (st->fd >= 0)
+               para_fd_set(st->fd, &s->rfds, &s->max_fileno);
+       if (task_get_notification(st->task) < 0)
+               return sched_min_delay(s);
+       if (st->fd < 0)
+               sched_request_barrier_or_min_delay(&st->next_exec, s);
+}
+
+static int status_post_select(struct sched *s, void *context)
+{
+       struct status_task *st = context;
+       size_t sz;
+       int ret, ret2;
+
+       ret = task_get_notification(st->task);
+       if (ret == -E_GUI_SIGCHLD && st->pid > 0) {
+               int exit_status;
+               if (waitpid(st->pid, &exit_status, WNOHANG) == st->pid) {
+                       st->pid = 0;
+                       PARA_ERROR_LOG("stat command exit status: %d",
+                               exit_status);
+               }
+       }
+       if (st->fd < 0) {
+               int fds[3] = {0, 1, 0};
+               if (st->pid > 0)
+                       return 0;
+               /* Avoid busy loop */
+               if (tv_diff(&st->next_exec, now, NULL) > 0)
+                       return 0;
+               st->next_exec.tv_sec = now->tv_sec + 2;
+               ret = para_exec_cmdline_pid(&st->pid, conf.stat_cmd_arg, fds);
+               if (ret < 0)
+                       return 0;
+               ret = mark_fd_nonblocking(fds[1]);
+               if (ret < 0) {
+                       close(fds[1]);
+                       return 0;
+               }
+               st->fd = fds[1];
+               return 0;
+       }
+
+       if (st->loaded >= st->bufsize) {
+               if (st->bufsize > 1000 * 1000) {
+                       st->loaded = 0;
+                       return 0;
+               }
+               st->bufsize += st->bufsize + 1000;
+               st->buf = para_realloc(st->buf, st->bufsize);
+       }
+       assert(st->loaded < st->bufsize);
+       ret = read_nonblock(st->fd, st->buf + st->loaded,
+               st->bufsize - st->loaded, &s->rfds, &sz);
+       st->loaded += sz;
+       ret2 = for_each_stat_item(st->buf, st->loaded, update_item);
+       if (ret < 0 || ret2 < 0) {
+               st->loaded = 0;
+               PARA_NOTICE_LOG("closing stat pipe: %s\n", para_strerror(-ret));
+               close(st->fd);
+               st->fd = -1;
+               clear_all_items();
+               free(stat_content[SI_BASENAME]);
+               stat_content[SI_BASENAME] =
+                       para_strdup("stat command terminated!?");
+               print_all_items();
+               return 0;
+       }
+       sz = ret2; /* what is left */
+       if (sz > 0 && sz < st->loaded)
+               memmove(st->buf, st->buf + st->loaded - sz, sz);
+       st->loaded = sz;
+       return 0;
+}
+
+/*
+ * init all windows
+ */
+static void init_wins(int top_lines)
+{
+       int top_y = 0, bot_y = top_lines + 1, sb_y = LINES - 2,
+               in_y = LINES - 1, sep_y = top_lines;
+       int bot_lines = LINES - top_lines - 3, sb_lines = 1, in_lines = 1,
+               sep_lines = 1;
+
+       assume_default_colors(theme.dflt.fg, theme.dflt.bg);
+       if (top.win) {
+               wresize(top.win, top_lines, COLS);
+               mvwin(top.win, top_y, 0);
+
+               wresize(sb.win, sb_lines, COLS);
+               mvwin(sb.win, sb_y, 0);
+
+               wresize(sep.win, sep_lines, COLS);
+               mvwin(sep.win, sep_y, 0);
+
+               wresize(bot.win, bot_lines, COLS);
+               mvwin(bot.win, bot_y, 0);
+
+               wresize(in.win, in_lines, COLS);
+               mvwin(in.win, in_y, 0);
+       } else {
+               sep.win = newwin(sep_lines, COLS, sep_y, 0);
+               top.win = newwin(top_lines, COLS, top_y, 0);
+               bot.win = newwin(bot_lines, COLS, bot_y, 0);
+               sb.win = newwin(sb_lines, COLS, sb_y, 0);
+               in.win = newwin(in_lines, COLS, in_y, 0);
+               if (!top.win || !bot.win || !sb.win || !in.win || !sep.win)
+                       die(EXIT_FAILURE, "Error: Cannot create curses windows\n");
+               wclear(bot.win);
+               wclear(sb.win);
+               wclear(in.win);
+               scrollok(bot.win, 1);
+               wattron(sb.win, COLOR_PAIR(COLOR_STATUSBAR));
+               wattron(sep.win, COLOR_PAIR(COLOR_SEPARATOR));
+               wattron(bot.win, COLOR_PAIR(COLOR_BOT));
+               wattron(top.win, COLOR_PAIR(COLOR_TOP));
+               nodelay(top.win, 1);
+               nodelay(bot.win, 1);
+               nodelay(sb.win, 1);
+               nodelay(in.win, 0);
+
+               keypad(top.win, 1);
+               keypad(bot.win, 1);
+               keypad(sb.win, 1);
+               keypad(in.win, 1);
+       }
+       wmove(sep.win, 0, 0);
+       whline(sep.win, theme.sep_char, COLS);
+       wclear(top.win);
+       print_all_items();
+       //wclear(bot.win);
+       wnoutrefresh(top.win);
+       wnoutrefresh(bot.win);
+       print_status_bar();
+       wnoutrefresh(sb.win);
+       wnoutrefresh(in.win);
+       wnoutrefresh(sep.win);
+       doupdate();
+}
+
 static void init_pair_or_die(short pair, short f, short b)
 {
        if (init_pair(pair, f, b) == ERR)
-               msg_n_exit(EXIT_FAILURE, "fatal: init_pair() failed\n");
+               die(EXIT_FAILURE, "fatal: init_pair() failed\n");
 }
 
 static void init_colors_or_die(void)
@@ -813,62 +753,48 @@ static void init_colors_or_die(void)
        int i;
 
        if (!has_colors())
-               msg_n_exit(EXIT_FAILURE, "fatal: No color term\n");
+               die(EXIT_FAILURE, "fatal: No color term\n");
        if (start_color() == ERR)
-               msg_n_exit(EXIT_FAILURE, "fatal: failed to start colors\n");
+               die(EXIT_FAILURE, "fatal: failed to start colors\n");
        FOR_EACH_STATUS_ITEM(i)
                if (theme.data[i].len)
-                       init_pair_or_die(i + 1, theme.data[i].fg,
-                               theme.data[i].bg);
-       init_pair_or_die(COLOR_STATUSBAR, theme.sb_fg, theme.sb_bg);
-       init_pair_or_die(COLOR_COMMAND, theme.cmd_fg, theme.cmd_bg);
-       init_pair_or_die(COLOR_OUTPUT, theme.output_fg, theme.output_bg);
-       init_pair_or_die(COLOR_MSG, theme.msg_fg, theme.msg_bg);
-       init_pair_or_die(COLOR_ERRMSG, theme.err_msg_fg, theme.err_msg_bg);
-       init_pair_or_die(COLOR_WELCOME, theme.welcome_fg, theme.welcome_bg);
-       init_pair_or_die(COLOR_SEPARATOR, theme.sep_fg, theme.sep_bg);
-       init_pair_or_die(COLOR_TOP, theme.default_fg, theme.default_bg);
-       init_pair_or_die(COLOR_BOT, theme.default_fg, theme.default_bg);
+                       init_pair_or_die(i + 1, theme.data[i].color.fg,
+                               theme.data[i].color.bg);
+       init_pair_or_die(COLOR_STATUSBAR, theme.sb.fg, theme.sb.bg);
+       init_pair_or_die(COLOR_COMMAND, theme.cmd.fg, theme.cmd.bg);
+       init_pair_or_die(COLOR_OUTPUT, theme.output.fg, theme.output.bg);
+       init_pair_or_die(COLOR_MSG, theme.msg.fg, theme.msg.bg);
+       init_pair_or_die(COLOR_ERRMSG, theme.err_msg.fg, theme.err_msg.bg);
+       init_pair_or_die(COLOR_SEPARATOR, theme.sep.fg, theme.sep.bg);
+       init_pair_or_die(COLOR_TOP, theme.dflt.fg, theme.dflt.bg);
+       init_pair_or_die(COLOR_BOT, theme.dflt.fg, theme.dflt.bg);
 }
 
 /* (Re-)initialize the curses library. */
 static void init_curses(void)
 {
-       curses_active = 1;
-       if (top.win && refresh() == ERR) /* refesh is really needed */
-               msg_n_exit(EXIT_FAILURE, "refresh() failed\n");
+       if (curses_active())
+               return;
+       if (top.win && refresh() == ERR) /* refresh is really needed */
+               die(EXIT_FAILURE, "refresh() failed\n");
        if (LINES < theme.lines_min || COLS < theme.cols_min)
-               msg_n_exit(EXIT_FAILURE, "Error: Terminal (%dx%d) too small"
+               die(EXIT_FAILURE, "Terminal (%dx%d) too small"
                        " (need at least %dx%d)\n", COLS, LINES,
                        theme.cols_min, theme.lines_min);
        curs_set(0); /* make cursor invisible, ignore errors */
        nonl(); /* do not NL->CR/NL on output, always returns OK */
        /* don't echo input */
        if (noecho() == ERR)
-               msg_n_exit(EXIT_FAILURE, "fatal: noecho() failed\n");
+               die(EXIT_FAILURE, "fatal: noecho() failed\n");
        /* take input chars one at a time, no wait for \n */
        if (cbreak() == ERR)
-               msg_n_exit(EXIT_FAILURE, "fatal: cbreak() failed\n");
+               die(EXIT_FAILURE, "fatal: cbreak() failed\n");
        init_colors_or_die();
        clear(); /* ignore non-fatal errors */
        init_wins(theme.top_lines_default);
-       print_all_items();
        // noecho(); /* don't echo input */
 }
 
-static void check_sigchld(void)
-{
-       int ret;
-       pid_t pid;
-reap_next_child:
-       ret = para_reap_child(&pid);
-       if (ret <= 0)
-               return;
-       if (pid == cmd_pid)
-               cmd_pid = 0;
-       goto reap_next_child;
-}
-
 /*
  * This sucker modifies its first argument. *handler and *arg are
  * pointers to 0-terminated strings (inside line). Crap.
@@ -888,313 +814,347 @@ err_out:
        return 0;
 }
 
-static int check_key_map_args(void)
+static void check_key_map_args_or_die(void)
 {
-       char *s;
-       int i, ret = -1;
-       char *tmp = NULL, *handler, *arg;
+       int i;
+       char *tmp = NULL;
 
        for (i = 0; i < conf.key_map_given; ++i) {
-               s = conf.key_map_arg[i];
-               if (!(*s))
-                       goto err_out;
+               char *handler, *arg;
+
                free(tmp);
-               tmp = para_strdup(s);
+               tmp = para_strdup(conf.key_map_arg[i]);
                if (!split_key_map(tmp, &handler, &arg))
-                       goto err_out;
+                       break;
                if (strlen(handler) != 1)
-                       goto err_out;
-               if (*handler != 'x'
-                       && *handler != 'd'
-                       && *handler != 'i'
-                       && *handler != 'p')
-                       goto err_out;
+                       break;
+               if (*handler != 'x' && *handler != 'd' && *handler != 'i'
+                               && *handler != 'p')
+                       break;
                if (*handler != 'i')
                        continue;
                if (find_cmd_byname(arg) < 0)
-                       goto err_out;
+                       break;
        }
-       ret = 0;
-err_out:
+       if (i != conf.key_map_given)
+               die(EXIT_FAILURE, "invalid key map: %s\n", conf.key_map_arg[i]);
        free(tmp);
-       return ret;
+}
+
+static void parse_config_file_or_die(bool override)
+{
+       bool err;
+       char *config_file;
+       struct gui_cmdline_parser_params params = {
+               .override = override,
+               .initialize = 0,
+               .check_required = !override,
+               .check_ambiguity = 0,
+               .print_errors = 1,
+       };
+
+       if (conf.config_file_given)
+               config_file = para_strdup(conf.config_file_arg);
+       else {
+               char *home = para_homedir();
+               config_file = make_message("%s/.paraslash/gui.conf", home);
+               free(home);
+       }
+       if (!file_exists(config_file)) {
+               if (!conf.config_file_given)
+                       err = false;
+               else {
+                       PARA_EMERG_LOG("config file %s does not exist\n",
+                               config_file);
+                       err = true;
+               }
+               goto out;
+       }
+       gui_cmdline_parser_config_file(config_file, &conf, &params);
+       loglevel = get_loglevel_by_name(conf.loglevel_arg);
+       check_key_map_args_or_die();
+       err = false;
+out:
+       free(config_file);
+       if (err)
+               exit(EXIT_FAILURE);
+       theme_init(conf.theme_arg, &theme);
+}
+
+/* reread configuration, terminate on errors */
+static void reread_conf(void)
+{
+       /*
+        * gengetopt might print to stderr and exit on errors. So we have to
+        * shutdown curses first.
+        */
+       shutdown_curses();
+       parse_config_file_or_die(true /* override */);
+       init_curses();
+       print_in_bar(COLOR_MSG, "config file reloaded\n");
 }
 
 /*
  * React to various signal-related events
  */
-static void handle_signal(int sig)
+static int signal_post_select(struct sched *s, __a_unused void *context)
 {
-       switch (sig) {
+       int ret = para_next_signal(&s->rfds);
+
+       if (ret <= 0)
+               return 0;
+       switch (ret) {
        case SIGTERM:
-               msg_n_exit(EXIT_FAILURE,
-                       "only the good die young (caught SIGTERM))\n");
-               return;
-       case SIGWINCH:
-               if (curses_active) {
-                       shutdown_curses();
-                       init_curses();
-                       redraw_bot_win();
-               }
-               return;
+               die(EXIT_FAILURE, "only the good die young (caught SIGTERM)\n");
+               return 1;
        case SIGINT:
-               PARA_WARNING_LOG("caught SIGINT, reset");
+               PARA_WARNING_LOG("caught SIGINT, reset\n");
                /* Nothing to do. SIGINT killed our child which gets noticed
                 * by do_select and resets everything.
                 */
-               return;
+               return 1;
        case SIGUSR1:
-               PARA_NOTICE_LOG("got SIGUSR1, rereading configuration");
-               com_reread_conf();
-               return;
+               PARA_NOTICE_LOG("got SIGUSR1, rereading configuration\n");
+               reread_conf();
+               return 1;
        case SIGCHLD:
-               check_sigchld();
-               return;
+               task_notify_all(s, E_GUI_SIGCHLD);
+               return 1;
        }
+       return 1;
 }
 
-static void status_pre_select(fd_set *rfds, int *max_fileno, struct timeval *tv)
+static enum exec_status exec_status(void)
 {
-       static struct timeval next_exec, atm, diff;
-       int ret, fds[3] = {0, 1, 0};
-       pid_t pid;
-
-       if (stat_pipe >= 0)
-               goto success;
-       /* Avoid busy loop */
-       gettimeofday(&atm, NULL);
-       if (tv_diff(&next_exec, &atm, &diff) > 0) {
-               if (tv_diff(&diff, tv, NULL) < 0)
-                       *tv = diff;
-               return;
-       }
-       next_exec.tv_sec = atm.tv_sec + 2;
-       ret = para_exec_cmdline_pid(&pid, conf.stat_cmd_arg, fds);
-       if (ret < 0)
-               return;
-       ret = mark_fd_nonblocking(fds[1]);
-       if (ret < 0) {
-               close(fds[1]);
-               return;
-       }
-       stat_pipe = fds[1];
-success:
-       para_fd_set(stat_pipe, rfds, max_fileno);
+       if (exec_fds[0] >= 0 || exec_fds[1] >= 0)
+               return EXEC_DCMD;
+       if (exec_pid > 0)
+               return EXEC_XCMD;
+       return EXEC_IDLE;
 }
 
-#define COMMAND_BUF_SIZE 32768
+static void exec_pre_select(struct sched *s, void *context)
+{
+       struct exec_task *et = context;
+       if (exec_fds[0] >= 0)
+               para_fd_set(exec_fds[0], &s->rfds, &s->max_fileno);
+       if (exec_fds[1] >= 0)
+               para_fd_set(exec_fds[1], &s->rfds, &s->max_fileno);
+       if (task_get_notification(et->task) < 0)
+               sched_min_delay(s);
+}
 
-/*
- * This is the core select loop. Besides the (internal) signal
- * pipe, the following other fds are checked according to the mode:
- *
- * GETCH_MODE: check stdin, return when key is pressed
- *
- * COMMAND_MODE: check command fds and stdin. Return when peer has closed both
- * stdout and stderr or when any key is pressed.
- *
- * EXTERNAL_MODE: Check only signal pipe. Used when an external command
- * is running. During that time curses is disabled.  Returns when
- * cmd_pid == 0.
- */
-static int do_select(int mode)
-{
-       fd_set rfds;
-       int ret, i, max_fileno;
-       char command_buf[2][COMMAND_BUF_SIZE] = {"", ""};
-       int cbo[2] = {0, 0}; /* command buf offsets */
-       struct timeval tv;
-       unsigned flags[2] = {0, 0}; /* for for_each_line() */
-
-repeat:
-       tv.tv_sec = conf.timeout_arg  / 1000;
-       tv.tv_usec = (conf.timeout_arg % 1000) * 1000;
-//     ret = refresh_status();
-       FD_ZERO(&rfds);
-       max_fileno = 0;
-       status_pre_select(&rfds, &max_fileno, &tv);
-       /* signal pipe */
-       para_fd_set(signal_pipe, &rfds, &max_fileno);
-       /* command pipe only for COMMAND_MODE */
-       if (mode == COMMAND_MODE) {
-               if (command_fds[0] >= 0)
-                       para_fd_set(command_fds[0], &rfds, &max_fileno);
-               if (command_fds[1] >= 0)
-                       para_fd_set(command_fds[1], &rfds, &max_fileno);
+static int exec_post_select(struct sched *s, void *context)
+{
+       struct exec_task *ct = context;
+       int i, ret;
+
+       ret = task_get_notification(ct->task);
+       if (ret == -E_GUI_SIGCHLD && exec_pid > 0) {
+               int exit_status;
+               if (waitpid(exec_pid, &exit_status, WNOHANG) == exec_pid) {
+                       exec_pid = 0;
+                       init_curses();
+                       PARA_INFO_LOG("command exit status: %d", exit_status);
+                       print_in_bar(COLOR_MSG, " ");
+               }
        }
-       if (mode == GETCH_MODE || mode == COMMAND_MODE)
-               para_fd_set(STDIN_FILENO, &rfds, &max_fileno);
-       ret = para_select(max_fileno + 1, &rfds, NULL, &tv);
-       if (ret <= 0)
-               goto check_return; /* skip fd checks */
-       /* signals */
-       ret = para_next_signal(&rfds);
-       if (ret > 0)
-               handle_signal(ret);
-       /* read command pipe if ready */
-       if (mode == COMMAND_MODE) {
-               for (i = 0; i < 2; i++) {
-                       size_t sz;
-                       if (command_fds[i] < 0)
-                               continue;
-                       ret = read_nonblock(command_fds[i],
-                               command_buf[i] + cbo[i],
-                               COMMAND_BUF_SIZE - 1 - cbo[i], &rfds, &sz);
-                       cbo[i] += sz;
-                       sz = cbo[i];
-                       cbo[i] = for_each_line(flags[i], command_buf[i], cbo[i],
-                               add_output_line, &i);
-                       if (sz != cbo[i]) { /* at least one line found */
-                               wrefresh(bot.win);
-                               flags[i] = 0;
-                       }
-                       if (ret < 0) {
+       for (i = 0; i < 2; i++) {
+               size_t sz;
+               if (exec_fds[i] < 0)
+                       continue;
+               ret = read_nonblock(exec_fds[i],
+                       ct->command_buf[i] + ct->cbo[i],
+                       COMMAND_BUF_SIZE - 1 - ct->cbo[i], &s->rfds, &sz);
+               ct->cbo[i] += sz;
+               sz = ct->cbo[i];
+               ct->cbo[i] = for_each_line(ct->flags[i], ct->command_buf[i],
+                       ct->cbo[i], add_output_line, &i);
+               if (sz != ct->cbo[i]) { /* at least one line found */
+                       refresh_window(&bot);
+                       ct->flags[i] = 0;
+               }
+               if (ret < 0 || exec_pid == 0) {
+                       if (ret < 0)
                                PARA_NOTICE_LOG("closing command fd %d: %s",
                                        i, para_strerror(-ret));
-                               close(command_fds[i]);
-                               command_fds[i] = -1;
-                               flags[i] = 0;
-                               if (command_fds[!i] < 0) /* both fds closed */
-                                       return 0;
-                       }
-                       if (cbo[i] == COMMAND_BUF_SIZE - 1) {
-                               PARA_NOTICE_LOG("discarding overlong line");
-                               cbo[i] = 0;
-                               flags[i] = FELF_DISCARD_FIRST;
-                       }
+                       close(exec_fds[i]);
+                       exec_fds[i] = -1;
+                       ct->flags[i] = 0;
+                       ct->cbo[i] = 0;
+                       if (exec_fds[!i] < 0) /* both fds closed */
+                               return 1;
                }
-       }
-       ret = read_stat_pipe(&rfds);
-       if (ret < 0) {
-               PARA_NOTICE_LOG("closing stat pipe: %s\n", para_strerror(-ret));
-               close(stat_pipe);
-               stat_pipe = -1;
-               clear_all_items();
-               free(stat_content[SI_BASENAME]);
-               stat_content[SI_BASENAME] =
-                       para_strdup("stat command terminated!?");
-               print_all_items();
-       }
-check_return:
-       switch (mode) {
-       case COMMAND_MODE:
-               ret = wgetch(top.win);
-               if (ret != ERR && ret != KEY_RESIZE) {
-                       if (command_fds[0] >= 0) {
-                               close(command_fds[0]);
-                               command_fds[0] = -1;
-                       }
-                       if (command_fds[1] >= 0) {
-                               close(command_fds[1]);
-                               command_fds[1] = -1;
-                       }
-                       if (cmd_pid)
-                               kill(cmd_pid, SIGTERM);
-                       return -1;
+               if (ct->cbo[i] == COMMAND_BUF_SIZE - 1) {
+                       PARA_NOTICE_LOG("discarding overlong line");
+                       ct->cbo[i] = 0;
+                       ct->flags[i] = FELF_DISCARD_FIRST;
                }
-               break;
-       case GETCH_MODE:
-               ret = wgetch(top.win);
-               if (ret != ERR && ret != KEY_RESIZE)
-                       return ret;
-               break;
-       case EXTERNAL_MODE:
-               if (cmd_pid == 0)
-                       return 0;
        }
-       goto repeat;
+       return 0;
 }
 
-/*
- * read from command pipe and print data to bot window
- */
-static void send_output(void)
+static void input_pre_select(struct sched *s, __a_unused void *context)
 {
-       int ret;
+       if (exec_status() != EXEC_XCMD)
+               para_fd_set(STDIN_FILENO, &s->rfds, &s->max_fileno);
+       if (window_update_needed())
+               sched_min_delay(s);
+}
+
+/* read from command pipe and print data to bot window */
+static void exec_and_display(const char *file_and_args)
+{
+       int ret, fds[3] = {0, 1, 1};
 
-       ret = mark_fd_nonblocking(command_fds[0]);
+       outputf(COLOR_COMMAND, "%s", file_and_args);
+       ret = para_exec_cmdline_pid(&exec_pid, file_and_args, fds);
+       if (ret < 0)
+               return;
+       ret = mark_fd_nonblocking(fds[1]);
        if (ret < 0)
                goto fail;
-       ret = mark_fd_nonblocking(command_fds[1]);
+       ret = mark_fd_nonblocking(fds[2]);
        if (ret < 0)
                goto fail;
-       if (do_select(COMMAND_MODE) >= 0)
-               PARA_INFO_LOG("command complete");
-       else
-               PARA_NOTICE_LOG("command aborted");
-       print_in_bar(COLOR_MSG, " ");
+       exec_fds[0] = fds[1];
+       exec_fds[1] = fds[2];
+       print_in_bar(COLOR_MSG, "hit any key to abort\n");
        return;
 fail:
        PARA_ERROR_LOG("%s\n", para_strerror(-ret));
-       close(command_fds[0]);
-       close(command_fds[1]);
+       close(exec_fds[0]);
+       close(exec_fds[1]);
 }
 
-static void para_cmd(char *cmd)
+static void exec_para(const char *args)
 {
-       int ret, fds[3] = {0, 1, 1};
-       char *c = make_message(BINDIR "/para_client -- %s", cmd);
+       char *file_and_args;
 
-       outputf(COLOR_COMMAND, "%s", c);
-       print_in_bar(COLOR_MSG, "executing client command, hit any key to abort\n");
-       ret = para_exec_cmdline_pid(&cmd_pid, c, fds);
-       free(c);
-       if (ret < 0)
-               return;
-       command_fds[0] = fds[1];
-       command_fds[1] = fds[2];
-       send_output();
+       file_and_args = make_message(BINDIR "/para_client -- %s", args);
+       exec_and_display(file_and_args);
+       free(file_and_args);
 }
 
 /*
- * exec command and print output to bot win
+ * shutdown curses and stat pipe before executing external commands
  */
-static void display_cmd(char *cmd)
+static void exec_external(char *file_and_args)
 {
-       int fds[3] = {0, 1, 1};
+       int fds[3] = {-1, -1, -1};
 
-       print_in_bar(COLOR_MSG, "executing display command, hit any key to abort");
-       outputf(COLOR_COMMAND, "%s", cmd);
-       if (para_exec_cmdline_pid(&cmd_pid, cmd, fds) < 0)
+       if (exec_pid)
                return;
-       command_fds[0] = fds[1];
-       command_fds[1] = fds[2];
-       send_output();
+       shutdown_curses();
+       para_exec_cmdline_pid(&exec_pid, file_and_args, fds);
 }
 
-/*
- * shutdown curses and stat pipe before executing external commands
- */
-static void external_cmd(char *cmd)
+static void handle_command(int c)
 {
-       int fds[3] = {-1, -1, -1};
+       int i;
 
-       if (cmd_pid)
-               return;
-       shutdown_curses();
-       if (para_exec_cmdline_pid(&cmd_pid, cmd, fds) < 0)
+       /* first check user-defined key bindings */
+       for (i = 0; i < conf.key_map_given; ++i) {
+               char *tmp, *handler, *arg;
+
+               tmp = para_strdup(conf.key_map_arg[i]);
+               if (!split_key_map(tmp, &handler, &arg)) {
+                       free(tmp);
+                       return;
+               }
+               if (strcmp(tmp, km_keyname(c))) {
+                       free(tmp);
+                       continue;
+               }
+               if (*handler == 'd')
+                       exec_and_display(arg);
+               else if (*handler == 'x')
+                       exec_external(arg);
+               else if (*handler == 'p')
+                       exec_para(arg);
+               else if (*handler == 'i') {
+                       int num = find_cmd_byname(arg);
+                       if (num >= 0)
+                               command_list[num].handler();
+               }
+               free(tmp);
                return;
-       do_select(EXTERNAL_MODE);
-       init_curses();
+       }
+       /* not found, check internal key bindings */
+       for (i = 0; command_list[i].handler; i++) {
+               if (!strcmp(km_keyname(c), command_list[i].key)) {
+                       command_list[i].handler();
+                       return;
+               }
+       }
+       print_in_bar(COLOR_ERRMSG, "key '%s' is not bound, press ? for help",
+               km_keyname(c));
+}
+
+static int input_post_select(__a_unused struct sched *s, __a_unused void *context)
+{
+       int ret;
+       enum exec_status exs = exec_status();
+
+       if (exs == EXEC_XCMD)
+               return 0;
+       if (window_update_needed()) {
+               if (top.needs_update)
+                       assert(wnoutrefresh(top.win) == OK);
+               if (bot.needs_update)
+                       assert(wnoutrefresh(bot.win) == OK);
+               if (sep.needs_update)
+                       assert(wnoutrefresh(sep.win) == OK);
+               if (sb.needs_update)
+                       assert(wnoutrefresh(sb.win) == OK);
+               if (in.needs_update)
+                       assert(wnoutrefresh(in.win) == OK);
+               doupdate();
+               top.needs_update = bot.needs_update = sb.needs_update =
+                       in.needs_update = sep.needs_update = false;
+       }
+       ret = wgetch(top.win);
+       if (ret == ERR)
+               return 0;
+       if (ret == KEY_RESIZE) {
+               if (curses_active()) {
+                       shutdown_curses();
+                       init_curses();
+                       redraw_bot_win();
+               }
+               return 0;
+       }
+       if (exs == EXEC_IDLE)
+               handle_command(ret);
+       else if (exec_pid > 0)
+               kill(exec_pid, SIGTERM);
+       return 0;
+}
+
+static void signal_pre_select(struct sched *s, void *context)
+{
+       struct signal_task *st = context;
+       para_fd_set(st->fd, &s->rfds, &s->max_fileno);
 }
 
 static void print_scroll_msg(void)
 {
        unsigned lines_total, filled = ringbuffer_filled(bot_win_rb);
        int first_rbe = first_visible_rbe(&lines_total);
+
        print_in_bar(COLOR_MSG, "scrolled view: %d-%d/%d\n", filled - first_rbe,
                filled - scroll_position, ringbuffer_filled(bot_win_rb));
 }
 
 static void com_scroll_top(void)
 {
-       int i = RINGBUFFER_SIZE - 1;
+       int i = RINGBUFFER_SIZE - 1, bot_lines = get_num_lines(&bot);
        unsigned lines = 0;
 
        while (i > 0 && !ringbuffer_get(bot_win_rb, i))
                i--;
        /* i is oldest entry */
-       for (; lines < bot.lines && i >= 0; i--) {
+       for (; lines < bot_lines && i >= 0; i--) {
                struct rb_entry *rbe = ringbuffer_get(bot_win_rb, i);
                if (!rbe)
                        break;
@@ -1210,7 +1170,7 @@ static void com_scroll_top(void)
        print_in_bar(COLOR_ERRMSG, "top of buffer is shown\n");
 }
 
-static void com_cancel_scrolling(void)
+static void com_cancel_scroll(void)
 {
 
        if (scroll_position == 0) {
@@ -1224,8 +1184,9 @@ static void com_cancel_scrolling(void)
 static void com_page_down(void)
 {
        unsigned lines = 0;
-       int i = scroll_position;
-       while (lines < bot.lines && --i > 0) {
+       int i = scroll_position, bot_lines = get_num_lines(&bot);
+
+       while (lines < bot_lines && --i > 0) {
                struct rb_entry *rbe = ringbuffer_get(bot_win_rb, i);
                if (!rbe)
                        break;
@@ -1243,7 +1204,7 @@ static void com_page_down(void)
 static void com_page_up(void)
 {
        unsigned lines;
-       int fvr = first_visible_rbe(&lines);
+       int fvr = first_visible_rbe(&lines), bot_lines = get_num_lines(&bot);
 
        if (fvr < 0 || fvr + 1 >= ringbuffer_filled(bot_win_rb)) {
                print_in_bar(COLOR_ERRMSG, "top of buffer is shown\n");
@@ -1252,7 +1213,7 @@ static void com_page_up(void)
        scroll_position = fvr + 1;
        for (; scroll_position > 0; scroll_position--) {
                first_visible_rbe(&lines);
-               if (lines == bot.lines)
+               if (lines == bot_lines)
                        break;
        }
        redraw_bot_win();
@@ -1262,7 +1223,7 @@ static void com_page_up(void)
 static void com_scroll_down(void)
 {
        struct rb_entry *rbe;
-       int rbe_lines;
+       int rbe_lines, bot_lines = get_num_lines(&bot);
 
        if (!scroll_position) {
                print_in_bar(COLOR_ERRMSG, "bottom of buffer is shown\n");
@@ -1272,10 +1233,10 @@ static void com_scroll_down(void)
        rbe = ringbuffer_get(bot_win_rb, scroll_position);
        rbe_lines = NUM_LINES(rbe->len);
        wscrl(bot.win, rbe_lines);
-       wmove(bot.win, bot.lines - rbe_lines, 0);
+       wmove(bot.win, bot_lines - rbe_lines, 0);
        wattron(bot.win, COLOR_PAIR(rbe->color));
        waddstr(bot.win, rbe->msg);
-       wrefresh(bot.win);
+       refresh_window(&bot);
        print_scroll_msg();
 }
 
@@ -1305,7 +1266,6 @@ static void com_scroll_up(void)
                        break;
                rbe_lines = NUM_LINES(rbe->len);
                lines += rbe_lines;
-//             fprintf(stderr, "msg: %s\n", rbe->msg);
                wattron(bot.win, COLOR_PAIR(rbe->color));
                waddstr(bot.win, "\n");
                waddstr(bot.win, rbe->msg);
@@ -1313,7 +1273,7 @@ static void com_scroll_up(void)
                        break;
                i--;
        }
-       wrefresh(bot.win);
+       refresh_window(&bot);
        print_scroll_msg();
        return;
 err_out:
@@ -1342,30 +1302,9 @@ static void com_ll_incr(void)
        print_in_bar(COLOR_MSG, "loglevel set to %d\n", loglevel);
 }
 
-/*
- * reread configuration, terminate on errors
- */
 static void com_reread_conf(void)
 {
-       char *cf =configfile_exists();
-       struct gui_cmdline_parser_params params = {
-               .override = 1,
-               .initialize = 1,
-               .check_required = 0,
-               .check_ambiguity = 0,
-               .print_errors = 0,
-       };
-
-       if (!cf) {
-               PARA_WARNING_LOG("there is no configuration to read");
-               return;
-       }
-       PARA_INFO_LOG("rereading command line options and config file");
-       gui_cmdline_parser_ext(_argc, _argv, &conf, &params);
-       gui_cmdline_parser_config_file(cf, &conf, &params);
-       PARA_NOTICE_LOG("config file reloaded");
-       if (check_key_map_args() < 0)
-               finish(EXIT_FAILURE);
+       reread_conf();
 }
 
 static void com_help(void)
@@ -1407,25 +1346,25 @@ static void com_help(void)
 
 static void com_shrink_top_win(void)
 {
-       if (top.lines <= theme.top_lines_min) {
-               PARA_WARNING_LOG("can not decrease top window");
+       int top_lines = get_num_lines(&top);
+
+       if (top_lines <= theme.top_lines_min) {
+               PARA_WARNING_LOG("can not decrease top window\n");
                return;
        }
-       init_wins(top.lines - 1);
-       wclear(top.win);
-       print_all_items();
+       init_wins(top_lines - 1);
        print_in_bar(COLOR_MSG, "%s", "decreased top window");
 }
 
 static void com_enlarge_top_win(void)
 {
-       if (bot.lines < 3) {
-               PARA_WARNING_LOG("can not increase top window");
+       int top_lines = get_num_lines(&top), bot_lines = get_num_lines(&bot);
+
+       if (bot_lines < 3) {
+               PARA_WARNING_LOG("can not increase top window\n");
                return;
        }
-       init_wins(top.lines + 1);
-       wclear(top.win);
-       print_all_items();
+       init_wins(top_lines + 1);
        print_in_bar(COLOR_MSG, "increased top window");
 }
 
@@ -1436,7 +1375,7 @@ static void com_version(void)
 
 __noreturn static void com_quit(void)
 {
-       finish(0);
+       die(EXIT_SUCCESS, "%s", "");
 }
 
 static void com_refresh(void)
@@ -1445,69 +1384,16 @@ static void com_refresh(void)
        init_curses();
 }
 
-static void change_theme(int next)
-{
-       if (next)
-               next_theme(&theme);
-       else
-               prev_theme(&theme);
-       /* This seems to be needed twice, why? */
-       com_refresh();
-       com_refresh();
-       PARA_NOTICE_LOG("new theme: %s", theme.name);
-}
-
 static void com_next_theme(void)
 {
-       change_theme(1);
+       theme_next(&theme);
+       com_refresh();
 }
 
 static void com_prev_theme(void)
 {
-       change_theme(0);
-}
-
-
-static void handle_command(int c)
-{
-       int i;
-
-       /* first check user's key bindings */
-       for (i = 0; i < conf.key_map_given; ++i) {
-               char *tmp, *handler, *arg;
-
-               tmp = para_strdup(conf.key_map_arg[i]);
-               if (!split_key_map(tmp, &handler, &arg)) {
-                       free(tmp);
-                       return;
-               }
-               if (strcmp(tmp, km_keyname(c))) {
-                       free(tmp);
-                       continue;
-               }
-               if (*handler == 'd')
-                       display_cmd(arg);
-               else if (*handler == 'x')
-                       external_cmd(arg);
-               else if (*handler == 'p')
-                       para_cmd(arg);
-               else if (*handler == 'i') {
-                       int num = find_cmd_byname(arg);
-                       if (num >= 0)
-                               command_list[num].handler();
-               }
-               free(tmp);
-               return;
-       }
-       /* not found, check internal key bindings */
-       for (i = 0; command_list[i].handler; i++) {
-               if (!strcmp(km_keyname(c), command_list[i].key)) {
-                       command_list[i].handler();
-                       return;
-               }
-       }
-       print_in_bar(COLOR_ERRMSG, "key '%s' is not bound, press ? for help",
-               km_keyname(c));
+       theme_prev(&theme);
+       com_refresh();
 }
 
 __noreturn static void print_help_and_die(void)
@@ -1519,54 +1405,90 @@ __noreturn static void print_help_and_die(void)
        exit(0);
 }
 
-int main(int argc, char *argv[])
+static int setup_tasks_and_schedule(void)
 {
-       int ret;
-       char *cf;
+       struct exec_task exec_task = {.task = NULL};
+       struct status_task status_task = {.fd = -1};
+       struct input_task input_task = {.task = NULL};
+       struct signal_task signal_task = {.task = NULL};
+       struct sched sched = {
+               .default_timeout = {
+                       .tv_sec = conf.timeout_arg  / 1000,
+                       .tv_usec = (conf.timeout_arg % 1000) * 1000,
+               },
+       };
 
-       _argc = argc;
-       _argv = argv;
+       exec_task.task = task_register(&(struct task_info) {
+               .name = "exec",
+               .pre_select = exec_pre_select,
+               .post_select = exec_post_select,
+               .context = &exec_task,
+       }, &sched);
+
+       status_task.task = task_register(&(struct task_info) {
+               .name = "status",
+               .pre_select = status_pre_select,
+               .post_select = status_post_select,
+               .context = &status_task,
+       }, &sched);
+
+       input_task.task = task_register(&(struct task_info) {
+               .name = "input",
+               .pre_select = input_pre_select,
+               .post_select = input_post_select,
+               .context = &input_task,
+       }, &sched);
+
+       signal_task.fd = para_signal_init();
+       para_install_sighandler(SIGINT);
+       para_install_sighandler(SIGTERM);
+       para_install_sighandler(SIGCHLD);
+       para_install_sighandler(SIGUSR1);
+       signal_task.task = task_register(&(struct task_info) {
+               .name = "signal",
+               .pre_select = signal_pre_select,
+               .post_select = signal_post_select,
+               .context = &signal_task,
+       }, &sched);
+       return schedule(&sched);
+}
 
+/**
+ * The main function of para_gui.
+ *
+ * \param argc Usual argument count.
+ * \param argv Usual argument vector.
+ *
+ * After initialization para_gui registers the following tasks to the paraslash
+ * scheduler: status, exec, signal, input.
+ *
+ * The status task executes the para_audioc stat command to obtain the status
+ * of para_server and para_audiod, and displays this information in the top
+ * window of para_gui.
+ *
+ * The exec task is responsible for printing the output of the currently
+ * running executable to the bottom window.
+ *
+ * The signal task performs suitable actions according to any signals received.
+ * For example it refreshes all windows on terminal size changes and resets the
+ * terminal on \p SIGTERM.
+ *
+ * The input task reads single key strokes from stdin. For each key pressed, it
+ * executes the command handler associated with this key.
+ *
+ * \return \p EXIT_SUCCESS or \p EXIT_FAILURE.
+ */
+int main(int argc, char *argv[])
+{
        gui_cmdline_parser(argc, argv, &conf); /* exits on errors */
        loglevel = get_loglevel_by_name(conf.loglevel_arg);
        version_handle_flag("gui", conf.version_given);
        if (conf.help_given || conf.detailed_help_given)
                print_help_and_die();
-       cf = configfile_exists();
-       if (!cf && conf.config_file_given) {
-               fprintf(stderr, "can not read config file %s\n",
-                       conf.config_file_arg);
-               exit(EXIT_FAILURE);
-       }
-       if (cf) {
-               struct gui_cmdline_parser_params params = {
-                       .override = 0,
-                       .initialize = 0,
-                       .check_required = 0,
-                       .check_ambiguity = 0,
-                       .print_errors = 1,
-               };
-               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\n");
-               exit(EXIT_FAILURE);
-       }
-       init_theme_or_die(conf.theme_arg, &theme);
-       top.lines = theme.top_lines_default;
-       setup_signal_handling();
+       parse_config_file_or_die(false /* override */);
        bot_win_rb = ringbuffer_new(RINGBUFFER_SIZE);
        setlocale(LC_CTYPE, "");
        initscr(); /* needed only once, always successful */
        init_curses();
-       print_welcome();
-       for (;;) {
-               print_status_bar();
-               ret = do_select(GETCH_MODE);
-               if (!ret)
-                       continue;
-               print_in_bar(COLOR_MSG, " ");
-               handle_command(ret);
-       }
+       return setup_tasks_and_schedule() < 0? EXIT_FAILURE : EXIT_SUCCESS;
 }
diff --git a/gui.h b/gui.h
index 2a3214d0e11acb64d8064ecbfd335a1e06898203..8a469346af4e56d9610ff636770692468af2310c 100644 (file)
--- a/gui.h
+++ b/gui.h
@@ -1,38 +1,72 @@
 /*
- * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 
 /** \file gui.h symbols used by gui and gui_theme */
 
+/**
+ * The foreground and background color of each status item, the decorations and
+ * all messages can be customized through an instance of this structure.
+ */
+struct gui_color_spec {
+       int fg; /**< Foreground color. */
+       int bg; /**< Background color. */
+};
+
+/** How to display one status item. */
 struct stat_item_data {
-       const char *prefix, *postfix;
-       unsigned x, y, len;
-       int fg, bg, align;
+       const char *prefix; /**< Text to print before the item content. */
+       const char *postfix; /**< Text to print after item content. */
+       unsigned x; /**< Horizontal start coordinate for this item. */
+       unsigned y; /**< Vertical start coordinate for this item. */
+       unsigned len; /**< Item width, including \a prefix and \a postfix. */
+       struct gui_color_spec color; /**< Foreground and background color. */
+       int align; /**< How to align this item. */
 };
 
+/** Theme definition. */
 struct gui_theme {
+       /** Printed at startup. */
        const char *name;
+       /** Also printed at startup. */
        const char *author;
-       int sb_fg, sb_bg;
-       int cmd_fg, cmd_bg;
-       int output_fg, output_bg;
-       int msg_fg, msg_bg;
-       int err_msg_fg, err_msg_bg;
-       int welcome_fg, welcome_bg;
-       int sep_fg, sep_bg;
-       const char *sep_str;
-       int default_fg, default_bg;
-
-       int top_lines_default, top_lines_min;
-       int lines_min, cols_min;
+       /** The character for the separator line. */
+       char sep_char;
+       /** Default color, see assume_default_colors(3). */
+       struct gui_color_spec dflt;
+       /** Default number of lines of the top window. */
+       int top_lines_default;
+       /** Minimal admissible number of lines to display the top window. */
+       int top_lines_min;
+       /** Minimal admissible number of lines to display this theme. */
+       int lines_min;
+       /** Minimal admissible number of columns to display this theme. */
+       int cols_min;
+       /** Individual status item properties. */
        struct stat_item_data data[NUM_STAT_ITEMS];
+       /** Color of the status bar. */
+       struct gui_color_spec sb;
+       /** Color of the name and args of the executing process. */
+       struct gui_color_spec cmd;
+       /** Color for stdout of the executing process. */
+       struct gui_color_spec output;
+       /** Color for log messages of moderate severity. */
+       struct gui_color_spec msg;
+       /** Color for severe log messages. */
+       struct gui_color_spec err_msg;
+       /** Color for the separator line. */
+       struct gui_color_spec sep;
 };
 
-void init_theme_or_die(const char *name, struct gui_theme *t);
-void next_theme(struct gui_theme *);
-void prev_theme(struct gui_theme *);
+void theme_init(const char *name, struct gui_theme *t);
+void theme_prev(struct gui_theme *t);
+void theme_next(struct gui_theme *t);
+
+/** Status item text should be left-aligned. */
 #define LEFT 1
+/** Status item text should be right-aligned. */
 #define RIGHT 2
+/** Status item text should be displayed centered. */
 #define CENTER 3
index a0c47fb0da23f0fb5ceb5243dff1f3bb80e81238..b860b359c120318f7693e2816345c6f0a604d7db 100644 (file)
@@ -1,9 +1,11 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 
+/** \file gui_theme.c Theme definitions. */
+
 #include "para.h"
 #include "gui.h"
 #include <curses.h>
@@ -16,28 +18,26 @@ static void init_theme_simple(struct gui_theme *t)
        t->top_lines_min = 2;
        t->cols_min = 40;
        t->top_lines_default = 2;
-       t->sb_bg = COLOR_CYAN;
-       t->sb_fg = COLOR_BLACK;
-       t->cmd_bg = COLOR_WHITE;
-       t->cmd_fg = COLOR_BLACK;
-       t->output_bg = COLOR_BLUE;
-       t->output_fg = COLOR_WHITE;
-       t->msg_bg = COLOR_BLUE;
-       t->msg_fg = COLOR_YELLOW;
-       t->err_msg_bg = COLOR_RED;
-       t->err_msg_fg = COLOR_WHITE;
-       t->welcome_bg = COLOR_BLUE;
-       t->welcome_fg = COLOR_WHITE;
-       t->sep_bg = COLOR_BLUE;
-       t->sep_fg = COLOR_CYAN;
-       t->default_fg = COLOR_WHITE;
-       t->default_bg = COLOR_BLUE;
-       t->sep_str = "*";
+       t->sb.bg = COLOR_CYAN;
+       t->sb.fg = COLOR_BLACK;
+       t->cmd.bg = COLOR_WHITE;
+       t->cmd.fg = COLOR_BLACK;
+       t->output.bg = COLOR_BLUE;
+       t->output.fg = COLOR_WHITE;
+       t->msg.bg = COLOR_BLUE;
+       t->msg.fg = COLOR_YELLOW;
+       t->err_msg.bg = COLOR_RED;
+       t->err_msg.fg = COLOR_WHITE;
+       t->sep.bg = COLOR_BLUE;
+       t->sep.fg = COLOR_CYAN;
+       t->dflt.fg = COLOR_WHITE;
+       t->dflt.bg = COLOR_BLUE;
+       t->sep_char = '*';
 
        d[SI_BASENAME].prefix = "";
        d[SI_BASENAME].postfix = "";
-       d[SI_BASENAME].fg = COLOR_WHITE;
-       d[SI_BASENAME].bg = COLOR_BLUE;
+       d[SI_BASENAME].color.fg = COLOR_WHITE;
+       d[SI_BASENAME].color.bg = COLOR_BLUE;
        d[SI_BASENAME].align = CENTER;
        d[SI_BASENAME].x = 0;
        d[SI_BASENAME].y = 7;
@@ -45,8 +45,8 @@ static void init_theme_simple(struct gui_theme *t)
 
        d[SI_STATUS].prefix = "para_server: ";
        d[SI_STATUS].postfix = "";
-       d[SI_STATUS].fg = COLOR_WHITE;
-       d[SI_STATUS].bg = COLOR_BLUE;
+       d[SI_STATUS].color.fg = COLOR_WHITE;
+       d[SI_STATUS].color.bg = COLOR_BLUE;
        d[SI_STATUS].align = CENTER;
        d[SI_STATUS].x = 0;
        d[SI_STATUS].y = 60;
@@ -54,8 +54,8 @@ static void init_theme_simple(struct gui_theme *t)
 
        d[SI_AUDIOD_STATUS].prefix = "para_audiod: ";
        d[SI_AUDIOD_STATUS].postfix = "";
-       d[SI_AUDIOD_STATUS].fg = COLOR_WHITE;
-       d[SI_AUDIOD_STATUS].bg = COLOR_BLUE;
+       d[SI_AUDIOD_STATUS].color.fg = COLOR_WHITE;
+       d[SI_AUDIOD_STATUS].color.bg = COLOR_BLUE;
        d[SI_AUDIOD_STATUS].align = CENTER;
        d[SI_AUDIOD_STATUS].x = 50;
        d[SI_AUDIOD_STATUS].y = 60;
@@ -75,29 +75,27 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
        t->top_lines_min = 9;
        t->top_lines_default = 11; /* default number of lines */
 
-       t->sb_bg = COLOR_GREEN; /* status bar background */
-       t->sb_fg = COLOR_BLACK; /* status bar foreground */
-       t->cmd_bg = COLOR_BLACK;
-       t->cmd_fg = COLOR_YELLOW;
-       t->output_bg = COLOR_BLACK;
-       t->output_fg = COLOR_CYAN;
-       t->msg_bg = COLOR_BLACK;
-       t->msg_fg = COLOR_WHITE;
-       t->err_msg_bg = COLOR_RED;
-       t->err_msg_fg = COLOR_WHITE;
-       t->welcome_bg = COLOR_BLUE;
-       t->welcome_fg = COLOR_WHITE;
-       t->sep_bg = COLOR_BLACK; /* color of the separator */
-       t->sep_fg = COLOR_BLUE;
-       t->sep_str = "-";
-       t->default_bg = COLOR_BLACK;
-       t->default_fg = COLOR_MAGENTA;
+       t->sb.bg = COLOR_GREEN; /* status bar background */
+       t->sb.fg = COLOR_BLACK; /* status bar foreground */
+       t->cmd.bg = COLOR_BLACK;
+       t->cmd.fg = COLOR_YELLOW;
+       t->output.bg = COLOR_BLACK;
+       t->output.fg = COLOR_CYAN;
+       t->msg.bg = COLOR_BLACK;
+       t->msg.fg = COLOR_WHITE;
+       t->err_msg.bg = COLOR_RED;
+       t->err_msg.fg = COLOR_WHITE;
+       t->sep.bg = COLOR_BLACK; /* color of the separator */
+       t->sep.fg = COLOR_BLUE;
+       t->sep_char = 0; /* default (ACS_HLINE) */
+       t->dflt.bg = COLOR_BLACK;
+       t->dflt.fg = COLOR_MAGENTA;
 
 
        d[SI_PLAY_TIME].prefix = "";
        d[SI_PLAY_TIME].postfix = "";
-       d[SI_PLAY_TIME].fg = COLOR_CYAN;
-       d[SI_PLAY_TIME].bg = COLOR_BLACK;
+       d[SI_PLAY_TIME].color.fg = COLOR_CYAN;
+       d[SI_PLAY_TIME].color.bg = COLOR_BLACK;
        d[SI_PLAY_TIME].align = CENTER;
        d[SI_PLAY_TIME].x = 0;
        d[SI_PLAY_TIME].y = 7;
@@ -105,8 +103,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_BASENAME].prefix = "";
        d[SI_BASENAME].postfix = "";
-       d[SI_BASENAME].fg = COLOR_CYAN;
-       d[SI_BASENAME].bg = COLOR_BLACK;
+       d[SI_BASENAME].color.fg = COLOR_CYAN;
+       d[SI_BASENAME].color.bg = COLOR_BLACK;
        d[SI_BASENAME].align = LEFT;
        d[SI_BASENAME].x = 35;
        d[SI_BASENAME].y = 7;
@@ -114,8 +112,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_STATUS].prefix = "";
        d[SI_STATUS].postfix = " ";
-       d[SI_STATUS].fg = COLOR_RED;
-       d[SI_STATUS].bg = COLOR_BLACK;
+       d[SI_STATUS].color.fg = COLOR_RED;
+       d[SI_STATUS].color.bg = COLOR_BLACK;
        d[SI_STATUS].align = RIGHT;
        d[SI_STATUS].x = 0;
        d[SI_STATUS].y = 17;
@@ -123,8 +121,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_STATUS_FLAGS].prefix = "(";
        d[SI_STATUS_FLAGS].postfix = ")";
-       d[SI_STATUS_FLAGS].fg = COLOR_RED;
-       d[SI_STATUS_FLAGS].bg = COLOR_BLACK;
+       d[SI_STATUS_FLAGS].color.fg = COLOR_RED;
+       d[SI_STATUS_FLAGS].color.bg = COLOR_BLACK;
        d[SI_STATUS_FLAGS].align = LEFT;
        d[SI_STATUS_FLAGS].x = 11;
        d[SI_STATUS_FLAGS].y = 17;
@@ -132,8 +130,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_IMAGE_ID].prefix = "img: ";
        d[SI_IMAGE_ID].postfix = "";
-       d[SI_IMAGE_ID].fg = COLOR_RED;
-       d[SI_IMAGE_ID].bg = COLOR_BLACK;
+       d[SI_IMAGE_ID].color.fg = COLOR_RED;
+       d[SI_IMAGE_ID].color.bg = COLOR_BLACK;
        d[SI_IMAGE_ID].align = CENTER;
        d[SI_IMAGE_ID].x = 21;
        d[SI_IMAGE_ID].y = 17;
@@ -141,8 +139,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_LYRICS_ID].prefix = "lyr: ";
        d[SI_LYRICS_ID].postfix = "";
-       d[SI_LYRICS_ID].fg = COLOR_RED;
-       d[SI_LYRICS_ID].bg = COLOR_BLACK;
+       d[SI_LYRICS_ID].color.fg = COLOR_RED;
+       d[SI_LYRICS_ID].color.bg = COLOR_BLACK;
        d[SI_LYRICS_ID].align = CENTER;
        d[SI_LYRICS_ID].x = 31;
        d[SI_LYRICS_ID].y = 17;
@@ -150,8 +148,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_FORMAT].prefix = "format: ";
        d[SI_FORMAT].postfix = "";
-       d[SI_FORMAT].fg = COLOR_RED;
-       d[SI_FORMAT].bg = COLOR_BLACK;
+       d[SI_FORMAT].color.fg = COLOR_RED;
+       d[SI_FORMAT].color.bg = COLOR_BLACK;
        d[SI_FORMAT].align = CENTER;
        d[SI_FORMAT].x = 42;
        d[SI_FORMAT].y = 17;
@@ -159,8 +157,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_NUM_PLAYED].prefix = "#";
        d[SI_NUM_PLAYED].postfix = "";
-       d[SI_NUM_PLAYED].fg = COLOR_RED;
-       d[SI_NUM_PLAYED].bg = COLOR_BLACK;
+       d[SI_NUM_PLAYED].color.fg = COLOR_RED;
+       d[SI_NUM_PLAYED].color.bg = COLOR_BLACK;
        d[SI_NUM_PLAYED].align = LEFT;
        d[SI_NUM_PLAYED].x = 60;
        d[SI_NUM_PLAYED].y = 17;
@@ -168,8 +166,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_BITRATE].prefix = "";
        d[SI_BITRATE].postfix = "";
-       d[SI_BITRATE].fg = COLOR_RED;
-       d[SI_BITRATE].bg = COLOR_BLACK;
+       d[SI_BITRATE].color.fg = COLOR_RED;
+       d[SI_BITRATE].color.bg = COLOR_BLACK;
        d[SI_BITRATE].align = CENTER;
        d[SI_BITRATE].x = 65;
        d[SI_BITRATE].y = 17;
@@ -177,8 +175,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_FREQUENCY].prefix = "";
        d[SI_FREQUENCY].postfix = "";
-       d[SI_FREQUENCY].fg = COLOR_RED;
-       d[SI_FREQUENCY].bg = COLOR_BLACK;
+       d[SI_FREQUENCY].color.fg = COLOR_RED;
+       d[SI_FREQUENCY].color.bg = COLOR_BLACK;
        d[SI_FREQUENCY].align = CENTER;
        d[SI_FREQUENCY].x = 78;
        d[SI_FREQUENCY].y = 17;
@@ -186,8 +184,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_SCORE].prefix = "sc: ";
        d[SI_SCORE].postfix = "";
-       d[SI_SCORE].fg = COLOR_RED;
-       d[SI_SCORE].bg = COLOR_BLACK;
+       d[SI_SCORE].color.fg = COLOR_RED;
+       d[SI_SCORE].color.bg = COLOR_BLACK;
        d[SI_SCORE].align = CENTER;
        d[SI_SCORE].x = 88;
        d[SI_SCORE].y = 17;
@@ -195,8 +193,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_AUDIOD_STATUS].prefix = "";
        d[SI_AUDIOD_STATUS].postfix = "";
-       d[SI_AUDIOD_STATUS].fg = COLOR_MAGENTA;
-       d[SI_AUDIOD_STATUS].bg = COLOR_BLACK;
+       d[SI_AUDIOD_STATUS].color.fg = COLOR_MAGENTA;
+       d[SI_AUDIOD_STATUS].color.bg = COLOR_BLACK;
        d[SI_AUDIOD_STATUS].align = CENTER;
        d[SI_AUDIOD_STATUS].x = 0;
        d[SI_AUDIOD_STATUS].y = 27;
@@ -204,8 +202,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_DECODER_FLAGS].prefix = "[";
        d[SI_DECODER_FLAGS].postfix = "]";
-       d[SI_DECODER_FLAGS].fg = COLOR_MAGENTA;
-       d[SI_DECODER_FLAGS].bg = COLOR_BLACK;
+       d[SI_DECODER_FLAGS].color.fg = COLOR_MAGENTA;
+       d[SI_DECODER_FLAGS].color.bg = COLOR_BLACK;
        d[SI_DECODER_FLAGS].align = CENTER;
        d[SI_DECODER_FLAGS].x = 5;
        d[SI_DECODER_FLAGS].y = 27;
@@ -213,8 +211,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_MTIME].prefix = "mod: ";
        d[SI_MTIME].postfix = "";
-       d[SI_MTIME].fg = COLOR_MAGENTA;
-       d[SI_MTIME].bg = COLOR_BLACK;
+       d[SI_MTIME].color.fg = COLOR_MAGENTA;
+       d[SI_MTIME].color.bg = COLOR_BLACK;
        d[SI_MTIME].align = CENTER;
        d[SI_MTIME].x = 15;
        d[SI_MTIME].y = 27;
@@ -222,8 +220,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_FILE_SIZE].prefix = "";
        d[SI_FILE_SIZE].postfix = "kb";
-       d[SI_FILE_SIZE].fg = COLOR_MAGENTA;
-       d[SI_FILE_SIZE].bg = COLOR_BLACK;
+       d[SI_FILE_SIZE].color.fg = COLOR_MAGENTA;
+       d[SI_FILE_SIZE].color.bg = COLOR_BLACK;
        d[SI_FILE_SIZE].align = CENTER;
        d[SI_FILE_SIZE].x = 37;
        d[SI_FILE_SIZE].y = 27;
@@ -231,8 +229,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_CHANNELS].prefix = "";
        d[SI_CHANNELS].postfix = "ch";
-       d[SI_CHANNELS].fg = COLOR_MAGENTA;
-       d[SI_CHANNELS].bg = COLOR_BLACK;
+       d[SI_CHANNELS].color.fg = COLOR_MAGENTA;
+       d[SI_CHANNELS].color.bg = COLOR_BLACK;
        d[SI_CHANNELS].align = CENTER;
        d[SI_CHANNELS].x = 47;
        d[SI_CHANNELS].y = 27;
@@ -240,8 +238,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_LAST_PLAYED].prefix = "lp: ";
        d[SI_LAST_PLAYED].postfix = "";
-       d[SI_LAST_PLAYED].fg = COLOR_MAGENTA;
-       d[SI_LAST_PLAYED].bg = COLOR_BLACK;
+       d[SI_LAST_PLAYED].color.fg = COLOR_MAGENTA;
+       d[SI_LAST_PLAYED].color.bg = COLOR_BLACK;
        d[SI_LAST_PLAYED].align = CENTER;
        d[SI_LAST_PLAYED].x = 52;
        d[SI_LAST_PLAYED].y = 27;
@@ -249,8 +247,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_NUM_CHUNKS].prefix = "";
        d[SI_NUM_CHUNKS].postfix = "x";
-       d[SI_NUM_CHUNKS].fg = COLOR_MAGENTA;
-       d[SI_NUM_CHUNKS].bg = COLOR_BLACK;
+       d[SI_NUM_CHUNKS].color.fg = COLOR_MAGENTA;
+       d[SI_NUM_CHUNKS].color.bg = COLOR_BLACK;
        d[SI_NUM_CHUNKS].align = RIGHT;
        d[SI_NUM_CHUNKS].x = 73;
        d[SI_NUM_CHUNKS].y = 27;
@@ -258,8 +256,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_CHUNK_TIME].prefix = "";
        d[SI_CHUNK_TIME].postfix = "ms";
-       d[SI_CHUNK_TIME].fg = COLOR_MAGENTA;
-       d[SI_CHUNK_TIME].bg = COLOR_BLACK;
+       d[SI_CHUNK_TIME].color.fg = COLOR_MAGENTA;
+       d[SI_CHUNK_TIME].color.bg = COLOR_BLACK;
        d[SI_CHUNK_TIME].align = LEFT;
        d[SI_CHUNK_TIME].x = 84;
        d[SI_CHUNK_TIME].y = 27;
@@ -267,8 +265,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_AMPLIFICATION].prefix = "amp:";
        d[SI_AMPLIFICATION].postfix = "";
-       d[SI_AMPLIFICATION].fg = COLOR_MAGENTA;
-       d[SI_AMPLIFICATION].bg = COLOR_BLACK;
+       d[SI_AMPLIFICATION].color.fg = COLOR_MAGENTA;
+       d[SI_AMPLIFICATION].color.bg = COLOR_BLACK;
        d[SI_AMPLIFICATION].align = RIGHT;
        d[SI_AMPLIFICATION].x = 92;
        d[SI_AMPLIFICATION].y = 27;
@@ -276,8 +274,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_TECHINFO].prefix = "";
        d[SI_TECHINFO].postfix = "";
-       d[SI_TECHINFO].fg = COLOR_GREEN;
-       d[SI_TECHINFO].bg = COLOR_BLACK;
+       d[SI_TECHINFO].color.fg = COLOR_GREEN;
+       d[SI_TECHINFO].color.bg = COLOR_BLACK;
        d[SI_TECHINFO].align = CENTER;
        d[SI_TECHINFO].x = 0;
        d[SI_TECHINFO].y = 43;
@@ -285,8 +283,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_TITLE].prefix = "";
        d[SI_TITLE].postfix = ",";
-       d[SI_TITLE].fg = COLOR_GREEN;
-       d[SI_TITLE].bg = COLOR_BLACK;
+       d[SI_TITLE].color.fg = COLOR_GREEN;
+       d[SI_TITLE].color.bg = COLOR_BLACK;
        d[SI_TITLE].align = RIGHT;
        d[SI_TITLE].x = 0;
        d[SI_TITLE].y = 53;
@@ -294,8 +292,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_ARTIST].prefix = " by ";
        d[SI_ARTIST].postfix = "";
-       d[SI_ARTIST].fg = COLOR_GREEN;
-       d[SI_ARTIST].bg = COLOR_BLACK;
+       d[SI_ARTIST].color.fg = COLOR_GREEN;
+       d[SI_ARTIST].color.bg = COLOR_BLACK;
        d[SI_ARTIST].align = LEFT;
        d[SI_ARTIST].x = 45;
        d[SI_ARTIST].y = 53;
@@ -303,8 +301,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_YEAR].prefix = "(";
        d[SI_YEAR].postfix = ")";
-       d[SI_YEAR].fg = COLOR_GREEN;
-       d[SI_YEAR].bg = COLOR_BLACK;
+       d[SI_YEAR].color.fg = COLOR_GREEN;
+       d[SI_YEAR].color.bg = COLOR_BLACK;
        d[SI_YEAR].align = RIGHT;
        d[SI_YEAR].x = 90;
        d[SI_YEAR].y = 53;
@@ -312,8 +310,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_ALBUM].prefix = "A: ";
        d[SI_ALBUM].postfix = ",";
-       d[SI_ALBUM].fg = COLOR_GREEN;
-       d[SI_ALBUM].bg = COLOR_BLACK;
+       d[SI_ALBUM].color.fg = COLOR_GREEN;
+       d[SI_ALBUM].color.bg = COLOR_BLACK;
        d[SI_ALBUM].align = RIGHT;
        d[SI_ALBUM].x = 0;
        d[SI_ALBUM].y = 63;
@@ -321,8 +319,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_COMMENT].prefix = " C: ";
        d[SI_COMMENT].postfix = "";
-       d[SI_COMMENT].fg = COLOR_GREEN;
-       d[SI_COMMENT].bg = COLOR_BLACK;
+       d[SI_COMMENT].color.fg = COLOR_GREEN;
+       d[SI_COMMENT].color.bg = COLOR_BLACK;
        d[SI_COMMENT].align = LEFT;
        d[SI_COMMENT].x = 50;
        d[SI_COMMENT].y = 63;
@@ -330,8 +328,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_AFS_MODE].prefix = "";
        d[SI_AFS_MODE].postfix = "";
-       d[SI_AFS_MODE].fg = COLOR_YELLOW;
-       d[SI_AFS_MODE].bg = COLOR_BLACK;
+       d[SI_AFS_MODE].color.fg = COLOR_YELLOW;
+       d[SI_AFS_MODE].color.bg = COLOR_BLACK;
        d[SI_AFS_MODE].align = CENTER;
        d[SI_AFS_MODE].x = 0;
        d[SI_AFS_MODE].y = 77;
@@ -339,8 +337,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_ATTRIBUTES_TXT].prefix = "";
        d[SI_ATTRIBUTES_TXT].postfix = "";
-       d[SI_ATTRIBUTES_TXT].fg = COLOR_YELLOW;
-       d[SI_ATTRIBUTES_TXT].bg = COLOR_BLACK;
+       d[SI_ATTRIBUTES_TXT].color.fg = COLOR_YELLOW;
+       d[SI_ATTRIBUTES_TXT].color.bg = COLOR_BLACK;
        d[SI_ATTRIBUTES_TXT].align = CENTER;
        d[SI_ATTRIBUTES_TXT].x = 0;
        d[SI_ATTRIBUTES_TXT].y = 87;
@@ -348,8 +346,8 @@ static void init_theme_colorful_blackness(struct gui_theme *t)
 
        d[SI_DIRECTORY].prefix = "dir: ";
        d[SI_DIRECTORY].postfix = "";
-       d[SI_DIRECTORY].fg = COLOR_YELLOW;
-       d[SI_DIRECTORY].bg = COLOR_BLACK;
+       d[SI_DIRECTORY].color.fg = COLOR_YELLOW;
+       d[SI_DIRECTORY].color.bg = COLOR_BLACK;
        d[SI_DIRECTORY].align = CENTER;
        d[SI_DIRECTORY].x = 0;
        d[SI_DIRECTORY].y = 97;
@@ -372,6 +370,7 @@ static struct theme_description themes[] = {
        },
 };
 
+/** Number of elements in the \a themes array. */
 #define NUM_THEMES (ARRAY_SIZE(themes))
 
 static int current_theme_num;
@@ -385,9 +384,18 @@ static void set_theme(int num, struct gui_theme *t)
        t->name = themes[num].name;
        themes[num].init(t);
        current_theme_num = num;
+       PARA_NOTICE_LOG("theme: %s\n", t->name);
 }
 
-void init_theme_or_die(const char *name, struct gui_theme *t)
+/**
+ * Initialize a theme.
+ *
+ * \param name Name of the theme to be initialized.
+ * \param t The function fills out this structure.
+ *
+ * This function exits if there is no theme called \a name.
+ */
+void theme_init(const char *name, struct gui_theme *t)
 {
        int i;
 
@@ -402,12 +410,30 @@ void init_theme_or_die(const char *name, struct gui_theme *t)
        exit(EXIT_FAILURE);
 }
 
-void prev_theme(struct gui_theme *t)
+/**
+ * Activate the previous available theme.
+ *
+ * \param t Theme definition is stored here.
+ *
+ * This picks the theme that comes before the currently active one, or the last
+ * availabe theme, if the current one is the first.
+ *
+ * \sa \ref theme_next().
+ */
+void theme_prev(struct gui_theme *t)
 {
        return set_theme(++current_theme_num, t);
 }
 
-void next_theme(struct gui_theme *t)
+/**
+ * Activate the next available theme.
+ *
+ * \param t Theme definition is stored here.
+ *
+ * This works exacly as theme_prev() but cycles forwards through the list of
+ * available themes.
+ */
+void theme_next(struct gui_theme *t)
 {
        return set_theme(--current_theme_num, t);
 }
index 7db8ba193c1eaa2fd6046efd91011c25d37da032..9deea791a598a42d4a3567885f3b0beb4bb8fcc7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -7,7 +7,12 @@
 /** \file http_recv.c paraslash's http receiver */
 
 #include <regex.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
 #include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
 
 #include "para.h"
 #include "error.h"
@@ -55,12 +60,12 @@ static char *make_request_msg(void)
        return ret;
 }
 
-static void http_recv_pre_select(struct sched *s, struct task *t)
+static void http_recv_pre_select(struct sched *s, void *context)
 {
-       struct receiver_node *rn = container_of(t, struct receiver_node, task);
+       struct receiver_node *rn = context;
        struct private_http_recv_data *phd = rn->private_data;
 
-       if (generic_recv_pre_select(s, t) <= 0)
+       if (generic_recv_pre_select(s, rn) <= 0)
                return;
        if  (phd->status == HTTP_CONNECTED)
                para_fd_set(rn->fd, &s->wfds, &s->max_fileno);
@@ -73,16 +78,16 @@ static void http_recv_pre_select(struct sched *s, struct task *t)
  * area with data read from the socket. In any case, update the state of the
  * connection if necessary.
  */
-static int http_recv_post_select(struct sched *s, struct task *t)
+static int http_recv_post_select(struct sched *s, void *context)
 {
-       struct receiver_node *rn = container_of(t, struct receiver_node, task);
+       struct receiver_node *rn = context;
        struct private_http_recv_data *phd = rn->private_data;
        struct btr_node *btrn = rn->btrn;
        int ret, iovcnt;
        struct iovec iov[2];
        size_t num_bytes;
 
-       ret = task_get_notification(t);
+       ret = task_get_notification(rn->task);
        if (ret < 0)
                goto out;
        ret = btr_node_status(btrn, 0, BTR_NT_ROOT);
index 52383b06b465d14b8369badbc3606a7753ec90c5..3e9c95393c5120c82bd91cc4bd84e5ea9c56f60c 100644 (file)
@@ -1,14 +1,19 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 
 /** \file http_send.c paraslash's http sender */
 
+#include <netinet/in.h>
+#include <sys/socket.h>
 #include <regex.h>
 #include <sys/types.h>
 #include <osl.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
 
 #include "para.h"
 #include "error.h"
diff --git a/imdct.c b/imdct.c
index aab498a390ba3ecdeded2452120d729540e84184..93393e9959edb611e32b92c41a8c09c61e3af55e 100644 (file)
--- a/imdct.c
+++ b/imdct.c
@@ -58,7 +58,9 @@ struct mdct_context {
        struct fft_context fft;
 };
 
-/** cos(2 * pi * x / n) for 0 <= x <= n / 4, followed by its reverse */
+/** \cond cosine_tabs */
+
+/* cos(2 * pi * x / n) for 0 <= x <= n / 4, followed by its reverse */
 #define COSINE_TAB(n) static fftsample_t cos_ ## n[n / 2] __a_aligned(16)
 
 COSINE_TAB(16);
@@ -79,6 +81,7 @@ static fftsample_t *cos_tabs[] = {
        cos_16, cos_32, cos_64, cos_128, cos_256, cos_512, cos_1024, cos_2048,
        cos_4096, cos_8192, cos_16384, cos_32768, cos_65536,
 };
+/** \endcond cosine_tabs */
 
 __a_const static int split_radix_permutation(int i, int n)
 {
diff --git a/install-sh b/install-sh
deleted file mode 100755 (executable)
index 6ce63b9..0000000
+++ /dev/null
@@ -1,294 +0,0 @@
-#!/bin/sh
-#
-# install - install a program, script, or datafile
-#
-# This originates from X11R5 (mit/util/scripts/install.sh), which was
-# later released in X11R6 (xc/config/util/install.sh) with the
-# following copyright and license.
-#
-# Copyright (C) 1994 X Consortium
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
-# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Except as contained in this notice, the name of the X Consortium shall not
-# be used in advertising or otherwise to promote the sale, use or other deal-
-# ings in this Software without prior written authorization from the X Consor-
-# tium.
-#
-#
-# FSF changes to this file are in the public domain.
-#
-# Calling this script install-sh is preferred over install.sh, to prevent
-# `make' implicit rules from creating a file called install from it
-# when there is no Makefile.
-#
-# This script is compatible with the BSD install script, but was written
-# from scratch.  It can only install one file at a time, a restriction
-# shared with many OS's install programs.
-
-
-# set DOITPROG to echo to test this script
-
-# Don't use :- since 4.3BSD and earlier shells don't like it.
-doit="${DOITPROG-}"
-
-
-# put in absolute paths if you don't have them in your path; or use env. vars.
-
-mvprog="${MVPROG-mv}"
-cpprog="${CPPROG-cp}"
-chmodprog="${CHMODPROG-chmod}"
-chownprog="${CHOWNPROG-chown}"
-chgrpprog="${CHGRPPROG-chgrp}"
-stripprog="${STRIPPROG-strip}"
-rmprog="${RMPROG-rm}"
-mkdirprog="${MKDIRPROG-mkdir}"
-
-transformbasename=""
-transform_arg=""
-instcmd="$mvprog"
-chmodcmd="$chmodprog 0755"
-chowncmd=""
-chgrpcmd=""
-stripcmd=""
-rmcmd="$rmprog -f"
-mvcmd="$mvprog"
-src=""
-dst=""
-dir_arg=""
-
-while [ x"$1" != x ]; do
-    case $1 in
-       -c) instcmd=$cpprog
-           shift
-           continue;;
-
-       -d) dir_arg=true
-           shift
-           continue;;
-
-       -m) chmodcmd="$chmodprog $2"
-           shift
-           shift
-           continue;;
-
-       -o) chowncmd="$chownprog $2"
-           shift
-           shift
-           continue;;
-
-       -g) chgrpcmd="$chgrpprog $2"
-           shift
-           shift
-           continue;;
-
-       -s) stripcmd=$stripprog
-           shift
-           continue;;
-
-       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
-           shift
-           continue;;
-
-       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
-           shift
-           continue;;
-
-       *)  if [ x"$src" = x ]
-           then
-               src=$1
-           else
-               # this colon is to work around a 386BSD /bin/sh bug
-               :
-               dst=$1
-           fi
-           shift
-           continue;;
-    esac
-done
-
-if [ x"$src" = x ]
-then
-       echo "$0: no input file specified" >&2
-       exit 1
-else
-       :
-fi
-
-if [ x"$dir_arg" != x ]; then
-       dst=$src
-       src=""
-
-       if [ -d "$dst" ]; then
-               instcmd=:
-               chmodcmd=""
-       else
-               instcmd=$mkdirprog
-       fi
-else
-
-# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
-# might cause directories to be created, which would be especially bad
-# if $src (and thus $dsttmp) contains '*'.
-
-       if [ -f "$src" ] || [ -d "$src" ]
-       then
-               :
-       else
-               echo "$0: $src does not exist" >&2
-               exit 1
-       fi
-
-       if [ x"$dst" = x ]
-       then
-               echo "$0: no destination specified" >&2
-               exit 1
-       else
-               :
-       fi
-
-# If destination is a directory, append the input filename; if your system
-# does not like double slashes in filenames, you may need to add some logic
-
-       if [ -d "$dst" ]
-       then
-               dst=$dst/`basename "$src"`
-       else
-               :
-       fi
-fi
-
-## this sed command emulates the dirname command
-dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
-
-# Make sure that the destination directory exists.
-#  this part is taken from Noah Friedman's mkinstalldirs script
-
-# Skip lots of stat calls in the usual case.
-if [ ! -d "$dstdir" ]; then
-defaultIFS='
-       '
-IFS="${IFS-$defaultIFS}"
-
-oIFS=$IFS
-# Some sh's can't handle IFS=/ for some reason.
-IFS='%'
-set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
-IFS=$oIFS
-
-pathcomp=''
-
-while [ $# -ne 0 ] ; do
-       pathcomp=$pathcomp$1
-       shift
-
-       if [ ! -d "$pathcomp" ] ;
-        then
-               $mkdirprog "$pathcomp"
-       else
-               :
-       fi
-
-       pathcomp=$pathcomp/
-done
-fi
-
-if [ x"$dir_arg" != x ]
-then
-       $doit $instcmd "$dst" &&
-
-       if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
-       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
-       if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
-       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
-else
-
-# If we're going to rename the final executable, determine the name now.
-
-       if [ x"$transformarg" = x ]
-       then
-               dstfile=`basename "$dst"`
-       else
-               dstfile=`basename "$dst" $transformbasename |
-                       sed $transformarg`$transformbasename
-       fi
-
-# don't allow the sed command to completely eliminate the filename
-
-       if [ x"$dstfile" = x ]
-       then
-               dstfile=`basename "$dst"`
-       else
-               :
-       fi
-
-# Make a couple of temp file names in the proper directory.
-
-       dsttmp=$dstdir/_inst.$$_
-       rmtmp=$dstdir/_rm.$$_
-
-# Trap to clean up temp files at exit.
-
-       trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
-       trap '(exit $?); exit' 1 2 13 15
-
-# Move or copy the file name to the temp name
-
-       $doit $instcmd "$src" "$dsttmp" &&
-
-# and set any options; do chmod last to preserve setuid bits
-
-# If any of these fail, we abort the whole thing.  If we want to
-# ignore errors from any of these, just make sure not to ignore
-# errors from the above "$doit $instcmd $src $dsttmp" command.
-
-       if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
-       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
-       if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
-       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
-
-# Now remove or move aside any old file at destination location.  We try this
-# two ways since rm can't unlink itself on some systems and the destination
-# file might be busy for other reasons.  In this case, the final cleanup
-# might fail but the new file should still install successfully.
-
-{
-       if [ -f "$dstdir/$dstfile" ]
-       then
-               $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
-               $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
-               {
-                 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
-                 (exit 1); exit
-               }
-       else
-               :
-       fi
-} &&
-
-# Now rename the file to the real destination.
-
-       $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
-
-fi &&
-
-# The final little trick to "correctly" pass the exit status to the exit trap.
-
-{
-       (exit 0); exit
-}
index 43cb99f2781979e74b66eef640fadb7878f30aeb..3d2f6d686e491fffd91a09281696bfdd07fdf0e5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2011-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -29,7 +29,7 @@ struct i9e_private {
        FILE *stderr_stream;
        int num_columns;
        char empty_line[1000];
-       struct task task;
+       struct task *task;
        struct btr_node *stdout_btrn;
        bool last_write_was_status;
        bool line_handler_running;
@@ -52,7 +52,7 @@ static struct i9e_private i9e_private, *i9ep = &i9e_private;
  */
 int i9e_get_error(void)
 {
-       return i9ep->task.error;
+       return task_status(i9ep->task);
 }
 
 static bool is_prefix(const char *partial, const char *full, size_t len)
@@ -227,6 +227,7 @@ static void wipe_bottom_line(void)
        fprintf(i9ep->stderr_stream, "\r");
 }
 
+#ifndef RL_FREE_KEYMAP_DECLARED
 /**
  * Free all storage associated with a keymap.
  *
@@ -237,6 +238,7 @@ static void wipe_bottom_line(void)
  * \param keymap The keymap to deallocate.
  */
 void rl_free_keymap(Keymap keymap);
+#endif
 
 /**
  * Reset the terminal and save the in-memory command line history.
@@ -312,7 +314,7 @@ free_line:
        free(line);
 }
 
-static int i9e_post_select(__a_unused struct sched *s, __a_unused struct task *t)
+static int i9e_post_select(__a_unused struct sched *s, __a_unused void *context)
 {
        int ret;
        struct i9e_client_info *ici = i9ep->ici;
@@ -369,7 +371,7 @@ out:
        return ret;
 }
 
-static void i9e_pre_select(struct sched *s, __a_unused struct task *t)
+static void i9e_pre_select(struct sched *s, __a_unused void *context)
 {
        int ret;
 
@@ -437,7 +439,6 @@ static int dispatch_key(__a_unused int count, int key)
  * The caller must allocate and initialize the structure \a ici points to.
  *
  * \return Standard.
- * \sa \ref register_task().
  */
 int i9e_open(struct i9e_client_info *ici, struct sched *s)
 {
@@ -451,10 +452,13 @@ int i9e_open(struct i9e_client_info *ici, struct sched *s)
        ret = mark_fd_nonblocking(ici->fds[1]);
        if (ret < 0)
                return ret;
-       i9ep->task.pre_select = i9e_pre_select;
-       i9ep->task.post_select = i9e_post_select;
-       sprintf(i9ep->task.status, "i9e");
-       register_task(s, &i9ep->task);
+       i9ep->task = task_register(&(struct task_info) {
+               .name = "i9e",
+               .pre_select = i9e_pre_select,
+               .post_select = i9e_post_select,
+               .context = i9ep,
+       }, s);
+
        rl_readline_name = "para_i9e";
        rl_basic_word_break_characters = " ";
        rl_attempted_completion_function = i9e_completer;
index 1d6b36aa1a57e87e2c61283a21627e0ab2271064..96401b16a3a89b68182464622e55b6e629b0bc82 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2011-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/ipc.c b/ipc.c
index 1ec53c30204e336a9b75a1992d063910c618e80d..b8a6fd0c3733d16faa0f35179329d563381c9ec8 100644 (file)
--- a/ipc.c
+++ b/ipc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -209,6 +209,7 @@ size_t shm_get_shmmax(void)
                                buf[ret] = '\0';
                                shmmax = strtoul(buf, NULL, 10);
                        }
+                       close(fd);
                }
        }
 #elif defined SYSCTL_SHMMAX_VARIABLE
index f8e29fea8693af08506fb6b91210010d722994ac..0df2fad8c9ff66bef9b633ed2ff0ebbf4042313e 100644 (file)
@@ -1,12 +1,12 @@
 args "--unamed-opts=audio_file --no-handle-version --no-handle-help"
 
-purpose "Print information about audio file(s)."
+purpose "Print information about audio file(s)"
 
 include(header.m4)
 include(loglevel.m4)
 
 <qu>
-option "chunk_table" c
+option "chunk-table" c
 #~~~~~~~~~~~~~~~~~~~~~
 "print also the chunk table"
 flag off
@@ -27,7 +27,7 @@ option "parser-friendly" p
 flag off
 details = "
        Currently this option only affects the format of the chunk table,
-       so it has no effect if --chunk_table is not given.
+       so it has no effect if --chunk-table is not given.
 
        The human-readable output (the default) consists of one output
        line per chunk and the output contains also the chunk number,
index f4da9d992c8ffc078710a95e182a764433e9ddf8..08c3152121797a39218bced32d4944635acc212a 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-version --no-help"
 
-purpose "Make an audio stream from a local file."
+purpose "Make an audio stream from a local file"
 
 description "
        The afh (audio format handler) receiver can be used to write
@@ -31,7 +31,7 @@ details = "
        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
+       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.
@@ -43,7 +43,7 @@ option "end-chunk" e
 int typestr = "chunk_num"
 optional
 details = "
-       For the chunk_num argument the same rules as for --begin_chunk
+       For the chunk_num argument the same rules as for --begin-chunk
        apply. The default is to write up to the last chunk.
 "
 
index 04b4963d3a9fbe6bc342ffa808ae6f33a8a168fa..b2c56218dcd6f6a2e41646fafebb883c74b09089 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-version --no-help"
 
-purpose "Native ALSA output plugin."
+purpose "Native ALSA output plugin"
 
 include(header.m4)
 
@@ -8,11 +8,29 @@ include(header.m4)
 option "device" d
 #~~~~~~~~~~~~~~~~
 "set PCM device"
-string typestr="device"
-default="default"
+string typestr = "device"
+default = "default"
 optional
-details="
-       On systems with dmix, a better choice than the default
-       value might be to use \"plug:swmix\".
+details = "
+       Check for the presence of a /proc/asound/ directory to see if
+       ALSA is present in your kernel. The file /proc/asound/devices
+       contains all devices ALSA knows about.
 "
+
+option "buffer-time" B
+#~~~~~~~~~~~~~~~~~~~~~
+"duration of the ALSA buffer"
+int typestr = "milliseconds"
+default = "170"
+optional
+details = "
+       This is only a hint as ALSA might pick a slightly different
+       time, depending on the sound hardware. The chosen value is
+       shown in debug output as BUFFER_TIME.
+
+       If synchronization between multiple clients is desired,
+       the same buffer time should be configured for all clients.
+"
+
 </qu>
+
index 2d4d4ce6ca5166355fa99bdbf28884a2a213daff..a02cc5b73f8e2bf85a94090d3b781b4f85efe827 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-version --no-help"
 
-purpose "Amplify the decoded audio stream."
+purpose "Amplify the decoded audio stream"
 
 option "amp" a
 #~~~~~~~~~~~~~
index ccee4ee62f5fc23903857f9ba29e0b470792548a..29112d711694b239c82dee218ca88745a3f38dc2 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-version --no-help"
 
-purpose "Output plugin for libao."
+purpose "Output plugin for libao"
 
 include(header.m4)
 <qu>
index 36520bfa0f16888020d431d7001c40c17c00146a..f216204f78330449c95bd09acfe35d1d1ded252f 100644 (file)
@@ -1,6 +1,6 @@
 args "--unamed-opts=command --conf-parser --no-handle-version --no-handle-help"
 
-purpose "Communicate with para_audiod through a local socket."
+purpose "Communicate with para_audiod through a local socket"
 
 include(header.m4)
 <qu>
index 7bae3435d19f20ed0a4f496b947cd1195e17bad5..2e6f936f3a94d058ee35d24afd59ca9966f958cf 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-handle-help --no-handle-version --conf-parser"
 
-purpose "Connect to para_server, receive, decode and play audio streams."
+purpose "Connect to para_server, receive, decode and play audio streams"
 
 include(header.m4)
 define(CURRENT_PROGRAM,para_audiod)
@@ -80,7 +80,7 @@ details="
        instructed to use also \"filename\" for connecting para_audiod.
 "
 
-option "user_allow" -
+option "user-allow" -
 #~~~~~~~~~~~~~~~~~~~~
 "allow this uid"
 int typestr="uid"
@@ -98,7 +98,7 @@ details="
        to connect to para_audiod.
 "
 
-option "clock_diff_count" -
+option "clock-diff-count" -
 #~~~~~~~~~~~~~~~~~~~~~~~~~~
 "sync clock on startup"
 int typestr="count"
@@ -195,7 +195,7 @@ details="
 
 "
 
-option "stream_delay" -
+option "stream-delay" -
 #~~~~~~~~~~~~~~~~~~~~~~
 "time for client sync"
 int typestr="milliseconds"
index f0bbc0bd8eadf2000e69f2f95e41b22c146f4080..0530d39551993fb5b9ec35641f975732c4b84068 100644 (file)
@@ -1,6 +1,6 @@
 args "--unamed-opts=command --no-handle-error --conf-parser --no-handle-version --no-handle-help"
 
-purpose "Communicate with para_server through the paraslash control port."
+purpose "Communicate with para_server through the paraslash control port"
 
 include(header.m4)
 define(CURRENT_PROGRAM,para_client)
@@ -9,8 +9,8 @@ define(DEFAULT_HISTORY_FILE,~/.paraslash/client.history)
 <qu>
 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 "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)
index 63e996f35b1683020dfd2c577c67966c53a6b71d..eb08178698d9b4cefa27103599b0c3163694b6ff 100644 (file)
@@ -8,7 +8,7 @@ values = "yes","no","auto"
 default = "auto"
 optional
 
-option "log_color" -
+option "log-color" -
 #~~~~~~~~~~~~~~~~~~~
 "select a color for one type of log message"
 string typestr="color_spec"
@@ -26,9 +26,9 @@ details="
 
        Examples:
 
-               --log_color \"debug:green\"
-               --log_color \"info:yellow bold\"
-               --log_color \"notice:white red bold\"
+               --log-color \"debug:green\"
+               --log-color \"info:yellow bold\"
+               --log-color \"notice:white red bold\"
 "
 
 </qu>
index 8c701a03987fe6c8e21c25a40475483b6d0bd7f7..501f46ccfd8f0730787c37e5290fa0b19dfa71a9 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-version --no-help"
 
-purpose "Dynamically adjust the volume of an audio stream."
+purpose "Dynamically adjust the volume of an audio stream"
 
 option "blocksize" b
 #~~~~~~~~~~~~~~~~~~~
@@ -26,7 +26,7 @@ option "inertia" i
 default="6"
 optional
 
-option "target_level" t
+option "target-level" t
 #~~~~~~~~~~~~~~~~~~~~~~
 "target signal level (0-32768)"
 int typestr="number"
index 318ba7a68101350630f04fec7af22716dabe6fc4..29f66b4440be2f238b66ead0bfed73a7d74785f7 100644 (file)
@@ -1,5 +1,5 @@
 <qu>
-option "config_file" c
+option "config-file" c
 #~~~~~~~~~~~~~~~~~~~~~
 "(default='</qu>DEFAULT_CONFIG_FILE<qu>')"
 string typestr="filename"
index f8191fe003bec99957155d71c8ef5a5be694376b..1ba3fb59e79fb462e67a97b926816f1c7885a84e 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-version --no-help"
 
-purpose "Receive a DCCP audio stream."
+purpose "Receive a DCCP audio stream"
 
 option "host" i
 "ip or host"
index 7c731c2b6ec1cdf15322131827fe99add0917e09..59389ffefb5105ee8af56e4d7b844377c9d5d9c7 100644 (file)
@@ -1,6 +1,6 @@
 args "--conf-parser --no-handle-version --no-handle-help"
 
-purpose "An alarm clock and volume-fader for OSS and ALSA."
+purpose "An alarm clock and volume-fader for OSS and ALSA"
 
 include(header.m4)
 define(CURRENT_PROGRAM,para_fade)
@@ -17,11 +17,11 @@ option "mode" o
 #~~~~~~~~~~~~~~
 "how to fade volume"
        enum typestr = "mode"
-       values = "sleep", "snooze", "fade"
+       values = "sleep", "fade", "set", "snooze"
        default = "sleep"
        optional
        details="
-               para_fade knows three different fading modes:
+               para_fade knows the following modes:
 
                sleep mode: Change to the initial volume and select
                the initial afs mood/playlist. Then fade out until
@@ -33,6 +33,8 @@ option "mode" o
                fade: Fade the volume to the given value in the
                given time.
 
+               set: Just set the value and exit.
+
                snooze: Fade out, sleep a bit and fade in.
 "
 
@@ -86,12 +88,15 @@ section "Options for sleep mode"
 option "ivol" -
 #~~~~~~~~~~~~~~
 "set initial volume"
-       int typestr = "volume"
+       string typestr = "[channel:]volume"
        default = "60"
        optional
+       multiple
        details = "
                Used as the start volume, before fading out to the
-               fade out volume.
+               fade out volume. The channel part may be omitted, in
+               which case the default channel is used. This option
+               may be given multiple times.
        "
 
 option "fo-mood" -
@@ -228,4 +233,14 @@ option "fade-time" t
        int typestr = "seconds"
        default = "5"
        optional
+
+section "Options for set mode"
+##############################
+
+option "val" -
+"value to set"
+       int typestr = "value"
+       default = "0"
+       optional
+
 </qu>
index 045b8657236b57ed58b8ececdd8cd183481acb53..4f98884f4bad2c5828f420068e103d14d3923dec 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-version --no-help"
 
-purpose "Output plugin that writes to a local file."
+purpose "Output plugin that writes to a local file"
 
 option "filename" f
 #~~~~~~~~~~~~~~~~~~
index baf6ecdb974a72ec7ceb8058d13e2264e1b448ad..b8b49f622600d749a2b1c7dccb1fe2b0f2b7c16a 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-handle-help --no-handle-version --conf-parser"
 
-purpose "Decode or process audio data from STDIN to STDOUT."
+purpose "Decode or process audio data from STDIN to STDOUT"
 
 include(header.m4)
 include(loglevel.m4)
index 1f5cf6e425bc506e8d7eae143a2b3a7319dd4a5e..8e21356f3bb362b3aecccd6f4d19bbaea58c7ae2 100644 (file)
@@ -1,6 +1,6 @@
 args "--conf-parser --no-handle-version --no-handle-help"
 
-purpose "Show para_audiod status in a curses window."
+purpose "Show para_audiod status in a curses window"
 
 include(header.m4)
 define(CURRENT_PROGRAM,para_gui)
@@ -34,7 +34,7 @@ details = "
        available themes is printed and the program terminates.
 "
 
-option "stat_cmd" s
+option "stat-cmd" s
 #~~~~~~~~~~~~~~~~~~
 "command to read status items from"
 string typestr = "command"
@@ -56,7 +56,7 @@ details = "
 section "Mapping keys to commands"
 #---------------------------------
 
-option "key_map" k
+option "key-map" k
 #~~~~~~~~~~~~~~~~~
 "Map key k to command c using mode m."
 
index 932d88bf06825cf0ba92bd21988d5944b1c93cb4..73e98a7836c8bf1989775b5206617717519dc247 100644 (file)
@@ -1,5 +1,5 @@
 <qu>
-option "history_file" -
+option "history-file" -
 #~~~~~~~~~~~~~~~~~~~~~~
 "(default='</qu>DEFAULT_HISTORY_FILE<qu>')"
 string typestr = "filename"
index b8ece39d9809a85dfa4e3e0d7b09afefd2475954..6db3ff0444fdc7feedd067c79292d8b7abc00bb1 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-version --no-help"
 
-purpose "Receive an HTTP audio stream."
+purpose "Receive an HTTP audio stream"
 
 include(header.m4)
 
index 548a3d5d83bcb406a66dc26a77c0a840745d868f..79e101a3e4e88f3e55b096b90780615b82b2e602 100644 (file)
@@ -1,6 +1,6 @@
 define ggo_opts
        --output-dir=$(cmdline_dir) \
-       --set-version="$(GIT_VERSION) ($(codename))" \
+       --set-version="$(GIT_VERSION)" \
        --arg-struct-name=$(*F)_args_info \
        --file-name=$(*F).cmdline \
        --func-name=$(*F)_cmdline_parser \
@@ -16,37 +16,11 @@ ifeq ($(ggo_descriptions_declared),no)
        echo 'extern const char *$(*F)_args_info_description;' >> $(cmdline_dir)/$(*F).cmdline.h
 endif
 
-$(ggo_dir)/server.ggo $(ggo_dir)/audiod.ggo: \
-       $(m4_ggo_dir)/loglevel.m4 $(m4_ggo_dir)/color.m4 \
-       $(m4_ggo_dir)/config_file.m4 $(m4_ggo_dir)/logfile.m4 \
-       $(m4_ggo_dir)/daemon.m4 $(m4_ggo_dir)/user.m4 \
-       $(m4_ggo_dir)/group.m4 $(m4_ggo_dir)/log_timing.m4 \
-       $(m4_ggo_dir)/config_file.m4
-
-$(ggo_dir)/afh.ggo: $(m4_ggo_dir)/loglevel.m4
-$(ggo_dir)/audioc.ggo: \
-       $(m4_ggo_dir)/loglevel.m4 \
-       $(m4_ggo_dir)/history_file.m4 \
-       $(m4_ggo_dir)/complete.m4
-$(ggo_dir)/filter.ggo: $(m4_ggo_dir)/loglevel.m4
-$(ggo_dir)/fsck.ggo: $(m4_ggo_dir)/loglevel.m4
-$(ggo_dir)/gui.ggo: $(m4_ggo_dir)/loglevel.m4 $(m4_ggo_dir)/config_file.m4
-$(ggo_dir)/recv.ggo: $(m4_ggo_dir)/loglevel.m4
-$(ggo_dir)/write.ggo: $(m4_ggo_dir)/loglevel.m4 \
-       $(m4_ggo_dir)/channels.m4 \
-       $(m4_ggo_dir)/sample_rate.m4 \
-       $(m4_ggo_dir)/sample_format.m4
-$(ggo_dir)/client.ggo: \
-       $(m4_ggo_dir)/loglevel.m4 \
-       $(m4_ggo_dir)/config_file.m4 \
-       $(m4_ggo_dir)/history_file.m4 \
-       $(m4_ggo_dir)/complete.m4
-$(ggo_dir)/fade.ggo: $(m4_ggo_dir)/loglevel.m4 $(m4_ggo_dir)/config_file.m4
-$(ggo_dir)/resample_filter.ggo: \
-       $(m4_ggo_dir)/channels.m4 \
-       $(m4_ggo_dir)/sample_rate.m4 \
-       $(m4_ggo_dir)/sample_format.m4
-$(ggo_dir)/play.ggo: $(m4_ggo_dir)/loglevel.m4 $(m4_ggo_dir)/config_file.m4
+$(m4depdir)/%.m4d: $(m4_ggo_dir)/%.m4 | $(m4depdir)
+       @[ -z "$(Q)" ] || echo 'M4D $<'
+       $(Q) m4 -I $(m4_ggo_dir) --debug=i $< 3>&1 1>/dev/null 2>&3 \
+               | awk '{if ($$0 ~ "^m4debug: input read from ") \
+               print "$(ggo_dir)/$(*F).ggo: " $$NF}' > $@
 
 $(ggo_dir)/%.ggo: $(m4_ggo_dir)/%.m4 $(m4_ggo_dir)/header.m4 | $(ggo_dir)
        @[ -z "$(Q)" ] || echo 'M4 $<'
index a6425b3e7f296485101c52e8dc5fa72a9acac355..8b187835d1ecd7d8b109244a9e5efc1b38c2936e 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-version --no-help"
 
-purpose "Decode an mp3 stream."
+purpose "Decode an mp3 stream"
 
 include(header.m4)
 
index 352bea5bc3cfe2e0d2d431c2e4b7c0fb1f31f60f..578d81387ec3562312572ec218b4aa4cf9a234cc 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-version --no-help"
 
-purpose "Output plugin for the Open Sound System."
+purpose "Output plugin for the Open Sound System"
 
 option "device" d
 #~~~~~~~~~~~~~~~~
index 5add6f2e6e340f5eacd4260d33e4166522751261..83ed737ca91168156cb3c3a05efea655e8ceaabd 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-version --no-help"
 
-purpose "Output plugin for Mac OS coreaudio."
+purpose "Output plugin for Mac OS coreaudio"
 
 section "osx options"
 #####################
index ea41f562fe504e00d0be096b83f174d4dc41129d..168755907fd302f8eb5f95c5484f04df210f95a9 100644 (file)
@@ -1,6 +1,6 @@
 args "--unamed-opts=audio_file --no-handle-version --conf-parser --no-handle-help"
 
-purpose "Command line audio player."
+purpose "Command line audio player"
 
 description "para_play operates either in command mode or in insert
 mode. In insert mode it presents a prompt and allows to enter commands
@@ -33,7 +33,7 @@ option "randomize" z
 "randomize playlist at startup."
 flag off
 
-option "key_map" k
+option "key-map" k
 #~~~~~~~~~~~~~~~~~
 "Map key k to a command."
 
index 9e84dcfcea04934a7f5a2f3f776d5afabe0b6bc1..20ff86fe4b332038e497313540a2cea515f486a4 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-version --no-help"
 
-purpose "Delay processing of an audio stream."
+purpose "Delay processing of an audio stream"
 
 option "duration" d
 #~~~~~~~~~~~~~~~~~~
index 086c9c0a5c73049630bda211a8433ddfebba3963..9a9a88046f66b8c31fc23c670df730539525912d 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-handle-help --no-handle-version"
 
-purpose "A command line HTTP/DCCP/UDP stream grabber."
+purpose "A command line HTTP/DCCP/UDP stream grabber"
 
 include(header.m4)
 include(loglevel.m4)
index 4f4af4b0c41182d21faecf888926488bb372095e..2e5f40054edcfa9c9239139e1be3aaf8a8857597 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-version --no-help"
 
-purpose "Transform raw audio to a different sample rate."
+purpose "Transform raw audio to a different sample rate"
 
 include(header.m4)
 
index 8707554f7719ace121dae2701e179c22ab687184..916e88563ea32af2fc75d94c19a74f5c03ea0b64 100644 (file)
@@ -1,6 +1,6 @@
 args "--conf-parser --no-handle-version --no-handle-help"
 
-purpose "Manage and stream audio files."
+purpose "Manage and stream audio files"
 
 include(header.m4)
 define(CURRENT_PROGRAM,para_server)
@@ -42,7 +42,7 @@ include(logfile.m4)
 include(config_file.m4)
 
 <qu>
-option "user_list" -
+option "user-list" -
 #~~~~~~~~~~~~~~~~~~~
 "(default='~/.paraslash/server.users')"
 
@@ -60,7 +60,7 @@ option "autoplay" a
 "start playing on startup"
 flag off
 
-option "autoplay_delay" -
+option "autoplay-delay" -
 #~~~~~~~~~~~~~~~~~~~~~~~~
 "time to wait before streaming"
 int typestr="ms"
@@ -76,7 +76,7 @@ details="
        already up when para_server starts to stream. Of course, this
        option depends on the autoplay option.
 "
-option "announce_time" A
+option "announce-time" A
 #~~~~~~~~~~~~~~~~~~~~~~~
 "grace time for clients"
 
@@ -95,7 +95,7 @@ details="
 section "audio file selector"
 #############################
 
-option "afs_database_dir" D
+option "afs-database-dir" D
 #~~~~~~~~~~~~~~~~~~~~~~~~~~
 "location of the database"
 string typestr="path"
@@ -105,7 +105,7 @@ details="
        file selector. The default is '~/.paraslash/afs_database-0.4'.
 "
 
-option "afs_socket" s
+option "afs-socket" s
 #~~~~~~~~~~~~~~~~~~~~
 "Command socket for afs"
 string typestr="path"
@@ -117,7 +117,7 @@ details="
        audio file selector via a local socket. This option specifies
        the location of that socket in the file system.
 "
-option "afs_initial_mode" i
+option "afs-initial-mode" i
 #~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 "Mood or playlist to load on startup."
@@ -128,7 +128,7 @@ 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
+               --afs-initial-mode p/foo
        loads the playlist named 'foo'.
 "
 
@@ -137,7 +137,7 @@ section "http sender"
 #####################
 
 
-option "http_port" -
+option "http-port" -
 #~~~~~~~~~~~~~~~~~~~
 "tcp port for http streaming"
 int typestr="portnumber"
@@ -149,20 +149,20 @@ details="
        http request message such as 'GET / HTTP/'.
 "
 
-option "http_default_deny" -
+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
+       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.
+       more http-access options.
 "
 
-option "http_access" -
+option "http-access" -
 #~~~~~~~~~~~~~~~~~~~~~
 "add an entry to the http ACL"
 string typestr="a.b.c.d/n"
@@ -170,13 +170,13 @@ optional
 multiple
 details="
        Add given host/network to access control list (whitelist if
-       http_default_deny was given, blacklist otherwise) before
+       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" -
+option "http-no-autostart" -
 #~~~~~~~~~~~~~~~~~~~~~~~~~~~
 "do not open tcp port on startup"
 flag off
@@ -186,7 +186,7 @@ details="
        later time by using the sender command.
 "
 
-option "http_max_clients" -
+option "http-max-clients" -
 #~~~~~~~~~~~~~~~~~~~~~~~~~~
 "maximal number of connections"
 int typestr="number"
@@ -204,45 +204,45 @@ section "dccp sender"
 #####################
 
 
-option "dccp_port" -
+option "dccp-port" -
 #~~~~~~~~~~~~~~~~~~~
 "port for dccp streaming"
 int typestr="portnumber"
 default="8000"
 optional
 details="
-       See http_port for details.
+       See http-port for details.
 "
 
-option "dccp_default_deny" -
+option "dccp-default-deny" -
 #~~~~~~~~~~~~~~~~~~~~~~~~~~~
 "make the dccp ACL a whitelist"
 flag off
 details="
-       See http_default_deny for details.
+       See http-default-deny for details.
 "
 
-option "dccp_access" -
+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.
+       See http-access for details.
 "
 
-option "dccp_max_clients" -
+option "dccp-max-clients" -
 #~~~~~~~~~~~~~~~~~~~~~~~~~~
 "maximal number of connections"
 int typestr="number"
 default="-1"
 optional
 details="
-       See http_max_clients for details.
+       See http-max-clients for details.
 "
 
-option "dccp_max_slice_size" -
+option "dccp-max-slice-size" -
 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 "Upper bound for the FEC slice size"
 int typestr = "size"
@@ -261,7 +261,7 @@ details = "
        the MPS of an incoming connection can not be set.
 "
 
-option "dccp_data_slices_per_group" -
+option "dccp-data-slices-per-group" -
 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 "The number of non-redundant slices per FEC group"
 int typestr = "num"
@@ -270,13 +270,13 @@ default = "3"
 details = "
        This determines the number of slices in each FEC group that are
        necessary to decode the group. The given number must be smaller
-       than the value of the dccp_slices_per_group option below.
+       than the value of the dccp-slices-per-group option below.
 
        Note that the duration of a FEC group is proportional to the
-       product dccp_max_slice_size * dccp_data_slices_per_group.
+       product dccp-max-slice-size * dccp-data-slices-per-group.
 "
 
-option "dccp_slices_per_group" -
+option "dccp-slices-per-group" -
 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 "The total number of slices per FEC group"
 int typestr = "num"
@@ -284,7 +284,7 @@ optional
 default = "4"
 details = "
        This value must be larger than the value given for above
-       dccp_data_slices_per_group above. The difference being the
+       dccp-data-slices-per-group above. The difference being the
        number of redundant slices per group, i.e.  the number of
        data packets that may be lost without causing interruptions
        of the resulting audio stream.
@@ -296,7 +296,7 @@ details = "
 section "udp sender"
 ####################
 
-option "udp_target" -
+option "udp-target" -
 #~~~~~~~~~~~~~~~~~~~~
 "add udp target with optional port"
 string typestr="host[:port]"
@@ -306,7 +306,7 @@ details="
        Add given host/port to the list of targets. The 'host' argument
        can be either an IPv4/v6 address or hostname (RFC 3986 syntax).
        The 'port' argument is an optional port number. If the 'port'
-       part is absent, the 'udp_default_port' value is used.
+       part is absent, the 'udp-default-port' value is used.
 
        The following examples are possible targets:
        '10.10.1.2:8000' (host:port); '10.10.1.2' (with default port);
@@ -317,7 +317,7 @@ details="
        This option can be given multiple times, for multiple targets.
 "
 
-option "udp_no_autostart" -
+option "udp-no-autostart" -
 #~~~~~~~~~~~~~~~~~~~~~~~~~~
 "do not start sending"
 flag off
@@ -326,20 +326,20 @@ details="
        a later time by using the sender command.
 "
 
-option "udp_default_port" -
+option "udp-default-port" -
 #~~~~~~~~~~~~~~~~~~~~~~~~~~
 "udp port to send to"
 int typestr="port"
 default="8000"
 optional
 
-option "udp_mcast_iface" -
+option "udp-mcast-iface" -
 #~~~~~~~~~~~~~~~~~~~~~~~~~~
 "outgoing udp multicast interface"
 string
 optional
 
-option "udp_header_interval" H
+option "udp-header-interval" H
 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 "duration for sending header"
 int typestr = "ms"
@@ -357,7 +357,7 @@ details = "
        audio formats, including mp3, don't need an audio file header.
 "
 
-option "udp_ttl" t
+option "udp-ttl" t
 #~~~~~~~~~~~~~~~~~
 "set time to live value"
 int typestr="num"
diff --git a/m4/gengetopt/sync_filter.m4 b/m4/gengetopt/sync_filter.m4
new file mode 100644 (file)
index 0000000..1e6f5f8
--- /dev/null
@@ -0,0 +1,45 @@
+args "--no-version --no-help"
+
+purpose "Synchronize playback between multiple clients."
+
+option "buddy" b
+#~~~~~~~~~~~~~~~
+"host to synchronize with"
+multiple
+string typestr = "url"
+optional
+details = "
+       This option may be given multiple times, one per buddy. Each
+       value may be given as a host, port pair in either IPv4 or
+       IPv6 form, with port being optional. If no port was specified
+       the listening port (as specified with --port, see below)
+       is used to send the synchronization packet to this buddy.
+"
+
+option "port" p
+#~~~~~~~~~~~~~~
+"UDP port for incoming synchronization packets"
+int typestr = "portnumber"
+default = "29900"
+optional
+details = "
+       The sync filter receives incoming synchronization packets on
+       this UDP port.
+"
+
+option "timeout" t
+#~~~~~~~~~~~~~~~~~
+"how long to wait for other clients"
+int typestr = "milliseconds"
+default = "2000"
+optional
+details = "
+       Once the sync filter receives its first chunk of input, a
+       synchronization period of the given number of milliseconds
+       begins. Playback is deferred until a synchronization packet
+       has been received from each defined buddy, or until the end
+       of the period. Buddies which did not send a synchronization
+       packet in time are temporarily disabled and are not waited for
+       during subsequent synchronization periods. They are re-enabled
+       automatically when another synchronization packet arrives.
+"
index 48770d974dc495f205a1538367511600fee97281..dcdad4f7b70143647ed40bc36e5c5cdefdc7975b 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-version --no-help"
 
-purpose "Receive an UDP audio stream."
+purpose "Receive an UDP audio stream"
 
 option "host" i
 "ip or host to receive udp packets from"
index 8b13f457a1480a3f430b31c478d5237ae9a0ba61..83e8bcabf4ccbfe642e39d8ab07eaa7371427943 100644 (file)
@@ -1,6 +1,6 @@
 args "--no-handle-help --no-handle-version"
 
-purpose "Play wav or raw audio."
+purpose "Play wav or raw audio"
 
 include(header.m4)
 include(loglevel.m4)
diff --git a/man_util.bash b/man_util.bash
new file mode 100755 (executable)
index 0000000..cb7519c
--- /dev/null
@@ -0,0 +1,108 @@
+#!/usr/bin/env bash
+
+# Receivers, filters, writers are called "modules" in this script
+print_modhelp()
+{
+       local ggo="$1"
+
+       $GENGETOPT --show-detailed-help \
+               --set-version "" \
+               --set-package "" \
+               < "$ggo" | awk 'BEGIN {
+                       have_purpose=0
+                       have_usage=0
+               } {
+                       if (!have_purpose) {
+                               if ($0 ~ /^ *$/)
+                                       next
+                               printf(" (%s):", $0)
+                               have_purpose=1
+                               next
+                       }
+                       if (!have_usage) {
+                               if ($0 ~ /^Usage: /) {
+                                       have_usage=1
+                               }
+                               next
+                       }
+                       print $0
+               }'
+}
+
+make_help()
+{
+       local target="$1" module ggo
+
+       ggo="$GGO_DIR/$1.ggo"
+       $GENGETOPT --show-detailed-help \
+               --set-version "$VERSION" \
+               --set-package "para_$1" \
+               < "$ggo"
+
+       if [[ "$target" == 'recv' || "$target" == 'audiod' ]]; then
+               for module in $RECEIVERS; do
+                       ggo="$GGO_DIR/${module}_recv.ggo"
+                       [[ ! -f "$ggo" ]] && continue
+                       printf "\nOptions for the $module receiver"
+                       print_modhelp "$ggo"
+               done
+       fi
+       if [[ "$target" == 'filter' || "$target" == 'audiod' ]]; then
+               for module in $FILTERS; do
+                       ggo="$GGO_DIR/${module}_filter.ggo"
+                       [[ ! -f "$ggo" ]] && continue
+                       printf "\nOptions for the $module filter"
+                       print_modhelp "$ggo"
+               done
+       fi
+       if [[ "$target" == 'write' || "$target" == 'audiod' ]]; then
+               for module in $WRITERS; do
+                       ggo="$GGO_DIR/${module}_write.ggo"
+                       [[ ! -f "$ggo" ]] && continue
+                       printf "\nOptions for the $module writer"
+                       print_modhelp "$ggo"
+               done
+       fi
+}
+
+set -u
+
+(($# != 1)) && exit 1
+
+# These must be set by the caller (make or help2man)
+export COMMAND_LISTS FILTERS GENGETOPT GGO_DIR HELP2MAN HELP2MAN_DIR \
+       RECEIVERS VERSION WRITERS
+
+# If either --version or --help-xxx was given, we are being called by help2man
+if [[ "$1" == "--version" ]]; then
+       echo "$VERSION"
+       exit $?
+fi
+if [[ "$1" =~ --help- ]]; then
+       make_help "${1#--help-}"
+       exit $?
+fi
+
+# Called by make, run help2man
+output_file="$1"
+target="${output_file##*/para_}"
+target="${target%.*}" # server, audiod, filter, ...
+link="$HELP2MAN_DIR/para_$target"
+
+cl_opts=
+for cl in $COMMAND_LISTS; do
+       cl_opts+=" --include $cl"
+done
+
+# Create a symlink para_$target, pointing to this script. This hack is
+# necessary because help2man always includes the name of the executable in its
+# output.
+ln -sf "$PWD/$0" "$link"
+
+# This will call us again twice, with either --help-$target or --version given.
+$HELP2MAN --no-info --help-option "--help-$target" $cl_opts \
+       "$link" > "$output_file"
+if (($? != 0)); then
+       rm -f "$output_file"
+       exit 1
+fi
diff --git a/mix.h b/mix.h
index 427a84f559c8f67369c24e9f4910f9cccdb83e8a..cfcfd72b6058bbd2ededbf6693805581d42957e5 100644 (file)
--- a/mix.h
+++ b/mix.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2012-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/mm.c b/mm.c
index 5ce3476eca25fc8f5304ae81d04c1f526c1b199a..6f2c088e9e653d375e4ab76157f58582f0d04797 100644 (file)
--- a/mm.c
+++ b/mm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/mm.h b/mm.h
index b635a5a841597a4d56c389c1aee4063c92be0f12..9c64002b59908520d11c187f935fffc2e37c6725 100644 (file)
--- a/mm.h
+++ b/mm.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/mood.c b/mood.c
index e5e8495369f1e7ffffe36bd463ec5aadf6163e39..897c22b9997d21d25f3644cd866706a7152182d9 100644 (file)
--- a/mood.c
+++ b/mood.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -18,6 +18,7 @@
 #include "ipc.h"
 #include "mm.h"
 #include "sideband.h"
+#include "mood.h"
 
 /**
  * Contains statistical data of the currently admissible audio files.
@@ -455,19 +456,6 @@ void mood_check_callback(int fd, __a_unused const struct osl_object *query)
        free(pb.buf);
 }
 
-#if 0
-static unsigned int_log2(uint64_t x)
-{
-       unsigned res = 0;
-
-       while (x) {
-               x /= 2;
-               res++;
-       }
-       return res;
-}
-#endif
-
 static int64_t normalized_value(int64_t x, int64_t n, int64_t sum, int64_t qd)
 {
        if (!n || !qd)
@@ -475,31 +463,13 @@ static int64_t normalized_value(int64_t x, int64_t n, int64_t sum, int64_t qd)
        return 100 * (n * x - sum) / (int64_t)int_sqrt(n * qd);
 }
 
-static long compute_num_played_score(struct afs_info *afsi)
+static long compute_score(struct afs_info *afsi, long mood_score)
 {
-       return -normalized_value(afsi->num_played, statistics.num,
+       mood_score -= normalized_value(afsi->num_played, statistics.num,
                statistics.num_played_sum, statistics.num_played_qd);
-}
-
-static long compute_last_played_score(struct afs_info *afsi)
-{
-       return -normalized_value(afsi->last_played, statistics.num,
+       mood_score -= normalized_value(afsi->last_played, statistics.num,
                statistics.last_played_sum, statistics.last_played_qd);
-}
-
-static long compute_dynamic_score(const struct osl_row *aft_row)
-{
-       struct afs_info afsi;
-       int64_t score, nscore = 0, lscore = 0;
-       int ret;
-
-       ret = get_afsi_of_row(aft_row, &afsi);
-       if (ret < 0)
-               return -100;
-       nscore = compute_num_played_score(&afsi);
-       lscore = compute_last_played_score(&afsi);
-       score = nscore + lscore;
-       return score;
+       return mood_score / 3;
 }
 
 static int add_afs_statistics(const struct osl_row *row)
@@ -691,7 +661,13 @@ static int update_afs_statistics(struct afs_info *old_afsi, struct afs_info *new
 
 static int add_to_score_table(const struct osl_row *aft_row, long mood_score)
 {
-       long score = (compute_dynamic_score(aft_row) + mood_score) / 3;
+       long score;
+       struct afs_info afsi;
+       int ret = get_afsi_of_row(aft_row, &afsi);
+
+       if (ret < 0)
+               return ret;
+       score = compute_score(&afsi, mood_score);
        return score_add(aft_row, score);
 }
 
@@ -772,9 +748,7 @@ static int mood_update_audio_file(const struct osl_row *aft_row,
                if (ret < 0)
                        return ret;
        }
-       score += compute_num_played_score(&afsi);
-       score += compute_last_played_score(&afsi);
-       score /= 3;
+       score = compute_score(&afsi, score);
        PARA_DEBUG_LOG("score: %li\n", score);
        percent = (score + 100) / 3;
        if (percent > 100)
@@ -865,7 +839,7 @@ int change_current_mood(char *mood_name)
        if (ret < 0)
                return ret;
        log_statistics();
-       PARA_INFO_LOG("%d admissible files \n", statistics.num);
+       PARA_INFO_LOG("%d admissible files\n", statistics.num);
        for (i = 0; i < statistics.num; i++) {
                struct admissible_file_info *a = aa.array + i;
                ret = add_to_score_table(a->aft_row, a->score);
diff --git a/mood.h b/mood.h
index f97081a96c7d16d06e2f8d8ea865547c34035134..10e2ba10eb87712b9a483cdeee56e37d8f96c6ae 100644 (file)
--- a/mood.h
+++ b/mood.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 251574a528d38a665b0ab67c88c213f6e27b5e41..2b558cbbaa1d8c82fd5fc121b6a1ce30fbff08ee 100644 (file)
--- a/mp3_afh.c
+++ b/mp3_afh.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2003-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 33c0dfc9f7d5019484a17f97a47064fb75798358..a51c77e28a84a6b032d151f1713bf64cf0674a89 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -77,9 +77,9 @@ static void mp3dec_close(struct filter_node *fn)
 
 #define MP3DEC_MAX_FRAME 8192
 
-static int mp3dec_post_select(__a_unused struct sched *s, struct task *t)
+static int mp3dec_post_select(__a_unused struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        int i, ret;
        struct private_mp3dec_data *pmd = fn->private_data;
        struct btr_node *btrn = fn->btrn;
diff --git a/net.c b/net.c
index 2ec3f03e546b3b1f3c038b7eea2e9cf8cf8a3438..8a190ddaa05100190761a7eecd918d78a546bb4d 100644 (file)
--- a/net.c
+++ b/net.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
  */
 #define _GNU_SOURCE
 
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/socket.h>
 #include <netdb.h>
 
 /* At least NetBSD needs these. */
@@ -142,9 +147,9 @@ static bool host_string_ok(const char *host)
  * \param hostlen The maximum length of \a host.
  * \param port   To return the port number (if any) of \a url.
  *
- * \return Pointer to \a host, or NULL if failed.
- * If NULL is returned, \a host and \a portnum are undefined. If no
- * port number was present in \a url, \a portnum is set to -1.
+ * \return Pointer to \a host, or \p NULL if failed.  If \p NULL is returned,
+ * \a host and \a port are undefined. If no port number was present in \a url,
+ * \a port is set to -1.
  *
  * \sa RFC 3986, 3.2.2/3.2.3
  */
@@ -168,16 +173,16 @@ char *parse_url(const char *url,
                if (*o++ != ']' || (*o != '\0' && *o != ':'))
                        goto failed;
        } else {
-               for (; (*c = *o == ':'? '\0' : *o); c++, o++)
-                       if (c == end)
+               for (; (*c = *o == ':'? '\0' : *o); c++, o++) {
+                       if (c == end && o[1])
                                goto failed;
+               }
        }
 
        if (*o == ':')
                if (para_atoi32(++o, port) < 0 ||
                    *port < 0 || *port > 0xffff)
                        goto failed;
-
        if (host_string_ok(host))
                return host;
 failed:
@@ -328,7 +333,14 @@ static void flowopt_setopts(int sockfd, struct flowopts *fo)
                }
 }
 
-static void flowopt_cleanup(struct flowopts *fo)
+/**
+ * Deallocate all resources of a flowopts structure.
+ *
+ * \param fo A pointer as returned from flowopt_new().
+ *
+ * It's OK to pass \p NULL here in which case the function does nothing.
+ */
+void flowopt_cleanup(struct flowopts *fo)
 {
        struct pre_conn_opt *cur, *next;
 
@@ -344,137 +356,148 @@ static void flowopt_cleanup(struct flowopts *fo)
 }
 
 /**
- * Resolve IPv4/IPv6 address and create a ready-to-use active or passive socket.
+ * Resolve an IPv4/IPv6 address.
  *
  * \param l4type The layer-4 type (\p IPPROTO_xxx).
- * \param passive Whether this is a passive (1) or active (0) socket.
+ * \param passive Whether \p AI_PASSIVE should be included as hint.
  * \param host Remote or local hostname or IPv/6 address string.
- * \param port_number Decimal port number.
- * \param fo Socket options to be set before making the connection.
+ * \param port_number Used to set the port in each returned address structure.
+ * \param result addrinfo structures are returned here.
  *
- * This creates a ready-made IPv4/v6 socket structure after looking up the
- * necessary parameters. The interpretation of \a host depends on the value of
- * \a passive:
- *     - on a passive socket host is interpreted as an interface IPv4/6 address
- *       (can be left NULL);
- *     - on an active socket, \a host is the peer DNS name or IPv4/6 address
- *       to connect to;
- *     - \a port_number is in either case the numeric port number (not service
- *       string).
- *
- * Furthermore, bind(2) is called on passive sockets, and connect(2) on active
- * sockets. The algorithm tries all possible address combinations until it
- * succeeds. If \a fo is supplied, options are set and cleanup is performed.
- *
- * \return This function returns 1 on success and \a -E_ADDRESS_LOOKUP when no
- * matching connection could be set up (with details in the error log).
- *
- *  \sa ipv6(7), getaddrinfo(3), bind(2), connect(2).
- */
-int makesock(unsigned l4type, bool passive,
-            const char *host, uint16_t port_number,
-            struct flowopts *fo)
-{
-       struct addrinfo *local = NULL, *src = NULL, *remote = NULL,
-               *dst = NULL, hints;
-       unsigned int    l3type = AF_UNSPEC;
-       int             rc, on = 1, sockfd = -1,
-                       socktype = sock_type(l4type);
+ * The interpretation of \a host depends on the value of \a passive. On a
+ * passive socket host is interpreted as an interface IPv4/6 address (can be
+ * left NULL). On an active socket, \a host is the peer DNS name or IPv4/6
+ * address to connect to.
+ *
+ * \return Standard.
+ *
+ * \sa getaddrinfo(3).
+ */
+int lookup_address(unsigned l4type, bool passive, const char *host,
+               int port_number, struct addrinfo **result)
+{
+       int ret;
        char port[6]; /* port number has at most 5 digits */
+       struct addrinfo *addr = NULL, hints;
 
-       sprintf(port, "%u", port_number);
+       *result = NULL;
+       sprintf(port, "%u", port_number & 0xffff);
        /* Set up address hint structure */
        memset(&hints, 0, sizeof(hints));
-       hints.ai_family = l3type;
-       hints.ai_socktype = socktype;
-       /* 
+       hints.ai_family = AF_UNSPEC;
+       hints.ai_socktype = sock_type(l4type);
+       /*
         * getaddrinfo does not support SOCK_DCCP, so for the sake of lookup
         * (and only then) pretend to be UDP.
         */
        if (l4type == IPPROTO_DCCP)
                hints.ai_socktype = SOCK_DGRAM;
-
        /* only use addresses available on the host */
        hints.ai_flags = AI_ADDRCONFIG;
-       if (l3type == AF_INET6)
-               /* use v4-mapped-v6 if no v6 addresses found */
-               hints.ai_flags |= AI_V4MAPPED | AI_ALL;
-
        if (passive && host == NULL)
                hints.ai_flags |= AI_PASSIVE;
-
        /* Obtain local/remote address information */
-       if ((rc = getaddrinfo(host, port, &hints, passive ? &local : &remote))) {
-               PARA_ERROR_LOG("can not resolve %s address %s#%s: %s.\n",
-                               layer4_name(l4type),
-                               host? host : (passive? "[loopback]" : "[localhost]"),
-                               port, gai_strerror(rc));
-               rc = -E_ADDRESS_LOOKUP;
-               goto out;
+       ret = getaddrinfo(host, port, &hints, &addr);
+       if (ret != 0) {
+               PARA_ERROR_LOG("can not resolve %s address %s#%s: %s\n",
+                       layer4_name(l4type),
+                       host? host : (passive? "[loopback]" : "[localhost]"),
+                       port, gai_strerror(ret));
+               return -E_ADDRESS_LOOKUP;
        }
+       *result = addr;
+       return 1;
+}
 
-       /* Iterate over all src/dst combination, exhausting dst first */
-       for (src = local, dst = remote; src != NULL || dst != NULL; /* no op */ ) {
-               if (src && dst && src->ai_family == AF_INET
-                               && dst->ai_family == AF_INET6)
-                       goto get_next_dst; /* v4 -> v6 is not possible */
-
-               sockfd = socket(src ? src->ai_family : dst->ai_family,
-                       socktype, l4type);
-               if (sockfd < 0)
-                       goto get_next_dst;
+/**
+ * Create an active or passive socket.
+ *
+ * \param l4type \p IPPROTO_TCP, \p IPPROTO_UDP, or \p IPPROTO_DCCP.
+ * \param passive Whether to call bind(2) or connect(2).
+ * \param ai Address information as obtained from \ref lookup_address().
+ * \param fo Socket options to be set before making the connection.
+ *
+ * bind(2) is called on passive sockets, and connect(2) on active sockets. The
+ * algorithm tries all possible address combinations until it succeeds. If \a
+ * fo is supplied, options are set but cleanup must be performed in the caller.
+ *
+ * \return File descriptor on success, \p E_MAKESOCK on errors.
+ *
+ * \sa \ref lookup_address(), \ref makesock(), ip(7), ipv6(7), bind(2),
+ * connect(2).
+ */
+int makesock_addrinfo(unsigned l4type, bool passive, struct addrinfo *ai,
+               struct flowopts *fo)
+{
+       int ret = -E_MAKESOCK, on = 1;
 
+       for (; ai; ai = ai->ai_next) {
+               int fd;
+               ret = socket(ai->ai_family, sock_type(l4type), l4type);
+               if (ret < 0)
+                       continue;
+               fd = ret;
+               flowopt_setopts(fd, fo);
+               if (!passive) {
+                       if (connect(fd, ai->ai_addr, ai->ai_addrlen) == 0)
+                               return fd;
+                       close(fd);
+                       continue;
+               }
                /*
                 * Reuse the address on passive sockets to avoid failure on
                 * restart (protocols using listen()) and when creating
                 * multiple listener instances (UDP multicast).
                 */
-               if (passive && setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
-                                                 &on, sizeof(on)) == -1) {
-                       rc = errno;
-                       close(sockfd);
-                       PARA_ERROR_LOG("can not set SO_REUSEADDR: %s\n",
-                                      strerror(rc));
-                       rc = -ERRNO_TO_PARA_ERROR(rc);
-                       break;
-               }
-               flowopt_setopts(sockfd, fo);
-
-               if (src) {
-                       if (bind(sockfd, src->ai_addr, src->ai_addrlen) < 0) {
-                               close(sockfd);
-                               goto get_next_src;
-                       }
-                       if (!dst) /* bind-only completed successfully */
-                               break;
+               if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on,
+                               sizeof(on)) == -1) {
+                       close(fd);
+                       continue;
                }
-
-               if (dst && connect(sockfd, dst->ai_addr, dst->ai_addrlen) == 0)
-                       break; /* connection completed successfully */
-               close(sockfd);
-get_next_dst:
-               if (dst && (dst = dst->ai_next))
+               if (bind(fd, ai->ai_addr, ai->ai_addrlen) < 0) {
+                       close(fd);
                        continue;
-get_next_src:
-               if (src && (src = src->ai_next)) /* restart inner loop */
-                       dst = remote;
+               }
+               return fd;
        }
-out:
-       if (local)
-               freeaddrinfo(local);
-       if (remote)
-               freeaddrinfo(remote);
-       flowopt_cleanup(fo);
-
-       if (src == NULL && dst == NULL) {
-               if (rc >= 0)
-                       rc = -E_MAKESOCK;
-               PARA_ERROR_LOG("can not create %s socket %s#%s.\n",
-                       layer4_name(l4type), host? host : (passive?
-                       "[loopback]" : "[localhost]"), port);
-               return rc;
+       return -E_MAKESOCK;
+}
+
+/**
+ * Resolve IPv4/IPv6 address and create a ready-to-use active or passive socket.
+ *
+ * \param l4type The layer-4 type (\p IPPROTO_xxx).
+ * \param passive Whether this is a passive or active socket.
+ * \param host Passed to \ref lookup_address().
+ * \param port_number Passed to \ref lookup_address().
+ * \param fo Passed to \ref makesock_addrinfo().
+ *
+ * This creates a ready-made IPv4/v6 socket structure after looking up the
+ * necessary parameters. The function first calls \ref lookup_address() and
+ * passes the address information to makesock_addrinfo() to create and
+ * initialize the socket.
+ *
+ * \return The newly created file descriptor on success, a negative error code
+ * on failure.
+ *
+ * \sa \ref lookup_address(), \ref makesock_addrinfo().
+ */
+int makesock(unsigned l4type, bool passive, const char *host, uint16_t port_number,
+               struct flowopts *fo)
+{
+       struct addrinfo *ai;
+       int ret = lookup_address(l4type, passive, host, port_number, &ai);
+
+       if (ret >= 0)
+               ret = makesock_addrinfo(l4type, passive, ai, fo);
+       if (ai)
+               freeaddrinfo(ai);
+       if (ret < 0) {
+               PARA_ERROR_LOG("can not create %s socket %s#%d.\n",
+               layer4_name(l4type), host? host : (passive?
+               "[loopback]" : "[localhost]"), port_number);
        }
-       return sockfd;
+       return ret;
 }
 
 /**
@@ -672,19 +695,45 @@ char *remote_name(int sockfd)
 
 /**
  * Extract IPv4 or IPv6-mapped-IPv4 address from sockaddr_storage.
- * \param ss Container of IPv4/6 address
- * \return Extracted IPv4 address (different from 0) or 0 if unsuccessful.
  *
- * \sa RFC 3493
+ * \param ss Container of IPv4/6 address.
+ * \param ia Extracted IPv4 address (different from 0) or 0 if unsuccessful.
+ *
+ * \sa RFC 3493.
  */
-struct in_addr extract_v4_addr(const struct sockaddr_storage *ss)
+void extract_v4_addr(const struct sockaddr_storage *ss, struct in_addr *ia)
 {
-       struct in_addr ia = {.s_addr = 0};
        const struct sockaddr *sa = normalize_ip_address(ss);
 
+       memset(ia, 0, sizeof(*ia));
        if (sa->sa_family == AF_INET)
-               ia = ((struct sockaddr_in *)sa)->sin_addr;
-       return ia;
+               *ia = ((struct sockaddr_in *)sa)->sin_addr;
+}
+
+/**
+ * Compare the address part of IPv4/6 addresses.
+ *
+ * \param sa1 First address.
+ * \param sa2 Second address.
+ *
+ * \return True iff the IP address of \a sa1 and \a sa2 match.
+ */
+bool sockaddr_equal(const struct sockaddr *sa1, const struct sockaddr *sa2)
+{
+       if (!sa1 || !sa2)
+               return false;
+       if (sa1->sa_family != sa2->sa_family)
+               return false;
+       if (sa1->sa_family == AF_INET) {
+               struct sockaddr_in *a1 = (typeof(a1))sa1,
+                       *a2 = (typeof (a2))sa2;
+               return a1->sin_addr.s_addr == a2->sin_addr.s_addr;
+       } else if (sa1->sa_family == AF_INET6) {
+               struct sockaddr_in6 *a1 = (typeof(a1))sa1,
+                       *a2 = (typeof (a2))sa2;
+               return !memcmp(a1, a2, sizeof(*a1));
+       } else
+               return false;
 }
 
 /**
@@ -914,16 +963,18 @@ int recv_cred_buffer(int fd, char *buf, size_t size)
        return recv_buffer(fd, buf, size) > 0? 1 : -E_RECVMSG;
 }
 #else /* HAVE_UCRED */
+
 /**
- * Send \p NULL-terminated buffer and Unix credentials of the current process.
+ * Send a buffer and the credentials of the current process to a socket.
  *
- * \param sock The socket file descriptor.
- * \param buf The buffer to be sent.
+ * \param sock The file descriptor of the sending socket.
+ * \param buf The zero-terminated buffer to send.
  *
- * \return On success, this call returns the number of characters sent.  On
- * error, \p -E_SENDMSG is returned.
+ * \return On success, this call returns the number of bytes sent. On errors,
+ * \p -E_SENDMSG is returned.
  *
- * \sa sendmsg(2), okir's Black Hats Manual.
+ * \sa \ref recv_cred_buffer, sendmsg(2), socket(7), unix(7), okir's Black Hats
+ * Manual.
  */
 ssize_t send_cred_buffer(int sock, char *buf)
 {
@@ -936,7 +987,7 @@ ssize_t send_cred_buffer(int sock, char *buf)
 
        /* Response data */
        iov.iov_base = buf;
-       iov.iov_len  = strlen(buf);
+       iov.iov_len = strlen(buf);
        c.pid = getpid();
        c.uid = getuid();
        c.gid = getgid();
@@ -954,7 +1005,7 @@ ssize_t send_cred_buffer(int sock, char *buf)
        *(struct ucred *)CMSG_DATA(cmsg) = c;
        msg.msg_controllen = cmsg->cmsg_len;
        ret = sendmsg(sock, &msg, 0);
-       if (ret  < 0)
+       if (ret < 0)
                ret = -E_SENDMSG;
        return ret;
 }
@@ -970,13 +1021,13 @@ static void dispose_fds(int *fds, unsigned num)
 /**
  * Receive a buffer and the Unix credentials of the sending process.
  *
- * \param fd the socket file descriptor.
- * \param buf the buffer to store the message.
- * \param size the size of \a buffer.
+ * \param fd The file descriptor of the receiving socket.
+ * \param buf The buffer to store the received message.
+ * \param size The length of \a buf in bytes.
  *
- * \return negative on errors, the user id on success.
+ * \return Negative on errors, the user id of the sending process on success.
  *
- * \sa recvmsg(2), okir's Black Hats Manual.
+ * \sa \ref send_cred_buffer and the references given there.
  */
 int recv_cred_buffer(int fd, char *buf, size_t size)
 {
@@ -1009,7 +1060,7 @@ int recv_cred_buffer(int fd, char *buf, size_t size)
                } else
                        if (cmsg->cmsg_level == SOL_SOCKET
                                        && cmsg->cmsg_type == SCM_RIGHTS) {
-                               dispose_fds((int *) CMSG_DATA(cmsg),
+                               dispose_fds((int *)CMSG_DATA(cmsg),
                                        (cmsg->cmsg_len - CMSG_LEN(0))
                                        / sizeof(int));
                        }
diff --git a/net.h b/net.h
index ae5e80150cca3b8d9b4aef93fb9dfe8e98592e79..877d1cbbe537bcb70f3d4ededc91514f226e61c0 100644 (file)
--- a/net.h
+++ b/net.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -61,6 +61,7 @@ struct flowopts;
 extern struct flowopts *flowopt_new(void);
 extern void flowopt_add(struct flowopts *fo, int level, int opt,
                const char *name, const void *val, int len);
+void flowopt_cleanup(struct flowopts *fo);
 /** Flowopt shortcut macros */
 #define OPT_ADD(fo, lev, opt, val, len)        flowopt_add(fo, lev, opt, #opt, val, len)
 
@@ -101,12 +102,17 @@ _static_inline_ bool is_valid_ipv6_address(const char *address)
        return inet_pton(AF_INET6, address, &test_it) != 0;
 }
 
+int lookup_address(unsigned l4type, bool passive, const char *host,
+               int port_number, struct addrinfo **result);
+
 /**
  * Generic socket creation (passive and active sockets).
  */
-extern int makesock(unsigned l4type, bool passive,
-                   const char *host, uint16_t port_number,
-                   struct flowopts *fo);
+int makesock(unsigned l4type, bool passive, const char *host,
+               uint16_t port_number, struct flowopts *fo);
+
+int makesock_addrinfo(unsigned l4type, bool passive, struct addrinfo *ai,
+               struct flowopts *fo);
 
 static inline int para_connect_simple(unsigned l4type,
                                      const char *host, uint16_t port)
@@ -114,7 +120,8 @@ static inline int para_connect_simple(unsigned l4type,
        return makesock(l4type, 0, host, port, NULL);
 }
 
-extern struct in_addr extract_v4_addr(const struct sockaddr_storage *ss);
+void extract_v4_addr(const struct sockaddr_storage *ss, struct in_addr *ia);
+bool sockaddr_equal(const struct sockaddr *sa1, const struct sockaddr *sa2);
 
 /**
  * Functions to support listening sockets.
index a6120be28bfcf8bfb581cc1fb37a8f37776a2533..debc0c9f3dec6e9416bf42ea52a0e3c05ff6d6e6 100644 (file)
--- a/ogg_afh.c
+++ b/ogg_afh.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2004-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index ac70eb3f0fc543a316f636c7a589cfaa60018c5c..21444fa33b1b35f8f1a7653b103f27469956e680 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2004-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index a4d44f4395a178c7cdfab2a0b74baba81c37aef3..59a5c486423e3e34f51dcdb3e541fe65efe15b60 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2010-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index f41150f2638c62d4dd48fc23f9705f1dcf94ac4d..8a3e261e122c2b92061bbe2bf73c44132884249a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -136,14 +136,13 @@ open:
                0, /* no initial bytes */
                ovc); /* the ov_open_callbacks */
        if (oret == OV_ENOTVORBIS || oret == OV_EBADHEADER) {
-               /* this might be due to the input buffer being too small */
+               /* maybe the input buffer is too small */
                if (!btr_no_parent(btrn)) {
                        fn->min_iqs += 1000;
                        iqs = btr_get_input_queue_size(btrn);
                        ret = 0;
                        if (iqs < fn->min_iqs)
                                goto out;
-                       PARA_CRIT_LOG("iqs: %zu\n", iqs);
                        btr_merge(btrn, fn->min_iqs);
                        pod->converted = 0;
                        goto open;
@@ -182,9 +181,9 @@ out:
 #define OGGDEC_MAX_OUTPUT_SIZE (96 * 1024)
 #define OGGDEC_OUTPUT_CHUNK_SIZE (32 * 1024)
 
-static void ogg_pre_select(struct sched *s, struct task *t)
+static void ogg_pre_select(struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        struct private_oggdec_data *pod = fn->private_data;
        struct btr_node *btrn = fn->btrn;
        int ret;
@@ -199,9 +198,9 @@ static void ogg_pre_select(struct sched *s, struct task *t)
        sched_min_delay(s);
 }
 
-static int ogg_post_select(__a_unused struct sched *s, struct task *t)
+static int ogg_post_select(__a_unused struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        struct private_oggdec_data *pod = fn->private_data;
        struct btr_node *btrn = fn->btrn;
        int ret, have;
@@ -236,13 +235,8 @@ static int ogg_post_select(__a_unused struct sched *s, struct task *t)
                        break;
                fn->min_iqs = 0;
                have += ret;
-               if (have < OGGDEC_OUTPUT_CHUNK_SIZE)
-                       continue;
-               if (btr_get_output_queue_size(btrn) > OGGDEC_MAX_OUTPUT_SIZE)
+               if (have >= OGGDEC_OUTPUT_CHUNK_SIZE)
                        break;
-               btr_add_output(buf, have, btrn);
-               buf = para_malloc(OGGDEC_OUTPUT_CHUNK_SIZE);
-               have = 0;
        }
        pod->have_more = (ret > 0);
        if (have > 0) {
index b079bcd5f3f373ed3b9e4826f010edd0e70a6201..10fe25d8e8dc00a3e085b4d6f2eae832f913b8a2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2012-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index cae9a6e9164de556ce5bde23de6c81aad7b476c3..fea6727463c858c87b0d9729a37800ff08a58b7b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2013-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 90e65bc369571fbf9e8cde134efc07a17b76e124..4e69a46efaf535405d0d3016ced360e6cf33c550 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2002-2007 Jean-Marc Valin
  * Copyright (c) 2008 CSIRO
  * Copyright (c) 2007-2012 Xiph.Org Foundation
- * Copyright (C) 2012-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2012-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -72,6 +72,7 @@ struct opusdec_context {
        int channels;
        int preskip;
        bool have_opus_stream;
+       bool have_more;
        ogg_int32_t opus_serialno;
 };
 
@@ -204,60 +205,84 @@ static int decode_packet(struct opusdec_context *ctx, ogg_packet *op,
        return 1;
 }
 
-static int opusdec_post_select(__a_unused struct sched *s, struct task *t)
+#define OPUSDEC_MAX_OUTPUT_SIZE (1024 * 1024)
+
+static int opusdec_post_select(__a_unused struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        struct opusdec_context *ctx = fn->private_data;
        struct btr_node *btrn = fn->btrn;
        int ret;
-       char *btr_buf, *data;
-       size_t nbytes;
        ogg_packet op;
 
        ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL);
-       if (ret <= 0)
-               goto out;
-       btr_merge(btrn, fn->min_iqs);
-       nbytes = btr_next_buffer(btrn, &btr_buf);
-       nbytes = PARA_MIN(nbytes, (size_t)32768);
-       ret = 0;
-       if (nbytes == 0)
-               goto out;
-       data = ogg_sync_buffer(&ctx->oy, nbytes);
-       memcpy(data, btr_buf, nbytes);
-       btr_consume(btrn, nbytes);
-       ogg_sync_wrote(&ctx->oy, nbytes);
-       for (;;) { /* loop over all ogg pages we got */
-               ret = 0;
-               if (ogg_sync_pageout(&ctx->oy, &ctx->ogg_page) != 1)
+       if (ret < 0) {
+               if (ret != -E_BTR_EOF) /* fatal error */
+                       goto out;
+               if (!ctx->have_more) /* EOF */
                        goto out;
-               if (!ctx->stream_init) {
-                       ogg_stream_init(&ctx->os, ogg_page_serialno(&ctx->ogg_page));
+       } else if (ret == 0 && !ctx->have_more) /* nothing to do */
+               goto out;
+       if (btr_get_output_queue_size(btrn) > OPUSDEC_MAX_OUTPUT_SIZE)
+               return 0;
+       for (;;) {
+               int serial;
+               if (ctx->stream_init) {
+                       ret = ogg_stream_packetout(&ctx->os, &op);
+                       if (ret == 1)
+                               break;
+               }
+               while (ogg_sync_pageout(&ctx->oy, &ctx->ogg_page) != 1) {
+                       char *btr_buf, *data;
+                       size_t nbytes = btr_next_buffer(btrn, &btr_buf);
+                       nbytes = PARA_MIN(nbytes, (size_t)24 * 1024);
+                       //PARA_CRIT_LOG("nbytes: %d\n", nbytes);
+                       ctx->have_more = false;
+                       if (nbytes == 0)
+                               return 0;
+                       data = ogg_sync_buffer(&ctx->oy, nbytes);
+                       memcpy(data, btr_buf, nbytes);
+                       btr_consume(btrn, nbytes);
+                       ogg_sync_wrote(&ctx->oy, nbytes);
+               }
+               ctx->have_more = true;
+               serial = ogg_page_serialno(&ctx->ogg_page);
+               if (ctx->stream_init) {
+                       if (serial != ctx->os.serialno)
+                               ogg_stream_reset_serialno(&ctx->os, serial);
+               } else {
+                       ogg_stream_init(&ctx->os, serial);
                        ctx->stream_init = true;
                }
-               if (ogg_page_serialno(&ctx->ogg_page) != ctx->os.serialno)
-                       ogg_stream_reset_serialno(&ctx->os,
-                               ogg_page_serialno(&ctx->ogg_page));
                /* Add page to the bitstream */
                ogg_stream_pagein(&ctx->os, &ctx->ogg_page);
-               for (;;) { /* loop over all opus packets */
-                       ret = ogg_stream_packetout(&ctx->os, &op);
-                       if (ret != 1)
-                               break;
-                       ret = decode_packet(ctx, &op, btrn);
-                       if (ret < 0)
-                               goto out;
-                       ctx->packet_count++;
-                       if (ctx->eos)
-                               ctx->have_opus_stream = false;
-               }
        }
+       ret = decode_packet(ctx, &op, btrn);
+       if (ret < 0)
+               goto out;
+       ctx->packet_count++;
+       if (ctx->eos)
+               ctx->have_opus_stream = false;
 out:
        if (ret < 0)
                btr_remove_node(&fn->btrn);
        return ret;
 }
 
+static void opusdec_pre_select(struct sched *s, void *context)
+{
+       struct filter_node *fn = context;
+       struct opusdec_context *ctx = fn->private_data;
+       int ret = btr_node_status(fn->btrn, fn->min_iqs, BTR_NT_INTERNAL);
+
+       if (ret != 0)
+               return sched_min_delay(s);
+       if (!ctx->have_more)
+               return;
+       if (btr_get_output_queue_size(fn->btrn) <= OPUSDEC_MAX_OUTPUT_SIZE)
+               return sched_min_delay(s);
+}
+
 /**
  * The init function of the opusdec filter.
  *
@@ -269,7 +294,7 @@ void opusdec_filter_init(struct filter *f)
 {
        f->open = opusdec_open;
        f->close = opusdec_close;
-       f->pre_select = generic_filter_pre_select;
+       f->pre_select = opusdec_pre_select;
        f->post_select = opusdec_post_select;
        f->execute = opusdec_execute;
 }
index 5182ad238b81f706ebac2f6abdcaec3859b809dc..5fbfea08e178a56f43a0ead27d3a88c603c4145b 100644 (file)
--- a/oss_mix.c
+++ b/oss_mix.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1998-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1998-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -98,7 +98,7 @@ static int oss_mix_set_channel(struct mixer_handle *handle,
                handle->id = i;
                return 1;
        }
-       return -E_OSS_MIXER_CHANNEL;
+       return -E_BAD_CHANNEL;
 }
 
 static int oss_mix_get(struct mixer_handle *handle)
index 3c61a445eec2456ec5fdcf585a9d95753d4cd71c..77fe2a51314e1268fdfcc3b5b1b2db68ac816788 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2009-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -44,9 +44,9 @@ static int get_oss_format(enum sample_format sf)
        }
 }
 
-static void oss_pre_select(struct sched *s, struct task *t)
+static void oss_pre_select(struct sched *s, void *context)
 {
-       struct writer_node *wn = container_of(t, struct writer_node, task);
+       struct writer_node *wn = context;
        struct private_oss_write_data *powd = wn->private_data;
        int ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
 
@@ -157,17 +157,16 @@ err_free:
        return ret;
 }
 
-static int oss_post_select(__a_unused struct sched *s,
-               struct task *t)
+static int oss_post_select(__a_unused struct sched *s, void *context)
 {
-       struct writer_node *wn = container_of(t, struct writer_node, task);
+       struct writer_node *wn = context;
        struct private_oss_write_data *powd = wn->private_data;
        struct btr_node *btrn = wn->btrn;
        size_t frames, bytes;
        int ret;
        char *data;
 
-       ret = task_get_notification(t);
+       ret = task_get_notification(wn->task);
        if (ret < 0)
                goto out;
        ret = btr_node_status(btrn, wn->min_iqs, BTR_NT_LEAF);
index f1e308d8beb498586f60acbe1fa93b24077bc320..229930be074794cb2eea575c40fdb980f2856585 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -274,9 +274,9 @@ static inline bool need_drain_delay(struct private_osx_write_data *powd)
        return btr_get_input_queue_size(powd->callback_btrn) != 0;
 }
 
-static void osx_write_pre_select(struct sched *s, struct task *t)
+static void osx_write_pre_select(struct sched *s, void *context)
 {
-       struct writer_node *wn = container_of(t, struct writer_node, task);
+       struct writer_node *wn = context;
        struct private_osx_write_data *powd = wn->private_data;
        int ret;
        bool drain_delay_nec = false;
@@ -301,14 +301,14 @@ static void osx_write_pre_select(struct sched *s, struct task *t)
        sched_request_timeout_ms(50, s);
 }
 
-static int osx_write_post_select(__a_unused struct sched *s, struct task *t)
+static int osx_write_post_select(__a_unused struct sched *s, void *context)
 {
-       struct writer_node *wn = container_of(t, struct writer_node, task);
+       struct writer_node *wn = context;
        struct private_osx_write_data *powd = wn->private_data;
        struct btr_node *btrn = wn->btrn;
        int ret;
 
-       ret = task_get_notification(t);
+       ret = task_get_notification(wn->task);
        if (ret < 0)
                goto fail;
        if (!powd) {
diff --git a/para.h b/para.h
index 4de4af4a23dd0f0a6e225279f9e72423a027adc4..6bd048d8c590cb2bc493a1f65860a30517f6230e 100644 (file)
--- a/para.h
+++ b/para.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 #include <limits.h>
 #include <stdarg.h>
 #include <ctype.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <sys/un.h> /* needed by create_pf_socket */
 #include <string.h>
 #include <assert.h>
 #include <stdbool.h>
+#include <inttypes.h>
+#include <sys/uio.h>
 #include "gcc-compat.h"
 
 /** used in various contexts */
@@ -62,7 +60,7 @@ extern __printf_2_3 void (*para_log)(int, const char*, ...);
  *
  */
 #define DEFINE_STDERR_LOGGER(funcname, loglevel_barrier) \
-       __printf_2_3 void funcname(int ll, const char* fmt,...) \
+       static __printf_2_3 void funcname(int ll, const char* fmt,...) \
        { \
                va_list argp; \
                if (ll < loglevel_barrier) \
@@ -82,14 +80,6 @@ extern __printf_2_3 void (*para_log)(int, const char*, ...);
 
 /** Sent by para_client to initiate the authentication procedure. */
 #define AUTH_REQUEST_MSG "auth rsa "
-/** Sent by para_server for commands that expect a data file. */
-#define AWAITING_DATA_MSG "\nAwaiting Data."
-/** Sent by para_server if authentication was successful. */
-#define PROCEED_MSG "Proceed."
-/** Length of the \p PROCEED_MSG string. */
-#define PROCEED_MSG_LEN strlen(PROCEED_MSG)
-/** Sent by para_client to indicate the end of the command line. */
-#define EOC_MSG "\nEnd of Command."
 
 /* exec */
 int para_exec_cmdline_pid(pid_t *pid, const char *cmdline, int *fds);
diff --git a/play.c b/play.c
index 01125ab647f73482bb248ecdbaac2b8b2ad13021..c2a383c1555eb53bf84fef487ec6ba622f9659b0 100644 (file)
--- a/play.c
+++ b/play.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2012-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -57,7 +57,7 @@ enum state_change_request_type {
 };
 
 struct play_task {
-       struct task task;
+       struct task *task;
        /* A bit array of invalid files (those will be skipped). */
        bool *invalid;
        /* The file which is currently open. */
@@ -243,13 +243,16 @@ static void wipe_receiver_node(struct play_task *pt)
 /* returns: 0 not eof, 1: eof, < 0: fatal error.  */
 static int get_playback_error(struct play_task *pt)
 {
-       int err = pt->wn.task.error;
+       int err;
 
+       if (!pt->wn.task)
+               return 0;
+       err = task_status(pt->wn.task);
        if (err >= 0)
                return 0;
-       if (pt->fn.task.error >= 0)
+       if (task_status(pt->fn.task) >= 0)
                return 0;
-       if (pt->rn.task.error >= 0)
+       if (task_status(pt->rn.task) >= 0)
                return 0;
        if (err == -E_BTR_EOF || err == -E_RECV_EOF || err == -E_EOF
                        || err == -E_WRITE_COMMON_EOF)
@@ -267,16 +270,19 @@ static int eof_cleanup(struct play_task *pt)
        if (ret == 0)
                return ret;
        PARA_NOTICE_LOG("cleaning up wn/fn nodes\n");
+       task_reap(&pt->wn.task);
        w->close(&pt->wn);
        btr_remove_node(&pt->wn.btrn);
        w->free_config(pt->wn.conf);
        memset(&pt->wn, 0, sizeof(struct writer_node));
 
+       task_reap(&pt->fn.task);
        decoder->close(&pt->fn);
        btr_remove_node(&pt->fn.btrn);
        free(pt->fn.conf);
        memset(&pt->fn, 0, sizeof(struct filter_node));
 
+       task_reap(&pt->rn.task);
        btr_remove_node(&pt->rn.btrn);
        /*
         * On eof (ret > 0), we do not wipe the receiver node struct until a
@@ -295,7 +301,7 @@ static int shuffle_compare(__a_unused const void *a, __a_unused const void *b)
 
 static void shuffle(char **base, size_t num)
 {
-       srandom(now->tv_sec);
+       srandom(time(NULL));
        qsort(base, num, sizeof(char *), shuffle_compare);
 }
 
@@ -351,9 +357,6 @@ static int open_new_file(struct play_task *pt)
                free(tmp);
                tmp = NULL;
        }
-       pt->rn.task.pre_select = afh_recv->pre_select;
-       pt->rn.task.post_select = afh_recv->post_select;
-       sprintf(pt->rn.task.status, "%s receiver node", afh_recv->name);
        return 1;
 fail:
        wipe_receiver_node(pt);
@@ -363,7 +366,7 @@ fail:
 static int load_file(struct play_task *pt)
 {
        const char *af;
-       char *tmp;
+       char *tmp, buf[20];
        int ret;
        struct filter *decoder;
 
@@ -373,7 +376,6 @@ static int load_file(struct play_task *pt)
                if (ret < 0)
                        return ret;
        } else {
-               char buf[20];
                pt->rn.btrn = new_recv_btrn(&pt->rn);
                sprintf(buf, "repos %lu", pt->start_chunk);
                ret = btr_exec_up(pt->rn.btrn, buf, &tmp);
@@ -392,9 +394,6 @@ static int load_file(struct play_task *pt)
                goto fail;
        pt->fn.filter_num = ret;
        decoder = filters + ret;
-       pt->fn.task.pre_select = decoder->pre_select;
-       pt->fn.task.post_select = decoder->post_select;
-       sprintf(pt->fn.task.status, "%s decoder", af);
        pt->fn.btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.name = decoder->name, .parent = pt->rn.btrn,
                        .handler = decoder->execute, .context = &pt->fn));
@@ -402,11 +401,23 @@ static int load_file(struct play_task *pt)
 
        /* setup default writer */
        pt->wn.conf = check_writer_arg_or_die(NULL, &pt->wn.writer_num);
-       pt->wn.task.error = 0;
 
        /* success, register tasks */
-       register_task(&sched, &pt->rn.task);
-       register_task(&sched, &pt->fn.task);
+       pt->rn.task = task_register(
+               &(struct task_info) {
+                       .name = afh_recv->name,
+                       .pre_select = afh_recv->pre_select,
+                       .post_select = afh_recv->post_select,
+                       .context = &pt->rn
+               }, &sched);
+       sprintf(buf, "%s decoder", af);
+       pt->fn.task = task_register(
+               &(struct task_info) {
+                       .name = buf,
+                       .pre_select = decoder->pre_select,
+                       .post_select = decoder->post_select,
+                       .context = &pt->fn
+               }, &sched);
        register_writer_node(&pt->wn, pt->fn.btrn, &sched);
        return 1;
 fail:
@@ -452,7 +463,8 @@ again:
 
 static void kill_stream(struct play_task *pt)
 {
-       task_notify(&pt->wn.task, E_EOF);
+       if (pt->wn.task)
+               task_notify(pt->wn.task, E_EOF);
 }
 
 #ifdef HAVE_READLINE
@@ -1083,9 +1095,8 @@ static void session_update_time_string(struct play_task *pt, char *str, unsigned
  * terminates. Subsequent calls to i9e_get_error() then return negative and we
  * are allowed to call i9e_close() and terminate as well.
  */
-static int session_post_select(__a_unused struct sched *s, struct task *t)
+static int session_post_select(__a_unused struct sched *s, struct play_task *pt)
 {
-       struct play_task *pt = container_of(t, struct play_task, task);
        int ret;
 
        if (pt->background)
@@ -1107,9 +1118,8 @@ static int session_post_select(__a_unused struct sched *s, struct task *t)
 
 #else /* HAVE_READLINE */
 
-static int session_post_select(struct sched *s, struct task *t)
+static int session_post_select(struct sched *s, struct play_task *pt)
 {
-       struct play_task *pt = container_of(t, struct play_task, task);
        char c;
 
        if (!FD_ISSET(STDIN_FILENO, &s->rfds))
@@ -1132,9 +1142,9 @@ static void session_update_time_string(__a_unused struct play_task *pt,
 }
 #endif /* HAVE_READLINE */
 
-static void play_pre_select(struct sched *s, struct task *t)
+static void play_pre_select(struct sched *s, void *context)
 {
-       struct play_task *pt = container_of(t, struct play_task, task);
+       struct play_task *pt = context;
        char state;
 
        para_fd_set(STDIN_FILENO, &s->rfds, &s->max_fileno);
@@ -1171,9 +1181,9 @@ static unsigned get_time_string(struct play_task *pt, char **result)
        );
 }
 
-static int play_post_select(struct sched *s, struct task *t)
+static int play_post_select(struct sched *s, void *context)
 {
-       struct play_task *pt = container_of(t, struct play_task, task);
+       struct play_task *pt = context;
        int ret;
 
        ret = eof_cleanup(pt);
@@ -1181,7 +1191,7 @@ static int play_post_select(struct sched *s, struct task *t)
                pt->rq = CRT_TERM_RQ;
                return 0;
        }
-       ret = session_post_select(s, t);
+       ret = session_post_select(s, pt);
        if (ret < 0)
                goto out;
        if (!pt->wn.btrn && !pt->fn.btrn) {
@@ -1230,7 +1240,6 @@ int main(int argc, char *argv[])
        filter_init();
        writer_init();
 
-       clock_get_realtime(now);
        sched.default_timeout.tv_sec = 5;
 
        parse_config_or_die(argc, argv);
@@ -1245,11 +1254,14 @@ int main(int argc, char *argv[])
        pt->rq = CRT_FILE_CHANGE;
        pt->current_file = conf.inputs_num - 1;
        pt->playing = true;
-       pt->task.pre_select = play_pre_select;
-       pt->task.post_select = play_post_select;
-       sprintf(pt->task.status, "play task");
-       register_task(&sched, &pt->task);
+       pt->task = task_register(&(struct task_info){
+               .name = "play",
+               .pre_select = play_pre_select,
+               .post_select = play_post_select,
+               .context = pt,
+       }, &sched);
        ret = schedule(&sched);
+       sched_shutdown(&sched);
        if (ret < 0)
                PARA_ERROR_LOG("%s\n", para_strerror(-ret));
        return ret < 0? EXIT_FAILURE : EXIT_SUCCESS;
index c822e0802c53fdfbb72b5d728e0ca84aabbedc45..b83f8df8c30e93a04af060714445f7c40ef9ee63 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index c72d6d4951bb784816502a982185647ef9bcfe63..7371038a57cd7ef4450f02ddaf0add12c09050ca 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 655c981b921e0a0b484b5567ad9d448077d39631..356fb54cb6a860f6e623e14c0cd819158c98ba19 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2009-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -28,9 +28,9 @@ struct private_prebuffer_data {
        struct timeval barrier;
 };
 
-static void prebuffer_pre_select(struct sched *s, struct task *t)
+static void prebuffer_pre_select(struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        struct btr_node *btrn = fn->btrn;
        size_t iqs = btr_get_input_queue_size(btrn);
        struct private_prebuffer_data *ppd = fn->private_data;
@@ -56,9 +56,9 @@ static void prebuffer_close(struct filter_node *fn)
        free(fn->private_data);
 }
 
-static int prebuffer_post_select(__a_unused struct sched *s, struct task *t)
+static int prebuffer_post_select(__a_unused struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        struct btr_node *btrn = fn->btrn;
        size_t iqs = btr_get_input_queue_size(btrn);
        struct private_prebuffer_data *ppd = fn->private_data;
@@ -70,7 +70,7 @@ static int prebuffer_post_select(__a_unused struct sched *s, struct task *t)
                return 0;
        if (iqs < conf->size_arg)
                return 0;
-       btr_splice_out_node(fn->btrn);
+       btr_splice_out_node(&fn->btrn);
        return -E_PREBUFFER_SUCCESS;
 }
 
diff --git a/recv.c b/recv.c
index f28809da6c2b8c5b03f975e940cbe61cbdd4b27c..d127882a8e02d72219140325460fd73d9e050794 100644 (file)
--- a/recv.c
+++ b/recv.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -65,6 +65,7 @@ int main(int argc, char *argv[])
        struct receiver_node rn;
        struct stdout_task sot = {.btrn = NULL};
        static struct sched s;
+       struct task_info ti;
 
        recv_cmdline_parser(argc, argv, &conf);
        loglevel = get_loglevel_by_name(conf.loglevel_arg);
@@ -91,17 +92,18 @@ int main(int argc, char *argv[])
 
        sot.btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.parent = rn.btrn, .name = "stdout"));
-       stdout_set_defaults(&sot);
-       register_task(&s, &sot.task);
+       stdout_task_register(&sot, &s);
 
-       rn.task.pre_select = r->pre_select;
-       rn.task.post_select = r->post_select;
-       sprintf(rn.task.status, "%s", r->name);
-       register_task(&s, &rn.task);
+       ti.name = r->name;
+       ti.pre_select = r->pre_select;
+       ti.post_select = r->post_select;
+       ti.context = &rn;
+       rn.task = task_register(&ti, &s);
 
        s.default_timeout.tv_sec = 1;
        s.default_timeout.tv_usec = 0;
        ret = schedule(&s);
+       sched_shutdown(&s);
 out:
        if (r_opened)
                r->close(&rn);
diff --git a/recv.h b/recv.h
index 68222acffc7fc41f8fa2c4d644ff70ee3c4f753d..4564337cc9047bb38d4d77a5ec1eede83cfbc78c 100644 (file)
--- a/recv.h
+++ b/recv.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -17,7 +17,7 @@ struct receiver_node {
        /** Pointer to the configuration data for this instance. */
        void *conf;
        /** The task associated with this instance. */
-       struct task task;
+       struct task *task;
        /** The receiver node is always the root of the buffer tree. */
        struct btr_node *btrn;
        /** Each receiver node maintains a buffer pool for the received data. */
@@ -103,7 +103,7 @@ struct receiver {
         *
         * \sa select(2), time.c struct task, struct sched.
         */
-       void (*pre_select)(struct sched *s, struct task *t);
+       void (*pre_select)(struct sched *s, void *context);
        /**
         * Evaluate the result from select().
         *
@@ -115,7 +115,7 @@ struct receiver {
         *
         * \sa select(2), struct receiver.
         */
-       int (*post_select)(struct sched *s, struct task *t);
+       int (*post_select)(struct sched *s, void *context);
 
        /** The two help texts of this receiver. */
        struct ggo_help help;
@@ -142,7 +142,7 @@ struct receiver {
 void recv_init(void);
 void *check_receiver_arg(char *ra, int *receiver_num);
 void print_receiver_helps(unsigned flags);
-int generic_recv_pre_select(struct sched *s, struct task *t);
+int generic_recv_pre_select(struct sched *s, struct receiver_node *rn);
 
 /** \cond receiver */
 extern void http_recv_init(struct receiver *r);
index 2ea8a5992034419cf0375bae43851172c136b765..280f5bc40a7b6703ca737efe3e4f9e57baf30bde 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -50,19 +50,19 @@ static void *parse_receiver_args(int receiver_num, char *options)
 }
 
 /**
- * check if given string is a valid command line for any receiver
+ * Check if the given string is a valid receiver specifier.
  *
  * \param \ra string of the form receiver_name:options
  * \param receiver_num contains the number of the receiver upon success
  *
  * This function checks whether \a ra starts with the name of a supported
  * paraslash receiver, optinally followed by a colon and any options for that
- * receiver. If a valid receiver name was found and further are present, the
- * remaining part of \a ra is passed to that receiver's config parser.
+ * receiver. If a valid receiver name was found the remaining part of \a ra is
+ * passed to the receiver's config parser.
  *
- * \return On success, a pointer to the gengetopt args info struct is returned
- * and \a receiver_num contains the number of the receiver. Otherwise this function
- * returns \p NULL.
+ * \return On success, a pointer to the receiver-specific gengetopt args info
+ * struct is returned and \a receiver_num contains the number of the receiver.
+ * On errors, the function returns \p NULL.
  */
 void *check_receiver_arg(char *ra, int *receiver_num)
 {
@@ -116,7 +116,7 @@ void print_receiver_helps(unsigned flags)
  * Simple pre-select hook, used by all receivers.
  *
  * \param s Scheduler info.
- * \param t Determines the receiver node.
+ * \param rn The receiver node.
  *
  * This requests a minimal delay from the scheduler if the status of the buffer
  * tree node indicates an error/eof condition. No file descriptors are added to
@@ -125,12 +125,10 @@ void print_receiver_helps(unsigned flags)
  * \return The status of the btr node of the receiver node, i.e. the return
  * value of the underlying call to \ref btr_node_status().
  */
-int generic_recv_pre_select(struct sched *s, struct task *t)
+int generic_recv_pre_select(struct sched *s, struct receiver_node *rn)
 {
-       struct receiver_node *rn = container_of(t, struct receiver_node, task);
        int ret = btr_node_status(rn->btrn, 0, BTR_NT_ROOT);
 
-       t->error = 0;
        if (ret < 0)
                sched_min_delay(s);
        return ret;
index 5ad584ded50eaad435f5afdfeedccac9f40bcd75..61ffd2b6f5090419d90b27c9c8972fc97eba839d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2012-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -65,9 +65,9 @@ static void resample_open(struct filter_node *fn)
        btr_log_tree(btr_parent(btr_parent(btrn)), LL_INFO);
 }
 
-static void resample_pre_select(struct sched *s, struct task *t)
+static void resample_pre_select(struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        struct resample_context *ctx = fn->private_data;
        int ret = btr_node_status(fn->btrn, fn->min_iqs, BTR_NT_INTERNAL);
 
@@ -202,10 +202,10 @@ static int resample_frames(int16_t *in, size_t num_frames, bool have_more,
        return data.input_frames_used;
 }
 
-static int resample_post_select(__a_unused struct sched *s, struct task *t)
+static int resample_post_select(__a_unused struct sched *s, void *context)
 {
        int ret;
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        struct resample_context *ctx = fn->private_data;
        struct resample_filter_args_info *conf = fn->conf;
        struct btr_node *btrn = fn->btrn;
index a5a1c2594f0de72f7fc75dffeac3d93c8cf59d6c..e85661e4c0d57e56fb6b245b5c106c6e87090180 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index ce89d4b792db234ea8bba7dc04f04ce1076cf08e..075eb070927c97429f62c6f4acb3c02af61cdafa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/sched.c b/sched.c
index d42e149801e4a7ecabd4f96cc1f79802eb7a4ff1..44062a66196c814a19b827f31a40cdec89fb4f37 100644 (file)
--- a/sched.c
+++ b/sched.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 #include "time.h"
 #include "error.h"
 
-static struct timeval now_struct;
-struct timeval *now = &now_struct;
-
-/*
- * Remove a task from the scheduler.
- *
- * \param t The task to remove.
- *
- * If the pre_select pointer of \a t is not \p NULL, it is removed from
- * the pre_select list of the scheduler. Same goes for \a post_select.
+/**
+ * The possible states of a task.
+ *
+ * In addition to the states listed here, a task may also enter zombie state.
+ * This happens when its ->post_select function returns negative, the ->status
+ * field is then set to this return value. Such tasks are not scheduled any
+ * more (i.e. ->pre_select() and ->post_select() are no longer called), but
+ * they stay on the scheduler task list until \ref task_reap() or
+ * \ref sched_shutdown() is called.
  */
-static void unregister_task(struct task *t)
-{
-       assert(t->error < 0);
-       PARA_INFO_LOG("unregistering %s (%s)\n", t->status,
-               para_strerror(-t->error));
-       if (t->pre_select)
-               list_del(&t->pre_select_node);
-       if (t->post_select)
-               list_del(&t->post_select_node);
-}
+enum task_status {
+       /** Task has been reaped and may be removed from the task list. */
+       TS_DEAD,
+       /** Task is active. */
+       TS_RUNNING,
+};
+
+struct task {
+       /** A copy of the task name supplied when the task was registered. */
+       char *name;
+       /** Copied during task_register(). */
+       struct task_info info;
+       /* TS_RUNNING, TS_DEAD, or zombie (negative value). */
+       int status;
+       /** Position of the task in the task list of the scheduler. */
+       struct list_head node;
+       /** If less than zero, the task was notified by another task. */
+       int notification;
+};
+
+static struct timeval now_struct;
+const struct timeval *now = &now_struct;
 
 static inline bool timeout_is_zero(struct sched *s)
 {
@@ -50,51 +61,67 @@ static void sched_preselect(struct sched *s)
 {
        struct task *t, *tmp;
 
-       list_for_each_entry_safe(t, tmp, &s->pre_select_list, pre_select_node) {
+       list_for_each_entry_safe(t, tmp, &s->task_list, node) {
+               if (t->status < 0)
+                       continue;
                if (t->notification != 0)
                        sched_min_delay(s);
-               if (t->pre_select)
-                       t->pre_select(s, t);
+               if (t->info.pre_select)
+                       t->info.pre_select(s, t->info.context);
        }
 }
 
+static void unlink_and_free_task(struct task *t)
+{
+       PARA_INFO_LOG("freeing task %s\n", t->name);
+       list_del(&t->node);
+       free(t->name);
+       free(t);
+}
+
 //#define SCHED_DEBUG 1
 static inline void call_post_select(struct sched *s, struct task *t)
 {
+       int ret;
+
 #ifndef SCHED_DEBUG
-       t->error = t->post_select(s, t);
+       ret = t->info.post_select(s, t->info.context);
 #else
        struct timeval t1, t2, diff;
        unsigned long pst;
 
        clock_get_realtime(&t1);
-       t->error = t->post_select(s, t);
+       ret = t->info.post_select(s, t->info.context);
        clock_get_realtime(&t2);
        tv_diff(&t1, &t2, &diff);
        pst = tv2ms(&diff);
        if (pst > 50)
                PARA_WARNING_LOG("%s: post_select time: %lums\n",
-                       t->status, pst);
+                       t->name, pst);
 #endif
+       t->status = ret < 0? ret : TS_RUNNING;
 }
 
-static void sched_post_select(struct sched *s)
+static unsigned sched_post_select(struct sched *s)
 {
        struct task *t, *tmp;
+       unsigned num_running_tasks = 0;
 
-       list_for_each_entry_safe(t, tmp, &s->post_select_list, post_select_node) {
-               if (t->error >= 0)
-                       call_post_select(s, t);
-//             PARA_INFO_LOG("%s: %d\n", t->status, t->ret);
-               t->notification = 0;
-               if (t->error >= 0)
-                       continue;
-               unregister_task(t);
+       list_for_each_entry_safe(t, tmp, &s->task_list, node) {
+               if (t->status == TS_DEAD) /* task has been reaped */
+                       unlink_and_free_task(t);
+               else if (t->status == TS_RUNNING) {
+                       call_post_select(s, t); /* sets t->status */
+                       t->notification = 0;
+                       if (t->status == TS_RUNNING)
+                               num_running_tasks++;
+               }
        }
+       return num_running_tasks;
 }
 
 /**
- * The core function for all paraslash programs.
+ * The core function of all paraslash programs.
  *
  * \param s Pointer to the scheduler struct.
  *
@@ -103,14 +130,15 @@ static void sched_post_select(struct sched *s)
  * the fd sets of \a s.  Next, it calls para_select() and makes the result available
  * to the registered tasks by calling their post_select hook.
  *
- * \return Zero if no more tasks are left in either of the two lists, negative
- * if para_select returned an error.
+ * \return Zero if no more tasks are left in the task list, negative if the
+ * select function returned an error.
  *
- * \sa task, now.
+ * \sa \ref now.
  */
 int schedule(struct sched *s)
 {
        int ret;
+       unsigned num_running_tasks;
 
        if (!s->select_function)
                s->select_function = para_select;
@@ -119,7 +147,7 @@ again:
        FD_ZERO(&s->wfds);
        s->select_timeout = s->default_timeout;
        s->max_fileno = -1;
-       clock_get_realtime(now);
+       clock_get_realtime(&now_struct);
        sched_preselect(s);
        ret = s->select_function(s->max_fileno + 1, &s->rfds, &s->wfds,
                &s->select_timeout);
@@ -135,42 +163,105 @@ again:
                FD_ZERO(&s->rfds);
                FD_ZERO(&s->wfds);
        }
-       clock_get_realtime(now);
-       sched_post_select(s);
-       if (list_empty(&s->pre_select_list) && list_empty(&s->post_select_list))
+       clock_get_realtime(&now_struct);
+       num_running_tasks = sched_post_select(s);
+       if (num_running_tasks == 0)
                return 0;
        goto again;
 }
 
 /**
- * Add a task to the scheduler.
+ * Obtain the error status of a task and deallocate its resources.
  *
- * \param t The task to add.
- * \param s The scheduler instance to add the task to.
+ * \param tptr Identifies the task to reap.
  *
- * If the pre_select pointer of \a t is not \p NULL, it is added to
- * the pre_select list of the scheduler. Same goes for post_select.
+ * This function is similar to wait(2) in that it returns information about a
+ * terminated task and allows to release the resources associated with the
+ * task. Until this function is called, the terminated task remains in a zombie
+ * state.
  *
- * \sa task::pre_select, task::post_select
+ * \return If \a tptr is \p NULL, or \a *tptr is \p NULL, the function does
+ * nothing and returns zero. Otherwise, it is checked whether the task
+ * identified by \a tptr is still running. If it is, the function returns zero
+ * and again, no action is taken. Otherwise the (negative) error code of the
+ * terminated task is returned and \a *tptr is set to \p NULL. The task will
+ * then be removed removed from the scheduler task list.
+ *
+ * \sa \ref sched_shutdown(), wait(2).
  */
-void register_task(struct sched *s, struct task *t)
+int task_reap(struct task **tptr)
 {
-       PARA_INFO_LOG("registering %s (%p)\n", t->status, t);
-       t->notification = 0;
-       if (!s->pre_select_list.next)
-               INIT_LIST_HEAD(&s->pre_select_list);
-       if (!s->post_select_list.next)
-               INIT_LIST_HEAD(&s->post_select_list);
-       if (t->pre_select) {
-               PARA_DEBUG_LOG("pre_select: %p\n", &t->pre_select);
-               list_add_tail(&t->pre_select_node, &s->pre_select_list);
-       }
-       if (t->post_select) {
-               PARA_DEBUG_LOG("post_select: %p\n", &t->post_select);
-               list_add_tail(&t->post_select_node, &s->post_select_list);
+       struct task *t;
+       int ret;
+
+       if (!tptr)
+               return 0;
+       t = *tptr;
+       if (!t)
+               return 0;
+       if (t->status >= 0)
+               return 0;
+       ret = t->status;
+       /*
+        * With list_for_each_entry_safe() it is only safe to remove the
+        * _current_ list item. Since we are being called from the loop in
+        * schedule() via some task's ->post_select() function, freeing the
+        * given task here would result in use-after-free bugs in schedule().
+        * So we only set the task status to TS_DEAD which tells schedule() to
+        * free the task in the next iteration of its loop.
+        */
+       t->status = TS_DEAD;
+
+       *tptr = NULL;
+       return ret;
+}
+
+/**
+ * Deallocate all resources of all tasks of a scheduler instance.
+ *
+ * \param s The scheduler instance.
+ *
+ * This should only be called after \ref schedule() has returned.
+ */
+void sched_shutdown(struct sched *s)
+{
+       struct task *t, *tmp;
+
+       list_for_each_entry_safe(t, tmp, &s->task_list, node) {
+               if (t->status == TS_RUNNING)
+                       /* The task list should contain only terminated tasks. */
+                       PARA_WARNING_LOG("shutting down running task %s\n",
+                               t->name);
+               unlink_and_free_task(t);
        }
 }
 
+/**
+ * Add a task to the scheduler task list.
+ *
+ * \param info Task information supplied by the caller.
+ * \param s The scheduler instance.
+ *
+ * \return A pointer to a newly allocated task structure. It will be
+ * freed by sched_shutdown().
+ */
+struct task *task_register(struct task_info *info, struct sched *s)
+{
+       struct task *t = para_malloc(sizeof(*t));
+
+       assert(info->post_select);
+
+       if (!s->task_list.next)
+               INIT_LIST_HEAD(&s->task_list);
+
+       t->info = *info;
+       t->name = para_strdup(info->name);
+       t->notification = 0;
+       t->status = TS_RUNNING;
+       list_add_tail(&t->node, &s->task_list);
+       return t;
+}
+
 /**
  * Get the list of all registered tasks.
  *
@@ -186,21 +277,15 @@ char *get_task_list(struct sched *s)
        struct task *t, *tmp;
        char *msg = NULL;
 
-       list_for_each_entry_safe(t, tmp, &s->pre_select_list, pre_select_node) {
-               char *tmp_msg;
-               tmp_msg = make_message("%s%p\tpre\t%s\n", msg? msg : "", t, t->status);
-               free(msg);
-               msg = tmp_msg;
-       }
-       list_for_each_entry_safe(t, tmp, &s->post_select_list, post_select_node) {
+       list_for_each_entry_safe(t, tmp, &s->task_list, node) {
                char *tmp_msg;
-//             if (t->pre_select)
-//                     continue;
-               tmp_msg = make_message("%s%p\tpost\t%s\n", msg? msg : "", t, t->status);
+               tmp_msg = make_message("%s%p\t%s\t%s\n", msg? msg : "", t,
+                       t->status == TS_DEAD? "dead" :
+                               (t->status == TS_RUNNING? "running" : "zombie"),
+                       t->name);
                free(msg);
                msg = tmp_msg;
        }
-       //PARA_DEBUG_LOG("task list:\n%s", msg);
        return msg;
 }
 
@@ -228,7 +313,7 @@ void task_notify(struct task *t, int err)
        assert(err > 0);
        if (t->notification == -err) /* ignore subsequent notifications */
                return;
-       PARA_INFO_LOG("notifying task %s: %s\n", t->status, para_strerror(err));
+       PARA_INFO_LOG("notifying task %s: %s\n", t->name, para_strerror(err));
        t->notification = -err;
 }
 
@@ -243,11 +328,30 @@ void task_notify(struct task *t, int err)
  *
  * \sa \ref task_notify().
  */
-int task_get_notification(struct task *t)
+int task_get_notification(const struct task *t)
 {
        return t->notification;
 }
 
+/**
+ * Return the status value of a task.
+ *
+ * \param t The task to get the status value from.
+ *
+ * \return Zero if task does not exist, one if task is running, negative error
+ * code if task has terminated.
+ */
+int task_status(const struct task *t)
+{
+       if (!t)
+               return 0;
+       if (t->status == TS_DEAD) /* pretend dead tasks don't exist */
+               return 0;
+       if (t->status == TS_RUNNING)
+               return 1;
+       return t->status;
+}
+
 /**
  * Set the notification value of all tasks of a scheduler instance.
  *
@@ -261,9 +365,7 @@ void task_notify_all(struct sched *s, int err)
 {
        struct task *t;
 
-       list_for_each_entry(t, &s->pre_select_list, pre_select_node)
-               task_notify(t, err);
-       list_for_each_entry(t, &s->post_select_list, post_select_node)
+       list_for_each_entry(t, &s->task_list, node)
                task_notify(t, err);
 }
 
diff --git a/sched.h b/sched.h
index 234a8458d5870a1f14c66c81c140b61c0c20bf01..07877c461b81b76e1c207478b88d57db1f1fafd9 100644 (file)
--- a/sched.h
+++ b/sched.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 /**
  * Paraslash's scheduler.
  *
- * Designed with KISS in mind. It manages two lists of tasks.  The pre_select
- * list contains pointers to functions that are called before calling select()
- * from the main loop. Similarly, \a post_select_list is a list of function
- * pointers each of which is called after the select call. Tasks add hooks to
- * these lists by registering themselves to the scheduler.
+ * Designed with KISS in mind. It maintains a list of task structures which is
+ * extended when a new task is registered. Each task may define a pre_select
+ * function which is called from the scheduler main loop before it calls
+ * select(). Similarly, each task must define a post_select function which is
+ * called after the select call.
  */
 struct sched {
        /** Initial value before any pre_select call. */
@@ -29,46 +29,37 @@ struct sched {
        int max_fileno;
        /** If non-NULL, use this function instead of para_select. */
        int (*select_function)(int, fd_set *, fd_set *, struct timeval *);
-       /** Currently active pre_select functions. */
-       struct list_head pre_select_list;
-       /** Currently active post_select functions. */
-       struct list_head post_select_list;
+       /** Tasks which have been registered to the scheduler. */
+       struct list_head task_list;
 };
 
-/**
- * Paraslash's task structure.
- *
- * Before registering a task to the scheduler, the task structure must be
- * filled in properly by the caller.
- *
- * \sa \ref sched.
- */
-struct task {
+struct task;
+
+/** Information that must be supplied by callers of \ref task_register(). */
+struct task_info {
+       /** Used for log messages and by \ref get_task_list(). */
+       const char *name;
        /**
-        * The pre select hook of \a t.
+        * The optional pre select method.
         *
         * Its purpose is to add file descriptors to the fd sets of the
         * scheduler and to decrease the select timeout if necessary.
         */
-       void (*pre_select)(struct sched *s, struct task *t);
+       void (*pre_select)(struct sched *s, void *context);
        /**
-        * The post select hook of \a t.
+        * The mandatory post select method.
         *
         * Its purpose is to evaluate and act upon the results of the previous
         * select call. If this function returns a negative value, the
         * scheduler unregisters the task.
         */
-       int (*post_select)(struct sched *s, struct task *t);
-       /** Whether this task is in error state. */
-       int error;
-       /** Position of the task in the pre_select list of the scheduler. */
-       struct list_head pre_select_node;
-       /** Position of the task in the post_select list of the scheduler. */
-       struct list_head post_select_node;
-       /** Descriptive text and current status of the task. */
-       char status[255];
-       /** If less than zero, the task was notified by another task. */
-       int notification;
+       int (*post_select)(struct sched *s, void *context);
+       /**
+        * This pointer is saved when the task is registered. It is passed to
+        * ->pre_select() and ->post_select(). Usually this is a pointer to the
+        * struct owned by the caller which contains the task pointer.
+        */
+       void *context;
 };
 
 /**
@@ -77,14 +68,17 @@ struct task {
  * scheduler are allowed to block, this value should be accurate enough so that
  * there is no need to call clock_gettime() directly.
  */
-extern struct timeval *now;
+extern const struct timeval *now;
 
-void register_task(struct sched *s, struct task *t);
+struct task *task_register(struct task_info *info, struct sched *s);
 int schedule(struct sched *s);
+void sched_shutdown(struct sched *s);
 char *get_task_list(struct sched *s);
 void task_notify(struct task *t, int err);
 void task_notify_all(struct sched *s, int err);
-int task_get_notification(struct task *t);
+int task_get_notification(const struct task *t);
+int task_status(const struct task *t);
+int task_reap(struct task **tptr);
 void sched_min_delay(struct sched *s);
 void sched_request_timeout(struct timeval *to, struct sched *s);
 void sched_request_timeout_ms(long unsigned ms, struct sched *s);
diff --git a/score.c b/score.c
index ca94e8de3d645015b45ae0462938f1e2e4ebe559..f1afd22be7bc5c580312ca8eca3d128d1044dee0 100644 (file)
--- a/score.c
+++ b/score.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -168,13 +168,11 @@ static int get_nth_score(unsigned n, long *score)
  * \param aft_row Determines the audio file to change.
  * \param percent The position to re-insert the audio file.
  *
- * The percent parameter must be between \p 0 and 100 and. A value of zero
- * means to re-insert the audio file into the score table with a score lower
- * than any other admissible file.
+ * The percent parameter must be between 0 and 100. A value of zero means to
+ * re-insert the audio file into the score table with a score lower than any
+ * other admissible file.
  *
- * \return Positive on success, negative on errors. Possible errors: Errors
- * returned by osl_get_row(), get_num_admissible_files(), osl_get_nth_row(),
- * osl_get_object(), osl_update_object().
+ * \return Positive on success, negative on errors.
  */
 int score_update(const struct osl_row *aft_row, long percent)
 {
diff --git a/send.h b/send.h
index 01e0d0a850586312d4c6f4376ee7373ccdde9f93..8a69cb714ecd6c4a33d5c9c3bd8e99a9b3aff454 100644 (file)
--- a/send.h
+++ b/send.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 250a2a0bc5a80f8973b33d43bcb2e12e3ee723e9..0baac3a6f5c9713e810f97b53d13275f4178c610 100644 (file)
@@ -1,13 +1,18 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 
 /** \file send_common.c Functions used by more than one paraslash sender. */
 
+#include <netinet/in.h>
+#include <sys/socket.h>
 #include <regex.h>
 #include <osl.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
 
 #include "para.h"
 #include "error.h"
index f26abef5753204c4628c4183519f50f02b8f674e..908e039b1cf66be5909b102edfb20aa83ceb2b2a 100644 (file)
--- a/server.c
+++ b/server.c
@@ -1,74 +1,48 @@
 /*
- * Copyright (C) 1997-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 
 /** \file server.c Paraslash's main server. */
 
-
 /**
- * \mainpage Paraslash API Reference
- *
- * Starting points for getting an overview:
- *
+ * \mainpage Main data structures:
  *
- *     - The main programs: \ref server.c, \ref audiod.c, \ref client.c,
- *       \ref audioc.c, \ref afh.c, \ref play.c,
  *     - Server: \ref server_command, \ref sender,
- *     - Audio file selector: \ref audio_format_handler, \ref afs_table,
- *     - Client: \ref receiver, \ref receiver_node, \ref filter,
- *       \ref filter_node, \ref writer_node.
- *
- *
- * The gory details, listed by topic:
+ *     - Audio file selector: \ref afs_info, \ref afs_table,
+ *     - Audio format handler: \ref audio_format_handler, \ref afh_info
+ *     - Receivers/filters/writers: \ref receiver, \ref receiver_node,
+ *       \ref filter, \ref filter_node, \ref writer_node, \ref writer.
  *
- *     - Audio format handlers: \ref send_common.c \ref mp3_afh.c,
- *       \ref ogg_afh.c, \ref aac_afh.c, \ref wma_afh.c, \ref spx_afh.c
- *     - Decoders: \ref mp3dec_filter.c, \ref oggdec_filter.c,
- *       \ref aacdec_filter.c, \ref wmadec_filter.c, spxdec_filter.c,
- *       \ref flacdec_filter.c,
- *     - Volume normalizer: \ref compress_filter.c,
- *     - Output: \ref alsa_write.c, \ref osx_write.c, \ref oss_write.c,
- *     - http: \ref http_recv.c, \ref http_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,
- *       \ref afs_info \ref afh_info,
- *     - Afs tables: \ref aft.c, \ref mood.c, \ref playlist.c,
- *       \ref attribute.c, \ref score.c,
- *     - The virtual streaming system: \ref vss.c, \ref chunk_queue.c.
+ * Selected APIs:
  *
- * Lower levels:
- *
- *     - Scheduling: \ref sched.c, \ref sched.h,
- *     - Networking: \ref net.c,
- *     - File descriptors: \ref fd.c,
- *     - Signals: \ref signal.c,
- *     - Daemons: \ref daemon.c,
- *     - Strings: \ref string.c, \ref string.h,
+ *     - Scheduling: \ref sched.h,
+ *     - Buffer trees: \ref buffer_tree.h,
+ *     - Sideband API: \ref sideband.h,
+ *     - Crypto: \ref crypt.h, \ref crypt_backend.h,
+ *     - Error subsystem: \ref error.h, \ref error2.c,
+ *     - Inter process communication: \ref ipc.h,
+ *     - Forward error correction: \ref fec.h,
+ *     - Daemons: \ref daemon.h,
+ *     - Mixer API: \ref mix.h,
+ *     - Interactive sessions: \ref interactive.h,
+ *     - File descriptors: \ref fd.h,
+ *     - Signals: \ref signal.h,
+ *     - Networking: \ref net.h,
  *     - Time: \ref time.c,
- *     - Spawning processes: \ref exec.c,
- *     - Inter process communication: \ref ipc.c,
- *     - Blob tables: \ref blob.c,
- *     - The error subsystem: \ref error.h.
- *     - Access control for paraslash senders: \ref acl.c, \ref acl.h.
- *     - Internal crypto API: \ref crypt.h.
- *     - interactive sessions (libreadline): \ref interactive.c.
- *
- * Low-level data structures:
- *
- *     - Doubly linked lists: \ref list.h,
- *     - Ring buffer: \ref ringbuffer.c, \ref ringbuffer.h,
- *     - openssl: \ref crypt.c
- *     - libgcrypt: \ref gcrypt.c
- *     - Forward error correction: \ref fec.c.
+ *     - Doubly linked lists: \ref list.h.
  */
 
+#include <netinet/in.h>
+#include <sys/socket.h>
 #include <signal.h>
 #include <regex.h>
 #include <osl.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
 
 #include "para.h"
 #include "error.h"
@@ -136,7 +110,7 @@ struct server_command_task {
        /** Argument vector passed to para_server's main function. */
        char **argv;
        /** The command task structure for scheduling. */
-       struct task task;
+       struct task *task;
 };
 
 static int want_colors(void)
@@ -261,9 +235,9 @@ out:
        exit(EXIT_FAILURE);
 }
 
-static void signal_pre_select(struct sched *s, struct task *t)
+static void signal_pre_select(struct sched *s, void *context)
 {
-       struct signal_task *st = container_of(t, struct signal_task, task);
+       struct signal_task *st = context;
        para_fd_set(st->fd, &s->rfds, &s->max_fileno);
 }
 
@@ -279,7 +253,7 @@ static void handle_sighup(void)
                kill(mmd->afs_pid, SIGHUP);
 }
 
-static int signal_post_select(struct sched *s, __a_unused struct task *t)
+static int signal_post_select(struct sched *s, __a_unused void *context)
 {
        int signum = para_next_signal(&s->rfds);
 
@@ -338,10 +312,6 @@ static void init_signal_task(void)
        static struct signal_task signal_task_struct,
                *st = &signal_task_struct;
 
-       st->task.pre_select = signal_pre_select;
-       st->task.post_select = signal_post_select;
-       sprintf(st->task.status, "signal task");
-
        PARA_NOTICE_LOG("setting up signal handling\n");
        st->fd = para_signal_init(); /* always successful */
        para_install_sighandler(SIGINT);
@@ -350,18 +320,24 @@ static void init_signal_task(void)
        para_install_sighandler(SIGCHLD);
        para_sigaction(SIGPIPE, SIG_IGN);
        add_close_on_fork_list(st->fd);
-       register_task(&sched, &st->task);
+       st->task = task_register(&(struct task_info) {
+               .name = "signal",
+               .pre_select = signal_pre_select,
+               .post_select = signal_post_select,
+               .context = st,
+
+       }, &sched);
 }
 
-static void command_pre_select(struct sched *s, struct task *t)
+static void command_pre_select(struct sched *s, void *context)
 {
-       struct server_command_task *sct = container_of(t, struct server_command_task, task);
+       struct server_command_task *sct = context;
        para_fd_set(sct->listen_fd, &s->rfds, &s->max_fileno);
 }
 
-static int command_post_select(struct sched *s, struct task *t)
+static int command_post_select(struct sched *s, void *context)
 {
-       struct server_command_task *sct = container_of(t, struct server_command_task, task);
+       struct server_command_task *sct = context;
 
        int new_fd, ret, i;
        char *peer_name;
@@ -391,6 +367,9 @@ static int command_post_select(struct sched *s, struct task *t)
                goto out;
        }
        if (child_pid) {
+               /* avoid problems with non-fork-safe PRNGs */
+               unsigned char buf[16];
+               get_random_bytes_or_die(buf, sizeof(buf));
                close(new_fd);
                /* parent keeps accepting connections */
                return 0;
@@ -422,8 +401,6 @@ static void init_server_command_task(int argc, char **argv)
                *sct = &server_command_task_struct;
 
        PARA_NOTICE_LOG("initializing tcp command socket\n");
-       sct->task.pre_select = command_pre_select;
-       sct->task.post_select = command_post_select;
        sct->argc = argc;
        sct->argv = argv;
        ret = para_listen_simple(IPPROTO_TCP, conf.port_arg);
@@ -434,8 +411,12 @@ static void init_server_command_task(int argc, char **argv)
        if (ret < 0)
                goto err;
        add_close_on_fork_list(sct->listen_fd); /* child doesn't need the listener */
-       sprintf(sct->task.status, "server command task");
-       register_task(&sched, &sct->task);
+       sct->task = task_register(&(struct task_info) {
+               .name = "server command",
+               .pre_select = command_pre_select,
+               .post_select = command_post_select,
+               .context = sct,
+       }, &sched);
        return;
 err:
        PARA_EMERG_LOG("%s\n", para_strerror(-ret));
@@ -507,9 +488,7 @@ static void server_init(int argc, char **argv)
        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 */
-       clock_get_realtime(now);
-       set_server_start_time(now);
+       set_server_start_time(NULL);
        init_user_list(user_list_file);
        /* become daemon */
        if (conf.daemon_given)
@@ -596,6 +575,7 @@ int main(int argc, char *argv[])
        server_init(argc, argv);
        mutex_lock(mmd_mutex);
        ret = schedule(&sched);
+       sched_shutdown(&sched);
        if (ret < 0) {
                PARA_EMERG_LOG("%s\n", para_strerror(-ret));
                exit(EXIT_FAILURE);
index 820295a3ed8f627431081e8eecc540e43c9a19c1..64f0cc75972b9ec17ff9693fe0664d24c9ec4a42 100644 (file)
--- a/server.h
+++ b/server.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 6004651f110537ecf0da5eaf220365078e264cd9..a5f191615b4582542e5408442c69cf5096d7eea3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2012-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 50daaa608f9b7cb507f07ea394cc522d4ed7a6f6..4a838cee916cba03e85634784b0b3488595873a7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2012-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -58,6 +58,8 @@
        DESIGNATOR(EXIT__SUCCESS), \
        /* Command failed. */ \
        DESIGNATOR(EXIT__FAILURE), \
+       /* The next chunk of the blob (addblob commands only) */ \
+       DESIGNATOR(BLOB_DATA), \
 
 /** Just prefix with \p SBD_. */
 #define DESIGNATOR(x) SBD_ ## x
index 3b202a2c8ba6a62b23fa46f7e99ed207c4f08750..972d9d129a03f8060cda1a8dd2d98e3b181b2875 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2004-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -11,6 +11,9 @@
 #include "para.h"
 #include "error.h"
 #include "fd.h"
+#include "list.h"
+#include "sched.h"
+#include "signal.h"
 
 static int signal_pipe[2];
 
index 92af8170529fc1cbe3d5fa41d8bc79a2257f29d7..a15349cae9b703a3aeb546a3fc321bdda1d57aa8 100644 (file)
--- a/signal.h
+++ b/signal.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -13,7 +13,7 @@ struct signal_task {
        /** The signal pipe. */
        int fd;
        /** The associated task structure. */
-       struct task task;
+       struct task *task;
 };
 
 int para_signal_init(void);
diff --git a/skencil/overview.sk b/skencil/overview.sk
deleted file mode 100644 (file)
index 5ab648c..0000000
+++ /dev/null
@@ -1,474 +0,0 @@
-##Sketch 1 2
-document()
-layout('A4',0)
-layer('Layer 1',1,1,0,0,(0,0,0))
-lw(1)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(184.297,654.341,0)
-bs(184.297,732.403,0)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('open file',(1.19433e-15,1,-1,1.19433e-15,181.259,668.683))
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('mp3 data',(-1.83691e-16,-1,1,-1.83691e-16,193.585,717.172))
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(190.547,726.853,0)
-bs(190.547,655.774,0)
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(145.824,181.165,0)
-bs(228.568,181.165,0)
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(228.568,161.165,0)
-bs(145.824,161.165,0)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('connect local socket',(1.19433e-15,1,-1,1.19433e-15,272.988,207.639))
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(307.4,339.815,0)
-bs(307.4,200,0)
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(280,200,0)
-bs(280,339.815,0)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('server & audiod status',(-1.83691e-16,-1,1,-1.83691e-16,310.438,332.705))
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(99.2303,144.289,0)
-bs(99.2303,73.1918,0)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('s&a status',(-1.83691e-16,-1,1,-1.83691e-16,102.268,137.713))
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(61.1648,150.482,0)
-bs(61.1647,71.2323,0)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('cmd output',(-1.83691e-16,-1,1,-1.83691e-16,64.2028,142.553))
-lw(0.992126)
-ld((0.10000000000000001, 1.0))
-b()
-bs(24.7094,792.443,0)
-bs(310.724,792.443,0)
-bs(310.421,640.011,0)
-bs(561.98,639.817,0)
-bs(561.98,538.528,0)
-bs(24.7094,538.528,0)
-bs(24.7094,792.443,0)
-bC()
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Italic')
-txt('server host',(252.845,779.314))
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Italic')
-txt('client host',(512.93,400.509))
-G()
-lw(1)
-r(119.09,0,0,-28.2587,39.0214,375.322)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(24)
-txt('para_client',(45.2504,355.601))
-G_()
-G()
-lw(1)
-r(143.312,0,0,-28.2587,408.597,189.57)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(24)
-txt('sound_device',(414.265,169.849))
-G_()
-G()
-lw(1)
-r(94.8684,0,0,-28.2587,34.9844,58.6731)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(24)
-txt('terminal',(42.4226,38.9517))
-G_()
-G()
-lw(1)
-r(131.201,0,0,-28.2587,237.937,189.4)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(24)
-txt('para_audioc',(244.894,169.678))
-G_()
-G()
-lw(1)
-r(94.8684,0,0,-28.2587,34.9844,189.4)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(24)
-txt('para_gui',(40.4306,169.678))
-G_()
-fp((0.9,0.9,0.9))
-lw(1)
-r(177.037,0,0,-89.6831,384.699,788.574)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Bold')
-Fs(36)
-txt('paraslash',(399.201,755.055))
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Bold')
-Fs(36)
-txt('0.4.0',(437.217,712.433))
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('fork & exec',(153.764,182.009))
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('s&a status',(158.223,162.009))
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('fork & exec',(1.19433e-15,1,-1,1.19433e-15,70.3615,232.519))
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(73.3994,201.263,0)
-bs(73.3995,330.639,0)
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(103.54,330.639,0)
-bs(103.539,201.263,0)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('cmd output',(-1.83691e-16,-1,1,-1.83691e-16,106.577,297.647))
-lw(0.992126)
-ld((0.10000000000000001, 1.0))
-b()
-bs(29.1803,415.392,0)
-bs(570.132,415.357,0)
-bs(570.132,26.3198,0)
-bs(27.1619,26.3198,0)
-bs(27.1619,413.359,0)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt(' server cmd',(2.57235e-15,1,-1,2.57235e-15,359.444,441.487))
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('result',(-1.83691e-16,-1,1,-1.83691e-16,380.89,496.536))
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('connect tcp',(1.19433e-15,1,-1,1.19433e-15,420.523,446.644))
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(426.278,433.194,0)
-bs(426.278,524.243,0)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('server status',(-1.83691e-16,-1,1,-1.83691e-16,438.254,513.515))
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(431.433,522.224,0)
-bs(431.433,434.203,0)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('mp3 data ',(-1.83691e-16,-1,1,-1.83691e-16,513.965,505.064))
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(506.551,520.71,0)
-bs(506.551,433.193,0)
-G()
-lw(1)
-r(301.847,0,0,-28.2587,220.095,375.322)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(24)
-txt('para_audiod',(311.703,355.601))
-G_()
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(144.486,419.683,0)
-bs(144.486,431.685,0)
-bs(368.033,431.685,0)
-bs(368.033,531.257,0)
-lw(1)
-la1(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(151.551,419.179,0)
-bs(151.551,424.722,0)
-bs(374.601,424.722,0)
-bs(374.601,529.224,0)
-lw(1)
-ld((4, 4))
-r(156.432,0,0,-101.428,50.1221,646.762)
-G()
-lw(1)
-r(41.883,0,0,-28.2587,160.634,643.23)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(24)
-txt('afh',(166.229,623.509))
-G_()
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Italic')
-txt('afs process',(106.135,651.24))
-lw(1)
-r(0,0,0,-0.504639,125.815,629.1)
-lw(1)
-ld((5, 5))
-r(272.999,0,0,-67.6189,281.238,614.467)
-lw(1)
-r(78.2156,0,0,-28.2587,289.816,609.925)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(24)
-txt('vss',(313.588,590.204))
-lw(1)
-r(73.674,0,0,-59.5452,470.974,609.925)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(24)
-txt('sender',(477.579,574.056))
-lw(1)
-r(167.533,0,0,-28.2587,289.816,577.629)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(24)
-txt('cmd',(0.886791,0,0,1,355.258,557.908))
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Italic')
-txt('server process',(286.284,618.44))
-G()
-lw(1)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(216.351,599.242,0)
-bs(272.871,599.242,0)
-lw(1)
-la1(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(216.351,603.697,0)
-bs(272.87,603.697,0)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('open fd',(223.502,588.236))
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('request fd',(217.951,607.917))
-G_()
-G()
-lw(1)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(216.688,555.341,0)
-bs(273.208,555.341,0)
-lw(1)
-la1(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(216.688,559.796,0)
-bs(273.207,559.796,0)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('result',(228.885,545.344))
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('afs cmd',(222.83,563.006))
-G_()
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(79.9931,735.431,0)
-bs(79.9931,652.573,0)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('osl result',(-1.83691e-16,-1,1,-1.83691e-16,83.0311,719.475))
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('osl query',(3.06152e-16,1,-1,3.06152e-16,68.1098,669.658))
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(73.6709,653.078,0)
-bs(73.6709,735.936,0)
-G()
-lw(1)
-r(119.595,0,0,-46.425,75.8576,784.523)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-txt('file system',(108.732,771.908))
-G()
-G()
-lw(1)
-r(48.4434,0,0,-21.1941,81.9131,764.929)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-txt('osl table',(85.9688,750.758))
-G_()
-G()
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-txt('mp3 file',(143.495,750.295))
-lw(1)
-r(48.4434,0,0,-21.1941,139.44,764.929)
-G_()
-G_()
-G_()
-lw(1)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(379.134,590.245,0)
-bs(461.495,590.245,0)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-txt('mp3 data',(397.646,596.3))
-G()
-lw(1)
-r(120.099,0,0,-53.4896,68.2886,608.411)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(24)
-txt('afs',(0.886791,0,0,1,115.93,576.074))
-G_()
-G()
-lw(1)
-r(75.1101,0,0,-28.2587,56.6797,643.23)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(24)
-txt('libosl',(67.5587,620.179))
-G_()
-G()
-lw(0.992126)
-la2(([(-4.0, 3.0), (2.0, 0.0), (-4.0, -3.0), (-4.0, 3.0)], 1))
-b()
-bs(466.036,335.949,0)
-bs(466.036,203.05,0)
-fp((0,0,0))
-le()
-lw(1)
-Fn('Times-Roman')
-Fs(14)
-txt('pcm data',(-1.83691e-16,-1,1,-1.83691e-16,476.076,294.966))
-G_()
-guidelayer('Guide Lines',1,0,0,1,(0,0,1))
-guide(-307.905,0)
-grid((0,0,20,20),0,(0,0,1),'Grid')
diff --git a/spx.h b/spx.h
index c4999f07a6a32c2229afa8187c13871c64b3a7f8..3ae2c87cd85abb42a89d7663ab0540903dff7e23 100644 (file)
--- a/spx.h
+++ b/spx.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2010-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 8f7d715cf20cc730d985845818c8dd49f4bde200..2afebb186573fdc190f473efb467923c2c052ca8 100644 (file)
--- a/spx_afh.c
+++ b/spx_afh.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2010-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 3bd3d48d2b9fbc70fe8c8283a3ab47421ef1c463..f770be7db07d759dac671e1c19bb459cb8a133e8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2002-2006 Jean-Marc Valin
- * Copyright (C) 2010-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2010-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 9bba042c040c0687eb33f0fc156dbf62f06392c9..8b29007c67e5a7299c52cf8aada7875bef964a48 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2002-2006 Jean-Marc Valin
- * Copyright (C) 2010-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2010-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -238,9 +238,9 @@ static int compute_skip_samples(ogg_page *og, struct private_spxdec_data *psd)
        return ret;
 }
 
-static int speexdec_post_select(__a_unused struct sched *s, struct task *t)
+static int speexdec_post_select(__a_unused struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        struct private_spxdec_data *psd = fn->private_data;
        struct btr_node *btrn = fn->btrn;
        int ret, ns;
diff --git a/stat.c b/stat.c
index 8036de3a9d682d9bfe7506a09ee52cabbb9780ea..afc9c389d801b8d1fe970a64f7001516e930a831 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
diff --git a/stdin.c b/stdin.c
index 20b9250e9b7fbf3c252e20dff8891bfeeb5112dd..a66ad469c2d648a875d4e8f1ce6917606a18967d 100644 (file)
--- a/stdin.c
+++ b/stdin.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 #include "buffer_tree.h"
 #include "string.h"
 
-/**
- * The pre_select function of the stdin task.
- *
- * \param s The scheduler this task was registered to.
- * \param t The task structure of the stdin task.
- *
- * This function is always successful. If there is space left in the
- * buffer of the stdin task, it adds \p STDIN_FILENO to the read fd set
- * of \a s.
+/*
+ * If there is space left in the buffer of the stdin task add STDIN_FILENO to
+ * the read fd set of s.
  */
-static void stdin_pre_select(struct sched *s, struct task *t)
+static void stdin_pre_select(struct sched *s, void *context)
 {
-       struct stdin_task *sit = container_of(t, struct stdin_task, task);
+       struct stdin_task *sit = context;
        int ret;
 
        ret = btr_node_status(sit->btrn, 0, BTR_NT_ROOT);
@@ -43,20 +37,14 @@ static void stdin_pre_select(struct sched *s, struct task *t)
        sched_request_timeout_ms(100, s);
 }
 
-/**
- * The post select function of the stdin task.
- *
- * \param s The scheduler this task was registered to.
- * \param t The task structure of the stdin task.
- *
- * This function checks if \p STDIN_FILENO was included by in the read fd set
- * of \a s during the previous pre_select call.  If yes, and \p STDIN_FILENO
- * appears to be readable, data is read from stdin and fed into the buffer
- * tree.
+/*
+ * This function checks if STDIN_FILENO was included by in the read fd set of s
+ * during the previous pre_select call. If so, and if STDIN_FILENO is readable,
+ * data is read from stdin and fed into the buffer tree.
  */
-static int stdin_post_select(struct sched *s, struct task *t)
+static int stdin_post_select(struct sched *s, void *context)
 {
-       struct stdin_task *sit = container_of(t, struct stdin_task, task);
+       struct stdin_task *sit = context;
        ssize_t ret;
        size_t sz, n;
        char *buf = NULL;
@@ -95,21 +83,25 @@ err:
 }
 
 /**
- * Initialize a stdin task structure with default values.
+ * Register a stdin task structure.
  *
- * \param sit The stdin task structure.
+ * \param sit The stdin task structure to register.
+ * \param s The task will be added to this scheduler's task list.
  *
- * This fills in the pre/post select function pointers of the task structure
- * given by \a sit and creates a buffer tree for I/O.
+ * This allocates a buffer tree pool for I/O, sets up \a sit and registers a
+ * task with \a sit as context pointer.
  */
-void stdin_set_defaults(struct stdin_task *sit)
+void stdin_task_register(struct stdin_task *sit, struct sched *s)
 {
        int ret;
+       struct task_info ti = {
+               .name = "stdin",
+               .pre_select = stdin_pre_select,
+               .post_select = stdin_post_select,
+               .context = sit,
+       };
 
-       sit->task.pre_select = stdin_pre_select;
-       sit->task.post_select = stdin_post_select;
        sit->btrp = btr_pool_new("stdin", 128 * 1024);
-       sprintf(sit->task.status, "stdin reader");
        /*
         * Both STDIN_FILENO and STDOUT_FILENO may refer to the same open file
         * description (the terminal), and thus share the same file status
@@ -124,4 +116,5 @@ void stdin_set_defaults(struct stdin_task *sit)
        }
        sit->fd_flags = ret;
        sit->must_set_nonblock_flag = (sit->fd_flags & O_NONBLOCK) == 0;
+       sit->task = task_register(&ti, s);
 }
diff --git a/stdin.h b/stdin.h
index cdf0c67fd57a1078f38a9f175d598adf65ece520..b40cf7eba0277f4bd002921d97f00c2ffc03c06f 100644 (file)
--- a/stdin.h
+++ b/stdin.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -9,7 +9,7 @@
 /** The task structure used for reading from stdin. */
 struct stdin_task {
        /** The task structure. */
-       struct task task;
+       struct task *task;
        /** Stdin is always the root of a buffer tree. */
        struct btr_node *btrn;
        /** Use a buffer pool to minimize memcpy due to alignment problems. */
@@ -20,4 +20,4 @@ struct stdin_task {
        bool must_set_nonblock_flag;
 };
 
-void stdin_set_defaults(struct stdin_task *sit);
+void stdin_task_register(struct stdin_task *sit, struct sched *s);
index cf33bf6d0b67cf49625d27b4d602dec35922d32d..bb921ad12dd84acc71b5fb7a9c3944bc0d117732 100644 (file)
--- a/stdout.c
+++ b/stdout.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 #include "stdout.h"
 #include "buffer_tree.h"
 
-/**
- * The pre_select function of the stdout task.
- *
- * \param s The scheduler this task was registered to.
- * \param t The task structure of the stdout task.
- *
- * This function is always successful. If there is input data available, it
- * adds \p STDOUT_FILENO to the write fd set of \a s.
- */
-static void stdout_pre_select(struct sched *s, struct task *t)
+/* Add STDOUT_FILENO to the write fd set if there is input data available. */
+static void stdout_pre_select(struct sched *s, void *context)
 {
-       struct stdout_task *sot = container_of(t, struct stdout_task, task);
+       struct stdout_task *sot = context;
        int ret;
 
        ret = btr_node_status(sot->btrn, 0, BTR_NT_LEAF);
@@ -37,18 +29,13 @@ static void stdout_pre_select(struct sched *s, struct task *t)
                sched_min_delay(s);
 }
 
-/**
- * The post select function of the stdout task.
- *
- * \param s The scheduler this task was registered to.
- * \param t The task structure of the stdout task.
- *
- * This function writes input data from the buffer tree to stdout if \p
+/*
+ * This function writes input data from the buffer tree to stdout if
  * STDOUT_FILENO is writable.
  */
-static int stdout_post_select(struct sched *s, struct task *t)
+static int stdout_post_select(struct sched *s, void *context)
 {
-       struct stdout_task *sot = container_of(t, struct stdout_task, task);
+       struct stdout_task *sot = context;
        struct btr_node *btrn = sot->btrn;
        int ret;
        char *buf;
@@ -85,21 +72,24 @@ out:
        }
        return ret;
 }
+
 /**
- * Initialize a stdout task structure with default values.
+ * Register a stdout task structure.
  *
- * \param sot The stdout task structure.
+ * \param sot The stdout task structure to register.
+ * \param s The task will be added to this scheduler's task list.
  *
- * This fills in the pre/post select function pointers of the task structure
- * given by \a sot.
+ * This sets up \a sot and registers a task with \a sot as context pointer.
  */
-void stdout_set_defaults(struct stdout_task *sot)
+void stdout_task_register(struct stdout_task *sot, struct sched *s)
 {
        int ret;
-
-       sot->task.pre_select = stdout_pre_select;
-       sot->task.post_select = stdout_post_select;
-       sprintf(sot->task.status, "stdout");
+       struct task_info ti = {
+               .pre_select = stdout_pre_select,
+               .post_select = stdout_post_select,
+               .context = sot,
+               .name = "stdout",
+       };
 
        /* See stdin.c for details. */
        ret = fcntl(STDOUT_FILENO, F_GETFL);
@@ -109,4 +99,5 @@ void stdout_set_defaults(struct stdout_task *sot)
        }
        sot->fd_flags = ret;
        sot->must_set_nonblock_flag = (sot->fd_flags & O_NONBLOCK) == 0;
+       sot->task = task_register(&ti, s);
 }
index a21b7cedfb699d9402f666a1a754a26d12cdcec1..531fc7c2d5564755c7b20804817d41545d4ba2df 100644 (file)
--- a/stdout.h
+++ b/stdout.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -13,7 +13,7 @@
  */
 struct stdout_task {
        /** The task structure used by the scheduler. */
-       struct task task;
+       struct task *task;
        /** Stdout is always a leaf node in the buffer tree. */
        struct btr_node *btrn;
        /** The descriptor flags of STDOUT at startup. */
@@ -22,4 +22,4 @@ struct stdout_task {
        bool must_set_nonblock_flag;
 };
 
-void stdout_set_defaults(struct stdout_task *sot);
+void stdout_task_register(struct stdout_task *sot, struct sched *s);
index 38e25b09c5f3ff2b289d6e943a0f7bde3bfc23ad..10b6073fe1ff9960bac98ac473146a8a3e00a575 100644 (file)
--- a/string.c
+++ b/string.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2004-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -36,7 +36,7 @@
  *
  * \sa realloc(3).
  */
-__must_check __malloc void *para_realloc(void *p, size_t size)
+__must_check void *para_realloc(void *p, size_t size)
 {
        /*
         * No need to check for NULL pointers: If p is NULL, the call
@@ -298,24 +298,6 @@ __must_check char *para_basename(const char *name)
        return ret;
 }
 
-/**
- * Cut trailing newline.
- *
- * \param buf The string to be chopped.
- *
- * Replace the last character in \p buf by zero if it is equal to
- * the newline character.
- */
-void chop(char *buf)
-{
-       int n = strlen(buf);
-
-       if (!n)
-               return;
-       if (buf[n - 1] == '\n')
-               buf[n - 1] = '\0';
-}
-
 /**
  * Get the logname of the current user.
  *
index 935c7d456c2c5b6910b356f2ddd52fd62848cf67..11ba1283000d3f382eab71a0463923f2991bed2c 100644 (file)
--- a/string.h
+++ b/string.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -84,7 +84,6 @@ __must_check __malloc __printf_1_2 char *make_message(const char *fmt, ...);
 __must_check __malloc char *para_strcat(char *a, const char *b);
 __must_check __malloc char *para_dirname(const char *name);
 __must_check char *para_basename(const char *name);
-void chop(char *buf);
 __must_check __malloc char *para_logname(void);
 __must_check __malloc char *para_homedir(void);
 __malloc char *para_hostname(void);
diff --git a/sync_filter.c b/sync_filter.c
new file mode 100644 (file)
index 0000000..fceb1d1
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2013 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file sync_filter.c Playback synchronization filter. */
+
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <regex.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
+
+#include "para.h"
+#include "sync_filter.cmdline.h"
+#include "list.h"
+#include "net.h"
+#include "sched.h"
+#include "ggo.h"
+#include "buffer_tree.h"
+#include "filter.h"
+#include "string.h"
+#include "fd.h"
+#include "error.h"
+
+struct sync_buddy_info {
+       const char *url;
+       char *host;
+       int port;
+       struct addrinfo *ai;
+       bool disabled;
+};
+
+/* per open/close data */
+struct sync_buddy {
+       int fd;
+       struct sync_buddy_info *sbi;
+       bool ping_received;
+       struct list_head node;
+};
+
+struct sync_filter_context {
+       int listen_fd;
+       struct list_head buddies;
+       struct timeval timeout;
+       bool ping_sent;
+};
+
+struct sync_filter_config {
+       struct sync_filter_args_info *conf;
+       struct sync_buddy_info *buddy_info;
+};
+
+#define FOR_EACH_BUDDY(_buddy, _list) \
+       list_for_each_entry(_buddy, _list, node)
+#define FOR_EACH_BUDDY_SAFE(_buddy, _tmp_buddy, _list) \
+       list_for_each_entry_safe(_buddy, _tmp_buddy, _list, node)
+
+static void sync_close_buddy(struct sync_buddy *buddy)
+{
+       if (buddy->fd < 0)
+               return;
+       PARA_DEBUG_LOG("closing %s\n", buddy->sbi->url);
+       close(buddy->fd);
+       buddy->fd = -1;
+}
+
+static void sync_close_buddies(struct sync_filter_context *ctx)
+{
+       struct sync_buddy *buddy;
+
+       FOR_EACH_BUDDY(buddy, &ctx->buddies)
+               sync_close_buddy(buddy);
+}
+
+static void sync_close(struct filter_node *fn)
+{
+       struct sync_filter_context *ctx = fn->private_data;
+
+       sync_close_buddies(ctx);
+       if (ctx->listen_fd >= 0) {
+               close(ctx->listen_fd);
+               ctx->listen_fd = -1;
+       }
+       free(ctx);
+       fn->private_data = NULL;
+}
+
+static void sync_free_config(void *conf)
+{
+       struct sync_filter_config *sfc = conf;
+       int i;
+
+       for (i = 0; i < sfc->conf->buddy_given; i++) {
+               free(sfc->buddy_info[i].host);
+               freeaddrinfo(sfc->buddy_info[i].ai);
+       }
+       sync_filter_cmdline_parser_free(sfc->conf);
+       free(sfc);
+}
+
+static void sync_open(struct filter_node *fn)
+{
+       int i, ret;
+       struct sync_filter_config *sfc = fn->conf;
+       struct sync_buddy *buddy;
+       struct sync_filter_context *ctx;
+
+       assert(sfc);
+
+       ctx = fn->private_data = para_calloc(sizeof(*ctx));
+       INIT_LIST_HEAD(&ctx->buddies);
+       ctx->listen_fd = -1;
+
+       /* create socket to listen for incoming packets */
+       ret = makesock(
+               IPPROTO_UDP,
+               true /* passive */,
+               NULL /* no host required */,
+               sfc->conf->port_arg,
+               NULL /* no flowopts */
+       );
+       if (ret < 0) {
+               PARA_ERROR_LOG("could not create UDP listening socket %d\n",
+                       sfc->conf->port_arg);
+               return;
+       }
+       ctx->listen_fd = ret;
+       PARA_INFO_LOG("listening on fd %d\n", ctx->listen_fd);
+
+       for (i = 0; i < sfc->conf->buddy_given; i++) {
+               struct sync_buddy_info *sbi = sfc->buddy_info + i;
+               const char *url = sfc->conf->buddy_arg[i];
+               int fd;
+
+               /* make buddy udp socket from address info */
+               assert(sbi->ai);
+               ret = makesock_addrinfo(
+                       IPPROTO_UDP,
+                       false /* not passive */,
+                       sbi->ai,
+                       NULL /* no flowopts */
+               );
+               if (ret < 0) {
+                       PARA_WARNING_LOG("could not make socket for %s\n",
+                               url);
+                       goto fail;
+               }
+               fd = ret;
+               ret = mark_fd_nonblocking(fd);
+               if (ret < 0) {
+                       PARA_ERROR_LOG("unable to set nonblock mode for %s\n",
+                               url);
+                       close(fd);
+                       goto fail;
+               }
+               buddy = para_malloc(sizeof(*buddy));
+               buddy->fd = fd;
+               buddy->sbi = sbi;
+               buddy->ping_received = false;
+               para_list_add(&buddy->node, &ctx->buddies);
+
+               PARA_INFO_LOG("opened buddy %s on fd %d\n", url, fd);
+               continue;
+fail:
+               PARA_WARNING_LOG("%s\n", para_strerror(-ret));
+       }
+}
+
+static int sync_parse_config(int argc, char **argv, void **result)
+{
+       int i, ret, n;
+       struct sync_filter_config *sfc;
+       struct sync_filter_args_info *conf = para_malloc(sizeof(*conf));
+
+       sync_filter_cmdline_parser(argc, argv, conf); /* exits on error */
+       sfc = para_calloc(sizeof(*sfc));
+       sfc->conf = conf;
+       n = conf->buddy_given;
+       sfc->buddy_info = para_malloc((n + 1) * sizeof(*sfc->buddy_info));
+       PARA_INFO_LOG("initializing buddy info array of length %d\n", n);
+       for (i = 0; i < n; i++) {
+               const char *url = conf->buddy_arg[i];
+               size_t len = strlen(url);
+               char *host = para_malloc(len + 1);
+               int port;
+               struct addrinfo *ai;
+               struct sync_buddy_info *sbi = sfc->buddy_info + i;
+
+               if (!parse_url(url, host, len, &port)) {
+                       free(host);
+                       PARA_ERROR_LOG("could not parse url %s\n", url);
+                       ret = -ERRNO_TO_PARA_ERROR(EINVAL);
+                       goto fail;
+               }
+               if (port < 0)
+                       port = conf->port_arg;
+               ret = lookup_address(IPPROTO_UDP, false /* not passive */,
+                       host, port, &ai);
+               if (ret < 0) {
+                       PARA_ERROR_LOG("host lookup failure for %s\n", url);
+                       free(host);
+                       goto fail;
+               }
+               sbi->url = url;
+               sbi->host = host;
+               sbi->port = port;
+               sbi->ai = ai;
+               sbi->disabled = false;
+               PARA_DEBUG_LOG("buddy #%d: %s\n", i, url);
+       }
+       *result = sfc;
+       return 1;
+fail:
+       assert(ret < 0);
+       PARA_ERROR_LOG("%s\n", para_strerror(-ret));
+       sync_free_config(sfc);
+       return ret;
+}
+
+/*
+ * True if we sent a packet to all budies and received a packet from each
+ * enabled buddy.
+ */
+static bool sync_complete(struct sync_filter_context *ctx)
+{
+       struct sync_buddy *buddy;
+
+       if (!ctx->ping_sent)
+               return false;
+       FOR_EACH_BUDDY(buddy, &ctx->buddies)
+               if (!buddy->sbi->disabled && !buddy->ping_received)
+                       return false;
+       return true;
+}
+
+static void sync_disable_active_buddies(struct sync_filter_context *ctx)
+{
+       struct sync_buddy *buddy;
+
+       FOR_EACH_BUDDY(buddy, &ctx->buddies) {
+               if (buddy->sbi->disabled)
+                       continue;
+               PARA_NOTICE_LOG("disabling %s\n", buddy->sbi->url);
+               buddy->sbi->disabled = true;
+       }
+}
+
+static void sync_set_timeout(struct sync_filter_context *ctx,
+               struct sync_filter_config *sfc)
+{
+       struct timeval to;
+
+       ms2tv(sfc->conf->timeout_arg, &to);
+       tv_add(now, &to, &ctx->timeout);
+}
+
+static void sync_pre_select(struct sched *s, void *context)
+{
+       int ret;
+       struct filter_node *fn = context;
+       struct sync_filter_context *ctx = fn->private_data;
+       struct sync_filter_config *sfc = fn->conf;
+
+       if (list_empty(&ctx->buddies))
+               return sched_min_delay(s);
+       if (ctx->listen_fd < 0)
+               return sched_min_delay(s);
+       ret = btr_node_status(fn->btrn, 0, BTR_NT_INTERNAL);
+       if (ret < 0)
+               return sched_min_delay(s);
+       para_fd_set(ctx->listen_fd, &s->rfds, &s->max_fileno);
+       if (ret == 0)
+               return;
+       if (ctx->timeout.tv_sec == 0) { /* must ping buddies */
+               sync_set_timeout(ctx, sfc);
+               return sched_min_delay(s);
+       }
+       if (sync_complete(ctx)) /* push down what we have */
+               return sched_min_delay(s);
+       sched_request_barrier_or_min_delay(&ctx->timeout, s);
+}
+
+static struct sync_buddy *sync_find_buddy(struct sockaddr *addr,
+               struct list_head *list)
+{
+       struct sync_buddy *buddy;
+
+       FOR_EACH_BUDDY(buddy, list)
+               if (sockaddr_equal(buddy->sbi->ai->ai_addr, addr))
+                       return buddy;
+       return NULL;
+}
+
+static int sync_post_select(__a_unused struct sched *s, void *context)
+{
+       int ret;
+       struct filter_node *fn = context;
+       struct sync_filter_context *ctx = fn->private_data;
+       struct sync_filter_config *sfc = fn->conf;
+       struct sync_buddy *buddy, *tmp;
+
+       if (list_empty(&ctx->buddies))
+               goto success;
+       ret = -E_SYNC_LISTEN_FD;
+       if (ctx->listen_fd < 0)
+               goto fail;
+       ret = btr_node_status(fn->btrn, 0, BTR_NT_INTERNAL);
+       if (ret < 0)
+               goto fail;
+       if (ret == 0)
+               return 0;
+       if (ctx->timeout.tv_sec == 0)
+               sync_set_timeout(ctx, sfc);
+       else {
+               if (tv_diff(&ctx->timeout, now, NULL) < 0) {
+                       sync_disable_active_buddies(ctx);
+                       goto success;
+               }
+       }
+       if (!ctx->ping_sent) {
+               FOR_EACH_BUDDY_SAFE(buddy, tmp, &ctx->buddies) {
+                       char c = '\0';
+                       PARA_INFO_LOG("pinging %s (%s)\n",
+                               buddy->sbi->url, buddy->sbi->disabled?
+                               "disabled" : "enabled");
+                       ret = xwrite(buddy->fd, &c, 1);
+                       sync_close_buddy(buddy);
+                       if (ret < 0) {
+                               PARA_WARNING_LOG("failed to write to %s: %s\n",
+                                       buddy->sbi->url, para_strerror(-ret));
+                               list_del(&buddy->node);
+                       }
+               }
+               ctx->ping_sent = true;
+       }
+       if (FD_ISSET(ctx->listen_fd, &s->rfds)) {
+               char c;
+               for (;;) {
+                       struct sockaddr src_addr;
+                       socklen_t len = sizeof(src_addr);
+                       ret = recvfrom(ctx->listen_fd, &c, 1, MSG_DONTWAIT,
+                               &src_addr, &len);
+                       if (ret < 0) {
+                               if (errno == EAGAIN || errno == EWOULDBLOCK)
+                                       break;
+                               ret = -ERRNO_TO_PARA_ERROR(errno);
+                               goto fail;
+                       }
+                       buddy = sync_find_buddy(&src_addr, &ctx->buddies);
+                       if (!buddy) {
+                               PARA_NOTICE_LOG("pinged by unknown\n");
+                               continue;
+                       }
+                       PARA_DEBUG_LOG("pinged by %s\n", buddy->sbi->url);
+                       if (buddy->sbi->disabled) {
+                               PARA_NOTICE_LOG("enabling %s\n",
+                                       buddy->sbi->url);
+                               buddy->sbi->disabled = false;
+                       }
+                       list_del(&buddy->node);
+               }
+       }
+       if (!sync_complete(ctx))
+               return 1;
+       /*
+        * Although all enabled buddies are in sync we do not splice out
+        * ourselves immediately. We rather wait until the timout expires,
+        * or the buddy list has become empty. This opens a time window
+        * for disabled buddies to become enabled by sending us a packet.
+        */
+       btr_pushdown(fn->btrn);
+       return 1;
+success:
+       ret = -E_SYNC_COMPLETE; /* success */
+       goto out;
+fail:
+       PARA_WARNING_LOG("%s\n", para_strerror(-ret));
+out:
+       sync_close_buddies(ctx);
+       btr_splice_out_node(&fn->btrn);
+       assert(ret < 0);
+       return ret;
+}
+
+/**
+ * The synchronization filter.
+ *
+ * \param f Pointer to the struct to initialize.
+ */
+void sync_filter_init(struct filter *f)
+{
+       struct sync_filter_args_info dummy;
+
+       sync_filter_cmdline_parser_init(&dummy);
+       f->open = sync_open;
+       f->close = sync_close;
+       f->pre_select = sync_pre_select;
+       f->post_select = sync_post_select;
+       f->parse_config = sync_parse_config;
+       f->free_config = sync_free_config;
+       f->help = (struct ggo_help)DEFINE_GGO_HELP(sync_filter);
+}
index 69c69bef36dcabe995a7e281ec6d790e98f5de37..6ef9ac84862be90980474f699911421140fc6618 100644 (file)
@@ -6,8 +6,9 @@ trash_dir := $(test_dir)/trashes
 test_options := --executables-dir $(shell pwd)
 test_options += --results-dir $(results_dir)
 test_options += --trash-dir $(trash_dir)
-test_options += --executables "$(executables)"
+test_options += --executables "$(prefixed_executables)"
 test_options += --objects "$(basename $(all_objs))"
+test_options += --man-dir $(man_dir)
 
 ifdef V
        ifeq ("$(origin V)", "command line")
index 3c878eb77bbd61eed1fa5fb82e4e50e7596d67ca..04d6cd609a33a9886130d31efff86f4af509ab6f 100755 (executable)
@@ -74,15 +74,15 @@ EOF
 
        $PARA_SERVER \
                --logfile "$serverlog" \
-               --config_file /dev/null \
+               --config-file /dev/null \
                --daemon \
                --loglevel $loglevel \
                --port $port \
-               --afs_database_dir "$db" \
-               --afs_socket "$sock" \
-               --user_list "$user_list" \
-               --http_port "$stream_port" \
-               --dccp_port "$stream_port"
+               --afs-database-dir "$db" \
+               --afs-socket "$sock" \
+               --user-list "$user_list" \
+               --http-port "$stream_port" \
+               --dccp-port "$stream_port"
 fi
 
 for ((i=0; i < ${#commands[@]}; i++)); do
@@ -114,9 +114,9 @@ for ((i=0; i < ${#commands[@]}; i++)); do
        test_expect_success "$command" "
        $PARA_CLIENT \
                --loglevel $loglevel \
-               --server_port $port \
-               --key_file $privkey \
-               --config_file /dev/null \
+               --server-port $port \
+               --key-file $privkey \
+               --config-file /dev/null \
                -- \
                ${cmdline[$i]} > $command.out &&
                { [[ -z \"${good[$i]}\" ]] || grep \"${good[$i]}\"; } < $command.out &&
diff --git a/t/t0005-man.sh b/t/t0005-man.sh
new file mode 100755 (executable)
index 0000000..7a627aa
--- /dev/null
@@ -0,0 +1,64 @@
+#!/usr/bin/env bash
+
+test_description='Parse generated man pages.
+
+Simple sanity checks of some man pages.
+
+* para_audiod: Check that list of audiod commands is present
+* para_server: Check that list of server/afs commands is present
+* para_play: Check that list of play commands is present
+
+* para_{recv,filter,write,audiod}: Check for presence of
+filter/receiver/writer options as appropriate '
+
+. ${0%/*}/test-lib.sh
+
+rfw_regex='Options for .\{100,\}Options for ' # recv/filter/writer
+
+grep_man()
+{
+       local regex="$1" exe="$2"
+       tr '\n' ' ' < "$o_man_dir/para_$exe.1" | grep -q "$regex"
+}
+
+# check that options of all reveivers/filters/writers are contained
+# in the man pages
+
+regex="$rfw_regex"
+test_expect_success 'para_recv: receiver options' "grep_man '$regex' recv"
+test_expect_success 'para_filter: filter options' "grep_man '$regex' filter"
+test_expect_success 'para_write: writer options' "grep_man '$regex' write"
+test_require_objects "audiod"
+if [[ -n "$result" ]]; then
+       test_skip 'para_audiod' "missing object(s): $result"
+else
+       test_expect_success 'para_audiod: recv/filter/writer options' \
+               "grep_man '$regex' audiod"
+fi
+
+# check various command lists
+
+test_require_objects "audiod"
+if [[ -n "$result" ]]; then
+       test_skip 'para_audiod' "missing object(s): $result"
+else
+       regex='LIST OF AUDIOD COMMANDS.\{200,\}'
+       test_expect_success 'para_audiod: command list' \
+               "grep_man '$regex' audiod"
+fi
+
+test_require_objects "server"
+missing_objects="$result"
+if [[ -n "$missing_objects" ]]; then
+       test_skip "para_server" "missing object(s): $missing_objects"
+else
+       regex='LIST OF SERVER COMMANDS.\{100,\}LIST OF AFS COMMANDS'
+       test_expect_success 'para_server: server/afs commands' \
+               "grep_man '$regex' server"
+fi
+
+# para_play is always built
+regex='LIST OF COMMANDS.\{100,\}'
+test_expect_success 'para_play: play commands' "grep_man '$regex' play"
+regex="$rfw_regex"
+test_done
index f1bb8cf65b66ff3890659f2b6009bae08d3cbd77..0e702b53c9b4c4150418dc0e2a07e55949817b04 100644 (file)
@@ -21,22 +21,22 @@ say_color()
        if [[ "$o_nocolor" != "true" && -n "$1" ]]; then
                export TERM=$ORIGINAL_TERM
                case "$1" in
-                       error) tput bold; tput setaf 1;;
-                       skip)  tput setaf 5;;
+                       error) tput $C_BOLD; tput $C_SETAF 1;;
+                       skip)  tput $C_SETAF 5;;
                        ok)
                                (($o_verbose == 0)) && return
-                               tput setaf 2;;
-                       pass)  tput bold; tput setaf 2;;
-                       info)  tput setaf 3;;
+                               tput $C_SETAF 2;;
+                       pass)  tput $C_BOLD; tput $C_SETAF 2;;
+                       info)  tput $C_SETAF 3;;
                        run)
                                (($o_verbose == 0)) && return
-                               tput setaf 6;;
+                               tput $C_SETAF 6;;
                esac
        fi
        shift
        printf "%s\n" "$*"
        if [[ "$o_nocolor" != "true" && -n "$1" ]]; then
-               tput sgr0
+               tput $C_SGR0
                export TERM=dumb
        fi
 }
@@ -218,9 +218,21 @@ can_use_colors()
        result="false"
        [[ "$TERM" == "dumb" ]] && return
        [[ -t 1 ]] || return
-       tput bold >/dev/null 2>&1 || return
-       tput setaf 1 >/dev/null 2>&1 || return
-       tput sgr0 >/dev/null 2>&1 || return
+       C_BOLD='bold'
+       tput $C_BOLD &>/dev/null || {
+               C_BOLD='md'
+               tput $C_BOLD &>/dev/null
+       } || return
+       C_SETAF='setaf'
+       tput $C_SETAF 1 &>/dev/null || {
+               C_SETAF='AF'
+               tput $C_SETAF 1 &>/dev/null
+       } || return
+       C_SGR0='sgr0'
+       tput $C_SGR0 >/dev/null 2>&1 || {
+               C_SGR0='me'
+               tput $C_SGR0 &>/dev/null
+       } || return
        result="true"
 }
 
@@ -235,6 +247,7 @@ parse_options()
                -v=1|--verbose=1) o_verbose="1"; shift;;
                -v|--verbose|-v=2|--verbose=2) o_verbose="2"; shift;;
                --no-color) o_nocolor="true"; shift;;
+               --man-dir) export o_man_dir="$2"; shift; shift;;
                --results-dir) o_results_dir="$2"; shift; shift;;
                --trash-dir) o_trash_dir="$2"; shift; shift;;
                --executables-dir) export o_executables_dir="$2"; shift; shift;;
@@ -265,11 +278,13 @@ fixup_dirs()
        [[ -z "$o_results_dir" ]] && o_results_dir="$test_dir/test-results"
        [[ -z "$o_executables_dir" ]] && o_executables_dir="$test_dir/.."
        [[ -z "$o_trash_dir" ]] && o_trash_dir="$test_dir/trashes"
+       [[ -z "$o_man_dir" ]] && o_man_dir="$test_dir/../build/man/man1"
 
        # we want alsolute paths because relative paths become invalid
        # after changing to the trash dir
        [[ -n "${o_results_dir##/*}" ]] && o_results_dir="$wd/$o_results_dir"
        [[ -n "${o_executables_dir##/*}" ]] && o_executables_dir="$wd/$o_results_dir"
+       [[ -n "${o_man_dir##/*}" ]] && o_man_dir="$wd/$o_man_dir"
        [[ -n "${o_trash_dir##/*}" ]] && o_trash_dir="$wd/$o_trash_dir"
 
        mkdir -p "$o_results_dir"
diff --git a/time.c b/time.c
index fe431208d27130f452e0d61e7d801477730fbbfa..c405351a96f978c39b18ec0466a65fad012aff26 100644 (file)
--- a/time.c
+++ b/time.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 436b298cb8f467a25bf10c270a11ee08c74d6937..bde4124384abe918225f58bc658c1ef7d99dfae9 100644 (file)
@@ -1,13 +1,18 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 /** \file udp_recv.c Paraslash's udp receiver */
 
+#include <netinet/in.h>
 #include <regex.h>
 #include <sys/socket.h>
 #include <net/if.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
 
 #include "para.h"
 #include "error.h"
 #include "net.h"
 #include "fd.h"
 
-static void udp_recv_pre_select(struct sched *s, struct task *t)
+static void udp_recv_pre_select(struct sched *s, void *context)
 {
-       struct receiver_node *rn = container_of(t, struct receiver_node, task);
+       struct receiver_node *rn = context;
 
-       if (generic_recv_pre_select(s, t) <= 0)
+       if (generic_recv_pre_select(s, rn) <= 0)
                return;
        para_fd_set(rn->fd, &s->rfds, &s->max_fileno);
 }
@@ -43,21 +48,21 @@ static int udp_check_eof(size_t sz, struct iovec iov[2])
        }
        if (memcmp(iov[0].iov_base, FEC_EOF_PACKET, iov[0].iov_len) != 0)
                return 0;
-       if (memcmp(iov[1].iov_base, FEC_EOF_PACKET + iov[0].iov_len,
+       if (memcmp(iov[1].iov_base, &FEC_EOF_PACKET[iov[0].iov_len],
                        FEC_EOF_PACKET_LEN - iov[0].iov_len) != 0)
                return 0;
        return -E_RECV_EOF;
 }
 
-static int udp_recv_post_select(__a_unused struct sched *s, struct task *t)
+static int udp_recv_post_select(__a_unused struct sched *s, void *context)
 {
-       struct receiver_node *rn = container_of(t, struct receiver_node, task);
+       struct receiver_node *rn = context;
        struct btr_node *btrn = rn->btrn;
        size_t num_bytes;
        struct iovec iov[2];
        int ret, readv_ret, iovcnt;
 
-       ret = task_get_notification(t);
+       ret = task_get_notification(rn->task);
        if (ret < 0)
                goto out;
        ret = btr_node_status(btrn, 0, BTR_NT_ROOT);
index 7930f09234486d3448b196ba45ae3b178845d001..6ed5026ac31102932d4fb3b23e6e87d375002096 100644 (file)
@@ -1,18 +1,22 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 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 <netinet/in.h>
+#include <sys/socket.h>
 #include <regex.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/udp.h>
 #include <net/if.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
 #include <osl.h>
+#include <netdb.h>
 
 #include "server.cmdline.h"
 #include "para.h"
index 31ffe67b6e96f44aaabb2c32ac31ef4cfee2d468..4815e5d368c28ce8f66d00d0da3af2ce6c9bc003 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 5a1d69208c2720ead0c37dcadd29acc08a918ccc..120b0fdb44d6f9e64b9264b85f22ddafe419131f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index f8f7e6a33f69a4624f347e8b2c95f88e61111bb7..d81da754be3982661d11b0feb66eb3f37fb75111 100644 (file)
--- a/version.c
+++ b/version.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2013-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -7,9 +7,7 @@
 /** \file version.c Some helpers for printing version and copyright strings. */
 
 #include "para.h"
-
-/** \file version.h Macros for printing the version string. */
-
+#include "version.h"
 #include "git-version.h"
 
 /**
@@ -28,8 +26,8 @@ __a_const const char *version_git(void)
  *
  * \param pfx The program name (without the leading "para_").
  *
- * \return A statically allocated string which contains the program name, the
- * git version and the codename. It must not be freed by the caller.
+ * \return A statically allocated string which contains the program name and
+ * the git version. It must not be freed by the caller.
  */
 const char *version_single_line(const char *pfx)
 {
@@ -56,7 +54,7 @@ const char *version_text(const char *pfx)
        static char buf[512];
 
        snprintf(buf, sizeof(buf) - 1, "%s\n"
-               "Copyright (C) 2013 Andre Noll\n"
+               "Copyright (C) 2014 Andre Noll\n"
                "This is free software with ABSOLUTELY NO WARRANTY."
                " See COPYING for details.\n"
                "Report bugs to <maan@systemlinux.org>.\n"
diff --git a/vss.c b/vss.c
index 06707d6cfee11a70089db3fd7ef230af454e1516..928ef6c2e2bf9e564872d60e99f7deef3c23bd6c 100644 (file)
--- a/vss.c
+++ b/vss.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
  * senders.
  */
 
+#include <sys/socket.h>
+#include <netinet/in.h>
 #include <regex.h>
 #include <osl.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
 
 #include "para.h"
 #include "error.h"
@@ -83,7 +89,7 @@ struct vss_task {
        /** The memory mapped audio file. */
        char *map;
        /** Used by the scheduler. */
-       struct task task;
+       struct task *task;
        /** Pointer to the header of the mapped audio file. */
        char *header_buf;
        /** Length of the audio file header. */
@@ -879,12 +885,9 @@ static void set_mmd_offset(void)
        mmd->offset = tv2ms(&offset);
 }
 
-/**
+/*
  * Compute the timeout for the main select-loop of the scheduler.
  *
- * \param s Pointer to the server scheduler.
- * \param t Pointer to the vss task structure.
- *
  * Before the timeout is computed, the current vss status flags are evaluated
  * and acted upon by calling appropriate functions from the lower layers.
  * Possible actions include
@@ -893,10 +896,10 @@ static void set_mmd_offset(void)
  *     - shutdown of all senders (stop/pause command),
  *     - reposition the stream (ff/jmp command).
  */
-static void vss_pre_select(struct sched *s, struct task *t)
+static void vss_pre_select(struct sched *s, void *context)
 {
        int i;
-       struct vss_task *vsst = container_of(t, struct vss_task, task);
+       struct vss_task *vsst = context;
 
        if (!vsst->map || vss_next() || vss_paused() || vss_repos()) {
                struct fec_client *fc, *tmp;
@@ -1120,10 +1123,10 @@ static void vss_send(struct vss_task *vsst)
        }
 }
 
-static int vss_post_select(struct sched *s, struct task *t)
+static int vss_post_select(struct sched *s, void *context)
 {
        int ret, i;
-       struct vss_task *vsst = container_of(t, struct vss_task, task);
+       struct vss_task *vsst = context;
 
        if (mmd->sender_cmd_data.cmd_num >= 0) {
                int num = mmd->sender_cmd_data.cmd_num,
@@ -1179,8 +1182,6 @@ void init_vss_task(int afs_socket, struct sched *s)
                        conf.autoplay_delay_arg : 0;
        vsst->header_interval.tv_sec = 5; /* should this be configurable? */
        vsst->afs_socket = afs_socket;
-       vsst->task.pre_select = vss_pre_select;
-       vsst->task.post_select = vss_post_select;
        ms2tv(announce_time, &vsst->announce_tv);
        PARA_INFO_LOG("announce timeval: %lums\n", tv2ms(&vsst->announce_tv));
        INIT_LIST_HEAD(&fec_client_list);
@@ -1200,6 +1201,10 @@ void init_vss_task(int afs_socket, struct sched *s)
                tv_add(&vsst->autoplay_barrier, &vsst->announce_tv,
                        &vsst->data_send_barrier);
        }
-       sprintf(vsst->task.status, "vss task");
-       register_task(s, &vsst->task);
+       vsst->task = task_register(&(struct task_info) {
+               .name = "vss task",
+               .pre_select = vss_pre_select,
+               .post_select = vss_post_select,
+               .context = vsst,
+       }, s);
 }
diff --git a/vss.h b/vss.h
index bedbb8017a1c4cddf12282d53a48b71b6bb60648..c4d6f7376933a9f59569405dfa9e847e2c9dc0b9 100644 (file)
--- a/vss.h
+++ b/vss.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
index 83b81fb2d5b4b9303feb1600cb808fe52accfa51..199db45abe2e0663baa30e51e9f4acefc7b9ec60 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -63,20 +63,19 @@ static void wav_open(struct filter_node *fn)
        *bof = 1;
 }
 
-static void wav_pre_select(struct sched *s, struct task *t)
+static void wav_pre_select(struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        size_t iqs = btr_get_input_queue_size(fn->btrn);
 
-       t->error = 0;
        if (iqs == 0)
                return;
        sched_min_delay(s);
 }
 
-static int wav_post_select(__a_unused struct sched *s, struct task *t)
+static int wav_post_select(__a_unused struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        struct btr_node *btrn = fn->btrn;
        size_t iqs = btr_get_input_queue_size(btrn);
        int ret;
@@ -113,7 +112,7 @@ static int wav_post_select(__a_unused struct sched *s, struct task *t)
        ret = -E_WAV_SUCCESS;
 err:
        if (ret == -E_WAV_SUCCESS)
-               btr_splice_out_node(btrn);
+               btr_splice_out_node(&fn->btrn);
        else {
                btr_remove_node(&fn->btrn);
                PARA_ERROR_LOG("%s\n", para_strerror(-ret));
diff --git a/web/dia/overview.dia b/web/dia/overview.dia
new file mode 100644 (file)
index 0000000..f9e0158
--- /dev/null
@@ -0,0 +1,3817 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/">
+  <dia:diagramdata>
+    <dia:attribute name="background">
+      <dia:color val="#ffffff"/>
+    </dia:attribute>
+    <dia:attribute name="pagebreak">
+      <dia:color val="#000099"/>
+    </dia:attribute>
+    <dia:attribute name="paper">
+      <dia:composite type="paper">
+        <dia:attribute name="name">
+          <dia:string>#A4#</dia:string>
+        </dia:attribute>
+        <dia:attribute name="tmargin">
+          <dia:real val="2.8222000598907471"/>
+        </dia:attribute>
+        <dia:attribute name="bmargin">
+          <dia:real val="2.8222000598907471"/>
+        </dia:attribute>
+        <dia:attribute name="lmargin">
+          <dia:real val="2.8222000598907471"/>
+        </dia:attribute>
+        <dia:attribute name="rmargin">
+          <dia:real val="2.8222000598907471"/>
+        </dia:attribute>
+        <dia:attribute name="is_portrait">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="scaling">
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="fitto">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+      </dia:composite>
+    </dia:attribute>
+    <dia:attribute name="grid">
+      <dia:composite type="grid">
+        <dia:attribute name="width_x">
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="width_y">
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="visible_x">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:attribute name="visible_y">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:composite type="color"/>
+      </dia:composite>
+    </dia:attribute>
+    <dia:attribute name="color">
+      <dia:color val="#d8e5e5"/>
+    </dia:attribute>
+    <dia:attribute name="guides">
+      <dia:composite type="guides">
+        <dia:attribute name="hguides"/>
+        <dia:attribute name="vguides"/>
+      </dia:composite>
+    </dia:attribute>
+  </dia:diagramdata>
+  <dia:layer name="Background" visible="true" active="true">
+    <dia:object type="Standard - Text" version="1" id="O0">
+      <dia:attribute name="obj_pos">
+        <dia:point val="0.13505,-23.1314"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="0.13505,-23.7264;3.15255,-22.9789"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Overview#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80000000000000004"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="0.13505,-23.1314"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O1">
+      <dia:attribute name="obj_pos">
+        <dia:point val="0.1367,0.8291"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="0.1367,0.2341;3.9392,0.9816"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#para_server#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80000000000000004"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="0.1367,0.8291"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O2">
+      <dia:attribute name="obj_pos">
+        <dia:point val="0.225,9.8561"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="0.213438,9.47704;14.6275,15.9009"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Incoming connections arrive via TCP at the dispatcher which creates a
+command handler process for each connection.
+
+After the connecting client has been authenticated, the command
+handler propagates the incoming request either to the audio file
+selector (afs) or to the virtual streaming system (vss). Results are sent
+back to the client.
+
+afs maintans the audio file database and  is responsible for selecting
+and loading audio files while vss controls the paraslash senders. When
+vss needs to stream an audio file it requests an open file descriptor from
+afs and feeds small chunks of data (e.g. mp3 frames) to the senders
+which send the chunks to all connected clients.#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="0.225,9.8561"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O3">
+      <dia:attribute name="obj_pos">
+        <dia:point val="3.1702,14.0975"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="3.1702,13.5025;3.1702,14.25"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>##</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80000000000000004"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="3.1702,14.0975"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:group>
+      <dia:object type="Network - Bus" version="0" id="O4">
+        <dia:attribute name="obj_pos">
+          <dia:point val="6.3534,2.3542"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="3.58996,2.30409;11.989,6.1401"/>
+        </dia:attribute>
+        <dia:attribute name="conn_endpoints">
+          <dia:point val="6.3534,2.3542"/>
+          <dia:point val="11.9389,2.3663"/>
+        </dia:attribute>
+        <dia:attribute name="line_color">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="bus_handles">
+          <dia:point val="5.21003,3.2968"/>
+          <dia:point val="3.6399,2.3744"/>
+          <dia:point val="7.88141,3.2968"/>
+          <dia:point val="10.175,6.1401"/>
+          <dia:point val="8.92435,3.44756"/>
+          <dia:point val="6.83847,3.44756"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="2" to="O9" connection="11"/>
+          <dia:connection handle="4" to="O10" connection="11"/>
+          <dia:connection handle="5" to="O12" connection="11"/>
+          <dia:connection handle="6" to="O10" connection="3"/>
+          <dia:connection handle="7" to="O10" connection="6"/>
+        </dia:connections>
+      </dia:object>
+      <dia:object type="Standard - Line" version="0" id="O5">
+        <dia:attribute name="obj_pos">
+          <dia:point val="5.21006,6.4287"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="5.16003,5.6082;5.26006,6.4787"/>
+        </dia:attribute>
+        <dia:attribute name="conn_endpoints">
+          <dia:point val="5.21006,6.4287"/>
+          <dia:point val="5.21003,5.6582"/>
+        </dia:attribute>
+        <dia:attribute name="numcp">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O13" connection="11"/>
+          <dia:connection handle="1" to="O8" connection="1"/>
+        </dia:connections>
+      </dia:object>
+      <dia:object type="Standard - ZigZagLine" version="1" id="O6">
+        <dia:attribute name="obj_pos">
+          <dia:point val="4.0215,3.74907"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="3.4702,3.69907;11.8875,8.4582"/>
+        </dia:attribute>
+        <dia:attribute name="orth_points">
+          <dia:point val="4.0215,3.74907"/>
+          <dia:point val="3.5202,3.74907"/>
+          <dia:point val="3.5202,8.4082"/>
+          <dia:point val="11.8375,8.4082"/>
+          <dia:point val="11.8375,6.88101"/>
+          <dia:point val="11.3172,6.88101"/>
+        </dia:attribute>
+        <dia:attribute name="orth_orient">
+          <dia:enum val="0"/>
+          <dia:enum val="1"/>
+          <dia:enum val="0"/>
+          <dia:enum val="1"/>
+          <dia:enum val="0"/>
+        </dia:attribute>
+        <dia:attribute name="autorouting">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O9" connection="8"/>
+          <dia:connection handle="1" to="O12" connection="5"/>
+        </dia:connections>
+      </dia:object>
+      <dia:object type="Standard - ZigZagLine" version="1" id="O7">
+        <dia:attribute name="obj_pos">
+          <dia:point val="10.175,7.62192"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="5.16006,7.28325;10.225,8.0832"/>
+        </dia:attribute>
+        <dia:attribute name="orth_points">
+          <dia:point val="10.175,7.62192"/>
+          <dia:point val="10.175,8.0332"/>
+          <dia:point val="5.21006,8.0332"/>
+          <dia:point val="5.21006,7.33325"/>
+        </dia:attribute>
+        <dia:attribute name="orth_orient">
+          <dia:enum val="1"/>
+          <dia:enum val="0"/>
+          <dia:enum val="1"/>
+        </dia:attribute>
+        <dia:attribute name="autorouting">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O12" connection="2"/>
+          <dia:connection handle="1" to="O13" connection="2"/>
+        </dia:connections>
+      </dia:object>
+      <dia:object type="Network - Storage" version="1" id="O8">
+        <dia:attribute name="obj_pos">
+          <dia:point val="4.7175,4.4993"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="4.6675,4.4493;5.75257,6.51078"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="4.7175,4.4993"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="0.9850649999999993"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="1.1588999999999992"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#cccccc"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>##</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.80010001542891407"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="5.21003,6.25828"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="BPMN - Task" version="1" id="O9">
+        <dia:attribute name="obj_pos">
+          <dia:point val="3.86929,3.2968"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="3.81929,3.2468;6.60076,4.25135"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="3.86929,3.2968"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="2.6814705898130646"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="0.90454545953539145"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#ffffff"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#dispatcher#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.52916666975065518"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="5.21003,3.88136"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="BPMN - Task" version="1" id="O10">
+        <dia:attribute name="obj_pos">
+          <dia:point val="6.83847,3.2968"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="6.78847,3.2468;8.97435,4.25135"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="6.83847,3.2968"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="2.0858823545189464"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="0.90454545953538812"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#ffffff"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#senders#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.52916666975065518"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="7.88141,3.88136"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="BPMN - Task" version="1" id="O11">
+        <dia:attribute name="obj_pos">
+          <dia:point val="7.35748,6.4287"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="7.30748,6.3787;8.45572,7.38325"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="7.35748,6.4287"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="1.0482352956954173"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="0.90454545953538545"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#ffffff"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#vss#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.52916666975065518"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="7.8816,7.01326"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="BPMN - Task" version="1" id="O12">
+        <dia:attribute name="obj_pos">
+          <dia:point val="8.8978,6.1401"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="8.8478,6.0901;11.5022,7.67192"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="8.8978,6.1401"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="2.5544117662836525"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="1.4818181901724667"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#ffffff"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#command
+handler#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.52916666975065518"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="10.175,6.74872"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="BPMN - Task" version="1" id="O13">
+        <dia:attribute name="obj_pos">
+          <dia:point val="4.71771,6.4287"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="4.66771,6.3787;5.75242,7.38325"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="4.71771,6.4287"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="0.98470588393071123"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="0.90454545953538301"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#ffffff"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#afs#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.52916666975065518"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="5.21006,7.01326"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Standard - Line" version="0" id="O14">
+        <dia:attribute name="obj_pos">
+          <dia:point val="7.8816,6.4287"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="7.83141,4.15135;7.9316,6.4787"/>
+        </dia:attribute>
+        <dia:attribute name="conn_endpoints">
+          <dia:point val="7.8816,6.4287"/>
+          <dia:point val="7.88141,4.20135"/>
+        </dia:attribute>
+        <dia:attribute name="numcp">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O11" connection="11"/>
+          <dia:connection handle="1" to="O10" connection="2"/>
+        </dia:connections>
+      </dia:object>
+      <dia:object type="Standard - Line" version="0" id="O15">
+        <dia:attribute name="obj_pos">
+          <dia:point val="8.3766,6.88097"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="8.3266,6.83097;9.0828,6.93101"/>
+        </dia:attribute>
+        <dia:attribute name="conn_endpoints">
+          <dia:point val="8.3766,6.88097"/>
+          <dia:point val="9.0328,6.88101"/>
+        </dia:attribute>
+        <dia:attribute name="numcp">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O11" connection="5"/>
+          <dia:connection handle="1" to="O12" connection="8"/>
+        </dia:connections>
+      </dia:object>
+      <dia:object type="Standard - Line" version="0" id="O16">
+        <dia:attribute name="obj_pos">
+          <dia:point val="5.66933,6.88097"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="5.61933,6.83097;7.4366,6.93097"/>
+        </dia:attribute>
+        <dia:attribute name="conn_endpoints">
+          <dia:point val="5.66933,6.88097"/>
+          <dia:point val="7.3866,6.88097"/>
+        </dia:attribute>
+        <dia:attribute name="numcp">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O13" connection="5"/>
+          <dia:connection handle="1" to="O11" connection="8"/>
+        </dia:connections>
+      </dia:object>
+    </dia:group>
+    <dia:object type="Network - An amplifier speaker" version="1" id="O17">
+      <dia:attribute name="obj_pos">
+        <dia:point val="9.8398,-22.1251"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="9.7898,-22.1751;11.2046,-19.4456"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="9.8398,-22.1251"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="1.314752411332281"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="2.6295048226645621"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#ffffff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Network - General Monitor (With Stand)" version="1" id="O18">
+      <dia:attribute name="obj_pos">
+        <dia:point val="3.20424,-21.8387"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="3.19174,-21.8512;5.40635,-18.76"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="3.20424,-21.8387"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="2.1896140767718091"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="2.1531205088256122"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.05000000074505806"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#ffffff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>##</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80010001542891407"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="4.29905,-19.0125"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O19">
+      <dia:attribute name="obj_pos">
+        <dia:point val="11.7649,-16.3593"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="11.7144,-16.4098;12.6724,-16.2995"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="11.7649,-16.3593"/>
+        <dia:point val="12.6218,-16.35"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O20" connection="5"/>
+        <dia:connection handle="1" to="O35" connection="2"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="BPMN - Task" version="1" id="O20">
+      <dia:attribute name="obj_pos">
+        <dia:point val="9.08475,-16.8116"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="9.03475,-16.8616;11.9353,-15.8571"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="9.08475,-16.8116"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="2.8005882368718877"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="0.90454545953538812"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#bbe7bb"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#para_server#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="10.485,-16.2359"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="BPMN - Task" version="1" id="O21">
+      <dia:attribute name="obj_pos">
+        <dia:point val="9.03812,-18.5769"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="8.98812,-18.6269;11.9893,-17.6608"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="9.03812,-18.5769"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="2.9011764721660049"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="0.86606061082624863"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#bbe7bb"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#para_audiod#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="10.4887,-18.0204"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="BPMN - Task" version="1" id="O22">
+      <dia:attribute name="obj_pos">
+        <dia:point val="5.75078,-18.5644"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="5.70078,-18.6144;8.66755,-17.6483"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="5.75078,-18.5644"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="2.8667647074601228"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="0.86606061082624919"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#ffffff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#para_audioc#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="7.18416,-18.0079"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="BPMN - Task" version="1" id="O23">
+      <dia:attribute name="obj_pos">
+        <dia:point val="6.01211,-21.1907"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="5.96211,-21.2407;8.43123,-20.2746"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="6.01211,-21.1907"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="2.369117647058824"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="0.8660606108262402"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#ffffff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#para_gui#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="7.19667,-20.6342"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="BPMN - Task" version="1" id="O24">
+      <dia:attribute name="obj_pos">
+        <dia:point val="2.98001,-16.8019"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="2.93001,-16.8519;5.65589,-15.8858"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="2.98001,-16.8019"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="2.6258823545189465"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="0.86606061082625097"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#ffffff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#para_client#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="4.29295,-16.2454"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O25">
+      <dia:attribute name="obj_pos">
+        <dia:point val="6.01211,-20.7577"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="5.35471,-20.8094;6.06224,-20.7076"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="6.01211,-20.7577"/>
+        <dia:point val="5.40484,-20.7593"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O23" connection="8"/>
+        <dia:connection handle="1" to="O18" connection="1"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O26">
+      <dia:attribute name="obj_pos">
+        <dia:point val="8.49446,-18.1314"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="8.44354,-18.1948;9.21742,-18.0805"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="8.49446,-18.1314"/>
+        <dia:point val="9.1665,-18.1439"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O22" connection="5"/>
+        <dia:connection handle="1" to="O21" connection="8"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O27">
+      <dia:attribute name="obj_pos">
+        <dia:point val="7.18416,-18.5644"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="7.13381,-20.3751;7.24702,-18.514"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="7.18416,-18.5644"/>
+        <dia:point val="7.19667,-20.3247"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O22" connection="11"/>
+        <dia:connection handle="1" to="O23" connection="11"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O28">
+      <dia:attribute name="obj_pos">
+        <dia:point val="10.4972,-19.4956"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="10.4382,-19.5461;10.5477,-18.5264"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="10.4972,-19.4956"/>
+        <dia:point val="10.4887,-18.5769"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O17" connection="2"/>
+        <dia:connection handle="1" to="O21" connection="11"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O29">
+      <dia:attribute name="obj_pos">
+        <dia:point val="5.47486,-16.3689"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="5.42473,-16.419;9.25532,-16.3092"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="5.47486,-16.3689"/>
+        <dia:point val="9.20519,-16.3593"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_color">
+        <dia:color val="#888888"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O24" connection="5"/>
+        <dia:connection handle="1" to="O20" connection="8"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O30">
+      <dia:attribute name="obj_pos">
+        <dia:point val="10.485,-16.8116"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="10.4348,-17.761;10.5389,-16.7614"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="10.485,-16.8116"/>
+        <dia:point val="10.4887,-17.7108"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_color">
+        <dia:color val="#888888"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O20" connection="11"/>
+        <dia:connection handle="1" to="O21" connection="2"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O31">
+      <dia:attribute name="obj_pos">
+        <dia:point val="1.575,-10.6689"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="1.575,-11.2639;1.575,-10.5164"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>##</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80000000000000004"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="1.575,-10.6689"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O32">
+      <dia:attribute name="obj_pos">
+        <dia:point val="3.6375,10.9686"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="3.6375,10.3736;3.6375,11.1211"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>##</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80000000000000004"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="3.6375,10.9686"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O33">
+      <dia:attribute name="obj_pos">
+        <dia:point val="2.6375,10.6686"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="2.6375,10.0736;2.6375,10.8211"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>##</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80000000000000004"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="2.6375,10.6686"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O34">
+      <dia:attribute name="obj_pos">
+        <dia:point val="4.29295,-16.8019"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="4.24287,-19.7231;4.34745,-16.7518"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="4.29295,-16.8019"/>
+        <dia:point val="4.29737,-19.673"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O24" connection="11"/>
+        <dia:connection handle="1" to="O18" connection="1"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Network - Storage" version="1" id="O35">
+      <dia:attribute name="obj_pos">
+        <dia:point val="12.6719,-16.9342"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="12.6219,-16.9842;13.7267,-15.1866"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="12.6719,-16.9342"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="1.0048306811423449"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="1.1821537425204058"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#cccccc"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>##</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="13.1743,-15.3816"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O36">
+      <dia:attribute name="obj_pos">
+        <dia:point val="0.171225,-14.4141"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="0.159662,-14.7932;14.6787,-7.87542"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#The two main applications of the paraslash suite (shaded green) are
+para_server and para_audiod. Both run in the background usually.
+para_server maintains the audio file database and acts as the streaming
+source, while para_audiod is the streaming client.
+
+The two client programs, para_client and para_audioc communicate
+with para_server and para_audiod, respectively.
+
+para_gui controls para_server/audiod by executing paraslash commands.
+Command output is shown in a curses window. para_gui automatically
+executes para_audioc to obtain the state of para_audiod and para_server
+and the metadata of the current audio file.
+
+Network connections are shaded grey, local connections black.#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="0.171225,-14.4141"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O37">
+      <dia:attribute name="obj_pos">
+        <dia:point val="0.1003,73.0082"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="0.1003,72.4132;4.0578,73.1607"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#para_audiod#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80000000000000004"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="0.1003,73.0082"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O38">
+      <dia:attribute name="obj_pos">
+        <dia:point val="0.116202,82.0061"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="0.116202,81.627;14.5828,87.0631"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#The purpose of para_audiod is to download, decode and play an audio
+stream received from para_server. It fetches the para_server status and
+starts a suitable buffer tree (shaded blue) if an audio stream is available.
+
+The buffer tree usually consists of a receiver, any number of filters and
+a writer. The receiver downloads the audio stream from para_server and
+the filters decode or modify the received data. The writer plays the
+decoded stream.
+
+The dispatcher acts on (local) requests from para_audioc, for example to
+dump information about the current audio file.#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="0.116202,82.0061"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O39">
+      <dia:attribute name="obj_pos">
+        <dia:point val="0.27019,32.9375"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="0.258628,32.5584;13.8202,37.5006"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#The audio file selector (afs) accepts two different kinds of incoming
+connections: A bidirectional pipe shared with para_server is used for
+passing the file descriptor of the current audio file to the server
+process. The local socket is used by command handlers which query
+or update the database.
+
+To add a new file to the database, afs opens the file and locates an
+audio format handler (afh) that recognizes the file. A new database
+entry with metadata obtained from the afh is then added to the
+database.#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="0.27019,32.9375"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O40">
+      <dia:attribute name="obj_pos">
+        <dia:point val="0.11118,24.9782"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="0.11118,24.3832;7.22118,25.1307"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#The audio file selector#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80000000000000004"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="0.11118,24.9782"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O41">
+      <dia:attribute name="obj_pos">
+        <dia:point val="6.8012,28.9591"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="5.61907,28.9091;6.85122,29.0096"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="6.8012,28.9591"/>
+        <dia:point val="5.66909,28.9596"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="4"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O50" connection="8"/>
+        <dia:connection handle="1" to="O43" connection="2"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O42">
+      <dia:attribute name="obj_pos">
+        <dia:point val="7.6012,28.5261"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="7.53094,27.1956;9.25521,28.5964"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="7.6012,28.5261"/>
+        <dia:point val="9.18495,27.2659"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O50" connection="10"/>
+        <dia:connection handle="1" to="O47" connection="0"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Network - Storage" version="1" id="O43">
+      <dia:attribute name="obj_pos">
+        <dia:point val="4.61551,28.3687"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="4.00418,28.3187;6.23168,30.1163"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="4.61551,28.3687"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="1.0048306811423449"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="1.1821537425204058"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#cccccc"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#audio files#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="5.11793,29.9213"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O44">
+      <dia:attribute name="obj_pos">
+        <dia:point val="7.2512,28.5261"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="7.19859,26.8922;7.30128,28.5762"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="7.2512,28.5261"/>
+        <dia:point val="7.24867,26.9423"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O50" connection="11"/>
+        <dia:connection handle="1" to="O46" connection="2"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O45">
+      <dia:attribute name="obj_pos">
+        <dia:point val="7.2512,29.3922"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="7.20042,29.3414;7.32552,30.9457"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="7.2512,29.3922"/>
+        <dia:point val="7.27474,30.8949"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O50" connection="2"/>
+        <dia:connection handle="1" to="O49" connection="11"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="BPMN - Task" version="1" id="O46">
+      <dia:attribute name="obj_pos">
+        <dia:point val="5.84838,26.0762"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="5.79838,26.0262;8.69897,26.9923"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="5.84838,26.0762"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="2.8005882368718877"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="0.86606061082624941"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#bbe7bb"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#para_server#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="7.24867,26.6327"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="BPMN - Task" version="1" id="O47">
+      <dia:attribute name="obj_pos">
+        <dia:point val="9.04127,26.3998"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="8.99127,26.3498;10.0786,27.3159"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="9.04127,26.3998"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="0.98735294275424068"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="0.86606061082625274"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#ffffff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#afh#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="9.53495,26.9563"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Network - Storage" version="1" id="O48">
+      <dia:attribute name="obj_pos">
+        <dia:point val="8.84318,28.3795"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="8.65435,28.3295;10.0368,30.1271"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="8.84318,28.3795"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="1.0048306811423449"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="1.1821537425204058"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#cccccc"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#osl db#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="9.3456,29.9321"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="BPMN - Task" version="1" id="O49">
+      <dia:attribute name="obj_pos">
+        <dia:point val="5.20738,30.8949"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="5.15738,30.8449;9.39209,31.811"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="5.20738,30.8949"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="4.1347058839307111"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="0.86606061082624874"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#ffffff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#command handler#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="7.27474,31.4514"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="BPMN - Task" version="1" id="O50">
+      <dia:attribute name="obj_pos">
+        <dia:point val="6.78135,28.5261"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="6.73135,28.4761;7.77105,29.4422"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="6.78135,28.5261"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="0.93970588393071131"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="0.86606061082625274"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#ffffff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#afs#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="7.2512,29.0826"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O51">
+      <dia:attribute name="obj_pos">
+        <dia:point val="7.7012,28.9591"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="7.65087,28.9088;8.844,29.0167"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="7.7012,28.9591"/>
+        <dia:point val="8.79367,28.9663"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O50" connection="5"/>
+        <dia:connection handle="1" to="O48" connection="2"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O52">
+      <dia:attribute name="obj_pos">
+        <dia:point val="0.1025,49.0569"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="0.1025,48.4619;5.9375,49.2094"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#The OSL database#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80000000000000004"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="0.1025,49.0569"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O53">
+      <dia:attribute name="obj_pos">
+        <dia:point val="0.2206,58.055"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="0.209037,57.6759;14.1806,68.0509"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Metadata about all known audio files is stored in serveral tables of a
+database which is driven by libosl, the object storage layer library.
+
+The "audio files" table is the main table of the database. It contains
+path, hash and metadata of each known file.
+
+The "attributes" table maps each of the 64 possible attributes to a
+string. The attribute value of the file's metadata is translated through
+this table.
+
+The tables shown shaded are blob tables which support add, rm, mv,
+cat, ls commands. All of these are optional.
+
+The "score" table describes the subset of admissible files for the
+current playlist or mood. This table is created on demand, resides
+only in memory and is discarded on exit.
+
+When the next audio file is to be streamed, the audio file selector gets
+the entry with the highest score from the "score" table, obtains path,
+hash, and metadata for this entry from the "audio files" table, opens
+the path and verifies the hash.#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.49388889176727813"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="0.2206,58.055"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:group>
+      <dia:object type="Flowchart - Extract" version="1" id="O54">
+        <dia:attribute name="obj_pos">
+          <dia:point val="2.048,53.4404"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="1.88598,53.3799;6.86502,55.0782"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="2.048,53.4404"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="4.6550000029802332"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="1.5877777865147884"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#ffffff"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#audio files#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.49388889176727813"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="4.3755,54.7547"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Flowchart - Extract" version="1" id="O55">
+        <dia:attribute name="obj_pos">
+          <dia:point val="9.0846,55.0212"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="8.94554,54.9564;13.0687,56.659"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="9.0846,55.0212"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="3.8450000029802323"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="1.5877777865147775"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#cccccc"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#playlists#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.49388889176727813"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="11.0071,56.3355"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Flowchart - Extract" version="1" id="O56">
+        <dia:attribute name="obj_pos">
+          <dia:point val="5.9317,52.7104"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="5.803,52.6426;9.5304,54.3482"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="5.9317,52.7104"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="3.4700000029802327"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="1.5877777865147873"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#cccccc"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#images#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.49388889176727813"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="7.6667,54.0247"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Flowchart - Extract" version="1" id="O57">
+        <dia:attribute name="obj_pos">
+          <dia:point val="6.8382,50.5875"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="6.68191,50.5261;11.4495,52.2253"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="6.8382,50.5875"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="4.4550000029802321"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="1.587777786514786"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#ffffff"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#attributes#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.49388889176727813"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="9.0657,51.9018"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Flowchart - Extract" version="1" id="O58">
+        <dia:attribute name="obj_pos">
+          <dia:point val="9.7265,52.7977"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="9.61888,52.7202;12.5141,54.4355"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="9.7265,52.7977"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="2.6800000029802327"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="1.5877777865147884"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#cccccc"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#lyrics#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.49388889176727813"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="11.0665,54.112"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Flowchart - Extract" version="1" id="O59">
+        <dia:attribute name="obj_pos">
+          <dia:point val="5.4821,55.0581"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="5.35938,54.9882;8.85482,56.6959"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="5.4821,55.0581"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="3.2500000029802325"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="1.58777778651479"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#cccccc"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#moods#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.49388889176727813"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="7.1071,56.3724"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Flowchart - Extract" version="1" id="O60">
+        <dia:attribute name="obj_pos">
+          <dia:point val="2.4988,50.5557"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="2.35946,50.4909;6.49314,52.1935"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="2.4988,50.5557"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="3.855000002980232"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="1.587777786514786"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#ffffff"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="4"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#score#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.49388889176727813"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="4.4263,51.87"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Standard - Line" version="0" id="O61">
+        <dia:attribute name="obj_pos">
+          <dia:point val="4.41144,52.1937"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="4.33898,52.1428;4.46231,53.4702"/>
+        </dia:attribute>
+        <dia:attribute name="conn_endpoints">
+          <dia:point val="4.41144,52.1937"/>
+          <dia:point val="4.38985,53.4194"/>
+        </dia:attribute>
+        <dia:attribute name="numcp">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O60" connection="12"/>
+          <dia:connection handle="1" to="O54" connection="12"/>
+        </dia:connections>
+      </dia:object>
+      <dia:object type="Standard - Line" version="0" id="O62">
+        <dia:attribute name="obj_pos">
+          <dia:point val="5.03792,53.8314"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="4.96922,52.1555;7.74887,53.9001"/>
+        </dia:attribute>
+        <dia:attribute name="conn_endpoints">
+          <dia:point val="5.03792,53.8314"/>
+          <dia:point val="7.68017,52.2242"/>
+        </dia:attribute>
+        <dia:attribute name="numcp">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O54" connection="12"/>
+          <dia:connection handle="1" to="O57" connection="12"/>
+        </dia:connections>
+      </dia:object>
+    </dia:group>
+    <dia:group>
+      <dia:object type="BPMN - Task" version="1" id="O63">
+        <dia:attribute name="obj_pos">
+          <dia:point val="4.42569,77.8748"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="4.37569,77.8248;7.15716,78.8293"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="4.42569,77.8748"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="2.6814705898130642"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="0.90454545953538923"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#ffffff"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#dispatcher#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.52916666975065518"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="5.76643,78.4594"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="BPMN - Task" version="1" id="O64">
+        <dia:attribute name="obj_pos">
+          <dia:point val="1.63592,76.2823"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="1.58592,76.2323;5.11916,77.2368"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="1.63592,76.2823"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="3.4332352956954173"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="0.9045454595353889"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#ffffff"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#status fetcher#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.52916666975065518"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="3.35254,76.8669"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Network - An amplifier speaker" version="1" id="O65">
+        <dia:attribute name="obj_pos">
+          <dia:point val="11.9716,75.7366"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="11.9216,75.6866;13.0196,77.7826"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="11.9716,75.7366"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="0.99802008040072598"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="1.996040160801452"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#ffffff"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="BPMN - Task" version="1" id="O66">
+        <dia:attribute name="obj_pos">
+          <dia:point val="4.31303,74.415"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="4.26303,74.365;7.16362,75.3311"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="4.31303,74.415"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="2.8005882368718877"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="0.8660606108262453"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#bbe7bb"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#para_server#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.49388889176727813"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="5.71332,74.9715"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="BPMN - Task" version="1" id="O67">
+        <dia:attribute name="obj_pos">
+          <dia:point val="7.11064,76.3016"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="7.06064,76.2516;9.18034,77.2177"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="7.11064,76.3016"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="2.0197058839307109"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="0.86606061082625108"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#bbbbee"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#receiver#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.49388889176727813"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="8.12049,76.8581"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="BPMN - Task" version="1" id="O68">
+        <dia:attribute name="obj_pos">
+          <dia:point val="9.56352,76.3016"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="9.51352,76.2516;11.1726,77.2177"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="9.56352,76.3016"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="1.5591176486365934"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="0.86606061082625141"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#bbbbee"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#filter1#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.49388889176727813"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="10.3431,76.8581"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="BPMN - Task" version="1" id="O69">
+        <dia:attribute name="obj_pos">
+          <dia:point val="9.48684,78.4014"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="9.43684,78.3514;11.2283,79.3175"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="9.48684,78.4014"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="1.691470589813064"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="0.86606061082625141"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#bbbbee"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#filter 2#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.49388889176727813"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="10.3326,78.9579"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="BPMN - Task" version="1" id="O70">
+        <dia:attribute name="obj_pos">
+          <dia:point val="11.6997,78.4014"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="11.6497,78.3514;13.2903,79.3175"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="11.6997,78.4014"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="1.5405882368718877"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="0.86606061082624797"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#bbbbee"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#writer#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.49388889176727813"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="12.47,78.9579"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="BPMN - Task" version="1" id="O71">
+        <dia:attribute name="obj_pos">
+          <dia:point val="4.32709,79.7644"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="4.27709,79.7144;7.24386,80.6805"/>
+        </dia:attribute>
+        <dia:attribute name="meta">
+          <dia:composite type="dict"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="4.32709,79.7644"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="2.8667647074601228"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="0.86606061082624586"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:attribute name="line_colour">
+          <dia:color val="#000000"/>
+        </dia:attribute>
+        <dia:attribute name="fill_colour">
+          <dia:color val="#888888"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_style">
+          <dia:enum val="0"/>
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#para_audioc#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="0.49388889176727813"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="5.76047,80.3209"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+        <dia:attribute name="flip_horizontal">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="flip_vertical">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="subscale">
+          <dia:real val="1"/>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Standard - ZigZagLine" version="1" id="O72">
+        <dia:attribute name="obj_pos">
+          <dia:point val="7.11362,74.848"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="7.06362,74.798;8.17049,76.3516"/>
+        </dia:attribute>
+        <dia:attribute name="orth_points">
+          <dia:point val="7.11362,74.848"/>
+          <dia:point val="8.12049,74.848"/>
+          <dia:point val="8.12049,76.3016"/>
+        </dia:attribute>
+        <dia:attribute name="orth_orient">
+          <dia:enum val="0"/>
+          <dia:enum val="1"/>
+        </dia:attribute>
+        <dia:attribute name="autorouting">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_color">
+          <dia:color val="#888888"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O66" connection="5"/>
+          <dia:connection handle="1" to="O67" connection="11"/>
+        </dia:connections>
+      </dia:object>
+      <dia:object type="Standard - ZigZagLine" version="1" id="O73">
+        <dia:attribute name="obj_pos">
+          <dia:point val="4.31303,74.848"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="3.26303,73.798;4.36303,76.3323"/>
+        </dia:attribute>
+        <dia:attribute name="orth_points">
+          <dia:point val="4.31303,74.848"/>
+          <dia:point val="3.31303,74.848"/>
+          <dia:point val="3.31303,73.848"/>
+          <dia:point val="3.35254,73.848"/>
+          <dia:point val="3.35254,76.2823"/>
+        </dia:attribute>
+        <dia:attribute name="orth_orient">
+          <dia:enum val="0"/>
+          <dia:enum val="1"/>
+          <dia:enum val="0"/>
+          <dia:enum val="1"/>
+        </dia:attribute>
+        <dia:attribute name="autorouting">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_color">
+          <dia:color val="#888888"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O66" connection="8"/>
+          <dia:connection handle="1" to="O64" connection="11"/>
+        </dia:connections>
+      </dia:object>
+      <dia:object type="Standard - ZigZagLine" version="1" id="O74">
+        <dia:attribute name="obj_pos">
+          <dia:point val="3.35254,77.1868"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="3.30254,77.1368;4.47569,78.3771"/>
+        </dia:attribute>
+        <dia:attribute name="orth_points">
+          <dia:point val="3.35254,77.1868"/>
+          <dia:point val="3.35254,78.3271"/>
+          <dia:point val="4.42569,78.3271"/>
+        </dia:attribute>
+        <dia:attribute name="orth_orient">
+          <dia:enum val="1"/>
+          <dia:enum val="0"/>
+        </dia:attribute>
+        <dia:attribute name="autorouting">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O64" connection="2"/>
+          <dia:connection handle="1" to="O63" connection="8"/>
+        </dia:connections>
+      </dia:object>
+      <dia:object type="Standard - ZigZagLine" version="1" id="O75">
+        <dia:attribute name="obj_pos">
+          <dia:point val="7.10716,78.3271"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="7.05716,77.1177;8.17049,78.3771"/>
+        </dia:attribute>
+        <dia:attribute name="orth_points">
+          <dia:point val="7.10716,78.3271"/>
+          <dia:point val="8.12049,78.3271"/>
+          <dia:point val="8.12049,77.1677"/>
+        </dia:attribute>
+        <dia:attribute name="orth_orient">
+          <dia:enum val="0"/>
+          <dia:enum val="1"/>
+        </dia:attribute>
+        <dia:attribute name="autorouting">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O63" connection="5"/>
+          <dia:connection handle="1" to="O67" connection="2"/>
+        </dia:connections>
+      </dia:object>
+      <dia:object type="Standard - Line" version="0" id="O76">
+        <dia:attribute name="obj_pos">
+          <dia:point val="5.76643,78.7793"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="5.71017,78.729;5.81673,79.8147"/>
+        </dia:attribute>
+        <dia:attribute name="conn_endpoints">
+          <dia:point val="5.76643,78.7793"/>
+          <dia:point val="5.76047,79.7644"/>
+        </dia:attribute>
+        <dia:attribute name="numcp">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O63" connection="2"/>
+          <dia:connection handle="1" to="O71" connection="11"/>
+        </dia:connections>
+      </dia:object>
+      <dia:object type="Standard - Line" version="0" id="O77">
+        <dia:attribute name="obj_pos">
+          <dia:point val="9.02049,76.7346"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="8.97049,76.6846;9.71808,76.7846"/>
+        </dia:attribute>
+        <dia:attribute name="conn_endpoints">
+          <dia:point val="9.02049,76.7346"/>
+          <dia:point val="9.66808,76.7346"/>
+        </dia:attribute>
+        <dia:attribute name="numcp">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O67" connection="5"/>
+          <dia:connection handle="1" to="O68" connection="8"/>
+        </dia:connections>
+      </dia:object>
+      <dia:object type="Standard - Line" version="0" id="O78">
+        <dia:attribute name="obj_pos">
+          <dia:point val="10.3431,77.1677"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="10.2822,77.1173;10.3935,78.4518"/>
+        </dia:attribute>
+        <dia:attribute name="conn_endpoints">
+          <dia:point val="10.3431,77.1677"/>
+          <dia:point val="10.3326,78.4014"/>
+        </dia:attribute>
+        <dia:attribute name="numcp">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O68" connection="2"/>
+          <dia:connection handle="1" to="O69" connection="11"/>
+        </dia:connections>
+      </dia:object>
+      <dia:object type="Standard - Line" version="0" id="O79">
+        <dia:attribute name="obj_pos">
+          <dia:point val="12.4706,77.7326"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="12.42,77.6826;12.5206,78.4514"/>
+        </dia:attribute>
+        <dia:attribute name="conn_endpoints">
+          <dia:point val="12.4706,77.7326"/>
+          <dia:point val="12.47,78.4014"/>
+        </dia:attribute>
+        <dia:attribute name="numcp">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O65" connection="2"/>
+          <dia:connection handle="1" to="O70" connection="11"/>
+        </dia:connections>
+      </dia:object>
+      <dia:object type="Standard - Line" version="0" id="O80">
+        <dia:attribute name="obj_pos">
+          <dia:point val="11.0658,78.8344"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="11.0158,78.7844;11.849,78.8844"/>
+        </dia:attribute>
+        <dia:attribute name="conn_endpoints">
+          <dia:point val="11.0658,78.8344"/>
+          <dia:point val="11.799,78.8344"/>
+        </dia:attribute>
+        <dia:attribute name="numcp">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:attribute name="line_width">
+          <dia:real val="0.10000000149011612"/>
+        </dia:attribute>
+        <dia:connections>
+          <dia:connection handle="0" to="O69" connection="5"/>
+          <dia:connection handle="1" to="O70" connection="8"/>
+        </dia:connections>
+      </dia:object>
+    </dia:group>
+  </dia:layer>
+</dia:diagram>
index 4d63a08fb9721ff0d0f824eda66ac5e4fb0b49e5..f292af25d723764f18e555e8daac714089f3d7f5 100644 (file)
@@ -30,6 +30,7 @@
        [<a href="para_write.man.html">para_write</a>]
        [<a href="para_gui.man.html">para_gui</a>]
        [<a href="para_fade.man.html">para_fade</a>]
+       [<a href="para_play.man.html">para_play</a>]
 </p>
 
 <h2> Source code documentation </h2>
diff --git a/web/gitweb.css b/web/gitweb.css
deleted file mode 100644 (file)
index 08110a6..0000000
+++ /dev/null
@@ -1,506 +0,0 @@
-body {
-       font-family: sans-serif;
-       font-size: small;
-       /*border: solid #d9d8d1;*/
-       border-width: 1px;
-       margin: 0px;
-       padding: 10px;
-       background-color: black; 
-       color: #cccccc;
-       height: 100%;
-}
-
-a {
-       color: #BA3708;
-}
-
-a:hover {
-       color: #BA3708;
-       background-color: #ffff00;
-}
-
-span.cntrl {
-       border: dashed #aaaaaa;
-       border-width: 1px;
-       padding: 0px 2px 0px 2px;
-       margin:  0px 2px 0px 2px;
-}
-
-img.logo {
-       float: right;
-       border-width: 0px;
-}
-
-div.page_header {
-       /*height: 10px;*/
-       padding: 8px;
-       font-size: 150%;
-       font-weight: bold;
-       background-color: #151515;
-}
-
-div.page_header a:visited, a.header {
-       color: #BA3708;
-}
-
-div.page_header a:hover {
-       color: #880000;
-}
-
-div.page_nav {
-       padding: 8px;
-}
-
-div.page_nav a:visited {
-       color: #BA3708;
-}
-
-div.page_path {
-       padding: 8px;
-       font-weight: bold;
-       border: solid #d9d8d1;
-       border-width: 0px 0px 1px;
-}
-
-div.page_footer {
-       height: 17px;
-       padding: 4px 8px;
-       background-color: #d9d8d1;
-}
-
-div.page_footer_text {
-       float: left;
-       color: #555555;
-       font-style: italic;
-}
-
-div.page_body {
-       padding: 8px;
-       font-family: monospace;
-}
-
-div.title, a.title {
-       display: block;
-       padding: 6px 8px;
-       font-weight: bold;
-       background-color: #555555;
-       text-decoration: none;
-       color: white;
-}
-
-a.title:hover {
-       background-color: #AA3100;
-}
-
-div.title_text {
-       padding: 6px 0px;
-       border: solid #d9d8d1;
-       border-width: 0px 0px 1px;
-       font-family: monospace;
-}
-
-div.log_body {
-       padding: 8px 8px 8px 150px;
-}
-
-span.age {
-       position: relative;
-       float: left;
-       width: 142px;
-       font-style: italic;
-}
-
-span.signoff {
-       color: #888888;
-}
-
-div.log_link {
-       padding: 0px 8px;
-       font-size: 70%;
-       font-family: sans-serif;
-       font-style: normal;
-       position: relative;
-       float: left;
-       width: 136px;
-}
-
-div.list_head {
-       padding: 6px 8px 4px;
-       border: solid #d9d8d1;
-       border-width: 1px 0px 0px;
-       font-style: italic;
-}
-
-div.author_date {
-       padding: 8px;
-       border: solid #d9d8d1;
-       border-width: 0px 0px 1px 0px;
-       font-style: italic;
-}
-
-a.list {
-       text-decoration: none;
-       color: #BA3708;
-}
-
-a.subject, a.name {
-       font-weight: bold;
-}
-
-table.tags a.subject {
-       font-weight: normal;
-}
-
-a.list:hover {
-       text-decoration: underline;
-       color: #880000;
-}
-
-a.text {
-       text-decoration: none;
-       color: #0000cc;
-}
-
-a.text:visited {
-       text-decoration: none;
-       color: #880000;
-}
-
-a.text:hover {
-       text-decoration: underline;
-       color: #880000;
-}
-
-table {
-       padding: 8px 4px;
-}
-
-table.project_list {
-       border-spacing: 0;
-}
-
-table.diff_tree {
-       border-spacing: 0;
-       font-family: monospace;
-}
-
-table.combined.diff_tree th {
-       text-align: center;
-}
-
-table.combined.diff_tree td {
-       padding-right: 24px;
-}
-
-table.combined.diff_tree th.link,
-table.combined.diff_tree td.link {
-       padding: 0px 2px;
-}
-
-table.combined.diff_tree td.nochange a {
-       color: #6666ff;
-}
-
-table.combined.diff_tree td.nochange a:hover,
-table.combined.diff_tree td.nochange a:visited {
-       color: #d06666;
-}
-
-table.blame {
-       border-collapse: collapse;
-}
-
-table.blame td {
-       padding: 0px 5px;
-       font-size: 100%;
-       vertical-align: top;
-}
-
-th {
-       padding: 2px 5px;
-       font-size: 100%;
-       text-align: left;
-}
-
-tr.light:hover {
-       background-color: yellow;
-       color: #BA3708;
-}
-
-tr.dark {
-       background-color: #333333;
-}
-
-tr.dark2 {
-       background-color: #333333;
-}
-
-tr.dark:hover {
-       background-color: yellow;
-       color: #BA3708;
-}
-
-td {
-       padding: 2px 5px;
-       font-size: 100%;
-       vertical-align: top;
-}
-
-td.link, td.selflink {
-       padding: 2px 5px;
-       font-family: sans-serif;
-       font-size: 70%;
-}
-
-td.selflink {
-       padding-right: 0px;
-}
-
-td.sha1 {
-       font-family: monospace;
-}
-
-td.error {
-       color: red;
-       background-color: yellow;
-}
-
-td.current_head {
-       text-decoration: underline;
-}
-
-table.diff_tree span.file_status.new {
-       color: #008000;
-}
-
-table.diff_tree span.file_status.deleted {
-       color: #c00000;
-}
-
-table.diff_tree span.file_status.moved,
-table.diff_tree span.file_status.mode_chnge {
-       color: #777777;
-}
-
-table.diff_tree span.file_status.copied {
-  color: #70a070;
-}
-
-/* noage: "No commits" */
-table.project_list td.noage {
-       color: #808080;
-       font-style: italic;
-}
-
-/* age2: 60*60*24*2 <= age */
-table.project_list td.age2, table.blame td.age2 {
-       font-style: italic;
-}
-
-/* age1: 60*60*2 <= age < 60*60*24*2 */
-table.project_list td.age1 {
-       color: #009900;
-       font-style: italic;
-}
-
-table.blame td.age1 {
-       color: #009900;
-       background: transparent;
-}
-
-/* age0: age < 60*60*2 */
-table.project_list td.age0 {
-       color: #009900;
-       font-style: italic;
-       font-weight: bold;
-}
-
-table.blame td.age0 {
-       color: #009900;
-       background: transparent;
-       font-weight: bold;
-}
-
-td.pre, div.pre, div.diff {
-       font-family: monospace;
-       font-size: 12px;
-       white-space: pre;
-}
-
-td.mode {
-       font-family: monospace;
-}
-
-/* styling of diffs (patchsets): commitdiff and blobdiff views */
-div.diff.header,
-div.diff.extended_header {
-       white-space: normal;
-}
-
-div.diff.header {
-       font-weight: bold;
-
-       background-color: #333333;
-
-       margin-top: 4px;
-       padding: 4px 0px 2px 0px;
-       border: solid #d9d8d1;
-       border-width: 1px 0px 1px 0px;
-}
-
-div.diff.header a.path {
-       text-decoration: underline;
-}
-
-div.diff.extended_header,
-div.diff.extended_header a.path,
-div.diff.extended_header a.hash {
-       color: #cccccc;
-}
-
-div.diff.extended_header .info {
-       color: #b0b0b0;
-}
-
-div.diff.extended_header {
-       background-color: #333333;
-       padding: 2px 0px 2px 0px;
-}
-
-div.diff a.list,
-div.diff a.path,
-div.diff a.hash {
-       text-decoration: none;
-}
-
-div.diff a.list:hover,
-div.diff a.path:hover,
-div.diff a.hash:hover {
-       text-decoration: underline;
-}
-
-div.diff.to_file a.path,
-div.diff.to_file {
-       color: #007000;
-}
-
-div.diff.add {
-       color: #008800;
-}
-
-div.diff.from_file a.path,
-div.diff.from_file {
-       color: #ff0000;
-}
-
-div.diff.rem {
-       color: #cc0000;
-}
-
-div.diff.chunk_header a,
-div.diff.chunk_header {
-       color: #990099;
-}
-
-div.diff.chunk_header {
-       border: dotted #ffe0ff;
-       border-width: 1px 0px 0px 0px;
-       margin-top: 2px;
-}
-
-div.diff.chunk_header span.chunk_info {
-       background-color: #000000;
-}
-
-div.diff.chunk_header span.section {
-       color: #aa22aa;
-}
-
-div.diff.incomplete {
-       color: #cccccc;
-}
-
-div.diff.nodifferences {
-       font-weight: bold;
-       color: #600000;
-}
-
-div.index_include {
-       border: solid #d9d8d1;
-       border-width: 0px 0px 1px;
-       padding: 12px 8px;
-}
-
-div.search {
-       font-size: 100%;
-       font-weight: normal;
-       margin: 4px 8px;
-       float: right;
-       top: 56px;
-       right: 12px
-}
-
-td.linenr {
-       text-align: right;
-}
-
-a.linenr {
-       color: #999999;
-       text-decoration: none
-}
-
-a.rss_logo {
-       float: right;
-       padding: 3px 0px;
-       width: 35px;
-       line-height: 10px;
-       border: 1px solid;
-       border-color: #fcc7a5 #7d3302 #3e1a01 #ff954e;
-       color: #ffffff;
-       background-color: #ff6600;
-       font-weight: bold;
-       font-family: sans-serif;
-       font-size: 70%;
-       text-align: center;
-       text-decoration: none;
-}
-
-a.rss_logo:hover {
-       background-color: #ee5500;
-}
-
-span.refs span {
-       padding: 0px 4px;
-       font-size: 70%;
-       font-weight: normal;
-       border: 1px solid;
-       background-color: #222222;
-       border-color: #ffccff #ff00ee #ff00ee #ffccff;
-}
-
-span.refs span.ref {
-       background-color: #aaaaff;
-       border-color: #ccccff #0033cc #0033cc #ccccff;
-}
-
-span.refs span.tag {
-       background-color: #ffffaa;
-       border-color: #ffffcc #ffee00 #ffee00 #ffffcc;
-}
-
-span.refs span.head {
-       background-color: #222222;
-       border-color: #ccffcc #00cc33 #00cc33 #ccffcc;
-}
-
-span.atnight {
-       color: #cc0000;
-}
-
-span.match {
-       color: #e00000;
-}
-
-div.binary {
-       font-style: italic;
-}
index d1338276b7ebe9e5a67d1c3dff4fa102a6658926..f7b40714160df14799e75dce31b440d595611ca4 100644 (file)
@@ -1,29 +1,28 @@
-<table border="0" cellpadding="10" cellspacing="0">
-<tr>
-       <td>
+<table>
+       <tr>
+               <td>
                        <a title="paraslash homepage" href="/">
-                       <img src="@web_root@/paraslash.png" alt="paraslash"/>
+                               <img src="@web_root@/paraslash.png" alt="paraslash"/>
                        </a>
-       </td>
-       <td>
-               <h3>Paraslash: Play, archive, rate and stream
-               large audio sets happily</h3>
-
-               A set of tools for doing just what its name
-               suggests.
-       </td>
-</tr>
+               </td>
+               <td>
+                       <h3>Paraslash network audio streaming tools</h3>
+               </td>
+       </tr>
 <tr>
-       <td valign="top">
-               <a href="@web_root@/index.html">Home</a><br></br>
-               <a href="@web_root@/NEWS.html">News</a><br></br>
-               <a href="@web_root@/FEATURES.html">Features</a><br></br>
-               <a href="@web_root@/download.html">Download</a><br></br>
-               <a href="@web_root@/screenshots.html">Screenshots</a><br></br>
-               <a href="/gitweb/gitweb.cgi?p=.git;a=summary">Changes</a><br></br>
-               <a href="@web_root@/documentation.html">Documentation</a><br></br>
-               <a href="@web_root@/license.html">License</a><br></br>
-               <a href="@web_root@/contact.html">Contact</a><br></br>
-               <a href="@web_root@/CREDITS.html">Credits</a><br></br>
+       <td>
+               <br />
+               <a href="@web_root@/index.html">Home</a><br />
+               <a href="@web_root@/FEATURES.html">Features</a><br />
+               <a href="@web_root@/screenshots.html">Screenshots</a><br />
+               <a href="@web_root@/download.html">Download</a><br />
+               <a href="@web_root@/documentation.html">Documentation</a><br />
+               <a href="/gitweb/gitweb.cgi?p=.git;a=summary">Changes</a><br />
+               <a href="@web_root@/devel.html">Development</a><br />
+               <a href="@web_root@/license.html">License</a><br />
+               <a href="@web_root@/contact.html">Contact</a><br />
+               <a href="@web_root@/CREDITS.html">Credits</a><br />
        </td>
-       <td valign="top">
+       <td>
+               <h1>Changes</h1>
+               <hr />
index f7cb27764a18d204b5fee1e491fdddeed1aff859..8f7428f7c54b5d5ec04dedad57971d5706212d25 100644 (file)
@@ -8,32 +8,29 @@
        <link rel="shortcut icon" href="paraslash.ico">
 </head>
 <body>
-       <basefont face="lucida, helvetica, arial" size="3">
-       <table border="0" cellpadding="10" cellspacing="0">
+       <table>
        <tr>
                <td>
-                       <a href="/"><IMG SRC="paraslash.png" alt="paraslash" border="0"></a><BR>
+                       <a title="paraslash homepage" href="/">
+                               <img src="paraslash.png" alt="paraslash">
+                       </a>
                </td>
                <td>
-                       <h3>Paraslash: Play, archive, rate and stream
-                       large audio sets happily</h3>
-
-                       A set of tools for doing just what its name
-                       suggests.
+                       <h3>Paraslash network audio streaming tools</h3>
                </td>
        </tr>
        <tr>
-               <td valign="TOP">
-                       <br><a href="index.html">Home</a>
-                       <br><a href="NEWS.html">News</a>
-                       <br><a href="FEATURES.html">Features</a>
-                       <br><a href="download.html">Download</a>
-                       <br><a href="screenshots.html">Screenshots</a>
-                       <br><a href="/gitweb/gitweb.cgi?p=.git;a=summary">Changes</a>
-                       <br><a href="documentation.html">Documentation</a>
-                       <br><a href="license.html">License</a>
-                       <br><a href="contact.html">Contact</a>
-                       <br><a href="CREDITS.html">Credits</a>
+               <td>
+                       <br>
+                       <a href="index.html">Home</a><br>
+                       <a href="FEATURES.html">Features</a><br>
+                       <a href="screenshots.html">Screenshots</a><br>
+                       <a href="download.html">Download</a><br>
+                       <a href="documentation.html">Documentation</a><br>
+                       <a href="/gitweb/gitweb.cgi?p=.git;a=summary">Changes</a><br>
+                       <a href="devel.html">Development</a><br>
+                       <a href="license.html">License</a><br>
+                       <a href="contact.html">Contact</a><br>
+                       <a href="CREDITS.html">Credits</a><br>
                </td>
-               <td Valign="TOP">
-       <hr>
+               <td>
index 94fbcad23938bae3e8a328feab7628f616535546..68980a865dc082af5a2ccbeae0e08184fe57a228 100644 (file)
@@ -8,32 +8,32 @@
        <link rel="shortcut icon" href="../../paraslash.ico">
 </head>
 <body>
-       <basefont face="lucida, helvetica, arial" size="3">
-       <table border="0" cellpadding="10" cellspacing="0">
+       <table>
        <tr>
                <td>
-                       <a href="../..//"><IMG SRC="../../paraslash.png" alt="paraslash" border="0"></a><BR>
+                       <a title="paraslash homepage" href="../..//">
+                               <img src="../../paraslash.png" alt="paraslash">
+                       </a>
                </td>
                <td>
-                       <h3>Paraslash: Play, archive, rate and stream
-                       large audio sets happily</h3>
-
-                       A set of tools for doing just what its name
-                       suggests.
+                       <h3>Paraslash network audio streaming tools</h3>
                </td>
        </tr>
        <tr>
-               <td valign="TOP">
-                       <br><a href="../../index.html">Home</a>
-                       <br><a href="../../NEWS.html">News</a>
-                       <br><a href="../../FEATURES.html">Features</a>
-                       <br><a href="../../download.html">Download</a>
-                       <br><a href="../../screenshots.html">Screenshots</a>
-                       <br><a href="../../gitweb/gitweb.cgi?p=.git;a=summary">Changes</a>
-                       <br><a href="../../documentation.html">Documentation</a>
-                       <br><a href="../../license.html">License</a>
-                       <br><a href="../../contact.html">Contact</a>
-                       <br><a href="../../CREDITS.html">Credits</a>
+               <td>
+                       <br>
+                       <a href="../../index.html">Home</a><br>
+                       <a href="../../FEATURES.html">Features</a><br>
+                       <a href="../../screenshots.html">Screenshots</a><br>
+                       <a href="../../download.html">Download</a><br>
+                       <a href="../../documentation.html">Documentation</a><br>
+                       <a href="/gitweb/gitweb.cgi?p=.git;a=summary">Changes</a><br>
+                       <a href="../../devel.html">Development</a><br>
+                       <a href="../../license.html">License</a><br>
+                       <a href="../../contact.html">Contact</a><br>
+                       <a href="../../CREDITS.html">Credits</a><br>
                </td>
-               <td Valign="TOP">
-       <hr>
+               <td>
+                       <h1>API Reference</h1>
+                       <hr />
+
index 860c5abd2c8bbe9a1557c1912666eb53f7d6394e..fd17a649265020637a64e568160f83098c42dafb 100644 (file)
Binary files a/web/images/paraslash.ico and b/web/images/paraslash.ico differ
index d4a1bd9aa42ea2eec7842754ddf08d30910b10c3..a06d6a1a9d67f4d4bf62fc81fcee3348c0d9993b 100644 (file)
Binary files a/web/images/paraslash.png and b/web/images/paraslash.png differ
diff --git a/web/index.in.html b/web/index.in.html
deleted file mode 100644 (file)
index c9a82a8..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-<h1>Events</h1>
-<hr>
-<ul>
-       <li>2013-07-29: <a href="releases/paraslash-0.4.13.tar.bz2">paraslash-0.4.13</a>
-               <a href="releases/paraslash-0.4.13.tar.bz2.asc">(sig)</a>
-               "spectral gravity"
-       </li>
-       <li>2012-12-20: <a href="releases/paraslash-0.4.12.tar.bz2">paraslash-0.4.12</a>
-               <a href="releases/paraslash-0.4.12.tar.bz2.asc">(sig)</a>
-               "volatile relativity"
-       </li>
-       <li>2012-07-20: <a href="releases/paraslash-0.4.11.tar.bz2">paraslash-0.4.11</a>
-               <a href="releases/paraslash-0.4.11.tar.bz2.asc">(sig)</a>
-               "mutual diversity"
-       </li>
-       <li>2012-03-30: <a href="releases/paraslash-0.4.10.tar.bz2">paraslash-0.4.10</a>
-               <a href="releases/paraslash-0.4.10.tar.bz2.asc">(sig)</a>
-               "heterogeneous vacuum"
-       </li>
-       <li>2011-12-06: <a href="releases/paraslash-0.4.9.tar.bz2">paraslash-0.4.9</a>
-               <a href="releases/paraslash-0.4.9.tar.bz2.asc">(sig)</a>
-               "hybrid causality"
-       </li>
-       <li>2011-08-19: <a href="releases/paraslash-0.4.8.tar.bz2">paraslash-0.4.8</a>
-               <a href="releases/paraslash-0.4.8.tar.bz2.asc">(sig)</a>
-               "nested assignment"
-       </li>
-       <li>2011-06-01: <a href="releases/paraslash-0.4.7.tar.bz2">paraslash-0.4.7</a>
-               <a href="releases/paraslash-0.4.7.tar.bz2.asc">(sig)</a>
-               "infinite rollback"
-       </li>
-       <li>2011-03-31: <a href="releases/paraslash-0.4.6.tar.bz2">paraslash-0.4.6</a>
-               <a href="releases/paraslash-0.4.6.tar.bz2.asc">(sig)</a>
-               "deterministic entropy"
-       </li>
-       <li>2010-12-17: <a href="releases/paraslash-0.4.5.tar.bz2">paraslash-0.4.5</a>
-               <a href="releases/paraslash-0.4.5.tar.bz2.asc">(sig)</a>
-               "symmetric randomization"
-       </li>
-       <li>2010-08-06: <a href="releases/paraslash-0.4.4.tar.bz2">paraslash-0.4.4</a>
-               <a href="releases/paraslash-0.4.4.tar.bz2.asc">(sig)</a>
-               "persistent regularity"
-       </li>
-       <li>2010-07-05: <a href="releases/paraslash-0.4.3.tar.bz2">paraslash-0.4.3</a>
-               <a href="releases/paraslash-0.4.3.tar.bz2.asc">(sig)</a>
-               "imaginary radiation"
-       </li>
-       <li>2010-06-23: <a href="cooking.html">What's cooking page</a> online</li>
-       <li>2010-04-23: <a href="releases/paraslash-0.4.2.tar.bz2">paraslash-0.4.2</a>
-               <a href="releases/paraslash-0.4.2.tar.bz2.asc">(sig)</a>
-               "associative expansion"
-       </li>
-       <li>2009-12-22: <a href="releases/paraslash-0.4.1.tar.bz2">paraslash-0.4.1</a>
-               <a href="releases/paraslash-0.4.1.tar.bz2.asc">(sig)</a>
-               "concurrent horizon"
-       </li>
-       <li>2009-12-07: <a href="releases/paraslash-0.3.6.tar.bz2">paraslash-0.3.6</a>
-               <a href="releases/paraslash-0.3.6.tar.bz2.asc">(sig)</a>
-               "cubic continuity"
-       </li>
-       <li>2009-11-10: <a href="releases/paraslash-0.4.0.tar.bz2">paraslash-0.4.0</a>
-               <a href="releases/paraslash-0.4.0.tar.bz2.asc">(sig)</a>
-               "simultaneous independence"
-       </li>
-       <li>2009-09-21: <a href="releases/paraslash-0.3.5.tar.bz2">paraslash-0.3.5</a>
-               <a href="releases/paraslash-0.3.5.tar.bz2.asc">(sig)</a>
-               "symplectic separability"
-       </li>
-       <li>2009-05-07: <a href="releases/paraslash-0.3.4.tar.bz2">paraslash-0.3.4</a>
-               <a href="releases/paraslash-0.3.4.tar.bz2.asc">(sig)</a>
-               "elliptic inheritance"
-       </li>
-       <li>2008-12-01: <a href="releases/paraslash-0.3.3.tar.bz2">paraslash-0.3.3</a>
-               <a href="releases/paraslash-0.3.3.tar.bz2.asc">(sig)</a>
-               "axiomatic perspectivity"
-       </li>
-       <li>2008-04-11: <a href="releases/paraslash-0.3.2.tar.bz2">paraslash-0.3.2</a>
-               <a href="releases/paraslash-0.3.2.tar.bz2.asc">(sig)</a>
-               "probabilistic parity"
-       </li>
-       <li>2008-02-23: <a href="releases/paraslash-0.3.1.tar.bz2">paraslash-0.3.1</a>
-               <a href="releases/paraslash-0.3.1.tar.bz2.asc">(sig)</a>
-               "liquid interaction"
-       </li>
-       <li>2008-01-12: <a href="releases/paraslash-0.3.0.tar.bz2">paraslash-0.3.0</a>
-               <a href="releases/paraslash-0.3.0.tar.bz2.asc">(sig)</a>
-               "solar saturation"
-       </li>
-       <li>2007-11-20: <a href="releases/paraslash-0.2.17.tar.bz2">paraslash-0.2.17</a>
-               <a href="releases/paraslash-0.2.17.tar.bz2.asc">(sig)</a>
-               "isotropic threshold"
-       </li>
-       <li>2007-04-05: <a href="releases/paraslash-0.2.16.tar.bz2">paraslash-0.2.16</a>
-               <a href="releases/paraslash-0.2.16.tar.bz2.asc">(sig)</a>
-               "neural discharge"
-       </li>
-       <li>2007-02-16: <a href="releases/paraslash-0.2.15.tar.bz2">paraslash-0.2.15</a>
-               <a href="releases/paraslash-0.2.15.tar.bz2.asc">(sig)</a>
-               "inductive resonance"
-       </li>
-       <li>2006-10-15: <a href="releases/paraslash-0.2.14.tar.bz2">paraslash-0.2.14</a>
-               <a href="releases/paraslash-0.2.14.tar.bz2.asc">(sig)</a>
-               "transient singularity"
-       </li>
-       <li>2006-07-14: <a href="releases/paraslash-0.2.13.tar.bz2">paraslash-0.2.13</a>
-               <a href="releases/paraslash-0.2.13.tar.bz2.asc">(sig)</a>
-               "sonic convolution"
-       </li>
-       <li>2006-05-12: <a href="releases/paraslash-0.2.12.tar.bz2">paraslash-0.2.12</a>
-               <a href="releases/paraslash-0.2.12.tar.bz2.asc">(sig)</a>
-               "oriented abstraction"
-       </li>
-       <li>2006-03-11: <a href="releases/paraslash-0.2.11.tar.bz2">paraslash-0.2.11</a>
-               <a href="releases/paraslash-0.2.11.tar.bz2.asc">(sig)</a>
-               "atomic duality"
-       </li>
-       <li>2006-02-22: <a href="/gitweb/gitweb.cgi?p=.git;a=shortlog">browsable changelog</a> (gitweb)</li>
-       <li>2006-02-17: <a href="releases/paraslash-0.2.10.tar.bz2">paraslash-0.2.10</a>
-       <a href="releases/paraslash-0.2.10.tar.bz2.asc">(sig)</a> "cyclic attractor"</li>
-       <li>2006-02-16: <a href="doxygen/html/index.html">API Reference</a> online</li>
-       <li>2006-01-24: paraslash-0.2.9 "progressive turbulence"</li>
-       <li>2006-01-02: paraslash-0.2.8 "dynamic accumulation"</li>
-       <li>2005-12-27: paraslash-0.2.7 "transparent invariance"</li>
-       <li>2005-11-12: new web pages</li>
-       <li>2005-10-29: paraslash-0.2.6 "recursive compensation"</li>
-       <li>2005-10-27: <a href="documentation.html">manual pages</a> online</li>
-       <li>2005-10-13: paraslash-0.2.5 "aggressive resolution"</li>
-       <li>2005-09-21: paraslash-0.2.4 "toxic anticipation"</li>
-       <li>2005-09-01: paraslash-0.2.3 "hydrophilic movement"</li>
-       <li>2005-08-19: paraslash-0.2.2 "tangential excitation"</li>
-       <li>2005-08-15: paraslash-0.2.1 "surreal experience"</li>
-       <li>2005-08-06: overview.pdf</li>
-       <li>2005-08-06: paraslash-0.2.0 "distributed diffusion"</li>
-       <li>2005-08-01: paraslash live stream</li>
-       <li>2005-04-18: paraslash-0.1.7 "melting penetration"</li>
-       <li>2005-03-05: paraslash-0.1.6 "asymptotic balance"</li>
-       <li>2004-12-31: paraslash-0.1.5 "opaque eternity"</li>
-       <li>2004-12-19: paraslash-0.1.4 "tunneling transition"</li>
-       <li>2004-12-10: paraslash-0.1.3 "vanishing inertia"</li>
-       <li>2004-11-28: paraslash-0.1.2 "spherical fluctuation"</li>
-       <li>2004-11-05: paraslash-0.1.1 "floating atmosphere"</li>
-       <li>2004-10-22: paraslash-0.1.0 "rotating cortex"</li>
-</ul>
index 3f5f148fba7819ac03395792ebabec54d84ed6a4..1f1c7f2aa063d63a5b4418556e4e2647cfc31901 100644 (file)
@@ -112,7 +112,7 @@ can be used by any scripting language to produce user interfaces with
 little programming effort.
 
 All connections between para_server and para_client are encrypted
-with a symmetric RC4 session key. For each user of paraslash you must
+with a symmetric session key. For each user of paraslash you must
 create a public/secret RSA key pair for authentication.
 
 If para_client is started without non-option arguments, an interactive
@@ -232,14 +232,6 @@ Detailed description: In any case you'll need
        scripts which run during compilation require the EMPH(Bourne
        again shell).  It is most likely already installed.
 
-       - XREFERENCE(http://www.openssl.org/, openssl) or
-       XREFERENCE(ftp://ftp.gnupg.org/gcrypt/libgcrypt/, libgcrypt).
-       At least one of these two libraries is needed as the backend
-       for cryptographic routines on both the server and the client
-       side. Both openssl and libgcrypt are usually shipped with the
-       distro, but you might have to install the development package
-       (libssl-dev or libgcrypt-dev on debian systems) as well.
-
        - XREFERENCE(ftp://ftp.gnu.org/pub/gnu/gengetopt/, gengetopt)
        is needed to generate the C code for the command line parsers
        of all paraslash executables.
@@ -249,6 +241,14 @@ Detailed description: In any case you'll need
 
 Optional:
 
+       - XREFERENCE(http://www.openssl.org/, openssl) or
+       XREFERENCE(ftp://ftp.gnupg.org/gcrypt/libgcrypt/, libgcrypt).
+       At least one of these two libraries is needed as the backend
+       for cryptographic routines on both the server and the client
+       side. Both openssl and libgcrypt are usually shipped with the
+       distro, but you might have to install the development package
+       (libssl-dev or libgcrypt-dev on debian systems) as well.
+
        - XREFERENCE(http://www.underbit.com/products/mad/, libmad).
        To compile in MP3 support for paraslash, the development
        package must be installed. It is called libmad0-dev on
@@ -406,7 +406,7 @@ the directory /var/paraslash that has been created during installation:
 
        sudo chown $LOGNAME /var/paraslash
 
-Alternatively, use the --afs_socket Option to specify a different
+Alternatively, use the --afs-socket Option to specify a different
 location for the AFS command socket.
 
 For this first try, we'll use the info loglevel to make the output
@@ -505,9 +505,9 @@ User management
 para_server uses a challenge-response mechanism to authenticate
 requests from incoming connections, similar to ssh's public key
 authentication method. Authenticated connections are encrypted using
-the RC4 stream cipher.
+a stream cipher, either RC4 or AES in integer counter mode.
 
-In this chapter we briefly describe RSA and RC4 and sketch the
+In this chapter we briefly describe RSA, RC4 and AES, and sketch the
 REFERENCE(Client-server authentication, authentication handshake)
 between para_client and para_server. User management is discussed
 in the section on REFERENCE(The user_list file, the user_list file).
@@ -517,8 +517,8 @@ in a REFERENCE(Connecting para_audiod, separate section).
 
 
 
-RSA and RC4
-~~~~~~~~~~~
+RSA, RC4, AES
+~~~~~~~~~~~~~
 
 RSA is an asymmetric block cipher which is used in many applications,
 including ssh and gpg. An RSA key consists in fact of two keys,
@@ -537,6 +537,15 @@ strong encryption by today's standards. Since the same key must never
 be used twice, a different, randomly-generated key is used for every
 new connection.
 
+AES, the advanced encryption standard, is a well-known symmetric block
+cipher, i.e. a transformation operating on fixed-length blocks which
+is determined by a single key for both encryption and decryption. Any
+block cipher can be turned into a stream cipher by generating
+a pseudo-random key stream by encrypting successive values of a
+counter. The AES_CTR128 stream cipher used in paraslash is obtained
+in this way from the AES block cipher with a 128 bit block size.
+
+
 Client-server authentication
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -557,7 +566,7 @@ as follows:
        fixed-length buffer with random bytes, encrypts that buffer
        using the public key and sends the encrypted buffer to the
        client. The first part of the buffer is the challenge which
-       is used for authentication while the second part is the RC4
+       is used for authentication while the second part is the
        session key.
 
        - para_client receives the encrypted buffer and decrypts it
@@ -574,12 +583,12 @@ as follows:
 
        - Otherwise the user is considered authenticated and the client
        is allowed to proceed by sending a command to be executed. From
-       this point on the communication is encrypted using the RC4
-       stream cipher with the session key known to both peers.
+       this point on the communication is encrypted using the stream
+       cipher with the session key known to both peers.
 
 paraslash relies on the quality of the pseudo-random bytes provided
 by the crypto library (openssl or libgcrypt), on the security of
-the implementation of the RSA and RC4 crypto routines and on the
+the implementation of the RSA, RC4 and AES crypto routines and on the
 infeasibility to invert the SHA1 function.
 
 Neither para_server or para_client create RSA keys on their own. This
@@ -592,7 +601,7 @@ The user_list file
 
 At startup para_server reads the user list file which contains one
 line per user. The default location of the user list file may be
-changed with the --user_list option.
+changed with the --user-list option.
 
 There should be at least one user in this file. Each user must have
 an RSA key pair. The public part of the key is needed by para_server
@@ -639,7 +648,7 @@ restricted on platforms that support UNIX socket credentials which
 allow para_audiod to obtain the Unix credentials of the connecting
 process.
 
-Use para_audiod's --user_allow option to allow connections only for
+Use para_audiod's --user-allow option to allow connections only for
 a limited set of users.
 
 -----------------------
@@ -1071,17 +1080,18 @@ It is possible to change the behaviour of the add command by using the
 Troubleshooting
 ~~~~~~~~~~~~~~~
 
-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.
+Use the debug loglevel (-l debug) to show debugging info. All paraslash
+executables have a brief online help which is displayed when -h is
+given. The --detailed-help option prints the full help text.
 
 If para_server crashed or was killed by SIGKILL (signal 9), it
 may refuse to start again because of "dirty osl tables". In this
 case you'll have to run the oslfsck program of libosl to fix your
-database. It might be necessary to use --force (even if your name
-isn't Luke). However, make sure para_server isn't running before
-executing oslfsck --force.
+database:
+
+       oslfsck -fd ~/.paraslash/afs_database-0.4
+
+However, make sure para_server isn't running before executing oslfsck.
 
 If you don't mind to recreate your database you can start
 from scratch by removing the entire database directory, i.e.
@@ -1099,6 +1109,14 @@ care about the table contents. To check for invalid table contents, use
 This prints out references to missing audio files as well as invalid
 playlists and mood definitions.
 
+Similarly, para_audiod refuses to start if its socket file exists, since
+this indicates that another instance of para_audiod is running. After
+a crash a stale socket file might remain and you must run
+
+       para_audiod --force
+
+once to fix it up.
+
 ---------------------------------------
 Audio formats and audio format handlers
 ---------------------------------------
@@ -1135,7 +1153,17 @@ Excited Linear Prediction) coding. It is designed for voice
 over IP applications, has modest complexity and a small memory
 footprint. Wideband and narrowband (telephone quality) speech are
 supported. As for Vorbis audio, Speex bit-streams are often stored
-in OGG files.
+in OGG files. As of 2012 this codec is considered obsolete since the
+Oppus codec, described below, surpasses its performance in all areas.
+
+*OGG/Opus*
+
+Opus is a lossy audio compression format standardized through RFC
+6716 in 2012. It combines the speech-oriented SILK codec and the
+low-latency CELT (Constrained Energy Lapped Transform) codec. Like
+OGG/Vorbis and OGG/Speex, Opus data is usually encapsulated in OGG
+containers. All known software patents which cover Opus are licensed
+under royalty-free terms.
 
 *AAC*
 
@@ -1217,10 +1245,9 @@ chunk table and reads the meta data.
 
 The audio format handler code is linked into para_server and executed
 via the _add_ command. The same code is also available as a stand-alone
-tool, para_afh, which can be used to print the technical data, the
-chunk table and the meta data of a file. Furthermore, one can use
-para_afh to cut an audio file, i.e. to select some of its chunks to
-produce a new file containing only these chunks.
+tool, para_afh, which prints the technical data, the chunk table
+and the meta data of a file. Moreover, all audio format handlers are
+combined in the afh receiver which is part of para_recv and para_play.
 
 ----------
 Networking
@@ -1506,10 +1533,10 @@ the output to STDOUT, the filter modules of para_audiod are always
 connected to a receiver which produces the input stream and a writer
 which absorbs the output stream.
 
-Some filters depend on a specific library being installed and are
-not compiled in if this library was not found at compile time. To
-see the list of supported filters, run para_filter and para_audiod
-with the --help option. The output looks similar to the following:
+Some filters depend on a specific library and are not compiled in
+if this library was not found at compile time. To see the list of
+supported filters, run para_filter and para_audiod with the --help
+option. The output looks similar to the following:
 
        Available filters:
                compress wav amp fecdec wmadec prebuffer oggdec aacdec mp3dec
@@ -1770,7 +1797,7 @@ a curses window. By default the command
 
        para_audioc -- stat -p
 
-is executed, but this can be customized via the --stat_cmd option. In
+is executed, but this can be customized via the --stat-cmd option. In
 particular it possible to use
 
        para_client -- stat -p
@@ -2181,6 +2208,8 @@ RFCs
        Congestion Control ID 2: TCP-like Congestion Control
        - XREFERENCE(http://www.ietf.org/rfc/rfc4342.txt, RFC 4342) (2006):
        Congestion Control ID 3: TCP-Friendly Rate Control (TFRC)
+       - XREFERENCE(http://www.ietf.org/rfc/rfc6716.txt, RFC 6716) (2012):
+       Definition of the Opus Audio Codec
 
 Application web pages
 ~~~~~~~~~~~~~~~~~~~~~
index f103abd349068a03c8b84d0aa3c17ddbc7b9f4ac..422f454eefebdbcdfc301c8cf2fed6f098b549d5 100644 (file)
@@ -1,29 +1,50 @@
-BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
+body,h1,h2,h3,h4,h5,h6,p,center,td,th,ul,dl,div {
        font-family: sans-serif;
-       font-size: small;
 }
 
-/*
-BODY,TD {
-       font-size: 90%;
+body {
+       background-color: black;
+       color: #bbbbbb;
+       margin: 0px;
 }
-H1 {
-       text-align: center;
-       font-size: 160%;
+
+table {
+       padding: 8px 4px;
 }
-H2 {
-       font-size: 120%;
+
+th {
+       padding: 2px 5px;
+       font-size: 100%;
+       text-align: left;
 }
-H3 {
+
+td {
+       padding: 2px 5px;
        font-size: 100%;
+       vertical-align: top;
+}
+
+a {
+       color: #cc3322;
+}
+
+hr {
+       height: 1px;
+       border: none;
+       border-top: 1px solid yellow;
+}
+
+img {
+       float: right;
+       border-width: 0px;
 }
-*/
-CAPTION { font-weight: bold }
+
+caption { font-weight: bold }
 
 /* doxgen */
 
 /* Data structure index. Box with clickable letters */
-DIV.qindex {
+div.qindex {
        width: 100%;
        background-color: #000055;
        border: 1px solid #ffff00;
@@ -32,78 +53,61 @@ DIV.qindex {
        padding: 2px;
        line-height: 140%;
 }
-/*
-DIV.nav {
-       width: 100%;
-       background-color: #48ee02;
-       border: 1px solid #ffff00;
-       text-align: center;
-       margin: 2px;
-       padding: 2px;
-       line-height: 140%;
-}
-DIV.navtab {
-       background-color: #48ee02;
-       border: 1px solid #ffff00;
-       text-align: center;
-       margin: 2px;
-       margin-right: 15px;
-       padding: 2px;
-}
-TD.navtab {
-       font-size: 70%;
-}
-*/
 
 /* Data structure index, clickable letters */
-A.qindex {
+a.qindex {
        text-decoration: none;
        font-weight: bold;
        color: #cc3322;
 }
-A.qindex:visited {
+
+a.qindex:visited {
        text-decoration: none;
        font-weight: bold;
        color: #cc3322
 }
-A.qindex:hover {
+
+a.qindex:hover {
        text-decoration: none;
        background-color: #ffff00;
 }
 
-/*
-A.qindexHL {
+a.el {
        text-decoration: none;
-       font-weight: bold;
-       background-color: #cccc00;
-       color: #000000;
-       border: 1px double #929502;
+       font-weight: bold
 }
-A.qindexHL:hover {
+
+a.elRef { font-weight: bold }
+
+a.code:link {
        text-decoration: none;
-       background-color: #ffff00;
-       color: #000000;
+       font-weight: normal;
+       color: #BA3708
 }
-A.qindexHL:visited {
+
+a.code:visited {
        text-decoration: none;
-       background-color: #e6c60c;
-       color: #000000
-}
-*/
-
-A.el { text-decoration: none; font-weight: bold }
-A.elRef { font-weight: bold }
-A.code:link { text-decoration: none; font-weight: normal; color: #BA3708}
-A.code:visited { text-decoration: none; font-weight: normal; color: #BA3708}
-A.codeRef:link { font-weight: normal; color: #BA3708}
-A.codeRef:visited { font-weight: normal; color: #BA3708}
-A:hover { text-decoration: none; background-color: #ffff00 }
-DL.el { margin-left: -1cm }
+       font-weight: normal;
+       color: #BA3708
+}
+
+a.codeRef:link {
+       font-weight: normal;
+       color: #BA3708
+}
+
+a.codeRef:visited {
+       font-weight: normal;
+       color: #BA3708
+}
+
+dl.el { margin-left: -1cm }
 .fragment {
        font-family: Fixed, monospace;
        font-size: 95%;
 }
-PRE.fragment {
+
+pre.fragment {
        border: 1px solid #CCCCCC;
        background-color: #351505;
        margin-top: 4px;
@@ -117,49 +121,29 @@ PRE.fragment {
 }
 
 /* data structures non-clickable letters */
-DIV.ah {
+div.ah {
        background-color: black;
        font-weight: bold;
        color: #cccccc;
        margin-bottom: 3px;
        margin-top: 3px
 }
-/*
-TD.md { background-color: #ff0000; font-weight: bold; }
 
-TD.mdPrefix {
-       background-color: #ffff00;
-       color: #606060;
-       font-size: 80%;
-}
-TD.mdname1 {
-       background-color: #000055;
-       font-weight: bold;
-       color: #ff0000;
-}
-TD.mdname {
-       background-color: #000055;
-       font-weight: bold;
-       color: #00CC00;
-       width: 600px;
-}
-*/
-DIV.groupHeader {
+div.groupHeader {
        margin-left: 16px;
        margin-top: 12px;
        margin-bottom: 6px;
        font-weight: bold;
 }
-DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
-BODY {
-       background: black;
-       color: #bbbbbb;
-       margin-right: 20px;
-       margin-left: 20px;
+
+div.groupText {
+       margin-left: 16px;
+       font-style: italic;
+       font-size: 90%
 }
 
 /* File list */
-TD.indexkey {
+td.indexkey {
        background-color: #000055;
        font-weight: bold;
        padding-right  : 10px;
@@ -173,7 +157,7 @@ TD.indexkey {
        border: 1px solid #ffff00;
 }
 
-TD.indexvalue {
+td.indexvalue {
        background-color: #000055;
        font-style: italic;
        padding-right  : 10px;
@@ -187,22 +171,12 @@ TD.indexvalue {
        border: 1px solid #ffff00;
 }
 
-TR.memlist {
-   background-color: #112244; 
+tr.memlist {
+   background-color: #112244;
 }
-P.formulaDsp { text-align: center; }
-IMG.formulaDsp { }
-IMG.formulaInl { vertical-align: middle; }
-/*
-SPAN.keyword       { color: #ffff00 }
-SPAN.keywordtype   { color: #ffff00 }
-SPAN.keywordflow   { color: #108000 }
-SPAN.comment       { color: #00CCCC }
-SPAN.preprocessor  { color: #CC00CC }
-SPAN.stringliteral { color: #e0e020 }
-SPAN.charliteral   { color: #0000ff }
-*/
-
+p.formulaDsp { text-align: center; }
+img.formulaDsp { }
+img.formulaInl { vertical-align: middle; }
 
 /* Overwiew on top of page for *.c file */
 
@@ -210,12 +184,14 @@ SPAN.charliteral   { color: #0000ff }
        padding: 0px 8px 4px 8px;
         margin: 0px;
 }
+
 .mdescRight { /* Short description */
        padding: 0px 8px 4px 8px;
         font-size: 100%;
         font-style: italic;
         margin: 0px;
 }
+
 .memItemLeft { /* return value */
        color: #ffffff;
         border-top-color: #ffff00;
@@ -228,6 +204,7 @@ SPAN.charliteral   { color: #0000ff }
         border-left-style: none;
         font-size: 100%;
 }
+
 .memItemRight { /* function declaration */
        color: #ffffff;
         border-top-color: #ffff00;
@@ -241,154 +218,545 @@ SPAN.charliteral   { color: #0000ff }
         font-size: 100%;
 }
 
-/*
-.memTemplItemLeft {
-       padding: 1px 0px 0px 8px;
-       margin: 4px;
-       border-top-width: 1px;
-       border-right-width: 1px;
-       border-bottom-width: 1px;
-       border-left-width: 1px;
-       border-top-color: #E0E000;
-       border-right-color: #E0E000;
-       border-bottom-color: #E0E000;
-       border-left-color: #E0E000;
-       border-top-style: none;
-       border-right-style: none;
-       border-bottom-style: none;
-       border-left-style: none;
-       background-color: #000000;
-       font-size: 80%;
-}
-.memTemplItemRight {
-       padding: 1px 8px 0px 8px;
-       margin: 4px;
-       border-top-width: 1px;
-       border-right-width: 1px;
-       border-bottom-width: 1px;
-       border-left-width: 1px;
-       border-top-color: #E0E000;
-       border-right-color: #E0E000;
-       border-bottom-color: #E0E000;
-       border-left-color: #E0E000;
-       border-top-style: none;
-       border-right-style: none;
-       border-bottom-style: none;
-       border-left-style: none;
-       background-color: #000000;
-       font-size: 80%;
-}
-.memTemplParams {
-       padding: 1px 0px 0px 8px;
-       margin: 4px;
-       border-top-width: 1px;
-       border-right-width: 1px;
-       border-bottom-width: 1px;
-       border-left-width: 1px;
-       border-top-color: #E0E000;
-       border-right-color: #E0E000;
-       border-bottom-color: #E0E000;
-       border-left-color: #E0E000;
-       border-top-style: solid;
-       border-right-style: none;
-       border-bottom-style: none;
-       border-left-style: none;
-       color: #606060;
-       background-color: #3A3A1A;
-       font-size: 80%;
-}
-*/
-.search     { color: #f03309;
-              font-weight: bold;
-}
-FORM.search {
-              margin-bottom: 0px;
-              margin-top: 0px;
-}
-INPUT.search { font-size: 75%;
-               color: #800000;
-               font-weight: normal;
-               background-color: #000000;
-}
-TD.tiny      {
-       font-size: 75%;
+.search {
+       color: #f03309;
+       font-weight: bold;
 }
 
-/* links */
-a {
-       color: #cc3322;
-/*     color: #BA4108; */
+form.search {
+       margin-bottom: 0px;
+       margin-top: 0px;
 }
 
-a:visited {
-/*     color: #BA3708; */
-       color: #cc3322;
+input.search {
+       font-size: 75%;
+       color: #800000;
+       font-weight: normal;
+       background-color: #000000;
+}
+
+td.tiny {
+       font-size: 75%;
 }
+
 .dirtab { padding: 4px;
           border-collapse: collapse;
           border: 1px solid #84b007;
 }
-TH.dirtab { background: #080e02;
-            font-weight: bold;
-}
-HR { height: 1px;
-     border: none;
-     border-top: 1px solid yellow;
+
+th.dirtab {
+       background: #080e02;
+       font-weight: bold;
 }
 
 /* Style for detailed member documentation */
 .memtemplate {
-  font-size: 100%;
-  color: #cccccc;
-  font-weight: normal;
-}
-/*
-.memnav {
-  border: 5px solid #845047;
-  text-align: center;
-  margin: 2px;
-  margin-right: 15px;
-  padding: 2px;
-}
-*/
+       font-size: 100%;
+       color: #cccccc;
+       font-weight: normal;
+}
+
 .memitem { /* outer border around function */
-  padding: 6px;
-  background-color: #000000;
-  border-width: 2px;
-  border-style: solid;
-  border-color: #ffff00;
-/*  -moz-border-radius: 8px 8px 8px 8px; */
+       padding: 6px;
+       background-color: #000000;
+       border-width: 2px;
+       border-style: solid;
+       border-color: #ffff00;
 }
+
 .memname {
-  color: #ffffff; /* name of the function */
-  white-space: nowrap;
-  font-weight: bold;
+       color: #ffffff; /* name of the function */
+       white-space: nowrap;
+       font-weight: bold;
 }
+
 .memdoc{
-  padding-left: 10px;
+       padding-left: 10px;
 }
 
 /* inner box containing function definition */
 .memproto {
-  background-color: #000055;
-  width: 100%;
-  border-width: 2px;
-  border-style: solid;
-  border-color: #ffff00;
-  font-weight: bold;
-/*  -moz-border-radius: 8px 8px 8px 8px;*/
+       background-color: #000055;
+       width: 100%;
+       border-width: 2px;
+       border-style: solid;
+       border-color: #ffff00;
+       font-weight: bold;
 }
 
 .paramkey {
-  color: #ff0000;
-  text-align: right;
+       color: #ff0000;
+       text-align: right;
 }
+
 .paramtype { /* type of function parameter, e.g. "int" */
-  color: #00ff00;
-  white-space: nowrap;
+       color: #00ff00;
+       white-space: nowrap;
 }
+
 .paramname { /* name of function parameter */
-  color: #ffff00;
-  font-style: italic;
+       color: #ffff00;
+       font-style: italic;
+}
+
+span.cntrl {
+       border: dashed #aaaaaa;
+       border-width: 1px;
+       padding: 0px 2px 0px 2px;
+       margin:  0px 2px 0px 2px;
+}
+
+div.page_header {
+       padding: 8px;
+       font-size: 120%;
+       font-weight: bold;
+       background-color: #151515;
+}
+
+div.page_header a:visited, a.header {
+       color: #cc3322;
+}
+
+div.page_header a:hover {
+       color: #880000;
+}
+
+div.page_nav {
+       padding: 8px;
+}
+
+div.page_nav a:visited {
+       color: #cc3322;
+}
+
+div.page_path {
+       padding: 8px;
+       font-weight: bold;
+       border: solid #d9d8d1;
+       border-width: 0px 0px 1px;
+}
+
+div.page_footer {
+       height: 17px;
+       padding: 4px 8px;
+       background-color: #d9d8d1;
+}
+
+div.page_footer_text {
+       float: left;
+       color: #555555;
+       font-style: italic;
+}
+
+div.page_body {
+       padding: 8px;
+       font-family: monospace;
+       font-size: 120%;
+}
+
+a.title:hover {
+       background-color: #AA3100;
 }
 
+div.title_text {
+       padding: 6px 0px;
+       border: solid #d9d8d1;
+       border-width: 0px 0px 1px;
+       font-family: monospace;
+}
+
+div.log_body {
+       padding: 8px 8px 8px 150px;
+       font-family: monospace;
+       font-size: 120%;
+}
+
+div.log {
+       font-family: monospace;
+       font-size: 120%;
+}
+
+span.age {
+       position: relative;
+       float: left;
+       width: 142px;
+       font-style: italic;
+}
+
+span.signoff {
+       color: #888888;
+}
+
+div.log_link {
+       padding: 0px 8px;
+       font-size: 70%;
+       font-family: sans-serif;
+       font-style: normal;
+       position: relative;
+       float: left;
+       width: 136px;
+}
+
+div.list_head {
+       padding: 6px 8px 4px;
+       border: solid #d9d8d1;
+       border-width: 1px 0px 0px;
+       font-style: italic;
+}
+
+div.author_date {
+       padding: 8px;
+       border: solid #d9d8d1;
+       border-width: 0px 0px 1px 0px;
+       font-style: italic;
+}
+
+a.list {
+       text-decoration: none;
+       color: #cc3322;
+}
+
+a.subject, a.name {
+       font-weight: bold;
+}
+
+table.tags a.subject {
+       font-weight: normal;
+}
+
+a.list:hover {
+       text-decoration: underline;
+       color: #880000;
+}
+
+a.text {
+       text-decoration: none;
+       color: #0000cc;
+}
+
+a.text:visited {
+       text-decoration: none;
+       color: #880000;
+}
+
+a.text:hover {
+       text-decoration: underline;
+       color: #880000;
+}
+
+table.project_list {
+       border-spacing: 0;
+}
+
+table.diff_tree {
+       border-spacing: 0;
+       font-family: monospace;
+}
+
+table.combined.diff_tree th {
+       text-align: center;
+}
+
+table.combined.diff_tree td {
+       padding-right: 24px;
+}
+
+table.combined.diff_tree th.link,
+table.combined.diff_tree td.link {
+       padding: 0px 2px;
+}
+
+table.combined.diff_tree td.nochange a {
+       color: #6666ff;
+}
+
+table.combined.diff_tree td.nochange a:hover,
+table.combined.diff_tree td.nochange a:visited {
+       color: #d06666;
+}
+
+table.blame {
+       border-collapse: collapse;
+}
+
+table.blame td {
+       padding: 0px 5px;
+       font-size: 100%;
+       vertical-align: top;
+}
+
+tr.light:hover {
+       background-color: yellow;
+       color: #cc3322;
+}
+
+tr.dark {
+       background-color: #333333;
+}
+
+tr.dark2 {
+       background-color: #333333;
+}
+
+tr.dark:hover {
+       background-color: yellow;
+       color: #cc3322;
+}
+
+td.link, td.selflink {
+       padding: 2px 5px;
+       font-family: sans-serif;
+       font-size: 70%;
+}
+
+td.selflink {
+       padding-right: 0px;
+}
+
+td.sha1 {
+       font-family: monospace;
+}
+
+td.error {
+       color: red;
+       background-color: yellow;
+}
+
+td.current_head {
+       text-decoration: underline;
+}
+
+table.diff_tree span.file_status.new {
+       color: #008000;
+}
+
+table.diff_tree span.file_status.deleted {
+       color: #c00000;
+}
+
+table.diff_tree span.file_status.moved,
+table.diff_tree span.file_status.mode_chnge {
+       color: #777777;
+}
+
+table.diff_tree span.file_status.copied {
+       color: #70a070;
+}
+
+/* noage: "No commits" */
+table.project_list td.noage {
+       color: #808080;
+       font-style: italic;
+}
+
+/* age2: 60*60*24*2 <= age */
+table.project_list td.age2, table.blame td.age2 {
+       font-style: italic;
+}
+
+/* age1: 60*60*2 <= age < 60*60*24*2 */
+table.project_list td.age1 {
+       color: #009900;
+       font-style: italic;
+}
+
+table.blame td.age1 {
+       color: #009900;
+       background: transparent;
+}
+
+/* age0: age < 60*60*2 */
+table.project_list td.age0 {
+       color: #009900;
+       font-style: italic;
+       font-weight: bold;
+}
+
+table.blame td.age0 {
+       color: #009900;
+       background: transparent;
+       font-weight: bold;
+}
+
+td.pre, div.pre, div.diff {
+       white-space: pre;
+}
+
+td.mode {
+       font-family: monospace;
+}
+
+/* styling of diffs (patchsets): commitdiff and blobdiff views */
+
+div.diff.header,
+div.diff.extended_header {
+       white-space: normal;
+}
+
+div.diff.header {
+       font-weight: bold;
+
+       background-color: #333333;
+
+       margin-top: 4px;
+       padding: 4px 0px 2px 0px;
+       border: solid #d9d8d1;
+       border-width: 1px 0px 1px 0px;
+}
+
+div.diff.header a.path {
+       text-decoration: underline;
+}
+
+div.diff.extended_header,
+div.diff.extended_header a.path,
+div.diff.extended_header a.hash {
+       color: #cccccc;
+}
+
+div.diff.extended_header .info {
+       color: #b0b0b0;
+}
+
+div.diff.extended_header {
+       background-color: #333333;
+       padding: 2px 0px 2px 0px;
+}
+
+div.diff a.list,
+div.diff a.path,
+div.diff a.hash {
+       text-decoration: none;
+}
+
+div.diff a.list:hover,
+div.diff a.path:hover,
+div.diff a.hash:hover {
+       text-decoration: underline;
+}
+
+div.diff.to_file a.path,
+div.diff.to_file {
+       color: #007000;
+}
+
+div.diff.add {
+       color: #008800;
+}
+
+div.diff.from_file a.path,
+div.diff.from_file {
+       color: #ff0000;
+}
+
+div.diff.rem {
+       color: #cc0000;
+}
+
+div.diff.chunk_header a,
+div.diff.chunk_header {
+       color: #990099;
+}
+
+div.diff.chunk_header {
+       border: dotted #ffe0ff;
+       border-width: 1px 0px 0px 0px;
+       margin-top: 2px;
+}
+
+div.diff.chunk_header span.chunk_info {
+       background-color: #000000;
+}
+
+div.diff.chunk_header span.section {
+       color: #aa22aa;
+}
+
+div.diff.incomplete {
+       color: #cccccc;
+}
+
+div.diff.nodifferences {
+       font-weight: bold;
+       color: #600000;
+}
+
+div.index_include {
+       border: solid #d9d8d1;
+       border-width: 0px 0px 1px;
+       padding: 12px 8px;
+}
+
+div.search {
+       font-size: 100%;
+       font-weight: normal;
+       margin: 4px 8px;
+       float: right;
+       top: 56px;
+       right: 12px
+}
+
+td.linenr {
+       text-align: right;
+}
+
+a.linenr {
+       color: #999999;
+       text-decoration: none
+}
+
+a.rss_logo {
+       float: right;
+       padding: 3px 0px;
+       width: 35px;
+       line-height: 10px;
+       border: 1px solid;
+       border-color: #fcc7a5 #7d3302 #3e1a01 #ff954e;
+       color: #ffffff;
+       background-color: #ff6600;
+       font-weight: bold;
+       font-family: sans-serif;
+       font-size: 70%;
+       text-align: center;
+       text-decoration: none;
+}
+
+a.rss_logo:hover {
+       background-color: #ee5500;
+}
+
+span.refs span {
+       padding: 0px 4px;
+       font-size: 70%;
+       font-weight: normal;
+       border: 1px solid;
+       background-color: #222222;
+       border-color: #ffccff #ff00ee #ff00ee #ffccff;
+}
+
+span.refs span.ref {
+       background-color: #aaaaff;
+       border-color: #ccccff #0033cc #0033cc #ccccff;
+}
+
+span.refs span.tag {
+       background-color: #ffffaa;
+       border-color: #ffffcc #ffee00 #ffee00 #ffffcc;
+}
+
+span.refs span.head {
+       background-color: #222222;
+       border-color: #ccffcc #00cc33 #00cc33 #ccffcc;
+}
+
+span.atnight {
+       color: #cc0000;
+}
+
+span.match {
+       color: #e00000;
+}
+
+div.binary {
+       font-style: italic;
+}
index c9e43663ecd783578fe0606b2612cc9771c38b1e..adc82b58bcc7257582dae581969ffbd22847eef1 100644 (file)
-Dec 08 19:23:27 meins 2 log_welcome: welcome to para_audiod git (Sat Dec  8 13:42:52 MET 2007)
-Dec 08 19:23:27 meins 2 init_writers: maximal number of writers: 3
-Dec 08 19:23:27 meins 2 check_writer_arg: checking  alsa -d plug:swmix
-Dec 08 19:23:27 meins 2 alsa_parse_config: options: -d plug:swmix, 2
-Dec 08 19:23:27 meins 2 alsa_parse_config: help given: 0
-Dec 08 19:23:27 meins 2 init_writers: mp3 writer #0: alsa
-Dec 08 19:23:27 meins 2 check_writer_arg: checking  alsa -d plug:swmix
-Dec 08 19:23:27 meins 2 alsa_parse_config: options: -d plug:swmix, 2
-Dec 08 19:23:27 meins 2 alsa_parse_config: help given: 0
-Dec 08 19:23:27 meins 2 init_writers: ogg writer #0: alsa
-Dec 08 19:23:27 meins 2 check_writer_arg: checking  alsa -d plug:swmix
-Dec 08 19:23:27 meins 2 alsa_parse_config: options: -d plug:swmix, 2
-Dec 08 19:23:27 meins 2 alsa_parse_config: help given: 0
-Dec 08 19:23:27 meins 2 init_writers: aac writer #0: alsa
-Dec 08 19:23:27 meins 2 init_receivers: initializing http receiver
-Dec 08 19:23:27 meins 2 init_receivers: initializing dccp receiver
-Dec 08 19:23:27 meins 2 init_receivers: initializing ortp receiver
-Dec 08 19:23:27 meins 2 init_filters: maximal number of filters: 6
-Dec 08 19:23:27 meins 2 add_filter: mp3 filter 1: mp3dec
-Dec 08 19:23:27 meins 2 add_filter: mp3 filter 2: compress
-Dec 08 19:23:27 meins 2 add_filter: ogg filter 1: oggdec
-Dec 08 19:23:27 meins 2 add_filter: ogg filter 2: compress
-Dec 08 19:23:27 meins 2 add_filter: aac filter 1: aacdec
-Dec 08 19:23:27 meins 2 add_filter: aac filter 2: compress
-Dec 08 19:23:27 meins 2 clear_slot: clearing slot 0
-Dec 08 19:23:27 meins 2 clear_slot: clearing slot 1
-Dec 08 19:23:27 meins 2 clear_slot: clearing slot 2
-Dec 08 19:23:27 meins 2 clear_slot: clearing slot 3
-Dec 08 19:23:27 meins 2 clear_slot: clearing slot 4
-Dec 08 19:23:27 meins 2 init_grabbing: grab init
-Dec 08 19:23:27 meins 2 setup_signal_handling: signal pipe: fd 4
-Dec 08 19:23:27 meins 3 audiod_get_socket: local socket: /var/paraslash/audiod_socket.meins
-Dec 08 19:23:27 meins 2 daemon_init: daemonizing
-Dec 08 19:23:27 meins 2 init_sched: initializing scheduler
-Dec 08 19:23:27 meins 2 register_task: registering signal task (0x80631bc)
-Dec 08 19:23:27 meins 2 register_task: registering command task (0xbfec3ec4)
-Dec 08 19:23:27 meins 2 register_task: registering status task (0x80632e8)
-Dec 08 19:23:27 meins 2 register_task: registering audiod task (0xbfec3fe8)
-Dec 08 19:23:27 meins 2 status_pre_select: clock diff count: 5
-Dec 08 19:23:27 meins 2 client_open: loglevel: 5
-Dec 08 19:23:27 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:23:27 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:23:27 meins 3 client_open: connecting localhost:2990
-Dec 08 19:23:27 meins 2 register_task: registering client (0x8067878)
-Dec 08 19:23:27 meins 2 client_post_select: --> auth rc4 maan
-Dec 08 19:23:27 meins 2 client_post_select: <-- [challenge]
-Dec 08 19:23:27 meins 2 client_post_select: --> 1499570993
-Dec 08 19:23:27 meins 2 client_post_select: decrypting session key
-Dec 08 19:23:27 meins 2 enable_crypt: rc4 encryption activated for fd 7
-Dec 08 19:23:27 meins 2 unregister_task: unregistering client (0x8067878)
-Dec 08 19:23:28 meins 2 handle_connect: connection from user 409, buf: stat
-Dec 08 19:23:28 meins 2 handle_connect: argv[0]: stat, argc= 1
-Dec 08 19:23:28 meins 2 com_stat: mask: 0xffffffff
-Dec 08 19:23:28 meins 2 stat_client_add: adding client on fd 7
-Dec 08 19:23:28 meins 2 dump_stat_client_list: stat client on fd 7
-Dec 08 19:23:28 meins 2 status_pre_select: clock diff count: 4
-Dec 08 19:23:28 meins 2 client_open: loglevel: 5
-Dec 08 19:23:28 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:23:28 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:23:28 meins 3 client_open: connecting localhost:2990
-Dec 08 19:23:28 meins 2 register_task: registering client (0x8067878)
-Dec 08 19:23:28 meins 2 client_post_select: --> auth rc4 maan
-Dec 08 19:23:28 meins 2 client_post_select: <-- [challenge]
-Dec 08 19:23:28 meins 2 client_post_select: --> 1400991892
-Dec 08 19:23:28 meins 2 client_post_select: decrypting session key
-Dec 08 19:23:28 meins 2 enable_crypt: rc4 encryption activated for fd 8
-Dec 08 19:23:28 meins 2 compute_time_diff: time diff (cur/avg): -1ms/+1ms
-Dec 08 19:23:28 meins 2 unregister_task: unregistering client (0x8067878)
-Dec 08 19:23:29 meins 2 status_pre_select: clock diff count: 3
-Dec 08 19:23:29 meins 2 client_open: loglevel: 5
-Dec 08 19:23:29 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:23:29 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:23:29 meins 3 client_open: connecting localhost:2990
-Dec 08 19:23:29 meins 2 register_task: registering client (0x8067878)
-Dec 08 19:23:29 meins 2 client_post_select: --> auth rc4 maan
-Dec 08 19:23:29 meins 2 client_post_select: <-- [challenge]
-Dec 08 19:23:29 meins 2 client_post_select: --> 1772412478
-Dec 08 19:23:29 meins 2 client_post_select: decrypting session key
-Dec 08 19:23:29 meins 2 enable_crypt: rc4 encryption activated for fd 8
-Dec 08 19:23:29 meins 2 compute_time_diff: time diff (cur/avg): -1ms/+1ms
-Dec 08 19:23:29 meins 2 unregister_task: unregistering client (0x8067878)
-Dec 08 19:23:30 meins 2 status_pre_select: clock diff count: 2
-Dec 08 19:23:30 meins 2 client_open: loglevel: 5
-Dec 08 19:23:30 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:23:30 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:23:30 meins 3 client_open: connecting localhost:2990
-Dec 08 19:23:30 meins 2 register_task: registering client (0x8067878)
-Dec 08 19:23:30 meins 2 client_post_select: --> auth rc4 maan
-Dec 08 19:23:30 meins 2 client_post_select: <-- [challenge]
-Dec 08 19:23:30 meins 2 client_post_select: --> 1882631692
-Dec 08 19:23:30 meins 2 client_post_select: decrypting session key
-Dec 08 19:23:30 meins 2 enable_crypt: rc4 encryption activated for fd 8
-Dec 08 19:23:30 meins 2 compute_time_diff: time diff (cur/avg): -1ms/+1ms
-Dec 08 19:23:30 meins 2 unregister_task: unregistering client (0x8067878)
-Dec 08 19:23:31 meins 2 status_pre_select: clock diff count: 1
-Dec 08 19:23:31 meins 2 client_open: loglevel: 5
-Dec 08 19:23:31 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:23:31 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:23:31 meins 3 client_open: connecting localhost:2990
-Dec 08 19:23:31 meins 2 register_task: registering client (0x8067878)
-Dec 08 19:23:31 meins 2 client_post_select: --> auth rc4 maan
-Dec 08 19:23:31 meins 2 client_post_select: <-- [challenge]
-Dec 08 19:23:31 meins 2 client_post_select: --> 1630455651
-Dec 08 19:23:31 meins 2 client_post_select: decrypting session key
-Dec 08 19:23:31 meins 2 enable_crypt: rc4 encryption activated for fd 8
-Dec 08 19:23:31 meins 2 compute_time_diff: time diff (cur/avg): -1ms/+1ms
-Dec 08 19:23:31 meins 2 unregister_task: unregistering client (0x8067878)
-Dec 08 19:23:36 meins 2 client_open: loglevel: 5
-Dec 08 19:23:36 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:23:36 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:23:36 meins 3 client_open: connecting localhost:2990
-Dec 08 19:23:36 meins 2 register_task: registering client (0x8067878)
-Dec 08 19:23:36 meins 2 client_post_select: --> auth rc4 maan
-Dec 08 19:23:36 meins 2 client_post_select: <-- [challenge]
-Dec 08 19:23:36 meins 2 client_post_select: --> 759215314
-Dec 08 19:23:36 meins 2 client_post_select: decrypting session key
-Dec 08 19:23:36 meins 2 enable_crypt: rc4 encryption activated for fd 8
-Dec 08 19:23:36 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+1ms
-Dec 08 19:23:36 meins 2 clear_slot: clearing slot 0
-Dec 08 19:23:36 meins 3 open_receiver: started ogg: dccp receiver in slot 0
-Dec 08 19:23:36 meins 2 register_task: registering dccp receiver node (0x806a324)
-Dec 08 19:23:37 meins 2 open_filters: opening ogg filters
-Dec 08 19:23:37 meins 3 open_filters: ogg filter 1/2 (oggdec) started in slot 0
-Dec 08 19:23:37 meins 3 open_filters: ogg filter 2/2 (compress) started in slot 0
-Dec 08 19:23:37 meins 2 register_task: registering filter chain (0x807460c)
-Dec 08 19:23:37 meins 3 ogg_convert: input buffer: 17032, opening ov callbacks
-Dec 08 19:23:37 meins 3 ogg_convert: 2 channels, 44100 Hz
-Dec 08 19:23:37 meins 2 open_writers: opening ogg writers
-Dec 08 19:23:37 meins 2 open_writers: samplerate: 44100
-Dec 08 19:23:37 meins 3 wng_open: opening wng 0x80a5660 with 1 writer(s)
-Dec 08 19:23:37 meins 2 register_task: registering  (0x80a5684)
-Dec 08 19:23:37 meins 2 alsa_open: 2 channel(s), 44100Hz
-Dec 08 19:23:37 meins 2 alsa_open: buffer time: 170658
-Dec 08 19:23:37 meins 2 alsa_open: buffer size: 7526, period_size: 940
-Dec 08 19:23:43 meins 3 rn_event_handler: dccp_recv: end of file
-Dec 08 19:23:43 meins 2 unregister_task: unregistering dccp receiver node (0x806a324)
-Dec 08 19:23:43 meins 2 unregister_task: unregistering client (0x8067878)
-Dec 08 19:23:43 meins 2 kill_all_decoders: unregistering writer node group in slot 0
-Dec 08 19:23:43 meins 2 unregister_task: unregistering writer node group (0x80a5684)
-Dec 08 19:23:43 meins 2 kill_all_decoders: unregistering filter chain in slot 0
-Dec 08 19:23:43 meins 2 unregister_task: unregistering filter chain (0x807460c)
-Dec 08 19:23:43 meins 2 try_to_close_slot: closing slot 0 
-Dec 08 19:23:43 meins 3 wng_close: closing wng with 1 writer(s)
-Dec 08 19:23:43 meins 2 alsa_close: closing writer node 0x80a57b0
-Dec 08 19:23:43 meins 3 close_filters: closing filter chain 0x80745e0
-Dec 08 19:23:43 meins 2 close_filters: closing oggdec filter
-Dec 08 19:23:43 meins 2 close_filters: closing compress filter
-Dec 08 19:23:43 meins 3 close_receiver: closing ogg receiver in slot 0 (eof = 1)
-Dec 08 19:23:43 meins 2 clear_slot: clearing slot 0
-Dec 08 19:23:48 meins 2 client_open: loglevel: 5
-Dec 08 19:23:48 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:23:48 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:23:48 meins 3 client_open: connecting localhost:2990
-Dec 08 19:23:48 meins 2 register_task: registering client (0x8067878)
-Dec 08 19:23:48 meins 2 client_post_select: --> auth rc4 maan
-Dec 08 19:23:48 meins 2 client_post_select: <-- [challenge]
-Dec 08 19:23:48 meins 2 client_post_select: --> 960122352
-Dec 08 19:23:48 meins 2 client_post_select: decrypting session key
-Dec 08 19:23:48 meins 2 enable_crypt: rc4 encryption activated for fd 8
-Dec 08 19:23:48 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:23:58 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:23:58 meins 2 clear_slot: clearing slot 0
-Dec 08 19:23:58 meins 3 open_receiver: started mp3: http receiver in slot 0
-Dec 08 19:23:58 meins 2 register_task: registering http receiver node (0x806a204)
-Dec 08 19:23:58 meins 2 http_recv_post_select: sending http request
-Dec 08 19:23:58 meins 2 http_recv_post_select: received ok msg, streaming
-Dec 08 19:23:59 meins 2 open_filters: opening mp3 filters
-Dec 08 19:23:59 meins 3 open_filters: mp3 filter 1/2 (mp3dec) started in slot 0
-Dec 08 19:23:59 meins 3 open_filters: mp3 filter 2/2 (compress) started in slot 0
-Dec 08 19:23:59 meins 2 register_task: registering filter chain (0x807260c)
-Dec 08 19:23:59 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:23:59 meins 2 audiod_pre_select: initial delay: 173 ms left
-Dec 08 19:23:59 meins 2 audiod_pre_select: initial delay: 147 ms left
-Dec 08 19:23:59 meins 2 audiod_pre_select: initial delay: 121 ms left
-Dec 08 19:23:59 meins 2 audiod_pre_select: initial delay: 95 ms left
-Dec 08 19:23:59 meins 2 audiod_pre_select: initial delay: 69 ms left
-Dec 08 19:23:59 meins 2 audiod_pre_select: initial delay: 43 ms left
-Dec 08 19:23:59 meins 2 audiod_pre_select: initial delay: 17 ms left
-Dec 08 19:23:59 meins 2 open_writers: opening mp3 writers
-Dec 08 19:23:59 meins 2 open_writers: samplerate: 44100
-Dec 08 19:23:59 meins 3 wng_open: opening wng 0x80a3c18 with 1 writer(s)
-Dec 08 19:23:59 meins 2 register_task: registering  (0x80a3c3c)
-Dec 08 19:23:59 meins 2 alsa_open: 2 channel(s), 44100Hz
-Dec 08 19:23:59 meins 2 alsa_open: buffer time: 170658
-Dec 08 19:23:59 meins 2 alsa_open: buffer size: 7526, period_size: 940
-Dec 08 19:24:43 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:24:57 meins 4 alsa_write_post_select: EAGAIN
-Dec 08 19:24:57 meins 4 alsa_write_post_select: EAGAIN
-Dec 08 19:25:33 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:25:43 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:25:51 meins 3 rn_event_handler: http_recv: end of file
-Dec 08 19:25:51 meins 2 unregister_task: unregistering http receiver node (0x806a204)
-Dec 08 19:25:51 meins 2 unregister_task: unregistering client (0x8067878)
-Dec 08 19:25:51 meins 2 kill_all_decoders: unregistering writer node group in slot 0
-Dec 08 19:25:51 meins 2 unregister_task: unregistering writer node group (0x80a3c3c)
-Dec 08 19:25:51 meins 2 kill_all_decoders: unregistering filter chain in slot 0
-Dec 08 19:25:51 meins 2 unregister_task: unregistering filter chain (0x807260c)
-Dec 08 19:25:51 meins 2 try_to_close_slot: closing slot 0 
-Dec 08 19:25:51 meins 3 wng_close: closing wng with 1 writer(s)
-Dec 08 19:25:51 meins 2 alsa_close: closing writer node 0x806a440
-Dec 08 19:25:51 meins 3 close_filters: closing filter chain 0x80725e0
-Dec 08 19:25:51 meins 2 close_filters: closing mp3dec filter
-Dec 08 19:25:51 meins 2 close_filters: closing compress filter
-Dec 08 19:25:51 meins 3 close_receiver: closing mp3 receiver in slot 0 (eof = 1)
-Dec 08 19:25:51 meins 2 clear_slot: clearing slot 0
-Dec 08 19:25:56 meins 2 client_open: loglevel: 5
-Dec 08 19:25:56 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:25:56 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:25:56 meins 3 client_open: connecting localhost:2990
-Dec 08 19:25:56 meins 2 register_task: registering client (0x8067878)
-Dec 08 19:25:56 meins 2 client_post_select: --> auth rc4 maan
-Dec 08 19:25:56 meins 2 client_post_select: <-- [challenge]
-Dec 08 19:25:56 meins 2 client_post_select: --> 563263924
-Dec 08 19:25:56 meins 2 client_post_select: decrypting session key
-Dec 08 19:25:56 meins 2 enable_crypt: rc4 encryption activated for fd 8
-Dec 08 19:25:56 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:26:06 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:26:06 meins 2 clear_slot: clearing slot 0
-Dec 08 19:26:06 meins 3 open_receiver: started mp3: http receiver in slot 0
-Dec 08 19:26:06 meins 2 register_task: registering http receiver node (0x806a29c)
-Dec 08 19:26:06 meins 2 http_recv_post_select: sending http request
-Dec 08 19:26:06 meins 2 http_recv_post_select: received ok msg, streaming
-Dec 08 19:26:06 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:26:06 meins 2 open_filters: opening mp3 filters
-Dec 08 19:26:06 meins 3 open_filters: mp3 filter 1/2 (mp3dec) started in slot 0
-Dec 08 19:26:06 meins 3 open_filters: mp3 filter 2/2 (compress) started in slot 0
-Dec 08 19:26:06 meins 2 register_task: registering filter chain (0x80726dc)
-Dec 08 19:26:06 meins 2 audiod_pre_select: initial delay: 173 ms left
-Dec 08 19:26:06 meins 2 audiod_pre_select: initial delay: 147 ms left
-Dec 08 19:26:06 meins 2 audiod_pre_select: initial delay: 121 ms left
-Dec 08 19:26:06 meins 2 audiod_pre_select: initial delay: 95 ms left
-Dec 08 19:26:06 meins 2 audiod_pre_select: initial delay: 69 ms left
-Dec 08 19:26:06 meins 2 audiod_pre_select: initial delay: 43 ms left
-Dec 08 19:26:07 meins 2 audiod_pre_select: initial delay: 17 ms left
-Dec 08 19:26:07 meins 2 open_writers: opening mp3 writers
-Dec 08 19:26:07 meins 2 open_writers: samplerate: 44100
-Dec 08 19:26:07 meins 3 wng_open: opening wng 0x80a3cb8 with 1 writer(s)
-Dec 08 19:26:07 meins 2 register_task: registering  (0x80a3cdc)
-Dec 08 19:26:07 meins 2 alsa_open: 2 channel(s), 44100Hz
-Dec 08 19:26:07 meins 2 alsa_open: buffer time: 170658
-Dec 08 19:26:07 meins 2 alsa_open: buffer size: 7526, period_size: 940
-Dec 08 19:26:51 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:26:58 meins 2 unregister_task: unregistering client (0x8067878)
-Dec 08 19:26:58 meins 2 kill_all_decoders: unregistering writer node group in slot 0
-Dec 08 19:26:58 meins 2 unregister_task: unregistering writer node group (0x80a3cdc)
-Dec 08 19:26:58 meins 2 kill_all_decoders: unregistering filter chain in slot 0
-Dec 08 19:26:58 meins 2 unregister_task: unregistering filter chain (0x80726dc)
-Dec 08 19:26:58 meins 2 kill_all_decoders: unregistering receiver_node in slot 0
-Dec 08 19:26:58 meins 2 unregister_task: unregistering http receiver node (0x806a29c)
-Dec 08 19:26:58 meins 2 try_to_close_slot: closing slot 0 
-Dec 08 19:26:58 meins 3 wng_close: closing wng with 1 writer(s)
-Dec 08 19:26:58 meins 2 alsa_close: closing writer node 0x80a3e08
-Dec 08 19:26:58 meins 3 close_filters: closing filter chain 0x80726b0
-Dec 08 19:26:58 meins 2 close_filters: closing mp3dec filter
-Dec 08 19:26:58 meins 2 close_filters: closing compress filter
-Dec 08 19:26:58 meins 3 close_receiver: closing mp3 receiver in slot 0 (eof = 1)
-Dec 08 19:26:58 meins 2 clear_slot: clearing slot 0
-Dec 08 19:27:04 meins 2 client_open: loglevel: 5
-Dec 08 19:27:04 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:27:04 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:27:04 meins 3 client_open: connecting localhost:2990
-Dec 08 19:27:04 meins 5 makesock: can not create TCP socket localhost#2990.
-Dec 08 19:27:04 meins 5 client_open: Connection refused
-Dec 08 19:27:09 meins 2 client_open: loglevel: 5
-Dec 08 19:27:09 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:27:09 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:27:09 meins 3 client_open: connecting localhost:2990
-Dec 08 19:27:09 meins 5 makesock: can not create TCP socket localhost#2990.
-Dec 08 19:27:09 meins 5 client_open: Connection refused
-Dec 08 19:27:14 meins 2 client_open: loglevel: 5
-Dec 08 19:27:14 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:27:14 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:27:14 meins 3 client_open: connecting localhost:2990
-Dec 08 19:27:14 meins 5 makesock: can not create TCP socket localhost#2990.
-Dec 08 19:27:14 meins 5 client_open: Connection refused
-Dec 08 19:27:19 meins 2 client_open: loglevel: 5
-Dec 08 19:27:19 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:27:19 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:27:19 meins 3 client_open: connecting localhost:2990
-Dec 08 19:27:19 meins 5 makesock: can not create TCP socket localhost#2990.
-Dec 08 19:27:19 meins 5 client_open: Connection refused
-Dec 08 19:27:24 meins 2 client_open: loglevel: 5
-Dec 08 19:27:24 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:27:24 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:27:24 meins 3 client_open: connecting localhost:2990
-Dec 08 19:27:24 meins 5 makesock: can not create TCP socket localhost#2990.
-Dec 08 19:27:24 meins 5 client_open: Connection refused
-Dec 08 19:27:29 meins 2 client_open: loglevel: 5
-Dec 08 19:27:29 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:27:29 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:27:29 meins 3 client_open: connecting localhost:2990
-Dec 08 19:27:29 meins 5 makesock: can not create TCP socket localhost#2990.
-Dec 08 19:27:29 meins 5 client_open: Connection refused
-Dec 08 19:27:34 meins 2 client_open: loglevel: 5
-Dec 08 19:27:34 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:27:34 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:27:34 meins 3 client_open: connecting localhost:2990
-Dec 08 19:27:34 meins 2 register_task: registering client (0x8067878)
-Dec 08 19:27:34 meins 2 client_post_select: --> auth rc4 maan
-Dec 08 19:27:34 meins 2 client_post_select: <-- [challenge]
-Dec 08 19:27:34 meins 2 client_post_select: --> 1725057215
-Dec 08 19:27:34 meins 2 client_post_select: decrypting session key
-Dec 08 19:27:34 meins 2 enable_crypt: rc4 encryption activated for fd 8
-Dec 08 19:27:34 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:27:45 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:27:45 meins 2 clear_slot: clearing slot 0
-Dec 08 19:27:45 meins 3 open_receiver: started mp3: http receiver in slot 0
-Dec 08 19:27:45 meins 2 register_task: registering http receiver node (0x806a7b4)
-Dec 08 19:27:45 meins 2 http_recv_post_select: sending http request
-Dec 08 19:27:45 meins 2 http_recv_post_select: received ok msg, streaming
-Dec 08 19:27:46 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:27:46 meins 2 open_filters: opening mp3 filters
-Dec 08 19:27:46 meins 3 open_filters: mp3 filter 1/2 (mp3dec) started in slot 0
-Dec 08 19:27:46 meins 3 open_filters: mp3 filter 2/2 (compress) started in slot 0
-Dec 08 19:27:46 meins 2 register_task: registering filter chain (0x80729f4)
-Dec 08 19:27:46 meins 2 audiod_pre_select: initial delay: 173 ms left
-Dec 08 19:27:46 meins 2 audiod_pre_select: initial delay: 147 ms left
-Dec 08 19:27:46 meins 2 audiod_pre_select: initial delay: 121 ms left
-Dec 08 19:27:46 meins 2 audiod_pre_select: initial delay: 95 ms left
-Dec 08 19:27:46 meins 2 audiod_pre_select: initial delay: 69 ms left
-Dec 08 19:27:46 meins 2 audiod_pre_select: initial delay: 43 ms left
-Dec 08 19:27:46 meins 2 audiod_pre_select: initial delay: 17 ms left
-Dec 08 19:27:46 meins 2 open_writers: opening mp3 writers
-Dec 08 19:27:46 meins 2 open_writers: samplerate: 44100
-Dec 08 19:27:46 meins 3 wng_open: opening wng 0x80a4000 with 1 writer(s)
-Dec 08 19:27:46 meins 2 register_task: registering  (0x80a4024)
-Dec 08 19:27:46 meins 2 alsa_open: 2 channel(s), 44100Hz
-Dec 08 19:27:46 meins 2 alsa_open: buffer time: 170658
-Dec 08 19:27:46 meins 2 alsa_open: buffer size: 7526, period_size: 940
-Dec 08 19:28:30 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:28:58 meins 3 rn_event_handler: http_recv: end of file
-Dec 08 19:28:58 meins 2 unregister_task: unregistering http receiver node (0x806a7b4)
-Dec 08 19:28:58 meins 2 unregister_task: unregistering client (0x8067878)
-Dec 08 19:28:58 meins 2 kill_all_decoders: unregistering writer node group in slot 0
-Dec 08 19:28:58 meins 2 unregister_task: unregistering writer node group (0x80a4024)
-Dec 08 19:28:58 meins 2 kill_all_decoders: unregistering filter chain in slot 0
-Dec 08 19:28:58 meins 2 unregister_task: unregistering filter chain (0x80729f4)
-Dec 08 19:28:58 meins 2 try_to_close_slot: closing slot 0 
-Dec 08 19:28:58 meins 3 wng_close: closing wng with 1 writer(s)
-Dec 08 19:28:58 meins 2 alsa_close: closing writer node 0x80a4150
-Dec 08 19:28:58 meins 3 close_filters: closing filter chain 0x80729c8
-Dec 08 19:28:58 meins 2 close_filters: closing mp3dec filter
-Dec 08 19:28:58 meins 2 close_filters: closing compress filter
-Dec 08 19:28:58 meins 3 close_receiver: closing mp3 receiver in slot 0 (eof = 1)
-Dec 08 19:28:58 meins 2 clear_slot: clearing slot 0
-Dec 08 19:29:03 meins 2 client_open: loglevel: 5
-Dec 08 19:29:03 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:29:03 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:29:03 meins 3 client_open: connecting localhost:2990
-Dec 08 19:29:03 meins 2 register_task: registering client (0x8067878)
-Dec 08 19:29:03 meins 2 client_post_select: --> auth rc4 maan
-Dec 08 19:29:03 meins 2 client_post_select: <-- [challenge]
-Dec 08 19:29:03 meins 2 client_post_select: --> 705434988
-Dec 08 19:29:03 meins 2 client_post_select: decrypting session key
-Dec 08 19:29:03 meins 2 enable_crypt: rc4 encryption activated for fd 8
-Dec 08 19:29:03 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:29:13 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:29:13 meins 2 clear_slot: clearing slot 0
-Dec 08 19:29:13 meins 3 open_receiver: started ogg: dccp receiver in slot 0
-Dec 08 19:29:13 meins 2 register_task: registering dccp receiver node (0x806a804)
-Dec 08 19:29:13 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:29:13 meins 2 open_filters: opening ogg filters
-Dec 08 19:29:13 meins 3 open_filters: ogg filter 1/2 (oggdec) started in slot 0
-Dec 08 19:29:13 meins 3 open_filters: ogg filter 2/2 (compress) started in slot 0
-Dec 08 19:29:13 meins 2 register_task: registering filter chain (0x8074a44)
-Dec 08 19:29:14 meins 3 ogg_convert: input buffer: 17167, opening ov callbacks
-Dec 08 19:29:14 meins 3 ogg_convert: 2 channels, 44100 Hz
-Dec 08 19:29:14 meins 2 open_writers: opening ogg writers
-Dec 08 19:29:14 meins 2 open_writers: samplerate: 44100
-Dec 08 19:29:14 meins 3 wng_open: opening wng 0x80c8d20 with 1 writer(s)
-Dec 08 19:29:14 meins 2 register_task: registering  (0x80c8d44)
-Dec 08 19:29:14 meins 2 alsa_open: 2 channel(s), 44100Hz
-Dec 08 19:29:14 meins 2 alsa_open: buffer time: 170658
-Dec 08 19:29:14 meins 2 alsa_open: buffer size: 7526, period_size: 940
-Dec 08 19:29:58 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:30:48 meins 2 compute_time_diff: time diff (cur/avg): -3ms/+1ms
-Dec 08 19:30:58 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+1ms
-Dec 08 19:31:48 meins 2 compute_time_diff: time diff (cur/avg): -2ms/+1ms
-Dec 08 19:31:58 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+1ms
-Dec 08 19:32:48 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+1ms
-Dec 08 19:32:58 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+1ms
-Dec 08 19:33:48 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:33:56 meins 3 rn_event_handler: dccp_recv: end of file
-Dec 08 19:33:56 meins 2 unregister_task: unregistering dccp receiver node (0x806a804)
-Dec 08 19:33:56 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:33:56 meins 3 filter_event_handler: filter chain: eof
-Dec 08 19:33:56 meins 2 unregister_task: unregistering filter chain (0x8074a44)
-Dec 08 19:33:56 meins 2 wng_event_handler: wng: end of file
-Dec 08 19:33:56 meins 2 unregister_task: unregistering writer node group (0x80c8d44)
-Dec 08 19:33:56 meins 2 try_to_close_slot: closing slot 0 
-Dec 08 19:33:56 meins 3 wng_close: closing wng with 1 writer(s)
-Dec 08 19:33:56 meins 2 alsa_close: closing writer node 0x80c8e70
-Dec 08 19:33:56 meins 3 close_filters: closing filter chain 0x8074a18
-Dec 08 19:33:56 meins 2 close_filters: closing oggdec filter
-Dec 08 19:33:56 meins 2 close_filters: closing compress filter
-Dec 08 19:33:56 meins 3 close_receiver: closing ogg receiver in slot 0 (eof = 1)
-Dec 08 19:33:56 meins 2 clear_slot: clearing slot 0
-Dec 08 19:33:58 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:33:58 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:33:58 meins 2 clear_slot: clearing slot 0
-Dec 08 19:33:58 meins 3 open_receiver: started ogg: dccp receiver in slot 0
-Dec 08 19:33:58 meins 2 register_task: registering dccp receiver node (0x80d0dc4)
-Dec 08 19:33:58 meins 2 open_filters: opening ogg filters
-Dec 08 19:33:58 meins 3 open_filters: ogg filter 1/2 (oggdec) started in slot 0
-Dec 08 19:33:58 meins 3 open_filters: ogg filter 2/2 (compress) started in slot 0
-Dec 08 19:33:58 meins 2 register_task: registering filter chain (0x807481c)
-Dec 08 19:33:58 meins 2 compute_time_diff: time diff (cur/avg): -3ms/+1ms
-Dec 08 19:33:58 meins 3 ogg_convert: input buffer: 16947, opening ov callbacks
-Dec 08 19:33:58 meins 3 ogg_convert: 2 channels, 44100 Hz
-Dec 08 19:33:58 meins 2 open_writers: opening ogg writers
-Dec 08 19:33:58 meins 2 open_writers: samplerate: 44100
-Dec 08 19:33:58 meins 3 wng_open: opening wng 0x809d860 with 1 writer(s)
-Dec 08 19:33:58 meins 2 register_task: registering  (0x809d884)
-Dec 08 19:33:58 meins 2 alsa_open: 2 channel(s), 44100Hz
-Dec 08 19:33:58 meins 2 alsa_open: buffer time: 170658
-Dec 08 19:33:58 meins 2 alsa_open: buffer size: 7526, period_size: 940
-Dec 08 19:34:48 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+1ms
-Dec 08 19:34:58 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+1ms
-Dec 08 19:35:48 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+1ms
-Dec 08 19:35:58 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+1ms
-Dec 08 19:36:48 meins 2 compute_time_diff: time diff (cur/avg): -3ms/+1ms
-Dec 08 19:36:54 meins 3 rn_event_handler: dccp_recv: end of file
-Dec 08 19:36:54 meins 2 unregister_task: unregistering dccp receiver node (0x80d0dc4)
-Dec 08 19:36:54 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+1ms
-Dec 08 19:36:54 meins 3 filter_event_handler: filter chain: eof
-Dec 08 19:36:54 meins 2 unregister_task: unregistering filter chain (0x807481c)
-Dec 08 19:36:54 meins 2 wng_event_handler: wng: end of file
-Dec 08 19:36:54 meins 2 unregister_task: unregistering writer node group (0x809d884)
-Dec 08 19:36:54 meins 2 try_to_close_slot: closing slot 0 
-Dec 08 19:36:54 meins 3 wng_close: closing wng with 1 writer(s)
-Dec 08 19:36:54 meins 2 alsa_close: closing writer node 0x809d9b0
-Dec 08 19:36:54 meins 3 close_filters: closing filter chain 0x80747f0
-Dec 08 19:36:54 meins 2 close_filters: closing oggdec filter
-Dec 08 19:36:54 meins 2 close_filters: closing compress filter
-Dec 08 19:36:54 meins 3 close_receiver: closing ogg receiver in slot 0 (eof = 1)
-Dec 08 19:36:54 meins 2 clear_slot: clearing slot 0
-Dec 08 19:36:56 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+1ms
-Dec 08 19:36:56 meins 2 clear_slot: clearing slot 0
-Dec 08 19:36:56 meins 3 open_receiver: started mp3: http receiver in slot 0
-Dec 08 19:36:56 meins 2 register_task: registering http receiver node (0x80d14ec)
-Dec 08 19:36:56 meins 2 http_recv_post_select: sending http request
-Dec 08 19:36:56 meins 2 http_recv_post_select: received ok msg, streaming
-Dec 08 19:36:56 meins 2 open_filters: opening mp3 filters
-Dec 08 19:36:56 meins 3 open_filters: mp3 filter 1/2 (mp3dec) started in slot 0
-Dec 08 19:36:56 meins 3 open_filters: mp3 filter 2/2 (compress) started in slot 0
-Dec 08 19:36:56 meins 2 register_task: registering filter chain (0x80d16ac)
-Dec 08 19:36:56 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+1ms
-Dec 08 19:36:56 meins 2 audiod_pre_select: initial delay: 174 ms left
-Dec 08 19:36:56 meins 2 audiod_pre_select: initial delay: 148 ms left
-Dec 08 19:36:56 meins 2 audiod_pre_select: initial delay: 122 ms left
-Dec 08 19:36:56 meins 2 audiod_pre_select: initial delay: 96 ms left
-Dec 08 19:36:56 meins 2 audiod_pre_select: initial delay: 70 ms left
-Dec 08 19:36:56 meins 2 audiod_pre_select: initial delay: 44 ms left
-Dec 08 19:36:56 meins 2 audiod_pre_select: initial delay: 18 ms left
-Dec 08 19:36:56 meins 2 open_writers: opening mp3 writers
-Dec 08 19:36:56 meins 2 open_writers: samplerate: 44100
-Dec 08 19:36:56 meins 3 wng_open: opening wng 0x80743a0 with 1 writer(s)
-Dec 08 19:36:56 meins 2 register_task: registering  (0x80743c4)
-Dec 08 19:36:56 meins 2 alsa_open: 2 channel(s), 44100Hz
-Dec 08 19:36:56 meins 2 alsa_open: buffer time: 170658
-Dec 08 19:36:56 meins 2 alsa_open: buffer size: 7526, period_size: 940
-Dec 08 19:36:58 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+1ms
-Dec 08 19:37:48 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+1ms
-Dec 08 19:37:58 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:38:48 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:38:58 meins 2 compute_time_diff: time diff (cur/avg): -0ms/+0ms
-Dec 08 19:39:06 meins 7 signal_event_handler: terminating on signal 15
-Dec 08 19:39:06 meins 7 clean_exit: caught deadly signal
-Dec 08 19:39:06 meins 2 log_welcome: welcome to para_audiod git (Sat Dec  8 13:42:52 MET 2007)
-Dec 08 19:39:06 meins 1 log_welcome: using loglevel 1
-Dec 08 19:39:06 meins 2 init_writers: maximal number of writers: 3
-Dec 08 19:39:06 meins 2 check_writer_arg: checking  alsa -d plug:swmix
-Dec 08 19:39:06 meins 2 alsa_parse_config: options: -d plug:swmix, 2
-Dec 08 19:39:06 meins 2 alsa_parse_config: help given: 0
-Dec 08 19:39:06 meins 2 init_writers: mp3 writer #0: alsa
-Dec 08 19:39:06 meins 2 check_writer_arg: checking  alsa -d plug:swmix
-Dec 08 19:39:06 meins 2 alsa_parse_config: options: -d plug:swmix, 2
-Dec 08 19:39:06 meins 2 alsa_parse_config: help given: 0
-Dec 08 19:39:06 meins 2 init_writers: ogg writer #0: alsa
-Dec 08 19:39:06 meins 2 check_writer_arg: checking  alsa -d plug:swmix
-Dec 08 19:39:06 meins 2 alsa_parse_config: options: -d plug:swmix, 2
-Dec 08 19:39:06 meins 2 alsa_parse_config: help given: 0
-Dec 08 19:39:06 meins 2 init_writers: aac writer #0: alsa
-Dec 08 19:39:06 meins 2 init_receivers: initializing http receiver
-Dec 08 19:39:06 meins 2 init_receivers: initializing dccp receiver
-Dec 08 19:39:06 meins 2 init_receivers: initializing ortp receiver
-Dec 08 19:39:06 meins 1 check_receiver_arg: checking http -i 127.0.0.1
-Dec 08 19:39:06 meins 1 parse_receiver_args: options: -i 127.0.0.1
-Dec 08 19:39:06 meins 1 parse_receiver_args: argc = 3, argv[0]: http
-Dec 08 19:39:06 meins 1 check_receiver_arg: checking dccp -i localhost
-Dec 08 19:39:06 meins 1 parse_receiver_args: options: -i localhost
-Dec 08 19:39:06 meins 1 parse_receiver_args: argc = 3, argv[0]: dccp
-Dec 08 19:39:06 meins 1 check_receiver_arg: checking dccp -i localhost
-Dec 08 19:39:06 meins 1 parse_receiver_args: options: -i localhost
-Dec 08 19:39:06 meins 1 parse_receiver_args: argc = 3, argv[0]: dccp
-Dec 08 19:39:06 meins 2 init_filters: maximal number of filters: 6
-Dec 08 19:39:06 meins 2 add_filter: mp3 filter 1: mp3dec
-Dec 08 19:39:06 meins 2 add_filter: mp3 filter 2: compress
-Dec 08 19:39:06 meins 2 add_filter: ogg filter 1: oggdec
-Dec 08 19:39:06 meins 2 add_filter: ogg filter 2: compress
-Dec 08 19:39:06 meins 2 add_filter: aac filter 1: aacdec
-Dec 08 19:39:06 meins 2 add_filter: aac filter 2: compress
-Dec 08 19:39:06 meins 2 clear_slot: clearing slot 0
-Dec 08 19:39:06 meins 2 clear_slot: clearing slot 1
-Dec 08 19:39:06 meins 2 clear_slot: clearing slot 2
-Dec 08 19:39:06 meins 2 clear_slot: clearing slot 3
-Dec 08 19:39:06 meins 2 clear_slot: clearing slot 4
-Dec 08 19:39:06 meins 2 init_grabbing: grab init
-Dec 08 19:39:06 meins 2 setup_signal_handling: signal pipe: fd 4
-Dec 08 19:39:06 meins 1 para_install_sighandler: catching signal 2
-Dec 08 19:39:06 meins 1 para_install_sighandler: catching signal 15
-Dec 08 19:39:06 meins 1 para_install_sighandler: catching signal 1
-Dec 08 19:39:06 meins 3 audiod_get_socket: local socket: /var/paraslash/audiod_socket.meins
-Dec 08 19:39:06 meins 2 daemon_init: daemonizing
-Dec 08 19:39:06 meins 2 init_sched: initializing scheduler
-Dec 08 19:39:06 meins 2 register_task: registering signal task (0x80631bc)
-Dec 08 19:39:06 meins 1 register_task: pre_select: 0x80631c0
-Dec 08 19:39:06 meins 1 register_task: post_select: 0x80631c0
-Dec 08 19:39:06 meins 2 register_task: registering command task (0xbfa7e274)
-Dec 08 19:39:06 meins 1 register_task: pre_select: 0xbfa7e278
-Dec 08 19:39:06 meins 1 register_task: post_select: 0xbfa7e278
-Dec 08 19:39:06 meins 2 register_task: registering status task (0x80632e8)
-Dec 08 19:39:06 meins 1 register_task: pre_select: 0x80632ec
-Dec 08 19:39:06 meins 1 register_task: post_select: 0x80632ec
-Dec 08 19:39:06 meins 2 register_task: registering audiod task (0xbfa7e398)
-Dec 08 19:39:06 meins 1 register_task: pre_select: 0xbfa7e39c
-Dec 08 19:39:06 meins 1 register_task: post_select: 0xbfa7e39c
-Dec 08 19:39:06 meins 2 status_pre_select: clock diff count: 5
-Dec 08 19:39:06 meins 2 client_open: loglevel: 5
-Dec 08 19:39:06 meins 2 client_open: config_file: /home/maan/.paraslash/client.conf
-Dec 08 19:39:06 meins 2 client_open: key_file: /home/maan/.paraslash/key.maan
-Dec 08 19:39:06 meins 3 client_open: connecting localhost:2990
-Dec 08 19:39:06 meins 2 register_task: registering client (0x8067878)
-Dec 08 19:39:06 meins 1 register_task: pre_select: 0x806787c
-Dec 08 19:39:06 meins 1 register_task: post_select: 0x806787c
-Dec 08 19:39:06 meins 2 client_post_select: --> auth rc4 maan
-Dec 08 19:39:06 meins 2 client_post_select: <-- [challenge]
-Dec 08 19:39:06 meins 2 client_post_select: --> 153889019
-Dec 08 19:39:06 meins 1 client_post_select: ++++ server info ++++
-
-Proceed.
-
-++++ end of server info ++++
-Dec 08 19:39:06 meins 2 client_post_select: decrypting session key
-Dec 08 19:39:06 meins 2 enable_crypt: rc4 encryption activated for fd 7
-Dec 08 19:39:06 meins 1 client_post_select: --> 
-stat
-1
-End of Command.
+Dec 29 02:18:32 klar (0) check_receiver_arg: checking udp
+Dec 29 02:18:32 klar (0) check_receiver_arg: checking udp
+Dec 29 02:18:32 klar (0) check_receiver_arg: checking udp
+Dec 29 02:18:32 klar (0) check_receiver_arg: checking udp
+Dec 29 02:18:32 klar (0) check_receiver_arg: checking udp
+Dec 29 02:18:32 klar (0) check_receiver_arg: checking udp
+Dec 29 02:18:32 klar (0) check_receiver_arg: checking udp
+Dec 29 02:18:32 klar (1) parse_receiver_args: receiving wma streams via udp receiver
+Dec 29 02:18:32 klar (1) parse_receiver_args: receiving ogg streams via udp receiver
+Dec 29 02:18:32 klar (1) parse_receiver_args: receiving spx streams via udp receiver
+Dec 29 02:18:32 klar (1) parse_receiver_args: receiving opus streams via udp receiver
+Dec 29 02:18:32 klar (1) parse_receiver_args: receiving aac streams via udp receiver
+Dec 29 02:18:32 klar (1) parse_receiver_args: receiving mp3 streams via udp receiver
+Dec 29 02:18:32 klar (1) parse_receiver_args: receiving flac streams via udp receiver
+Dec 29 02:18:32 klar (1) add_filter: wma filter 0: fecdec
+Dec 29 02:18:32 klar (1) add_filter: ogg filter 0: fecdec
+Dec 29 02:18:32 klar (1) add_filter: spx filter 0: fecdec
+Dec 29 02:18:32 klar (1) add_filter: opus filter 0: fecdec
+Dec 29 02:18:32 klar (1) add_filter: aac filter 0: fecdec
+Dec 29 02:18:32 klar (1) add_filter: mp3 filter 0: fecdec
+Dec 29 02:18:32 klar (1) add_filter: flac filter 0: fecdec
+Dec 29 02:18:32 klar (1) add_filter: mp3 filter 1: mp3dec
+Dec 29 02:18:32 klar (1) add_filter: ogg filter 1: oggdec
+Dec 29 02:18:32 klar (1) add_filter: aac filter 1: aacdec
+Dec 29 02:18:32 klar (1) add_filter: wma filter 1: wmadec
+Dec 29 02:18:32 klar (1) add_filter: spx filter 1: spxdec
+Dec 29 02:18:32 klar (1) add_filter: flac filter 1: flacdec
+Dec 29 02:18:32 klar (1) add_filter: opus filter 1: opusdec
+Dec 29 02:18:32 klar (1) add_filter: wma filter 2: amp
+Dec 29 02:18:32 klar (1) add_filter: ogg filter 2: amp
+Dec 29 02:18:32 klar (1) add_filter: spx filter 2: amp
+Dec 29 02:18:32 klar (1) add_filter: opus filter 2: amp
+Dec 29 02:18:32 klar (1) add_filter: aac filter 2: amp
+Dec 29 02:18:32 klar (1) add_filter: mp3 filter 2: amp
+Dec 29 02:18:32 klar (1) add_filter: flac filter 2: amp
+Dec 29 02:18:32 klar (1) add_filter: wma filter 3: compress
+Dec 29 02:18:32 klar (1) add_filter: ogg filter 3: compress
+Dec 29 02:18:32 klar (1) add_filter: spx filter 3: compress
+Dec 29 02:18:32 klar (1) add_filter: opus filter 3: compress
+Dec 29 02:18:32 klar (1) add_filter: aac filter 3: compress
+Dec 29 02:18:32 klar (1) add_filter: mp3 filter 3: compress
+Dec 29 02:18:32 klar (1) add_filter: flac filter 3: compress
+Dec 29 02:18:32 klar (1) parse_writer_args: wma writer: alsa (default)
+Dec 29 02:18:32 klar (1) parse_writer_args: ogg writer: alsa (default)
+Dec 29 02:18:32 klar (1) parse_writer_args: spx writer: alsa (default)
+Dec 29 02:18:32 klar (1) parse_writer_args: opus writer: alsa (default)
+Dec 29 02:18:32 klar (1) parse_writer_args: aac writer: alsa (default)
+Dec 29 02:18:32 klar (1) parse_writer_args: mp3 writer: alsa (default)
+Dec 29 02:18:32 klar (1) parse_writer_args: flac writer: alsa (default)
+Dec 29 02:18:32 klar (1) log_welcome: welcome to para_audiod git (Sun Dec 29 01:49:51 MET 2013)
+Dec 29 02:18:32 klar (1) clear_slot: clearing slot 0
+Dec 29 02:18:32 klar (1) clear_slot: clearing slot 1
+Dec 29 02:18:32 klar (1) clear_slot: clearing slot 2
+Dec 29 02:18:32 klar (1) clear_slot: clearing slot 3
+Dec 29 02:18:32 klar (1) clear_slot: clearing slot 4
+Dec 29 02:18:32 klar (1) setup_signal_handling: signal pipe: fd 4
+Dec 29 02:18:32 klar (0) para_sigaction: catching signal 2
+Dec 29 02:18:32 klar (0) para_sigaction: catching signal 15
+Dec 29 02:18:32 klar (0) para_sigaction: catching signal 1
+Dec 29 02:18:32 klar (0) para_sigaction: catching signal 13
+Dec 29 02:18:32 klar (1) btr_new_node: added stat as btr root
+Dec 29 02:18:32 klar (2) audiod_get_socket: local socket: /var/paraslash/audiod_socket.klar
+Dec 29 02:18:32 klar (1) register_task: registering signal task (0x807fc2c)
+Dec 29 02:18:32 klar (0) register_task: pre_select: 0x807fc2c
+Dec 29 02:18:32 klar (0) register_task: post_select: 0x807fc30
+Dec 29 02:18:32 klar (1) register_task: registering command task (0xbf84acd0)
+Dec 29 02:18:32 klar (0) register_task: pre_select: 0xbf84acd0
+Dec 29 02:18:32 klar (0) register_task: post_select: 0xbf84acd4
+Dec 29 02:18:32 klar (1) register_task: registering stat (0x807fabc)
+Dec 29 02:18:32 klar (0) register_task: pre_select: 0x807fabc
+Dec 29 02:18:32 klar (0) register_task: post_select: 0x807fac0
+Dec 29 02:18:32 klar (1) client_parse_config: loglevel: warning
+Dec 29 02:18:32 klar (1) client_parse_config: config_file: /home/maan/.paraslash/client.conf
+Dec 29 02:18:32 klar (1) client_parse_config: key_file: /home/maan/.paraslash/key.maan
+Dec 29 02:18:32 klar (2) client_connect: connecting p133:2990
+Dec 29 02:18:32 klar (1) btr_new_node: new root: client recv (was stat)
+Dec 29 02:18:32 klar (1) btr_new_node: added client send as btr root
+Dec 29 02:18:32 klar (1) register_task: registering client (0x80db404)
+Dec 29 02:18:32 klar (0) register_task: pre_select: 0x80db404
+Dec 29 02:18:32 klar (0) register_task: post_select: 0x80db408
+Dec 29 02:18:32 klar (1) parse_features: server feature: sideband
+Dec 29 02:18:32 klar (1) client_post_select: --> auth rsa maan sideband
+Dec 29 02:18:32 klar (1) client_post_select: <-- [challenge] (256 bytes)
+Dec 29 02:18:33 klar (1) client_post_select: --> 3c9229389de0fd26030b79ab4b10719801372d98
+Dec 29 02:18:33 klar (0) send_sb_command: --> stat
+Dec 29 02:18:33 klar (0) dispatch_sbb: band: OUTPUT
+Dec 29 02:18:33 klar (0) dispatch_sbb: band: OUTPUT
+Dec 29 02:18:33 klar (1) clear_slot: clearing slot 0
+Dec 29 02:18:33 klar (1) btr_new_node: added udp as btr root
+Dec 29 02:18:33 klar (1) udp_recv_open: receiving from 224.0.1.38:8000, fd=8
+Dec 29 02:18:33 klar (1) btr_pool_new: udp_recv, 327680 bytes
+Dec 29 02:18:33 klar (2) open_receiver: started ogg: udp receiver in slot 0
+Dec 29 02:18:33 klar (1) register_task: registering udp receiver node (0x80dbfcc)
+Dec 29 02:18:33 klar (0) register_task: pre_select: 0x80dbfcc
+Dec 29 02:18:33 klar (0) register_task: post_select: 0x80dbfd0
+Dec 29 02:18:33 klar (1) open_filters: opening ogg filters
+Dec 29 02:18:33 klar (1) btr_new_node: new leaf node: fecdec (child of udp)
+Dec 29 02:18:33 klar (1) register_task: registering  (0x80dc8c8)
+Dec 29 02:18:33 klar (0) register_task: pre_select: 0x80dc8c8
+Dec 29 02:18:33 klar (0) register_task: post_select: 0x80dc8cc
+Dec 29 02:18:33 klar (2) open_filters: ogg filter 0/4 (fecdec) started in slot 0
+Dec 29 02:18:33 klar (1) btr_new_node: new leaf node: oggdec (child of fecdec)
+Dec 29 02:18:33 klar (1) register_task: registering  (0x80dca04)
+Dec 29 02:18:33 klar (0) register_task: pre_select: 0x80dca04
+Dec 29 02:18:33 klar (0) register_task: post_select: 0x80dca08
+Dec 29 02:18:33 klar (2) open_filters: ogg filter 1/4 (oggdec) started in slot 0
+Dec 29 02:18:33 klar (1) btr_new_node: new leaf node: amp (child of oggdec)
+Dec 29 02:18:33 klar (1) amp_open: amplification: 0 (scaling factor: 1.00)
+Dec 29 02:18:33 klar (1) register_task: registering  (0x80dcb40)
+Dec 29 02:18:33 klar (0) register_task: pre_select: 0x80dcb40
+Dec 29 02:18:33 klar (0) register_task: post_select: 0x80dcb44
+Dec 29 02:18:33 klar (2) open_filters: ogg filter 2/4 (amp) started in slot 0
+Dec 29 02:18:33 klar (1) btr_new_node: new leaf node: compress (child of amp)
+Dec 29 02:18:33 klar (1) register_task: registering  (0x80dcc7c)
+Dec 29 02:18:33 klar (0) register_task: pre_select: 0x80dcc7c
+Dec 29 02:18:33 klar (0) register_task: post_select: 0x80dcc80
+Dec 29 02:18:33 klar (2) open_filters: ogg filter 3/4 (compress) started in slot 0
+Dec 29 02:18:33 klar (1) btr_new_node: new leaf node: alsa writer (child of compress)
+Dec 29 02:18:33 klar (1) register_task: registering alsa writer (0x80dc270)
+Dec 29 02:18:33 klar (0) register_task: pre_select: 0x80dc270
+Dec 29 02:18:33 klar (0) register_task: post_select: 0x80dc274
+Dec 29 02:18:33 klar (2) open_writers: alsa writer started in slot 0
+Dec 29 02:18:33 klar (2)  udp
+Dec 29 02:18:33 klar (2)   fecdec
+Dec 29 02:18:33 klar (2)    oggdec
+Dec 29 02:18:33 klar (2)     amp
+Dec 29 02:18:33 klar (2)      compress
+Dec 29 02:18:33 klar (2)       alsa writer
+Dec 29 02:18:33 klar (2) btr_splice_out_node: splicing out amp
+Dec 29 02:18:33 klar (1) btr_splice_out_node: parent(compress): oggdec
+Dec 29 02:18:33 klar (1) unregister_task: unregistering amp (slot 0) (no amplification necessary)
+Dec 29 02:18:33 klar (0) add_slice: group 374 complete, ignoring slice 26
+Dec 29 02:18:33 klar (0) add_slice: group 375 complete, ignoring slice 26
+Dec 29 02:18:33 klar (2) dispatch_slice: init fec (26, 27)
+Dec 29 02:18:33 klar (1) btr_pool_new: fecdec, 131072 bytes
+Dec 29 02:18:33 klar (0) decode_group: decoding group 375 (26 slices)
+Dec 29 02:18:33 klar (0) decode_group: writing group 375 (4245/8710 decoded data bytes)
+Dec 29 02:18:33 klar (1) decode_group: writing audio file header
+Dec 29 02:18:33 klar (0) decode_group: decoding group 376 (26 slices)
+Dec 29 02:18:33 klar (0) decode_group: writing group 376 (4157/4160 decoded data bytes)
+Dec 29 02:18:33 klar (2) ogg_init: iqs: 12752, min_iqs: 8000, opening ov callbacks
+Dec 29 02:18:33 klar (0) cb_read: vorbis requests 65536 bytes have 12752
+Dec 29 02:18:33 klar (2) ogg_init: 2 channels, 44100 Hz
+Dec 29 02:18:33 klar (0) add_slice: group 376 complete, ignoring slice 26
+Dec 29 02:18:34 klar (0) decode_group: decoding group 377 (26 slices)
+Dec 29 02:18:34 klar (0) decode_group: writing group 377 (4370/4394 decoded data bytes)
+Dec 29 02:18:34 klar (0) add_slice: group 377 complete, ignoring slice 26
+Dec 29 02:18:34 klar (0) decode_group: decoding group 378 (26 slices)
+Dec 29 02:18:34 klar (0) decode_group: writing group 378 (4230/4238 decoded data bytes)
+Dec 29 02:18:34 klar (0) add_slice: group 378 complete, ignoring slice 26
+Dec 29 02:18:34 klar (0) decode_group: decoding group 379 (26 slices)
+Dec 29 02:18:34 klar (0) decode_group: writing group 379 (4193/4212 decoded data bytes)
+Dec 29 02:18:34 klar (0) cb_read: vorbis requests 65536 bytes have 12793
+Dec 29 02:18:34 klar (1) btr_exec_up: executing sample_rate on oggdec
+Dec 29 02:18:34 klar (1) btr_exec_up: sample_rate(oggdec): 44100
+Dec 29 02:18:34 klar (1) btr_exec_up: executing channels on oggdec
+Dec 29 02:18:34 klar (1) btr_exec_up: channels(oggdec): 2
+Dec 29 02:18:34 klar (1) btr_exec_up: executing sample_format on oggdec
+Dec 29 02:18:34 klar (1) btr_exec_up: sample_format(oggdec): 2
+Dec 29 02:18:34 klar (1) alsa_write_post_select: 2 channel(s), 44100Hz
+Dec 29 02:18:34 klar (1) alsa_init: opening default
+Dec 29 02:18:35 klar (1) alsa_init: dumping alsa configuration
+Dec 29 02:18:35 klar (1) alsa_init: Plug PCM: Rate conversion PCM (48000, sformat=S16_LE)
+Dec 29 02:18:35 klar (1) alsa_init: Converter: linear-interpolation
+Dec 29 02:18:35 klar (1) alsa_init: Protocol version: 10002
+Dec 29 02:18:35 klar (1) alsa_init: Its setup is:
+Dec 29 02:18:35 klar (1) alsa_init:   stream       : PLAYBACK
+Dec 29 02:18:35 klar (1) alsa_init:   access       : RW_INTERLEAVED
+Dec 29 02:18:35 klar (1) alsa_init:   format       : S16_LE
+Dec 29 02:18:35 klar (1) alsa_init:   subformat    : STD
+Dec 29 02:18:35 klar (1) alsa_init:   channels     : 2
+Dec 29 02:18:35 klar (1) alsa_init:   rate         : 44100
+Dec 29 02:18:35 klar (1) alsa_init:   exact rate   : 44100 (44100/1)
+Dec 29 02:18:35 klar (1) alsa_init:   msbits       : 16
+Dec 29 02:18:35 klar (1) alsa_init:   buffer_size  : 15052
+Dec 29 02:18:35 klar (1) alsa_init:   period_size  : 940
+Dec 29 02:18:35 klar (1) alsa_init:   period_time  : 21333
+Dec 29 02:18:35 klar (1) alsa_init:   tstamp_mode  : NONE
+Dec 29 02:18:35 klar (1) alsa_init:   period_step  : 1
+Dec 29 02:18:35 klar (1) alsa_init:   avail_min    : 940
+Dec 29 02:18:35 klar (1) alsa_init:   period_event : 0
+Dec 29 02:18:35 klar (1) alsa_init:   start_threshold  : 15052
+Dec 29 02:18:35 klar (1) alsa_init:   stop_threshold   : 15052
+Dec 29 02:18:35 klar (1) alsa_init:   silence_threshold: 0
+Dec 29 02:18:35 klar (1) alsa_init:   silence_size : 0
+Dec 29 02:18:35 klar (1) alsa_init:   boundary     : 986447872
+Dec 29 02:18:35 klar (1) alsa_init: Slave: Direct Stream Mixing PCM
+Dec 29 02:18:35 klar (1) alsa_init: Its setup is:
+Dec 29 02:18:35 klar (1) alsa_init:   stream       : PLAYBACK
+Dec 29 02:18:35 klar (1) alsa_init:   access       : MMAP_INTERLEAVED
+Dec 29 02:18:35 klar (1) alsa_init:   format       : S16_LE
+Dec 29 02:18:35 klar (1) alsa_init:   subformat    : STD
+Dec 29 02:18:35 klar (1) alsa_init:   channels     : 2
+Dec 29 02:18:35 klar (1) alsa_init:   rate         : 48000
+Dec 29 02:18:35 klar (1) alsa_init:   exact rate   : 48000 (48000/1)
+Dec 29 02:18:35 klar (1) alsa_init:   msbits       : 16
+Dec 29 02:18:35 klar (1) alsa_init:   buffer_size  : 16384
+Dec 29 02:18:35 klar (1) alsa_init:   period_size  : 1024
+Dec 29 02:18:35 klar (1) alsa_init:   period_time  : 21333
+Dec 29 02:18:35 klar (1) alsa_init:   tstamp_mode  : NONE
+Dec 29 02:18:35 klar (1) alsa_init:   period_step  : 1
+Dec 29 02:18:35 klar (1) alsa_init:   avail_min    : 1024
+Dec 29 02:18:35 klar (1) alsa_init:   period_event : 0
+Dec 29 02:18:35 klar (1) alsa_init:   start_threshold  : 16384
+Dec 29 02:18:35 klar (1) alsa_init:   stop_threshold   : 16384
+Dec 29 02:18:35 klar (1) alsa_init:   silence_threshold: 0
+Dec 29 02:18:35 klar (1) alsa_init:   silence_size : 0
+Dec 29 02:18:35 klar (1) alsa_init:   boundary     : 1073741824
+Dec 29 02:18:35 klar (1) alsa_init: Hardware PCM card 0 'Ensoniq AudioPCI' device 0 subdevice 0
+Dec 29 02:18:35 klar (1) alsa_init: Its setup is:
+Dec 29 02:18:35 klar (1) alsa_init:   stream       : PLAYBACK
+Dec 29 02:18:35 klar (1) alsa_init:   access       : MMAP_INTERLEAVED
+Dec 29 02:18:35 klar (1) alsa_init:   format       : S16_LE
+Dec 29 02:18:35 klar (1) alsa_init:   subformat    : STD
+Dec 29 02:18:35 klar (1) alsa_init:   channels     : 2
+Dec 29 02:18:35 klar (1) alsa_init:   rate         : 48000
+Dec 29 02:18:35 klar (1) alsa_init:   exact rate   : 48000 (1572864000/32768)
+Dec 29 02:18:35 klar (1) alsa_init:   msbits       : 16
+Dec 29 02:18:35 klar (1) alsa_init:   buffer_size  : 16384
+Dec 29 02:18:35 klar (1) alsa_init:   period_size  : 1024
+Dec 29 02:18:35 klar (1) alsa_init:   period_time  : 21333
+Dec 29 02:18:35 klar (1) alsa_init:   tstamp_mode  : ENABLE
+Dec 29 02:18:35 klar (1) alsa_init:   period_step  : 1
+Dec 29 02:18:35 klar (1) alsa_init:   avail_min    : 1024
+Dec 29 02:18:35 klar (1) alsa_init:   period_event : 0
+Dec 29 02:18:35 klar (1) alsa_init:   start_threshold  : 1
+Dec 29 02:18:35 klar (1) alsa_init:   stop_threshold   : 1073741824
+Dec 29 02:18:35 klar (1) alsa_init:   silence_threshold: 0
+Dec 29 02:18:35 klar (1) alsa_init:   silence_size : 1073741824
+Dec 29 02:18:35 klar (1) alsa_init:   boundary     : 1073741824
+Dec 29 02:18:35 klar (1) alsa_init:   appl_ptr     : 0
+Dec 29 02:18:35 klar (1) alsa_init:   hw_ptr       : 1040
+Dec 29 02:18:35 klar (0) add_slice: group 379 complete, ignoring slice 26
+Dec 29 02:18:35 klar (0) decode_group: decoding group 380 (26 slices)
+Dec 29 02:18:35 klar (0) decode_group: writing group 380 (4158/4160 decoded data bytes)
+Dec 29 02:18:35 klar (0) add_slice: group 380 complete, ignoring slice 26
+Dec 29 02:18:35 klar (0) decode_group: decoding group 381 (26 slices)
+Dec 29 02:18:35 klar (0) decode_group: writing group 381 (4241/4264 decoded data bytes)
+Dec 29 02:18:35 klar (0) add_slice: group 381 complete, ignoring slice 26
+Dec 29 02:18:35 klar (0) cb_read: vorbis requests 65536 bytes have 8399
+Dec 29 02:18:35 klar (0) cb_read: vorbis requests 65536 bytes have 0
+Dec 29 02:18:35 klar (0) decode_group: decoding group 382 (26 slices)
+Dec 29 02:18:35 klar (0) decode_group: writing group 382 (4281/4290 decoded data bytes)
+Dec 29 02:18:35 klar (0) add_slice: group 382 complete, ignoring slice 26
+Dec 29 02:18:35 klar (0) cb_read: vorbis requests 65536 bytes have 4281
+Dec 29 02:18:35 klar (0) cb_read: vorbis requests 65536 bytes have 0
index 2a6c7443d1b1852481eb0a7b92cba4e576c6afd0..9166de768a76adb05f73a5984325184f557c9734 100644 (file)
Binary files a/web/screenshots/gui.png and b/web/screenshots/gui.png differ
index f84ede8161f817ff99d197a646e04b4a5b3d72df..c8287b37361b5bdeec2902f89911dc8bbd5ad763 100644 (file)
-Dec 08 19:28:58 2: (21285) log_welcome: welcome to para_server git (Sat Dec  8 13:42:52 MET 2007)
-Dec 08 19:28:58 1: (21285) log_welcome: using loglevel 1
-Dec 08 19:28:58 1: (21285) populate_user_list: found entry for maan
-Dec 08 19:28:58 1: (21285) populate_user_list: found 4 perm entries
-Dec 08 19:28:58 1: (21285) populate_user_list: found entry for install
-Dec 08 19:28:58 1: (21285) populate_user_list: found 4 perm entries
-Dec 08 19:28:58 1: (21285) populate_user_list: found entry for www
-Dec 08 19:28:58 1: (21285) populate_user_list: found 4 perm entries
-Dec 08 19:28:58 2: (21285) daemon_init: daemonizing
-Dec 08 19:28:58 3: (21286) server_init: initializing audio format handlers
-Dec 08 19:28:58 2: (21286) afh_init: supported audio formats: mp3 ogg aac
-Dec 08 19:28:58 3: (21286) afh_init: initializing mp3 handler
-Dec 08 19:28:58 3: (21286) afh_init: initializing ogg handler
-Dec 08 19:28:58 3: (21286) afh_init: initializing aac handler
-Dec 08 19:28:58 3: (21286) server_init: initializing virtual streaming system
-Dec 08 19:28:58 2: (21286) vss_init: announce timeval: 300ms
-Dec 08 19:28:58 3: (21286) vss_init: initializing http sender
-Dec 08 19:28:58 2: (21286) para_listen: listening on TCP port 8000, fd 4
-Dec 08 19:28:58 1: (21286) http_send_init: http sender init complete
-Dec 08 19:28:58 3: (21286) vss_init: initializing dccp sender
-Dec 08 19:28:58 2: (21286) para_listen: listening on DCCP port 5001, fd 5
-Dec 08 19:28:58 3: (21286) vss_init: initializing ortp sender
-Dec 08 19:28:58 1: (21286) ortp_send_init: ortp sender init complete
-Dec 08 19:28:58 3: (21286) setup_signal_handling: setting up signal handlers
-Dec 08 19:28:58 1: (21286) para_install_sighandler: catching signal 2
-Dec 08 19:28:58 1: (21286) para_install_sighandler: catching signal 15
-Dec 08 19:28:58 1: (21286) para_install_sighandler: catching signal 1
-Dec 08 19:28:58 1: (21286) para_install_sighandler: catching signal 17
-Dec 08 19:28:58 1: (21286) para_install_sighandler: catching signal 10
-Dec 08 19:28:58 3: (21286) server_init: initializing the audio file selector
-Dec 08 19:28:58 2: (21287) get_database_dir: afs_database dir /home/maan/.paraslash/afs_database
-Dec 08 19:28:58 3: (21287) open_afs_tables: opening 7 osl tables in /home/maan/.paraslash/afs_database
-Dec 08 19:28:58 2: (21287) osl_open_table: opening table audio_files
-Dec 08 19:28:58 1: (21287) init_table_structure: creating table structure for 'audio_files' from table description
-Dec 08 19:28:58 1: (21287) init_table_structure: OK. Index entry size: 32
-Dec 08 19:28:58 1: (21287) map_table: mapping table 'audio_files' (index: /home/maan/.paraslash/afs_database/audio_files/index)
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/audio_files/index: size 218667
-Dec 08 19:28:58 1: (21287) read_table_desc: 5 columns
-Dec 08 19:28:58 1: (21287) compare_table_descriptions: table description of 'audio_files' matches on-disk data, good
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/audio_files/2346ad27d7568ba9896f1b7da6b5991251debdf2: size 143430
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/audio_files/3150ecd5e0294534a81ae047ddac559de481d774: size 436636
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/audio_files/94ea39e309f3f31357ab60b190b6b8c32f21620b: size 225390
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/audio_files/b063ad096f9d142a388ca2a10d46b56904e26cda: size 1174409
-Dec 08 19:28:58 1: (21287) osl_open_table: num rows: 6830
-Dec 08 19:28:58 2: (21286) init_afs: afs_socket: 8, afs_socket_cookie: 1363241225
-Dec 08 19:28:58 3: (21286) server_init: initializing tcp command socket
-Dec 08 19:28:58 2: (21286) para_listen: listening on TCP port 2990, fd 9
-Dec 08 19:28:58 3: (21286) server_init: server init complete
-Dec 08 19:28:58 1: (21286) chk_barrier: autoplay_delay barrier: 14981ms left
-Dec 08 19:28:58 1: (21286) status_refresh: 0 events, forcing status update
-Dec 08 19:28:58 1: (21286) para_next_signal: next signal: 10
-Dec 08 19:28:58 1: (21286) chk_barrier: autoplay_delay barrier: 14981ms left
-Dec 08 19:28:58 1: (21286) para_next_signal: next signal: 10
-Dec 08 19:28:58 1: (21286) chk_barrier: autoplay_delay barrier: 14981ms left
-Dec 08 19:28:58 2: (21287) aft_open: audio file table contains 6830 files
-Dec 08 19:28:58 2: (21287) osl_open_table: opening table attributes
-Dec 08 19:28:58 1: (21287) init_table_structure: creating table structure for 'attributes' from table description
-Dec 08 19:28:58 1: (21287) init_table_structure: OK. Index entry size: 16
-Dec 08 19:28:58 1: (21287) map_table: mapping table 'attributes' (index: /home/maan/.paraslash/afs_database/attributes/index)
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/attributes/index: size 396
-Dec 08 19:28:58 1: (21287) read_table_desc: 2 columns
-Dec 08 19:28:58 1: (21287) compare_table_descriptions: table description of 'attributes' matches on-disk data, good
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/attributes/fd1e48caeff7212c45fc08608b7187feb10a7a2d: size 42
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/attributes/6ae999552a0d2dca14d62e2bc8b764d377b1dd6c: size 141
-Dec 08 19:28:58 1: (21287) osl_open_table: num rows: 21
-Dec 08 19:28:58 2: (21287) osl_open_table: opening table score
-Dec 08 19:28:58 1: (21287) init_table_structure: creating table structure for 'score' from table description
-Dec 08 19:28:58 1: (21287) init_table_structure: OK. Index entry size: 0
-Dec 08 19:28:58 1: (21287) osl_open_table: num rows: 0
-Dec 08 19:28:58 2: (21287) osl_open_table: opening table moods
-Dec 08 19:28:58 1: (21287) init_table_structure: creating table structure for 'moods' from table description
-Dec 08 19:28:58 1: (21287) init_table_structure: OK. Index entry size: 16
-Dec 08 19:28:58 1: (21287) map_table: mapping table 'moods' (index: /home/maan/.paraslash/afs_database/moods/index)
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/moods/index: size 235
-Dec 08 19:28:58 1: (21287) read_table_desc: 3 columns
-Dec 08 19:28:58 1: (21287) compare_table_descriptions: table description of 'moods' matches on-disk data, good
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/moods/87ea5dfc8b8e384d848979496e706390b497e547: size 50
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/moods/6ae999552a0d2dca14d62e2bc8b764d377b1dd6c: size 67
-Dec 08 19:28:58 1: (21287) osl_open_table: num rows: 10
-Dec 08 19:28:58 2: (21287) osl_open_table: opening table lyrics
-Dec 08 19:28:58 1: (21287) init_table_structure: creating table structure for 'lyrics' from table description
-Dec 08 19:28:58 1: (21287) init_table_structure: OK. Index entry size: 16
-Dec 08 19:28:58 1: (21287) map_table: mapping table 'lyrics' (index: /home/maan/.paraslash/afs_database/lyrics/index)
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/lyrics/index: size 347
-Dec 08 19:28:58 1: (21287) read_table_desc: 3 columns
-Dec 08 19:28:58 1: (21287) compare_table_descriptions: table description of 'lyrics' matches on-disk data, good
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/lyrics/87ea5dfc8b8e384d848979496e706390b497e547: size 85
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/lyrics/6ae999552a0d2dca14d62e2bc8b764d377b1dd6c: size 478
-Dec 08 19:28:58 1: (21287) osl_open_table: num rows: 17
-Dec 08 19:28:58 2: (21287) osl_open_table: opening table images
-Dec 08 19:28:58 1: (21287) init_table_structure: creating table structure for 'images' from table description
-Dec 08 19:28:58 1: (21287) init_table_structure: OK. Index entry size: 16
-Dec 08 19:28:58 1: (21287) map_table: mapping table 'images' (index: /home/maan/.paraslash/afs_database/images/index)
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/images/index: size 7227
-Dec 08 19:28:58 1: (21287) read_table_desc: 3 columns
-Dec 08 19:28:58 1: (21287) compare_table_descriptions: table description of 'images' matches on-disk data, good
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/images/87ea5dfc8b8e384d848979496e706390b497e547: size 2235
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/images/6ae999552a0d2dca14d62e2bc8b764d377b1dd6c: size 12950
-Dec 08 19:28:58 1: (21287) osl_open_table: num rows: 447
-Dec 08 19:28:58 2: (21287) osl_open_table: opening table playlists
-Dec 08 19:28:58 1: (21287) init_table_structure: creating table structure for 'playlists' from table description
-Dec 08 19:28:58 1: (21287) init_table_structure: OK. Index entry size: 16
-Dec 08 19:28:58 1: (21287) map_table: mapping table 'playlists' (index: /home/maan/.paraslash/afs_database/playlists/index)
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/playlists/index: size 107
-Dec 08 19:28:58 1: (21287) read_table_desc: 3 columns
-Dec 08 19:28:58 1: (21287) compare_table_descriptions: table description of 'playlists' matches on-disk data, good
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/playlists/87ea5dfc8b8e384d848979496e706390b497e547: size 10
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/playlists/6ae999552a0d2dca14d62e2bc8b764d377b1dd6c: size 7
-Dec 08 19:28:58 1: (21287) osl_open_table: num rows: 2
-Dec 08 19:28:58 2: (21287) afs_init: server_socket: 9, afs_socket_cookie: 1363241225
-Dec 08 19:28:58 1: (21287) osl_open_disk_object: filename: /home/maan/.paraslash/afs_database/moods/f3f1dd33eb2a8b380b64a830e5fd90eab77d9ff3/9d/b063f3b5e0adfd0d29a03db0a1c207b3740a94
-Dec 08 19:28:58 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/moods/f3f1dd33eb2a8b380b64a830e5fd90eab77d9ff3/9d/b063f3b5e0adfd0d29a03db0a1c207b3740a94: size 31
-Dec 08 19:28:58 1: (21287) parse_mood_line: accept entry added, method: 0x806c0f4
-Dec 08 19:28:58 3: (21287) change_current_mood: computing statistics of admissible files
-Dec 08 19:28:58 2: (21287) log_statistics: last_played mean: 1193159581, last_played sigma: 4161524
-Dec 08 19:28:58 2: (21287) log_statistics: num_played mean: 32, num_played sigma: 21
-Dec 08 19:28:58 2: (21287) change_current_mood: 26 admissible files 
-Dec 08 19:28:58 3: (21287) change_current_mood: loaded mood gulp
-Dec 08 19:28:58 2: (21287) register_signal_task: signal pipe: fd 8
-Dec 08 19:28:58 1: (21287) para_install_sighandler: catching signal 2
-Dec 08 19:28:58 1: (21287) para_install_sighandler: catching signal 15
-Dec 08 19:28:58 1: (21287) para_install_sighandler: catching signal 13
-Dec 08 19:28:58 1: (21287) para_install_sighandler: catching signal 1
-Dec 08 19:28:58 2: (21287) init_sched: initializing scheduler
-Dec 08 19:28:58 2: (21287) register_task: registering signal task (0x806f244)
-Dec 08 19:28:58 1: (21287) register_task: pre_select: 0x806f248
-Dec 08 19:28:58 1: (21287) register_task: post_select: 0x806f248
-Dec 08 19:28:58 2: (21287) setup_command_socket_or_die: listening on socket /var/paraslash/afs_command_socket (fd 1)
-Dec 08 19:28:58 2: (21287) register_task: registering command task (0x806f118)
-Dec 08 19:28:58 1: (21287) register_task: pre_select: 0x806f11c
-Dec 08 19:28:58 1: (21287) register_task: post_select: 0x806f11c
-Dec 08 19:28:59 2: (21286) main: got connection from ::ffff:127.0.0.1#42344, forking
-Dec 08 19:28:59 1: (21356) close_listed_fds: closing fd 9
-Dec 08 19:28:59 1: (21356) close_listed_fds: closing fd 8
-Dec 08 19:28:59 1: (21356) close_listed_fds: closing fd 6
-Dec 08 19:28:59 1: (21356) close_listed_fds: closing fd 5
-Dec 08 19:28:59 1: (21356) close_listed_fds: closing fd 4
-Dec 08 19:28:59 1: (21286) chk_barrier: autoplay_delay barrier: 13507ms left
-Dec 08 19:28:59 1: (21356) handle_connect: received rc4 request for user maan
-Dec 08 19:28:59 1: (21356) handle_connect: sending 64 byte challenge
-Dec 08 19:28:59 2: (21356) handle_connect: good auth for maan (1081806111)
-Dec 08 19:28:59 1: (21356) init_rc4_keys: rc4 keys initialized (84:105)
-Dec 08 19:28:59 2: (21356) enable_crypt: rc4 encryption activated for fd 10
-Dec 08 19:28:59 3: (21356) handle_connect: invalid command
-Dec 08 19:28:59 1: (21286) para_next_signal: next signal: 17
-Dec 08 19:28:59 1: (21286) para_reap_child: child 21356 exited. Exit status: 1
-Dec 08 19:28:59 1: (21286) chk_barrier: autoplay_delay barrier: 13498ms left
-Dec 08 19:29:03 2: (21286) main: got connection from ::ffff:127.0.0.1#42345, forking
-Dec 08 19:29:03 1: (21362) close_listed_fds: closing fd 9
-Dec 08 19:29:03 1: (21362) close_listed_fds: closing fd 8
-Dec 08 19:29:03 1: (21362) close_listed_fds: closing fd 6
-Dec 08 19:29:03 1: (21362) close_listed_fds: closing fd 5
-Dec 08 19:29:03 1: (21362) close_listed_fds: closing fd 4
-Dec 08 19:29:03 1: (21286) chk_barrier: autoplay_delay barrier: 9951ms left
-Dec 08 19:29:03 1: (21362) handle_connect: received rc4 request for user maan
-Dec 08 19:29:03 1: (21362) handle_connect: sending 64 byte challenge
-Dec 08 19:29:03 2: (21362) handle_connect: good auth for maan (705434988)
-Dec 08 19:29:03 1: (21362) init_rc4_keys: rc4 keys initialized (18:65)
-Dec 08 19:29:03 2: (21362) enable_crypt: rc4 encryption activated for fd 10
-Dec 08 19:29:03 1: (21362) check_perms: checking permissions
-Dec 08 19:29:03 3: (21362) handle_connect: calling com_stat() for maan@::ffff:127.0.0.1#42345
-Dec 08 19:29:13 1: (21286) chk_barrier: autoplay_delay barrier: 3ms left
-Dec 08 19:29:13 1: (21286) vss_preselect: ready and playing, but no audio file
-Dec 08 19:29:13 3: (21286) vss_post_select: requesting new fd from afs
-Dec 08 19:29:13 1: (21287) execute_server_command: received: new
-Dec 08 19:29:13 3: (21287) open_next_audio_file: getting next audio file
-Dec 08 19:29:13 1: (21287) osl_open_disk_object: filename: /home/maan/.paraslash/afs_database/audio_files/7e078c9876ccabef154017c770e05195c85b5e4d/55/b5e38d467105bd88133cf5ded70e551e582593
-Dec 08 19:29:13 1: (21287) mmap_full_file: /home/maan/.paraslash/afs_database/audio_files/7e078c9876ccabef154017c770e05195c85b5e4d/55/b5e38d467105bd88133cf5ded70e551e582593: size 4532
-Dec 08 19:29:13 1: (21287) mmap_full_file: /home/mp3/checked/dvd_07/cd_46/The_G.U.L.P.__Scheiss_Krieg.ogg: size 5274482
-Dec 08 19:29:13 1: (21287) mood_update_audio_file: score: 6
-Dec 08 19:29:13 1: (21287) mood_update_audio_file: moving from rank 26 to 35%
-Dec 08 19:29:13 1: (21287) score_update: new score: 0, rank 9/26
-Dec 08 19:29:13 1: (21287) osl_update_object: updating column 1 of score
-Dec 08 19:29:13 1: (21287) score_update: new score: -65, rank 1/26
-Dec 08 19:29:13 1: (21287) osl_update_object: updating column 1 of score
-Dec 08 19:29:13 1: (21287) save_afd: size: 8932
-Dec 08 19:29:13 1: (21287) pass_afd: passing 8 bytes and fd 12
-Dec 08 19:29:13 1: (21286) recv_afs_result: fd: 10, code: 0, shmid: 28442631
-Dec 08 19:29:13 1: (21286) chk_barrier: data send barrier: 300ms left
-Dec 08 19:29:13 1: (21286) status_refresh: 1 events, forcing status update
-Dec 08 19:29:13 1: (21286) chk_barrier: data send barrier: 300ms left
-Dec 08 19:29:13 1: (21286) chk_barrier: data send barrier: 300ms left
-Dec 08 19:29:13 1: (21286) para_next_signal: next signal: 10
-Dec 08 19:29:13 1: (21286) chk_barrier: data send barrier: 300ms left
-Dec 08 19:29:13 3: (21286) dccp_post_select: connection from ::ffff:127.0.0.1#46539
-Dec 08 19:29:13 1: (21286) chk_barrier: data send barrier: 287ms left
-Dec 08 19:29:13 1: (21286) chk_barrier: data send barrier: 287ms left
-Dec 08 19:29:13 1: (21287) para_next_signal: next signal: 10
-Dec 08 19:29:13 1: (21286) status_refresh: 2 events, forcing status update
-Dec 08 19:29:13 1: (21286) para_next_signal: next signal: 10
-Dec 08 19:29:13 1: (21287) para_next_signal: next signal: 10
-Dec 08 19:29:14 1: (21286) cq_enqueue: 4446 bytes queued for 0x8072eb0
+Dec 29 02:12:57 (1) (16077) log_welcome: welcome to para_server git (Sun Dec 29 01:49:51 MET 2013)
+Dec 29 02:12:57 (0) (16077) populate_user_list: found entry for user maan
+Dec 29 02:12:57 (0) (16077) populate_user_list: found 4 perm entries
+Dec 29 02:12:57 (0) (16077) populate_user_list: found entry for user sshmaan
+Dec 29 02:12:57 (1) (16077) get_asymmetric_key: decoding public rsa-ssh key /home/maan/.ssh/id_rsa.pub
+Dec 29 02:12:57 (0) (16077) check_ssh_key_header: type: ssh-rsa, rlen: 7
+Dec 29 02:12:57 (0) (16077) read_bignum: bnsize: 3
+Dec 29 02:12:57 (0) (16077) read_bignum: bnsize: 257
+Dec 29 02:12:57 (0) (16077) populate_user_list: found 4 perm entries
+Dec 29 02:12:57 (0) (16077) populate_user_list: found entry for user install
+Dec 29 02:12:57 (3) (16077) populate_user_list: public key /home/maan/.paraslash/key.pub.install too short (64)
+Dec 29 02:12:57 (0) (16077) populate_user_list: found entry for user www
+Dec 29 02:12:57 (3) (16077) populate_user_list: public key /home/maan/.paraslash/key.pub.www too short (64)
+Dec 29 02:12:57 (0) (16077) populate_user_list: found entry for user maan@albrecht
+Dec 29 02:12:57 (0) (16077) populate_user_list: found 2 perm entries
+Dec 29 02:12:57 (2) (16077) server_init: initializing audio format handlers
+Dec 29 02:12:57 (1) (16077) afh_init: supported audio formats: mp3 wma ogg spx aac flac
+Dec 29 02:12:57 (2) (16077) afh_init: initializing mp3 handler
+Dec 29 02:12:57 (2) (16077) afh_init: initializing ogg handler
+Dec 29 02:12:57 (2) (16077) afh_init: initializing aac handler
+Dec 29 02:12:57 (2) (16077) afh_init: initializing wma handler
+Dec 29 02:12:57 (2) (16077) afh_init: initializing spx handler
+Dec 29 02:12:57 (2) (16077) afh_init: initializing flac handler
+Dec 29 02:12:57 (2) (16077) afh_init: initializing opus handler
+Dec 29 02:12:57 (0) (16077) para_sigaction: catching signal 10
+Dec 29 02:12:57 (0) (16077) para_block_signal: blocking signal 17
+Dec 29 02:12:57 (2) (16077) server_init: initializing the audio file selector
+Dec 29 02:12:57 (1) (16077) init_afs: afs_socket: 4, afs_socket_cookie: 3213854017
+Dec 29 02:12:57 (2) (16077) init_signal_task: setting up signal handling
+Dec 29 02:12:57 (0) (16077) para_sigaction: catching signal 2
+Dec 29 02:12:57 (0) (16077) para_sigaction: catching signal 15
+Dec 29 02:12:57 (0) (16078) para_sigaction: catching signal 13
+Dec 29 02:12:57 (0) (16077) para_sigaction: catching signal 1
+Dec 29 02:12:57 (0) (16077) para_sigaction: catching signal 17
+Dec 29 02:12:57 (0) (16077) para_sigaction: catching signal 13
+Dec 29 02:12:57 (1) (16077) register_task: registering signal task (0x807c3e4)
+Dec 29 02:12:57 (0) (16077) register_task: pre_select: 0x807c3e4
+Dec 29 02:12:57 (0) (16077) register_task: post_select: 0x807c3e8
+Dec 29 02:12:57 (0) (16077) para_unblock_signal: unblocking signal 17
+Dec 29 02:12:57 (2) (16077) server_init: initializing virtual streaming system
+Dec 29 02:12:57 (1) (16078) register_signal_task: signal pipe: fd 4
+Dec 29 02:12:57 (0) (16078) para_sigaction: catching signal 2
+Dec 29 02:12:57 (0) (16078) para_sigaction: catching signal 15
+Dec 29 02:12:57 (1) (16077) init_vss_task: announce timeval: 300ms
+Dec 29 02:12:57 (0) (16078) para_sigaction: catching signal 1
+Dec 29 02:12:57 (2) (16077) init_vss_task: initializing http sender
+Dec 29 02:12:57 (1) (16078) register_task: registering signal task (0x807cec4)
+Dec 29 02:12:57 (0) (16078) register_task: pre_select: 0x807cec4
+Dec 29 02:12:57 (1) (16077) acl_add_entry: adding 192.168.0.0/24 to access list
+Dec 29 02:12:57 (0) (16078) register_task: post_select: 0x807cec8
+Dec 29 02:12:57 (1) (16077) acl_add_entry: adding 127.0.0.1/32 to access list
+Dec 29 02:12:57 (1) (16078) get_database_dir: afs_database dir /home/maan/.paraslash/afs_database-0.4
+Dec 29 02:12:57 (2) (16078) open_afs_tables: opening 7 osl tables in /home/maan/.paraslash/afs_database-0.4
+Dec 29 02:12:57 (1) (16077) para_listen: listening on TCP port 8000, fd 7
+Dec 29 02:12:57 (2) (16077) init_vss_task: initializing dccp sender
+Dec 29 02:12:57 (1) (16077) para_listen: listening on DCCP port 8000, fd 8
+Dec 29 02:12:57 (2) (16077) init_vss_task: initializing udp sender
+Dec 29 02:12:57 (1) (16077) udp_com_add: adding to target list (224.0.1.38:8000)
+Dec 29 02:12:57 (1) (16077) udp_com_add: adding to target list (192.168.0.2:8000)
+Dec 29 02:12:57 (0) (16077) udp_send_init: udp sender init complete
+Dec 29 02:12:57 (1) (16077) register_task: registering vss task (0x807c65c)
+Dec 29 02:12:57 (0) (16077) register_task: pre_select: 0x807c65c
+Dec 29 02:12:57 (0) (16077) register_task: post_select: 0x807c660
+Dec 29 02:12:57 (2) (16077) init_server_command_task: initializing tcp command socket
+Dec 29 02:12:57 (1) (16077) para_listen: listening on TCP port 2990, fd 11
+Dec 29 02:12:57 (1) (16077) register_task: registering server command task (0x807c2c0)
+Dec 29 02:12:57 (0) (16077) register_task: pre_select: 0x807c2c0
+Dec 29 02:12:57 (0) (16077) register_task: post_select: 0x807c2c4
+Dec 29 02:12:57 (2) (16077) server_init: server init complete
+Dec 29 02:12:57 (0) (16077) status_refresh: 0 events, forcing status update
+Dec 29 02:12:57 (1) (16078) aft_open: audio file table contains 9212 files
+Dec 29 02:12:57 (1) (16078) afs_init: server_socket: 5, afs_socket_cookie: 3213854017
+Dec 29 02:12:57 (0) (16078) parse_mood_line: accept entry added, method: 0x806fdac
+Dec 29 02:12:57 (2) (16078) change_current_mood: computing statistics of admissible files
+Dec 29 02:12:57 (1) (16078) log_statistics: last_played mean: 1385279255, last_played sigma: 2805987
+Dec 29 02:12:57 (1) (16078) log_statistics: num_played mean: 48, num_played sigma: 18
+Dec 29 02:12:57 (1) (16078) change_current_mood: 26 admissible files
+Dec 29 02:12:57 (2) (16078) change_current_mood: loaded mood gulp
+Dec 29 02:12:57 (1) (16078) setup_command_socket_or_die: listening on socket /var/paraslash/afs_command_socket-0.4 (fd 7)
+Dec 29 02:12:57 (1) (16078) register_task: registering afs command task (0x807cfec)
+Dec 29 02:12:57 (0) (16078) register_task: pre_select: 0x807cfec
+Dec 29 02:12:57 (0) (16078) register_task: post_select: 0x807cff0
+Dec 29 02:12:57 (1) (16077) command_post_select: got connection from 192.168.0.4:60731, forking
+Dec 29 02:12:57 (0) (16079) close_listed_fds: closing fd 11
+Dec 29 02:12:57 (0) (16079) close_listed_fds: closing fd 10
+Dec 29 02:12:57 (0) (16079) close_listed_fds: closing fd 9
+Dec 29 02:12:57 (0) (16079) close_listed_fds: closing fd 8
+Dec 29 02:12:57 (0) (16079) close_listed_fds: closing fd 7
+Dec 29 02:12:57 (0) (16079) close_listed_fds: closing fd 5
+Dec 29 02:12:57 (0) (16079) close_listed_fds: closing fd 4
+Dec 29 02:12:57 (0) (16079) para_sigaction: catching signal 17
+Dec 29 02:12:57 (0) (16079) para_sigaction: catching signal 2
+Dec 29 02:12:57 (0) (16079) para_sigaction: catching signal 15
+Dec 29 02:12:57 (0) (16079) para_sigaction: catching signal 1
+Dec 29 02:12:57 (0) (16079) parse_auth_request: received auth request for user maan
+Dec 29 02:12:57 (0) (16079) handle_connect: received auth request for user maan
+Dec 29 02:12:57 (0) (16079) handle_connect: sending 64 byte challenge + rc4 keys (256 bytes)
+Dec 29 02:12:57 (0) (16079) handle_connect: received 20 bytes challenge response
+Dec 29 02:12:57 (1) (16079) handle_connect: good auth for maan
+Dec 29 02:12:57 (0) (16079) check_perms: checking permissions
+Dec 29 02:12:57 (2) (16079) handle_connect: calling com_stat() for maan@192.168.0.4:60731
+Dec 29 02:12:57 (0) (16079) para_sigaction: catching signal 10
+Dec 29 02:13:02 (1) (16077) command_post_select: got connection from 192.168.0.1:58527, forking
+Dec 29 02:13:02 (0) (16080) close_listed_fds: closing fd 11
+Dec 29 02:13:02 (0) (16080) close_listed_fds: closing fd 10
+Dec 29 02:13:02 (0) (16080) close_listed_fds: closing fd 9
+Dec 29 02:13:02 (0) (16080) close_listed_fds: closing fd 8
+Dec 29 02:13:02 (0) (16080) close_listed_fds: closing fd 7
+Dec 29 02:13:02 (0) (16080) close_listed_fds: closing fd 5
+Dec 29 02:13:02 (0) (16080) close_listed_fds: closing fd 4
+Dec 29 02:13:02 (0) (16080) para_sigaction: catching signal 17
+Dec 29 02:13:02 (0) (16080) para_sigaction: catching signal 2
+Dec 29 02:13:02 (0) (16080) para_sigaction: catching signal 15
+Dec 29 02:13:02 (0) (16080) para_sigaction: catching signal 1
+Dec 29 02:13:02 (0) (16080) parse_auth_request: received auth request for user maan
+Dec 29 02:13:02 (0) (16080) handle_connect: received auth request for user maan
+Dec 29 02:13:02 (0) (16080) handle_connect: sending 64 byte challenge + rc4 keys (256 bytes)
+Dec 29 02:13:02 (0) (16080) handle_connect: received 20 bytes challenge response
+Dec 29 02:13:02 (1) (16080) handle_connect: good auth for maan
+Dec 29 02:13:02 (0) (16080) check_perms: checking permissions
+Dec 29 02:13:02 (2) (16080) handle_connect: calling com_stat() for maan@192.168.0.1:58527
+Dec 29 02:13:02 (0) (16080) para_sigaction: catching signal 10
+Dec 29 02:13:09 (1) (16077) command_post_select: got connection from 192.168.0.1:58528, forking
+Dec 29 02:13:09 (0) (16089) close_listed_fds: closing fd 11
+Dec 29 02:13:09 (0) (16089) close_listed_fds: closing fd 10
+Dec 29 02:13:09 (0) (16089) close_listed_fds: closing fd 9
+Dec 29 02:13:09 (0) (16089) close_listed_fds: closing fd 8
+Dec 29 02:13:09 (0) (16089) close_listed_fds: closing fd 7
+Dec 29 02:13:09 (0) (16089) close_listed_fds: closing fd 5
+Dec 29 02:13:09 (0) (16089) close_listed_fds: closing fd 4
+Dec 29 02:13:09 (0) (16089) para_sigaction: catching signal 17
+Dec 29 02:13:09 (0) (16089) para_sigaction: catching signal 2
+Dec 29 02:13:09 (0) (16089) para_sigaction: catching signal 15
+Dec 29 02:13:09 (0) (16089) para_sigaction: catching signal 1
+Dec 29 02:13:09 (0) (16089) parse_auth_request: received auth request for user maan
+Dec 29 02:13:09 (0) (16089) handle_connect: received auth request for user maan
+Dec 29 02:13:09 (0) (16089) handle_connect: sending 64 byte challenge + rc4 keys (256 bytes)
+Dec 29 02:13:09 (0) (16089) handle_connect: received 20 bytes challenge response
+Dec 29 02:13:09 (1) (16089) handle_connect: good auth for maan
+Dec 29 02:13:09 (0) (16089) check_perms: checking permissions
+Dec 29 02:13:09 (2) (16089) handle_connect: calling com_play() for maan@192.168.0.1:58528
+Dec 29 02:13:09 (0) (16077) para_next_signal: next signal: 17
+Dec 29 02:13:09 (0) (16077) para_reap_child: child 16089 exited. Exit status: 0
+Dec 29 02:13:09 (0) (16077) vss_pre_select: ready and playing, but no audio file
+Dec 29 02:13:09 (0) (16077) status_refresh: 1 events, forcing status update
+Dec 29 02:13:09 (2) (16077) vss_post_select: requesting new fd from afs
+Dec 29 02:13:09 (2) (16078) open_next_audio_file: getting next audio file
+Dec 29 02:13:09 (2) (16078) open_and_update_audio_file: /home/mp3/checked/dvd_07/cd_45/The_G.U.L.P.__Popstar.ogg
+Dec 29 02:13:09 (1) (16078) shm_get_shmmax: shmmax: 33554432
+Dec 29 02:13:09 (0) (16078) mood_update_audio_file: score: -11
+Dec 29 02:13:09 (0) (16078) mood_update_audio_file: moving from rank 26 to 29%
+Dec 29 02:13:09 (0) (16078) score_update: new score: -13, rank 8/26
+Dec 29 02:13:09 (0) (16078) score_update: new score: -67, rank 1/26
+Dec 29 02:13:09 (0) (16078) pass_afd: passing 8 bytes and fd 8
+Dec 29 02:13:09 (0) (16077) recv_afs_result: fd: 12, code: 0, shmid: 121700353
+Dec 29 02:13:09 (0) (16077) vorbis_get_header_callback: processing ogg packet #0
+Dec 29 02:13:09 (0) (16077) add_ogg_page: header/body/old/new: 28/30/0/58
+Dec 29 02:13:09 (1) (16077) process_packets_2_and_3: ogg page serial: 867600341
+Dec 29 02:13:09 (0) (16077) vorbis_get_header_callback: processing ogg packet #1
+Dec 29 02:13:09 (1) (16077) vorbis_get_header_callback: replacing metadata packet
+Dec 29 02:13:09 (1) (16077) process_packets_2_and_3: ogg page serial: 867600341
+Dec 29 02:13:09 (0) (16077) vorbis_get_header_callback: processing ogg packet #2
+Dec 29 02:13:09 (0) (16077) add_ogg_page: header/body/old/new: 45/4247/58/4350
+Dec 29 02:13:09 (1) (16077) vorbis_get_header: created 4350 byte ogg vorbis header
+Dec 29 02:13:09 (0) (16077) chk_barrier: data send barrier: 203ms left
+Dec 29 02:13:09 (0) (16077) status_refresh: 2 events, forcing status update
+Dec 29 02:13:09 (0) (16079) connect_local_socket: connecting to /var/paraslash/afs_command_socket-0.4
+Dec 29 02:13:09 (0) (16080) connect_local_socket: connecting to /var/paraslash/afs_command_socket-0.4
+Dec 29 02:13:09 (2) (16077) udp_init_session: sending to udp 192.168.0.2:8000
+Dec 29 02:13:09 (1) (16077) udp_init_fec: current MPS = 548 bytes
+Dec 29 02:13:09 (1) (16077) initialize_fec_client: mps: 548, k: 26, n: 28, extra slices: 12
+Dec 29 02:13:09 (0) (16077) set_group_timing: durations (group/chunk/slice): 226/226/8
+Dec 29 02:13:09 (0) (16077) setup_next_fec_group: FEC group 0: 1 chunks (0 - 0), 4350 bytes
+Dec 29 02:13:09 (0) (16077) setup_next_fec_group: slice_bytes: 168, 0 header slices, 26 data slices
+Dec 29 02:13:09 (0) (16077) vss_send: sending 0:0 (168 bytes)
+Dec 29 02:13:09 (2) (16077) udp_init_session: sending to udp 224.0.1.38:8000
+Dec 29 02:13:09 (1) (16077) udp_init_fec: current MPS = 548 bytes
+Dec 29 02:13:09 (1) (16077) initialize_fec_client: mps: 548, k: 26, n: 27, extra slices: 24
+Dec 29 02:13:09 (0) (16077) set_group_timing: durations (group/chunk/slice): 226/226/8
+Dec 29 02:13:09 (0) (16077) setup_next_fec_group: FEC group 0: 1 chunks (0 - 0), 4350 bytes
+Dec 29 02:13:09 (0) (16077) setup_next_fec_group: slice_bytes: 168, 0 header slices, 26 data slices
+Dec 29 02:13:09 (0) (16077) vss_send: sending 0:0 (168 bytes)
+Dec 29 02:13:09 (0) (16077) status_refresh: 3 events, forcing status update
+Dec 29 02:13:09 (0) (16079) connect_local_socket: connecting to /var/paraslash/afs_command_socket-0.4
+Dec 29 02:13:09 (0) (16080) connect_local_socket: connecting to /var/paraslash/afs_command_socket-0.4
+Dec 29 02:13:09 (0) (16077) vss_send: sending 0:1 (168 bytes)
+Dec 29 02:13:09 (0) (16077) vss_send: sending 0:1 (168 bytes)
+Dec 29 02:13:09 (0) (16077) vss_send: sending 0:2 (168 bytes)
+Dec 29 02:13:09 (0) (16077) vss_send: sending 0:2 (168 bytes)
+Dec 29 02:13:09 (0) (16077) vss_send: sending 0:3 (168 bytes)
diff --git a/wma.h b/wma.h
index f0ba7f631703b35878606facde8f2980de621bce..15b9c5d492560f2c6532935460cc7ca4f38ca571 100644 (file)
--- a/wma.h
+++ b/wma.h
@@ -20,8 +20,14 @@ struct asf_header_info {
        uint32_t bit_rate;
        /** Further decoding information (ignored). */
        uint32_t flags1;
-       /** Whether to use exp_vlc, bit reservoir, variable block len. */
+       /** Encodes exp_vlc, bit reservoir, vbl, number of block sizes. */
        uint16_t flags2;
+       /** Whether exponents are coded with VLC codes. */
+       bool use_exp_vlc;
+       /** If false, a frame is equal to a superframe. */
+       bool use_bit_reservoir;
+       /** Whether blocks are of variable or of constant size. */
+       bool use_variable_block_len;
 };
 
 /* wma_common.c */
index 207b0ba8cae25c024172023d58d3691e7c4f5e9b..65795fd8b8e4ac66cc1e3cf1cba8e18d68800636 100644 (file)
--- a/wma_afh.c
+++ b/wma_afh.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2009-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -132,7 +132,7 @@ static const char album_tag_header[] = { /* WM/AlbumTitle */
 static void read_asf_tags(const char *buf, int buf_size, struct taginfo *ti)
 {
        const char *p, *end = buf + buf_size, *q;
-       uint16_t len1, len2, len3, len4, len5;
+       uint16_t len1, len2, len3, len4;
 
        p = search_pattern(comment_header, sizeof(comment_header),
                buf, buf_size);
@@ -149,7 +149,7 @@ static void read_asf_tags(const char *buf, int buf_size, struct taginfo *ti)
        p += 2;
        len4 = read_u16(p);
        p += 2;
-       len5 = read_u16(p);
+       /* ignore length of the rating information */
        p += 2;
        if (p + len1 >= end)
                goto next;
@@ -158,10 +158,10 @@ static void read_asf_tags(const char *buf, int buf_size, struct taginfo *ti)
        if (p + len2 >= end)
                goto next;
        ti->artist = get_str16(p, len2);
-       p += len2 + len3 + len4;
-       if (p + len5 >= end)
+       p += len2 + len3;
+       if (p + len4 >= end)
                goto next;
-       ti->comment = get_str16(p, len5);
+       ti->comment = get_str16(p, len4);
 next:
        p = search_pattern(extended_content_header, sizeof(extended_content_header),
                buf, buf_size);
@@ -257,6 +257,15 @@ static int wma_get_file_info(char *map, size_t numbytes, __a_unused int fd,
        afhi->frequency = ahi.sample_rate;
        afhi->channels = ahi.channels;
        afhi->header_len = ahi.header_len;
+
+       afhi->techinfo = make_message("%s%s%s%s%s",
+               ahi.use_exp_vlc? "exp vlc" : "",
+               (ahi.use_bit_reservoir && ahi.use_exp_vlc)? ", " : "",
+               ahi.use_bit_reservoir? "bit reservoir" : "",
+               (ahi.use_variable_block_len &&
+                       (ahi.use_exp_vlc || ahi.use_bit_reservoir)? ", " : ""),
+               ahi.use_variable_block_len? "vbl" : ""
+       );
        wma_make_chunk_table(map + ahi.header_len, numbytes - ahi.header_len,
                ahi.block_align, afhi);
        read_asf_tags(map, ahi.header_len, &afhi->tags);
index b101d0a6e88e921d814e630113d59a263a657fd1..e53cdf5e400aca8f7552052a5586a4e4d5a04bfe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2009-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -115,6 +115,9 @@ int read_asf_header(const char *buf, int loaded, struct asf_header_info *ahi)
        ahi->flags2 = read_u16(start + 60);
        PARA_INFO_LOG("read_asf_header: flags1: %d, flag2: %d\n",
                ahi->flags1, ahi->flags2);
+       ahi->use_exp_vlc = ahi->flags2 & 0x0001;
+       ahi->use_bit_reservoir = ahi->flags2 & 0x0002;
+       ahi->use_variable_block_len = ahi->flags2 & 0x0004;
        return 1;
 }
 
index 8b751f04592eff0f7d6b3e5fe73ade1938c17382..188b0a416cf9ad587b5de922a2b7912c1101ece0 100644 (file)
@@ -62,17 +62,11 @@ struct private_wmadec_data {
        /** Information contained in the audio file header. */
        struct asf_header_info ahi;
        struct getbit_context gb;
-       /** Whether to use the bit reservoir. */
-       int use_bit_reservoir;
-       /** Whether to use variable block length. */
-       int use_variable_block_len;
-       /** Whether to use exponent coding. */
-       int use_exp_vlc;
        /** Whether perceptual noise is added. */
        int use_noise_coding;
        /** Depends on number of the bits per second and the frame length. */
        int byte_offset_bits;
-       /** Only used if use_exp_vlc is true. */
+       /** Only used if ahi->use_exp_vlc is true. */
        struct vlc exp_vlc;
        uint16_t exponent_bands[BLOCK_NB_SIZES][25];
        /** The index of the first coef in high band. */
@@ -96,7 +90,7 @@ struct private_wmadec_data {
        int frame_len;
        /** log2 of frame_len. */
        int frame_len_bits;
-       /** Number of block sizes. */
+       /** Number of block sizes, one if !ahi->use_variable_block_len. */
        int nb_block_sizes;
        /* block info */
        int reset_block_lengths;
@@ -149,6 +143,8 @@ struct private_wmadec_data {
 #define VLCBITS 9
 #define VLCMAX DIV_ROUND_UP(22, VLCBITS)
 
+/** \cond sine_winows */
+
 #define SINE_WINDOW(x) static float sine_ ## x[x] __a_aligned(16)
 
 SINE_WINDOW(128);
@@ -161,6 +157,7 @@ SINE_WINDOW(4096);
 static float *sine_windows[6] = {
        sine_128, sine_256, sine_512, sine_1024, sine_2048, sine_4096
 };
+/** \endcond sine_windows */
 
 /* Generate a sine window. */
 static void sine_window_init(float *window, int n)
@@ -177,7 +174,7 @@ static void wmadec_cleanup(struct private_wmadec_data *pwd)
 
        for (i = 0; i < pwd->nb_block_sizes; i++)
                imdct_end(pwd->mdct_ctx[i]);
-       if (pwd->use_exp_vlc)
+       if (pwd->ahi.use_exp_vlc)
                free_vlc(&pwd->exp_vlc);
        if (pwd->use_noise_coding)
                free_vlc(&pwd->hgain_vlc);
@@ -311,7 +308,7 @@ static int wma_init(struct private_wmadec_data *pwd)
        else
                pwd->frame_len_bits = 11;
        pwd->frame_len = 1 << pwd->frame_len_bits;
-       if (pwd->use_variable_block_len) {
+       if (pwd->ahi.use_variable_block_len) {
                int nb_max, nb;
                nb = ((flags2 >> 3) & 3) + 1;
                if ((ahi->bit_rate / ahi->channels) >= 32000)
@@ -392,7 +389,7 @@ static int wma_init(struct private_wmadec_data *pwd)
                pwd->frame_len, bps, bps1,
                high_freq, pwd->byte_offset_bits);
        PARA_INFO_LOG("use_noise_coding=%d use_exp_vlc=%d nb_block_sizes=%d\n",
-               pwd->use_noise_coding, pwd->use_exp_vlc, pwd->nb_block_sizes);
+               pwd->use_noise_coding, pwd->ahi.use_exp_vlc, pwd->nb_block_sizes);
 
        compute_scale_factor_band_sizes(pwd, high_freq);
        /* init MDCT windows : simple sinus window */
@@ -407,7 +404,7 @@ static int wma_init(struct private_wmadec_data *pwd)
 
        if (pwd->use_noise_coding) {
                /* init the noise generator */
-               if (pwd->use_exp_vlc)
+               if (pwd->ahi.use_exp_vlc)
                        pwd->noise_mult = 0.02;
                else
                        pwd->noise_mult = 0.04;
@@ -481,10 +478,6 @@ static int wma_decode_init(char *initial_buf, int len, struct private_wmadec_dat
                return ret;
        }
 
-       pwd->use_exp_vlc = pwd->ahi.flags2 & 0x0001;
-       pwd->use_bit_reservoir = pwd->ahi.flags2 & 0x0002;
-       pwd->use_variable_block_len = pwd->ahi.flags2 & 0x0004;
-
        ret = wma_init(pwd);
        if (ret < 0)
                return ret;
@@ -501,7 +494,7 @@ static int wma_decode_init(char *initial_buf, int len, struct private_wmadec_dat
                        wma_hgain_huffcodes, 2);
        }
 
-       if (pwd->use_exp_vlc) {
+       if (pwd->ahi.use_exp_vlc) {
                PARA_INFO_LOG("using exp_vlc\n");
                init_vlc(&pwd->exp_vlc, EXPVLCBITS, sizeof(wma_scale_huffbits),
                        wma_scale_huffbits, wma_scale_huffcodes, 4);
@@ -847,7 +840,7 @@ static int wma_decode_block(struct private_wmadec_data *pwd)
        int nb_coefs[MAX_CHANNELS];
 
        /* compute current block length */
-       if (pwd->use_variable_block_len) {
+       if (pwd->ahi.use_variable_block_len) {
                n = wma_log2(pwd->nb_block_sizes - 1) + 1;
 
                if (pwd->reset_block_lengths) {
@@ -924,7 +917,7 @@ static int wma_decode_block(struct private_wmadec_data *pwd)
        if ((pwd->block_len_bits == pwd->frame_len_bits) || get_bit(&pwd->gb)) {
                for (ch = 0; ch < pwd->ahi.channels; ch++) {
                        if (pwd->channel_coded[ch]) {
-                               if (pwd->use_exp_vlc) {
+                               if (pwd->ahi.use_exp_vlc) {
                                        ret = decode_exp_vlc(pwd, ch);
                                        if (ret < 0)
                                                return ret;
@@ -1093,7 +1086,7 @@ static int wma_decode_superframe(struct private_wmadec_data *pwd, void *data,
        buf_size = pwd->ahi.block_align;
        samples = data;
        init_get_bits(&pwd->gb, buf, buf_size);
-       if (pwd->use_bit_reservoir) {
+       if (pwd->ahi.use_bit_reservoir) {
                int i, nb_frames, bit_offset, pos, len;
                uint8_t *q;
 
@@ -1210,9 +1203,9 @@ static int wmadec_execute(struct btr_node *btrn, const char *cmd, char **result)
 
 #define WMA_OUTPUT_BUFFER_SIZE (128 * 1024)
 
-static int wmadec_post_select(__a_unused struct sched *s, struct task *t)
+static int wmadec_post_select(__a_unused struct sched *s, void *context)
 {
-       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct filter_node *fn = context;
        int ret, converted, out_size;
        struct private_wmadec_data *pwd = fn->private_data;
        struct btr_node *btrn = fn->btrn;
diff --git a/write.c b/write.c
index 6799db4175282b779c2fd454d11988be31b933d8..eaf56f413412bbd6420767d59803bda7ab0bcb71 100644 (file)
--- a/write.c
+++ b/write.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -71,19 +71,19 @@ static void setup_writer_node(const char *arg, struct btr_node *parent,
 }
 
 struct write_task {
-       struct task task;
+       struct task *task;
        struct check_wav_context *cwc;
 };
 
-static void write_pre_select(struct sched *s, struct task *t)
+static void write_pre_select(struct sched *s, void *context)
 {
-       struct write_task *wt = container_of(t, struct write_task, task);
+       struct write_task *wt = context;
        check_wav_pre_select(s, wt->cwc);
 }
 
-static int write_post_select(__a_unused struct sched *s, struct task *t)
+static int write_post_select(__a_unused struct sched *s, void *context)
 {
-       struct write_task *wt = container_of(t, struct write_task, task);
+       struct write_task *wt = context;
        return check_wav_post_select(wt->cwc);
 }
 
@@ -94,22 +94,20 @@ static int setup_and_schedule(void)
        struct writer_node *wns;
        static struct sched s;
        struct wav_params wp;
-       struct write_task wt = {
-               .task = {
-                       .pre_select = write_pre_select,
-                       .post_select = write_post_select,
-                       .status = "write task",
-               },
-       };
+       struct write_task wt;
 
        sit.btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.name = "stdin"));
-       stdin_set_defaults(&sit);
-       register_task(&s, &sit.task);
+       stdin_task_register(&sit, &s);
 
        COPY_WAV_PARMS(&wp, &conf);
        wt.cwc = check_wav_init(sit.btrn, NULL, &wp, &cw_btrn);
-       register_task(&s, &wt.task);
+       wt.task = task_register(&(struct task_info) {
+               .name = "write",
+               .pre_select = write_pre_select,
+               .post_select = write_post_select,
+               .context = &wt,
+       }, &s);
        if (!conf.writer_given) {
                wns = para_calloc(sizeof(*wns));
                setup_writer_node(NULL, cw_btrn, wns, &s);
@@ -125,16 +123,17 @@ static int setup_and_schedule(void)
        s.default_timeout.tv_usec = 50000;
        ret = schedule(&s);
        if (ret >= 0) {
-               int j;
+               int j, ts;
                for (j = 0; j < i; j++) {
-                       struct task *t = &wns[j].task;
-                       assert(t->error < 0);
-                       if (t->error != -E_WRITE_COMMON_EOF
-                                       && t->error != -E_BTR_EOF) {
-                               PARA_ERROR_LOG("%s: %s\n", t->status,
-                                       para_strerror(-t->error));
+                       struct writer_node *wn = wns + j;
+                       ts = task_status(wn->task);
+                       assert(ts < 0);
+                       if (ts != -E_WRITE_COMMON_EOF && ts != -E_BTR_EOF) {
+                               const char *name = writer_names[wn->writer_num];
+                               PARA_ERROR_LOG("%s: %s\n", name,
+                                       para_strerror(-ts));
                                if (ret >= 0)
-                                       ret = t->error;
+                                       ret = ts;
                        }
                }
        }
@@ -149,6 +148,7 @@ static int setup_and_schedule(void)
        }
        free(wns);
        check_wav_shutdown(wt.cwc);
+       sched_shutdown(&s);
        return ret;
 }
 
diff --git a/write.h b/write.h
index 829216088c3c2ae16f1be035bd75a490e1989076..cb73498881d1fb2d32e5d259d0bd21fd4227d8f4 100644 (file)
--- a/write.h
+++ b/write.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -22,7 +22,7 @@ struct writer_node {
        /** The buffer tree node associated with this writer node. */
        struct btr_node *btrn;
        /** The task of this writer node. */
-       struct task task;
+       struct task *task;
        /** The minimal input queue size (size of one audio sample). */
        size_t min_iqs;
 };
@@ -59,13 +59,13 @@ struct writer {
         * This is called from scheduler. It may use the sched pointer to add
         * any file descriptors or to decrease the select timeout.
         */
-       void (*pre_select)(struct sched *s, struct task *t);
+       void (*pre_select)(struct sched *s, void *context);
        /**
         * Write audio data.
         *
         * Called from the post_select function of the writer node's task.
         */
-       int (*post_select)(struct sched *s, struct task *t);
+       int (*post_select)(struct sched *s, void *context);
        /**
         * Close one instance of the writer.
         *
index 33ef8be60d0a5fa04e2acd4d21f9b9ad7fc75d2a..4c5ef4bca5f6e7975348c74ddd83a4bcb6ebdb33 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -16,6 +16,7 @@
 #include "buffer_tree.h"
 #include "write.h"
 #include "error.h"
+#include "write_common.h"
 
 /** the array containing the names of all supported writers */
 const char *writer_names[] ={WRITER_NAMES};
@@ -106,16 +107,16 @@ void register_writer_node(struct writer_node *wn, struct btr_node *parent,
                struct sched *s)
 {
        struct writer *w = writers + wn->writer_num;
-       char *name = make_message("%s writer", writer_names[wn->writer_num]);
 
        wn->btrn = btr_new_node(&(struct btr_node_description)
-               EMBRACE(.name = name, .parent = parent,
+               EMBRACE(.name = writer_names[wn->writer_num], .parent = parent,
                .handler = w->execute, .context = wn));
-       strcpy(wn->task.status, name);
-       free(name);
-       wn->task.pre_select = w->pre_select;
-       wn->task.post_select = w->post_select;
-       register_task(s, &wn->task);
+       wn->task = task_register(&(struct task_info) {
+               .name = writer_names[wn->writer_num],
+               .pre_select = w->pre_select,
+               .post_select = w->post_select,
+               .context = wn,
+       }, s);
 }
 
 /**
index ecad2d18eb2fe37b9e9d39691238b9acefebb3a2..e0351602f2331da0913fa826f9d800663e3b9b92 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2014 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */