Merge ../paraslash.meins/paraslash
authorAndre Noll <maan@systemlinux.org>
Mon, 29 Jan 2007 08:56:07 +0000 (09:56 +0100)
committerAndre Noll <maan@systemlinux.org>
Mon, 29 Jan 2007 08:56:07 +0000 (09:56 +0100)
17 files changed:
Makefile.in
NEWS
audiod.cmd [new file with mode: 0644]
audiod.h
audiod_command.c
command.c
command_util.sh [new file with mode: 0755]
configure.ac
mysql_selector.c
mysql_selector.cmd [new file with mode: 0644]
playlist_selector.c
playlist_selector.cmd [new file with mode: 0644]
random_selector.c
random_selector.cmd [new file with mode: 0644]
server.cmd [new file with mode: 0644]
server.h
web/documentation.in.html

index d7e2856..cf1a9a6 100644 (file)
@@ -1,4 +1,4 @@
-COPYRIGHT = Copyright (c) 1997-2006 by Andre Noll
+COPYRIGHT = Copyright (c) 1997-2007 by Andre Noll
 DISCLAIMER = This is free software with ABSOLUTELY NO WARRANTY. See COPYING for details.
 
 prefix = @prefix@
@@ -19,14 +19,10 @@ cc_version = $(shell $(CC) --version | head -n 1)
 codename = inductive resonance
 
 DEBUG_CPPFLAGS += -Wno-sign-compare -g -Wunused -Wundef -W
-
 DEBUG_CPPFLAGS += -Wredundant-decls
-
 # produces false positives
 # DEBUG_CPPFLAGS += -Wunreachable-code
-
 #CPPFLAGS += -Wwrite-strings
-
 # invalid option for gcc-3.3.5
 # CPPFLAGS += -Wextra
 
@@ -48,18 +44,20 @@ CPPFLAGS += -Wmissing-format-attribute
 CPPFLAGS += -Wunused-macros
 CPPFLAGS += -Wshadow
 
-BINARIES = para_server para_client para_gui para_audioc para_recv para_filter para_write @extra_binaries@
-
+BINARIES = para_server para_client para_gui para_audioc para_recv \
+       para_filter para_write @extra_binaries@
+man_binaries := para_server para_client para_gui para_audioc para_recv \
+        para_filter para_write  para_fade para_sdl_gui para_audiod
+man_pages := $(patsubst %, man/man1/%.1, $(man_binaries))
+man_pages_html := $(patsubst %, man/html/%.html, $(man_binaries))
 FONTS := $(wildcard fonts/*.png)
 PICS := $(wildcard pics/paraslash/*.jpg)
-MANS := $(wildcard doc/man/man1/*.1)
 gengetopts := $(wildcard *.ggo)
 gengetopts_c := $(gengetopts:.ggo=.cmdline.c)
 gengetopts_h := $(gengetopts:.ggo=.cmdline.h)
 all_c_files := $(wildcard *.c)
 c_sources := $(filter-out $(gengetopts_c), $(all_c_files))
-grutatxt := COPYING NEWS README.mysql CREDITS INSTALL README \
-       FEATURES GPL
+grutatxt := COPYING NEWS README.mysql CREDITS INSTALL README FEATURES GPL
 grutatxt_html := $(grutatxt:=.html)
 html_in := $(wildcard web/*.in.html)
 gen_html := $(subst web/,web/sync/,$(html_in))
@@ -68,28 +66,30 @@ gruta_in := $(grutatxt:=.in.html)
 gruta_in := $(patsubst %,web/%,$(gruta_in))
 gruta_html := $(grutatxt:=.html)
 gruta_html := $(patsubst %,web/sync/%,$(gruta_html))
-shots := gui-2005-11-12.png para_audiod-startup.txt
-shots += para_krell-2005-02.png para_server-startup.txt
-shots += para_slider-2004-12.png sdl_gui.jpg para_krell-2005-02.png
+shots := gui-2005-11-12.png para_audiod-startup.txt para_krell-2005-02.png \
+       para_server-startup.txt para_slider-2004-12.png sdl_gui.jpg \
+       para_krell-2005-02.png
 shots := $(patsubst %,web/sync/%,$(shots))
 web_pics := web/sync/paraslash.png web/sync/paraslash.ico
-web_misc := overview.pdf versions/paraslash-git.tar.bz2 PUBLIC_KEY key.anonymous para.css doc
+web_misc := overview.pdf versions/paraslash-git.tar.bz2 PUBLIC_KEY \
+       key.anonymous para.css
 web_misc := $(patsubst %,web/sync/%,$(web_misc))
-
+web_man := web/sync/man
 autocrap := config.h.in configure
-
 tarball_pfx := @PACKAGE_TARNAME@-@PACKAGE_VERSION@
-
 tarball_delete = web versions pics/screenshots pics/web .changelog_before_cvs \
        .changelog_cvs
 tarball_delete := $(patsubst %,$(tarball_pfx)/%,$(tarball_delete))
 tarball_add := $(gengetopts_c) $(gengetopts_h) $(autocrap)
 
-.PHONY: clean distclean maintainer-clean install html www tags ChangeLog doxygen gruta
+.PHONY: clean distclean maintainer-clean install html www tags doxygen gruta \
+       man html_man
 all: $(BINARIES)
-www: $(gen_html) $(gruta_html) $(web_pics) $(web_misc) $(shots) tags doxygen doc
+www: $(gen_html) $(gruta_html) $(web_pics) $(web_misc) $(shots) $(web_man) \
+       tags doxygen
 gruta: $(gen_html) $(gruta_html)
-
+man: $(man_pages)
+html_man: $(man_pages_html)
 
 sdl_gui_objs = sdl_gui.cmdline.o SFont.o sdl_gui.o gui_common.o exec.o \
        close_on_fork.o string.o stat.o fd.o
@@ -102,7 +102,7 @@ slider_objs = slider.o string.o
 
 include Makefile.deps
 
-V := ($(TGZ_PREFIX)@PACKAGE_STRING@, $(codename))\n$(COPYRIGHT)\n$(DISCLAIMER)
+V := (@PACKAGE_STRING@, $(codename))\n$(COPYRIGHT)\n$(DISCLAIMER)
 module_ggo_opts := --set-version="(@PACKAGE_STRING@, $(codename))"
 
 grab_client.cmdline.h grab_client.cmdline.c: grab_client.ggo
@@ -148,6 +148,30 @@ grab_client.cmdline.h grab_client.cmdline.c: grab_client.ggo
                --set-package="para_$(subst .cmdline,,$(*F))" \
                --set-version="$V"  < $<
 
+%_command_list.c %_command_list.h: %.cmd
+       ./command_util.sh c < $< >$@
+       ./command_util.sh h < $< >$(@:%.c=%.h)
+
+%_command_list.man: %.cmd
+       ./command_util.sh man < $< > $@
+
+server_command_lists = server_command_list.man random_selector_command_list.man \
+       playlist_selector_command_list.man mysql_selector_command_list.man
+man/man1/para_server.1: para_server $(server_command_lists)
+       opts="-N `for i in $(server_command_lists); do echo "-i $$i"; done`"; \
+       help2man $$opts ./para_server > $@
+
+man/man1/para_audiod.1: para_audiod audiod_command_list.man
+       help2man -N -i audiod_command_list.man ./para_audiod > $@
+
+man/man1/%.1: %
+       help2man -N $< > $@
+
+man/html/%.html: man/man1/%.1
+       man2html $< > $@
+
+
+
 ortp_recv.o: ortp_recv.c
        $(CC) -c $(CPPFLAGS) $(DEBUG_CPPFLAGS) @ortp_cppflags@ $<
 
@@ -226,7 +250,6 @@ para_krell.so: $(krell_objs)
 
 clean:
        rm -f *.o $(BINARIES)
-
 distclean: clean
        rm -f Makefile autoscan.log config.status config.log && \
        rm -rf web/sync/* autom4te.cache aclocal.m4
@@ -234,52 +257,45 @@ distclean: clean
 
 maintainer-clean: distclean
        rm -f $(gengetopts_c) $(gengetopts_h) *.tar.bz2 \
-               $(grutatxt_html) ChangeLog* config.h configure \
+               $(grutatxt_html) config.h configure \
                config.h.in skencil/*.pdf skencil/*.ps
-       rm -rf doc
+       rm -f *_command_list.* *.man man/man1/* man/html/*
+
 
 install: all
-       umask 022 && \
-       mkdir -p $(BINDIR) && \
-       $(install_sh) -s -m 755 $(BINARIES) $(BINDIR) && \
-       mkdir -p $(FONTDIR) && \
-       $(install_sh) -m 644 $(FONTS) $(FONTDIR) && \
-       mkdir -p $(PICDIR) && \
-       $(install_sh) -m 644 $(PICS) $(PICDIR) && \
-       mkdir -p $(MANDIR) && \
-       $(install_sh) -m 644 $(MANS) $(MANDIR) \
-       mkdir -p $(VARDIR) > /dev/null 2>&1 || exit 0
-
-@PACKAGE_TARNAME@-@PACKAGE_VERSION@.tar.bz2: $(tarball_add) doc
-       rm -f $(tarball_pfx).tar.bz2
-       git-archive --format=tar --prefix=$(tarball_pfx)/ HEAD | tar --delete $(tarball_delete) > $(tarball_pfx).tar
+       mkdir -p $(BINDIR) $(FONTDIR) $(PICDIR) $(MANDIR) $(VARDIR)
+       $(install_sh) -s -m 755 $(BINARIES) $(BINDIR)
+       $(install_sh) -m 644 $(FONTS) $(FONTDIR)
+       $(install_sh) -m 644 $(PICS) $(PICDIR)
+       $(install_sh) -m 644 $(man_pages) $(MANDIR)
+
+@PACKAGE_TARNAME@-@PACKAGE_VERSION@.tar.bz2: $(tarball_add) $(man_pages)
+       rm -rf $(tarball_pfx).tar.bz2 $(tarball_pfx)
+       git-archive --format=tar --prefix=$(tarball_pfx)/ HEAD \
+               | tar --delete $(tarball_delete) > $(tarball_pfx).tar
        mkdir $(tarball_pfx)
        cp -r $(tarball_add) $(tarball_pfx)
-       tar c doc/man | (cd $(tarball_pfx); tar x)
+       mkdir -p $(tarball_pfx)/man/man1
+       cp -r $(man_pages) $(tarball_pfx)/man/man1
        tar rf $(tarball_pfx).tar $(tarball_pfx)/*
        rm -rf $(tarball_pfx)
        bzip2 -9 $(tarball_pfx).tar
        rm -f $(tarball_pfx).tar
        ls -l $(tarball_pfx).tar.bz2
 
-ChangeLog:
-       para_util changelog > $@
 web/%.in.html: %
        grutatxt -nb  < $< > $@
 tags:
        rm -rf web/sync/HTML && gtags && htags -nF && mv HTML web/sync
-doc:
-       para_util doc
 web/header2.html: web/header.html
        sed -e 's|href="|href="\.\.\/\.\./|g' \
                -e 's|SRC="|SRC="\.\.\/\.\./|g' $< > $@
 doxygen: web/header2.html
        mkdir -p web/sync/doxygen
        doxygen
-web/sync/doc: doc
-       cp -a $< $@
-web/sync/doxygen:
+web/sync/man: html_man
        mkdir -p $@
+       cp -a $(man_pages_html) $@
 web/sync/%.html: web/%.in.html web/header.html web/footer.html web/sync
        cat web/header.html $< web/footer.html > $@
 web/sync/%.png: pics/web/%.png web/sync
diff --git a/NEWS b/NEWS
index ccfdf72..40dd534 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,14 +4,23 @@ NEWS
 ----------------------------------------------
 0.2.15 (to be announced) "inductive resonance"
 ----------------------------------------------
+
+Minor improvements, more documentation and a bunch of bug fixes.
+
        - para_server: The server.users file is only read once on server
          startup rather than for each connection
        - mp3dec: Fix decoding of corrupt mp3 files
+       - afs (audio file sender) is now called vss (virtual streaming
+         system). Consequently, the permission flags specified in
+         ~/.paraslash/server.users have also changed: AFS_READ and AFS_WRITE
+         become VSS_READ and VSS_WRITE respectively.
        - para_audiod/para_filter: Fix a bug that caused the last chunk
          of audio data not being written under certain circumstances
        - audiod: compute the difference of server time and local time
          correctly
        - documentation improvements
+       - configure.ac: fix checks for para_krell
+       - new man pages
 
 -------------------------------------------
 0.2.14 (2006-10-15) "transient singularity"
diff --git a/audiod.cmd b/audiod.cmd
new file mode 100644 (file)
index 0000000..8300e44
--- /dev/null
@@ -0,0 +1,64 @@
+FN: audiod_command_list
+HC: prototypes for the audiod command handlers
+CC: array of audiod commands
+AT: audiod_command
+IN: list para sched audiod
+SN: list of audiod commands
+---
+N: cycle
+D: switch to next mode
+U: cycle
+H: on -> standby -> off -> on
+---
+N: grab
+D: grab the audio stream
+L:
+U: -- grab [grab_options]
+H: grab ('splice') the audio stream at any position in the filter
+H: chain and send that data back to the client. Try
+H:     para_audioc -- grab -h
+H: for the list of available options.
+---
+N: help
+D: display command list or help for given command
+U: help [command]
+H: When I was younger, so much younger than today, I never needed anybody's help
+H: in any way. But now these days are gone, I'm not so self assured. Now I find
+H: I've changed my mind and opened up the doors.
+H:                                                              -- Beatles: Help
+---
+N: kill
+D: kill an active audiod task
+U: kill task_id [task_id ...]
+H: call sched_unregister() and the event_handler of the given task(s)
+---
+N: off
+D: deactivate para_audiod
+U: off
+H: Close connection to para_server and stop all decoders.
+---
+N: on
+D: activate para_audiod
+U: on
+H: Establish connection to para_server, retrieve para_server's current status. If
+H: playing, start corresponding decoder. Otherwise stop all decoders.
+---
+N: sb
+D: enter standby mode
+U: sb
+H: Stop all decoders but leave connection to para_server open.
+---
+N: stat
+D: print status information
+U: stat [item1 ...]
+H: Dump given status items (all if none given) to stdout.
+---
+N: tasks
+D: list current tasks
+U: tasks
+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.
index 234c67a..8ead334 100644 (file)
--- a/audiod.h
+++ b/audiod.h
@@ -1,4 +1,24 @@
+/*
+ * Copyright (C) 2006-2007 Andre Noll <maan@systemlinux.org>
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ */
+
 /** \file audiod.h symbols exported from audiod.c */
+
+
 int num_filters(int audio_format_num);
 int get_audio_format_num(char *name);
 
@@ -20,6 +40,26 @@ extern const char *audio_formats[];
 */
 enum {AUDIOD_OFF, AUDIOD_ON, AUDIOD_STANDBY};
 
+/** defines one command of para_audiod */
+struct audiod_command {
+       /** the name of the command */
+       const char *name;
+       /** pointer to the function that handles the command */
+       int (*handler)(int, int, char**);
+       /**
+        * if the command prefers to handle the full line (rather than the usual
+        * argv[] array), it stores a pointer to the corresponding line handling
+        * function here. In this case, the above \a handler pointer must be NULL.
+        */
+       int (*line_handler)(int, char*);
+       /** one-line description of the command */
+       const char *description;
+       /** summary of the command line options */
+       const char *usage;
+       /** the long help text */
+       const char *help;
+};
+
 /**
  * describes one instance of a receiver-filter-writer chain
  *
index 312cfee..2fa7eb1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2006 Andre Noll <noll@mathematik.tu-darmstadt.de>
+ * Copyright (C) 2005-2007 Andre Noll <noll@mathematik.tu-darmstadt.de>
  *
  *     This program is free software; you can redistribute it and/or modify
  *     it under the terms of the GNU General Public License as published by
 #include "daemon.h"
 #include "string.h"
 #include "fd.h"
-
-/** defines one command of para_audiod */
-struct audiod_command {
-       /** the name of the command */
-       const char *name;
-       /** pointer to the function that handles the command */
-       int (*handler)(int, int, char**);
-       /**
-        * if the command prefers to handle the full line (rather than the usual
-        * argv[] array), it stores a pointer to the corresponding line handling
-        * function here. In this case, the above \a handler pointer must be NULL.
-        */
-       int (*line_handler)(int, char*);
-       /** one-line description of the command */
-       const char *description;
-       /** summary of the command line options */
-       const char *synopsis;
-       /** the long help text */
-       const char *help;
-};
-static int com_grab(int, char *);
-static int com_cycle(int, int, char **);
-static int com_help(int, int, char **);
-static int com_kill(int, int, char **);
-static int com_off(int, int, char **);
-static int com_on(int, int, char **);
-static int com_sb(int, int, char **);
-static int com_stat(int, int, char **);
-static int com_tasks(int, int, char **);
-static int com_term(int, int, char **);
-static struct audiod_command cmds[] = {
-{
-.name = "cycle",
-.handler = com_cycle,
-.description = "switch to next mode",
-.synopsis = "cycle",
-.help =
-
-"on -> standby -> off -> on\n"
-
-},
-{
-.name = "grab",
-.line_handler = com_grab,
-.description = "grab the audio stream",
-.synopsis = "-- grab [grab_options]",
-.help =
-
-"grab ('splice') the audio stream at any position in the filter      \n"
-"chain and send that data back to the client. Try\n"
-"\t para_audioc -- grab -h\n"
-"for the list of available options.\n"
-},
-
-{
-.name = "help",
-.handler = com_help,
-.description = "display command list or help for given command",
-.synopsis = "help [command]",
-.help =
-
-"When I was younger, so much younger than today, I never needed\n"
-"anybody's help in any way. But now these days are gone, I'm not so\n"
-"self assured. Now I find I've changed my mind and opened up the doors.\n"
-"\n"
-"                              -- Beatles: Help\n"
-
-},
-{
-.name = "kill",
-.handler = com_kill,
-.description = "kill an active audiod task",
-.synopsis = "kill task_id [task_id ...]",
-.help =
-
-"call sched_unregister() and the event_handler of the given task(s)\n"
-
-},
-{
-.name = "off",
-.handler = com_off,
-.description = "deactivate para_audiod",
-.synopsis = "off",
-.help =
-
-"Close connection to para_server and stop all decoders.\n"
-
-},
-{
-.name = "on",
-.handler = com_on,
-.description = "activate para_audiod",
-.synopsis = "on",
-.help =
-
-"Establish connection to para_server, retrieve para_server's current\n"
-"status. If playing, start corresponding decoder. Otherwise stop\n"
-"all decoders.\n"
-
-},
-{
-.name = "sb",
-.handler = com_sb,
-.description = "enter standby mode",
-.synopsis = "sb",
-.help =
-
-"Stop all decoders but leave connection to para_server open.\n"
-
-},
-{
-.name = "stat",
-.handler = com_stat,
-.description = "print status information",
-.synopsis = "stat [item1 ...]",
-.help =
-
-"Dump given status items (all if none given) to stdout.\n"
-
-},
-{
-.name = "tasks",
-.handler = com_tasks,
-.description = "list current tasks",
-.synopsis = "tasks",
-.help =
-
-"print the list of task ids together with the status of each task\n"
-
-},
-{
-.name = "term",
-.handler = com_term,
-.description = "terminate audiod",
-.synopsis = "term",
-.help =
-
-"Stop all decoders, shut down connection to para_server and exit.\n"
-
-},
-{
-.name = NULL,
-}
-};
+#include "audiod_command_list.h"
 
 /** iterate over the array of all audiod commands */
-#define FOR_EACH_COMMAND(c) for (c = 0; cmds[c].name; c++)
+#define FOR_EACH_COMMAND(c) for (c = 0; audiod_cmds[c].name; c++)
 
 static int client_write(int fd, const char *buf)
 {
@@ -284,8 +141,8 @@ static int dump_commands(int fd)
        ssize_t ret;
 
        FOR_EACH_COMMAND(i) {
-               tmp = make_message("%s%s\t%s\n", buf, cmds[i].name,
-                       cmds[i].description);
+               tmp = make_message("%s%s\t%s\n", buf, audiod_cmds[i].name,
+                       audiod_cmds[i].description);
                free(buf);
                buf = tmp;
        }
@@ -300,7 +157,7 @@ static int dump_commands(int fd)
  * to each individual command to close the fd if necessary.
  */
 
-static int com_help(int fd, int argc, char **argv)
+int com_help(int fd, int argc, char **argv)
 {
        int i, ret;
        char *buf;
@@ -311,16 +168,16 @@ static int com_help(int fd, int argc, char **argv)
                goto out;
        }
        FOR_EACH_COMMAND(i) {
-               if (strcmp(cmds[i].name, argv[1]))
+               if (strcmp(audiod_cmds[i].name, argv[1]))
                        continue;
                buf = make_message(
                        "NAME\n\t%s -- %s\n"
                        "SYNOPSIS\n\tpara_audioc %s\n"
                        "DESCRIPTION\n%s\n",
                        argv[1],
-                       cmds[i].description,
-                       cmds[i].synopsis,
-                       cmds[i].help
+                       audiod_cmds[i].description,
+                       audiod_cmds[i].usage,
+                       audiod_cmds[i].help
                );
                ret = client_write(fd, buf);
                free(buf);
@@ -335,7 +192,7 @@ out:
        return ret;
 }
 
-static int com_tasks(int fd, __a_unused int argc, __a_unused char **argv)
+int com_tasks(int fd, __a_unused int argc, __a_unused char **argv)
 {
        char *tl = get_task_list();
        int ret = 1;
@@ -347,7 +204,7 @@ static int com_tasks(int fd, __a_unused int argc, __a_unused char **argv)
        return ret;
 }
 
-static int com_kill(int fd, int argc, char **argv)
+int com_kill(int fd, int argc, char **argv)
 {
        int i, ret = 1;
        if (argc < 2)
@@ -362,7 +219,7 @@ static int com_kill(int fd, int argc, char **argv)
        return ret;
 }
 
-static int com_stat(int fd, __a_unused int argc, __a_unused char **argv)
+int com_stat(int fd, __a_unused int argc, __a_unused char **argv)
 {
        int i, ret;
        char *buf = NULL;
@@ -456,7 +313,7 @@ static struct filter_node *find_filter_node(int slot_num, int format, int filter
        return NULL;
 }
 
-static int com_grab(int fd, char *cmdline)
+int com_grab(int fd, char *cmdline)
 {
        struct grab_client *gc;
        struct filter_node *fn;
@@ -493,34 +350,34 @@ err_out:
        return 1;
 }
 
-static int __noreturn com_term(int fd, __a_unused int argc, __a_unused char **argv)
+int __noreturn com_term(int fd, __a_unused int argc, __a_unused char **argv)
 {
        close(fd);
        clean_exit(EXIT_SUCCESS, "terminating on user request");
 }
 
-static int com_on(int fd, __a_unused int argc, __a_unused char **argv)
+int com_on(int fd, __a_unused int argc, __a_unused char **argv)
 {
        audiod_status = AUDIOD_ON;
        close(fd);
        return 1;
 }
 
-static int com_off(int fd, __a_unused int argc, __a_unused char **argv)
+int com_off(int fd, __a_unused int argc, __a_unused char **argv)
 {
        audiod_status = AUDIOD_OFF;
        close(fd);
        return 1;
 }
 
-static int com_sb(int fd, __a_unused int argc, __a_unused char **argv)
+int com_sb(int fd, __a_unused int argc, __a_unused char **argv)
 {
        audiod_status = AUDIOD_STANDBY;
        close(fd);
        return 1;
 }
 
-static int com_cycle(int fd, int argc, char **argv)
+int com_cycle(int fd, int argc, char **argv)
 {
        switch (audiod_status) {
                case  AUDIOD_ON:
@@ -575,21 +432,21 @@ int handle_connect(int accept_fd)
                *p = '\0';
                p++;
        }
-       for (i = 0; cmds[i].name; i++) {
+       for (i = 0; audiod_cmds[i].name; i++) {
                int j;
-               if (strcmp(cmds[i].name, cmd))
+               if (strcmp(audiod_cmds[i].name, cmd))
                        continue;
-               if (cmds[i].handler) {
+               if (audiod_cmds[i].handler) {
                        argc = split_args(buf, &argv, "\n");
                        PARA_INFO_LOG("argv[0]: %s, argc= %d\n", argv[0], argc);
-                       ret = cmds[i].handler(clifd, argc, argv);
+                       ret = audiod_cmds[i].handler(clifd, argc, argv);
                        goto out;
                }
                for (j = 0; p[j]; j++)
                        if (p[j] == '\n')
                                p[j] = ' ';
                PARA_INFO_LOG("cmd: %s, options: %s\n", cmd, p);
-               ret = cmds[i].line_handler(clifd, p);
+               ret = audiod_cmds[i].line_handler(clifd, p);
                goto out;
        }
        ret = -E_INVALID_AUDIOD_CMD;
index 474e1bb..2113124 100644 (file)
--- a/command.c
+++ b/command.c
@@ -32,6 +32,7 @@
 #include "string.h"
 #include "fd.h"
 #include "user_list.h"
+#include "server_command_list.h"
 
 static RC4_KEY rc4_recv_key;
 static RC4_KEY rc4_send_key;
@@ -42,266 +43,6 @@ extern struct misc_meta_data *mmd;
 extern struct audio_file_selector selectors[];
 extern struct sender senders[];
 extern char *user_list;
-struct sockaddr_in *in_addr;
-
-static int com_si(int, int, char **);
-static int com_version(int, int, char **);
-static int com_sb(int, int, char **);
-static int com_sc(int, int, char **);
-static int com_stat(int, int, char **);
-static int com_help(int, int, char **);
-static int com_hup(int, int, char **);
-static int com_term(int, int, char **);
-static int com_play(int, int, char **);
-static int com_stop(int, int, char **);
-static int com_pause(int, int, char **);
-static int com_next(int, int, char **);
-static int com_nomore(int, int, char **);
-static int com_chs(int, int, char **);
-static int com_ff(int, int, char **);
-static int com_jmp(int, int, char **);
-static int com_sender(int, int, char **);
-
-
-/* commands that are handled by the server itself */
-static struct server_command cmd_struct[] = {
-{
-.name = "chs",
-.handler = com_chs,
-.perms = DB_READ | DB_WRITE,
-.description = "change the current audio file selector",
-.synopsis = "chs [new_selector]",
-.help =
-"Shutdown the current selector and activate new_selector. If no\n"
-"argument was given, print the name of the current selector.\n"
-},
-
-{
-.name = "ff",
-.handler = com_ff,
-.perms = VSS_READ | VSS_WRITE,
-.description = "jmp amount of time forwards or backwards "
-       "in current audio file",
-.synopsis = "ff n[-]",
-.help =
-
-"\tSet the 'R' (reposition request) bit of the vss status flags\n"
-"\tand enqueue a request to jump n seconds forwards or backwards\n"
-"\tin the current audio file.\n"
-"\n"
-"EXAMPLE\n"
-"\n"
-"\t\tff 30-\n"
-"\n"
-"\tjumps 30 seconds backwards.\n"
-
-},
-
-{
-.name = "help",
-.handler = com_help,
-.perms = 0,
-.description = "print help text",
-.synopsis = "help [command]",
-.help =
-
-"Without any arguments, help prints a list of availible commands. When\n"
-"issued with a command name as first argument, print out a description\n"
-"for that command.\n"
-
-},
-
-{
-.name = "hup",
-.handler = com_hup,
-.perms = VSS_WRITE,
-.description = "force reload of config file and log file",
-.synopsis = "hup",
-.help =
-
-"After rereading the config file, a signal is sent to all children\n"
-"which forces them to close/reopen the log file.\n"
-
-},
-
-{
-.name = "jmp",
-.handler = com_jmp,
-.perms = VSS_READ | VSS_WRITE,
-.description = "jmp to given position in current audio file",
-.synopsis = "jmp [n]",
-.help =
-
-"\tSet the 'R' (reposition request) bit of the vss status flags\n"
-"\tand enqueue a request to jump to n% of the current audio file,\n"
-"\twhere 0 <= n <= 100.\n"
-
-},
-
-{
-.name = "next",
-.handler = com_next,
-.perms = VSS_READ | VSS_WRITE,
-.description = "skip rest of current audio file",
-.synopsis = "next",
-.help =
-
-"\tSet the 'N' (next audio file) bit of the vss status flags. When\n"
-"\tplaying, change audio file immediately. Equivalent to stop\n"
-"\tif paused, NOP if stopped.\n"
-
-
-},
-
-{
-.name = "nomore",
-.handler = com_nomore,
-.perms = VSS_READ | VSS_WRITE,
-.description = "stop playing after current audio file",
-.synopsis = "nomore",
-.help =
-
-"Set the 'O' (no more) bit of the vss status flags. This instructs\n"
-"para_server to clear the 'P' (playing) bit as soon as it encounters\n"
-"the 'N' (next audio file) bit being set.\n"
-"\n"
-"Use this command instead of stop if you don't like\n"
-"sudden endings.\n"
-
-},
-
-{
-.name ="pause",
-.handler = com_pause,
-.perms = VSS_READ | VSS_WRITE,
-.description = "pause current audio file",
-.synopsis = "pause",
-.help =
-
-"\tClear the 'P' (playing) bit of the vss status flags.\n"
-
-},
-
-{
-.name = "play",
-.handler = com_play,
-.perms = VSS_READ | VSS_WRITE,
-.description = "start playing or resume playing when paused",
-.synopsis = "play",
-.help =
-
-"\tSet the 'P' (playing) bit of the vss status flags. This\n"
-"\tresults in starting/continuing to stream.\n"
-
-},
-
-{
-.name = "sb",
-.handler = com_sb,
-.perms = VSS_READ,
-.description = "print status bar for current audio file",
-.synopsis = "sb [n]",
-.help =
-
-"Without any arguments, sb continuously prints a status bar of the form\n"
-"\n"
-"      12:34 [56:12] (56%) filename\n"
-"\n"
-"indicating playing time, remaining time, percentage and the name of\n"
-"the file beeing streamed. Use the optional number n to let stat exit\n"
-"after having displayed the status bar n times.\n"
-
-},
-{
-.name = "sc",
-.handler = com_sc,
-.perms = VSS_READ,
-.description = "print name of audio file whenever it changes",
-.synopsis = "sc [n]",
-.help =
-
-"\tsc prints exactly one line (the filename of the audio file\n"
-"\tbeing played) whenever the audio file changes. Stops after\n"
-"\tn iterations, or never if n is not specified.\n"
-
-},
-{
-.name = "sender",
-.handler = com_sender,
-.perms = VSS_READ | VSS_WRITE,
-.description = "control paraslash internal senders",
-.synopsis = "sender [s cmd [arguments]]",
-.help =
-
-"send command cmd to sender s. cmd may be one of the following:\n"
-"help, on, off, add, delete, allow, or deny. Note that not all senders\n"
-"support each command. Try e.g. 'para_client sender http help' for\n"
-"more information about the http sender. If no argument is given,\n"
-"print out a list of all senders that are compiled in.\n"
-
-},
-{
-.name = "si",
-.handler = com_si,
-.perms = 0,
-.description = "print server info",
-.synopsis = "si",
-.help =
-"Print server uptime and other information.\n"
-},
-
-{
-.name = "stat",
-.handler = com_stat,
-.perms = VSS_READ,
-.description = "print status info for current audio file",
-.synopsis = "stat [n]",
-.help =
-
-"\tWithout any arguments, stat continuously prints status messages\n"
-"\tof the audio file being streamed. Use the optional number n\n"
-"\tto let stat exit after having displayed status n times.\n"
-
-},
-
-{
-.name = "stop",
-.handler = com_stop,
-.perms = VSS_READ | VSS_WRITE,
-.description = "stop playing",
-.synopsis = "stop",
-.help =
-
-"\tClear the 'P' (play) bit and set the 'N' bit of the vss status\n"
-"\tflags.\n"
-
-},
-{
-.name = "term",
-.handler = com_term,
-.perms = VSS_READ | VSS_WRITE,
-.description = "terminate para_server",
-.synopsis = "term",
-.help =
-
-"Shuts down the server. Instead of this command, you can also send\n"
-"SIGINT or SIGTERM. It should never be necessary to send SIGKILL.\n"
-
-},
-{
-.name = "version",
-.handler = com_version,
-.perms = 0,
-.description = "print server's version",
-.synopsis = "version",
-.help =
-"Show version and other info\n"
-},
-/* this indicates the end of the list. Do not touch. */
-{
-.name = NULL,
-}
-};
 
 static void dummy(__a_unused int s)
 {}
@@ -330,14 +71,14 @@ static char *vss_status_tohuman(unsigned int flags)
 /*
  * return human readable permission string. Never returns NULL.
  */
-char *cmd_perms_itohuman(unsigned int perms)
+static char *cmd_perms_itohuman(unsigned int perms)
 {
-       char *msg = para_malloc(7 * sizeof(char));
+       char *msg = para_malloc(5 * sizeof(char));
 
-       msg[0] = perms & DB_READ? 'd' : '-';
-       msg[1] = perms & DB_WRITE? 'D' : '-';
-       msg[2] = perms & VSS_READ? 'a' : '-';
-       msg[3] = perms & VSS_WRITE? 'A' : '-';
+       msg[0] = perms & DB_READ? 'a' : '-';
+       msg[1] = perms & DB_WRITE? 'A' : '-';
+       msg[2] = perms & VSS_READ? 'v' : '-';
+       msg[3] = perms & VSS_WRITE? 'V' : '-';
        msg[4] = '\0';
        return msg;
 }
@@ -360,7 +101,7 @@ static char *vss_get_status_flags(unsigned int flags)
 /*
  * compute status bar string. Never returns NULL
  */
-char *get_sb_string(struct misc_meta_data *nmmd)
+static char *get_sb_string(struct misc_meta_data *nmmd)
 {
        char *base, *ret;
        long long unsigned secs = 0, rsecs = 0, percent = 0;
@@ -509,7 +250,7 @@ static int check_sender_args(int argc, char **argv, struct sender_command_data *
        return 1;
 }
 
-static int com_sender(int fd, int argc, char **argv)
+int com_sender(int fd, int argc, char **argv)
 {
        int i, ret;
        struct sender_command_data scd;
@@ -551,7 +292,7 @@ static int com_sender(int fd, int argc, char **argv)
 }
 
 /* server info */
-static int com_si(int fd, int argc, __a_unused char **argv)
+int com_si(int fd, int argc, __a_unused char **argv)
 {
        int i, ret;
        char *ut;
@@ -600,7 +341,7 @@ static int com_si(int fd, int argc, __a_unused char **argv)
 }
 
 /* version */
-static int com_version(int socket_fd, int argc, __a_unused char **argv)
+int com_version(int socket_fd, int argc, __a_unused char **argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
@@ -613,7 +354,7 @@ static int com_version(int socket_fd, int argc, __a_unused char **argv)
 }
 
 /* sc */
-static int com_sc(int socket_fd, int argc, char **argv)
+int com_sc(int socket_fd, int argc, char **argv)
 {
        char *name = NULL;
        int ret, old = 0, count = -1; /* print af change forever */
@@ -641,7 +382,7 @@ repeat:
 }
 
 /* sb */
-static int com_sb(int socket_fd, int argc, char **argv)
+int com_sb(int socket_fd, int argc, char **argv)
 {
        char *sb;
        int ret, nr = -1;       /* status bar will be printed that many
@@ -668,7 +409,7 @@ static int com_sb(int socket_fd, int argc, char **argv)
 }
 
 /* stat */
-static int com_stat(int socket_fd, int argc, char **argv)
+int com_stat(int socket_fd, int argc, char **argv)
 {
        int ret, num = 0;/* status will be printed that many
                          * times. num <= 0 means: print forever
@@ -720,9 +461,9 @@ static int send_list_of_commands(int fd, struct server_command *cmd,
 /* always returns string that must be freed by the caller in handler */
 static struct server_command *get_cmd_ptr(char *name, char **handler)
 {
-       struct server_command *cmd = cmd_struct;
+       struct server_command *cmd;
 
-       for (cmd = cmd_struct; cmd->name; cmd++)
+       for (cmd = server_cmds; cmd->name; cmd++)
                if (!strcmp(cmd->name, name)) {
                        if (handler)
                                *handler = para_strdup("para_server"); /* server commands */
@@ -742,7 +483,7 @@ static struct server_command *get_cmd_ptr(char *name, char **handler)
 }
 
 /* help */
-static int com_help(int fd, int argc, char **argv)
+int com_help(int fd, int argc, char **argv)
 {
        struct server_command *cmd;
        char *perms, *handler;
@@ -750,7 +491,7 @@ static int com_help(int fd, int argc, char **argv)
 
        if (argc < 2) {
                /* no argument given, print list of commands */
-               if ((ret = send_list_of_commands(fd, cmd_struct, "server")) < 0)
+               if ((ret = send_list_of_commands(fd, server_cmds, "server")) < 0)
                        return ret;
                mmd_lock();
                handler = para_strdup(selectors[mmd->selector_num].name);
@@ -768,20 +509,17 @@ static int com_help(int fd, int argc, char **argv)
        }
        perms = cmd_perms_itohuman(cmd->perms);
        ret = send_va_buffer(fd,
-               "NAME\n\t%s - %s\n"
-               "SYNOPSIS\n\t para_client %s\n"
-               "DESCRIPTION\n%s\n"
-               "HANDLER\n"
-               "This command is handled by %s.\n\n"
-               "PERMISSIONS\n"
-               "Needed privileges for %s: %s\n",
+               "%s - %s\n\n"
+               "handler: %s\n"
+               "permissions: %s\n"
+               "usage: %s\n\n"
+               "%s\n",
                argv[1],
                cmd->description,
-               cmd->synopsis,
-               cmd->help,
                handler,
-               argv[1],
-               perms
+               perms,
+               cmd->usage,
+               cmd->help
        );
        free(perms);
        free(handler);
@@ -789,7 +527,7 @@ static int com_help(int fd, int argc, char **argv)
 }
 
 /* hup */
-static int com_hup(__a_unused int socket_fd, int argc, __a_unused char **argv)
+int com_hup(__a_unused int socket_fd, int argc, __a_unused char **argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
@@ -798,7 +536,7 @@ static int com_hup(__a_unused int socket_fd, int argc, __a_unused char **argv)
 }
 
 /* term */
-static int com_term(__a_unused int socket_fd, int argc, __a_unused char **argv)
+int com_term(__a_unused int socket_fd, int argc, __a_unused char **argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
@@ -806,7 +544,7 @@ static int com_term(__a_unused int socket_fd, int argc, __a_unused char **argv)
        return 1;
 }
 
-static int com_play(__a_unused int socket_fd, int argc, __a_unused char **argv)
+int com_play(__a_unused int socket_fd, int argc, __a_unused char **argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
@@ -819,7 +557,7 @@ static int com_play(__a_unused int socket_fd, int argc, __a_unused char **argv)
 }
 
 /* stop */
-static int com_stop(__a_unused int socket_fd, int argc, __a_unused char **argv)
+int com_stop(__a_unused int socket_fd, int argc, __a_unused char **argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
@@ -832,7 +570,7 @@ static int com_stop(__a_unused int socket_fd, int argc, __a_unused char **argv)
 }
 
 /* pause */
-static int com_pause(__a_unused int socket_fd, int argc, __a_unused char **argv)
+int com_pause(__a_unused int socket_fd, int argc, __a_unused char **argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
@@ -845,7 +583,7 @@ static int com_pause(__a_unused int socket_fd, int argc, __a_unused char **argv)
        return 1;
 }
 
-static int com_chs(int fd, int argc, char **argv)
+int com_chs(int fd, int argc, char **argv)
 {
        int i, ret;
 
@@ -871,7 +609,7 @@ static int com_chs(int fd, int argc, char **argv)
 }
 
 /* next */
-static int com_next(__a_unused int socket_fd, int argc, __a_unused char **argv)
+int com_next(__a_unused int socket_fd, int argc, __a_unused char **argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
@@ -883,7 +621,7 @@ static int com_next(__a_unused int socket_fd, int argc, __a_unused char **argv)
 }
 
 /* nomore */
-static int com_nomore(__a_unused int socket_fd, int argc, __a_unused char **argv)
+int com_nomore(__a_unused int socket_fd, int argc, __a_unused char **argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
@@ -895,7 +633,7 @@ static int com_nomore(__a_unused int socket_fd, int argc, __a_unused char **argv
 }
 
 /* ff */
-static int com_ff(__a_unused int socket_fd, int argc, char **argv)
+int com_ff(__a_unused int socket_fd, int argc, char **argv)
 {
        long promille;
        int ret, backwards = 0;
@@ -934,7 +672,7 @@ out:
 }
 
 /* jmp */
-static int com_jmp(__a_unused int socket_fd, int argc, char **argv)
+int com_jmp(__a_unused int socket_fd, int argc, char **argv)
 {
        long unsigned int i;
        int ret;
@@ -988,7 +726,7 @@ static struct server_command *parse_cmd(const char *cmdstr)
        return get_cmd_ptr(buf, NULL);
 }
 
-long int para_rand(long unsigned max)
+static long int para_rand(long unsigned max)
 {
        return (long int) ((max + 0.0) * (random() / (RAND_MAX + 1.0)));
 }
@@ -1018,6 +756,37 @@ static void rc4_send(unsigned long len, const unsigned char *indata,
        RC4(&rc4_send_key, len, indata, outdata);
 }
 
+/**
+ * perform user authentication and execute a command
+ *
+ * \param fd the file descriptor to send output to
+ * \param addr socket address info of peer
+ *
+ * \return EXIT_SUCCESS or EXIT_FAILURE
+ *
+ * Whenever para_server accepts an incoming tcp connection on
+ * the port it listens on, it forks and the resulting child
+ * calls this function.
+ *
+ * An RSA-based challenge/response is used to authenticate
+ * the peer. It that authentication succeeds, a random RC4
+ * session key is generated and sent back to the peer,
+ * encrypted with its RSA public key.  From this point on,
+ * all transfers are crypted with this session key.
+ *
+ * Next it is checked if the peer supplied  a valid server
+ * command or a command for the audio file selector currently
+ * in use.  If yes, and if the user has sufficient
+ * permissions to execute that command, the function calls
+ * the corresponding command handler which does argument
+ * checking and further processing.
+ *
+ * In order to cope with a DOS attacks, a timeout is set up
+ * which terminates the function if the connection was not
+ * authenticated when the timeout expires.
+ *
+ * \sa alarm(2), rc4(3), crypt.c, crypt.h
+ */
 int handle_connect(int fd, struct sockaddr_in *addr)
 {
        int numbytes, ret, argc, use_rc4 = 0;
@@ -1035,7 +804,6 @@ int handle_connect(int fd, struct sockaddr_in *addr)
        signal(SIGHUP, SIG_DFL);
        signal(SIGUSR1, SIG_IGN);
 
-       in_addr = addr;
        challenge_nr = random();
        /* send Welcome message */
        ret = send_va_buffer(fd, "This is para_server, version "
diff --git a/command_util.sh b/command_util.sh
new file mode 100755 (executable)
index 0000000..326bb03
--- /dev/null
@@ -0,0 +1,240 @@
+#!/bin/bash
+
+
+dump_array_member()
+{
+       echo '{'
+       echo ".name = \"$name_txt\","
+       if test $line_handler -eq 0; then
+               echo ".handler = com_$name_txt,"
+       else
+               echo ".handler = NULL,"
+               echo ".line_handler = com_$name_txt,"
+       fi
+       if test -n "$perms_txt"; then
+               echo ".perms = $perms_txt,"
+       fi
+       echo ".description = \"$desc_txt\","
+       echo ".usage = \"$usage_txt\","
+       echo ".help = "
+       echo "$help_txt" | sed -e 's/^/\"/g' -e 's/$/\\n\"/g'
+       echo '},'
+}
+
+read_header()
+{
+       local key value i
+
+       while read key value; do
+               case "$key" in
+               ---)
+                       break
+                       ;;
+               HC:)
+                       header_comment="$value"
+                       ;;
+               CC:)
+                       c_file_comment="$value"
+                       ;;
+               FN:)
+                       file_name="$value"
+                       array_name=${value%command_list}cmds
+                       ;;
+               AT:)
+                       array_type="$value"
+                       ;;
+               IN:)
+                       for i in $value; do
+                               includes="$includes
+#include \"$i.h\""
+                       done
+                       includes="$includes
+#include \"$file_name.h\""
+                       ;;
+               SN:)
+                       section_name="$value"
+               esac
+       done
+       if test -z "$header_comment" -o -z "$c_file_comment" \
+                       -o -z "$file_name"; then
+               echo "header error" 1&>2
+               exit 1
+       fi
+}
+
+read_one_command()
+{
+       local line
+
+       name_txt=""
+       desc_txt=""
+       usage_txt=""
+       help_txt=""
+       perms_txt=""
+       line_handler=0
+       mkdir -p man/man1
+       while read key value; do
+               case "$key" in
+               ---)
+                       break
+                       ;;
+               N:)
+                       name_txt="$value"
+                       ;;
+               P:)
+                       perms_txt="$value"
+                       ;;
+               D:)
+                       desc_txt="$value"
+                       ;;
+               L:)
+                       line_handler=1
+                       ;;
+               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 -n "$name_txt" -a -n "$desc_txt" -a -n "$usage_txt" \
+                       -a -n "$help_txt"; then
+               ret=1
+               return
+       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"
+}
+
+dump_man()
+{
+       echo ".SS \"$name_txt\""
+       echo "$desc_txt"
+       echo
+       echo "\\fBusage: \\fP$usage_txt"
+       echo
+       echo "$help_txt"
+       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
+}
+
+com_c_file()
+{
+       echo "/** \file $file_name.c $c_file_comment */"
+       echo "$includes"
+       echo "struct $array_type $array_name[] = {"
+       while : ; do
+               read_one_command
+               if test $ret -lt 0; then
+                       exit 1
+               fi
+               if test $ret -eq 0; then
+                       break
+               fi
+               dump_array_member
+       done
+       echo '{.name = NULL}};'
+}
+
+dump_proto()
+{
+       echo '/**'
+       echo " * $desc_txt"
+       echo ' *'
+       echo ' * \param fd the file descriptor to send output to'
+       if test $line_handler -eq 0; then
+               echo ' * \param argc the number of arguments'
+               echo ' * \param argv the argument vector'
+       else
+               echo ' * \param cmdline the full command line'
+       fi
+       echo ' * '
+       echo " * usage: $usage_txt"
+       echo ' * '
+       echo "$help_txt" | sed -e 's/^/ * /g'
+       echo ' */'
+       if test $line_handler -eq 0; then
+               echo "int com_$name_txt(int fd, int argc, char **argv);"
+       else
+               echo "int com_$name_txt(int fd, char *cmdline);"
+       fi
+       echo
+}
+
+com_header()
+{
+       echo "/** \file $file_name.h $header_comment */"
+       echo
+       echo "extern struct $array_type $array_name[];"
+       while : ; do
+               read_one_command
+               if test $ret -lt 0; then
+                       exit 1
+               fi
+               if test $ret -eq 0; then
+                       break
+               fi
+               dump_proto
+       done
+}
+
+read_header
+arg="$1"
+shift
+case "$arg" in
+       "c")
+               com_c_file
+               ;;
+       "h")
+               com_header
+               ;;
+       "man")
+               com_man $*
+               ;;
+esac
index 4977057..1fa5ac4 100644 (file)
@@ -72,7 +72,8 @@ audioc_cmdline_objs="audioc.cmdline"
 audioc_errlist_objs="audioc string net fd"
 
 audiod_cmdline_objs="audiod.cmdline grab_client.cmdline compress_filter.cmdline
-       http_recv.cmdline dccp_recv.cmdline file_write.cmdline client.cmdline"
+       http_recv.cmdline dccp_recv.cmdline file_write.cmdline client.cmdline
+       audiod_command_list"
 audiod_errlist_objs="audiod signal string daemon stat net
        time grab_client filter_chain wav compress http_recv dccp dccp_recv
        recv_common fd sched write_common file_write audiod_command crypt
@@ -80,7 +81,8 @@ audiod_errlist_objs="audiod signal string daemon stat net
 audiod_ldflags=""
 audiod_audio_formats=""
 
-server_cmdline_objs="server.cmdline"
+server_cmdline_objs="server.cmdline server_command_list random_selector_command_list
+       playlist_selector_command_list"
 server_errlist_objs="server mp3_afh vss command net string signal random_selector
        time daemon stat crypt http_send db close_on_fork playlist_selector
        ipc dccp dccp_send fd user_list"
@@ -185,17 +187,26 @@ if test ${have_core_audio} = yes; then
        AC_DEFINE(HAVE_CORE_AUDIO, 1, define to 1 on Mac Os X)
 fi
 ########################################################################### gtk2
-pkg_modules="gtk+-2.0 >= 2.0.0"
 build_para_krell="yes"
+OLD_CPPFLAGS="$CPPFLAGS"
+OLD_LD_FLAGS="$LDFLAGS"
+OLD_LIBS="$LIBS"
+pkg_modules="gtk+-2.0 >= 2.0.0"
+PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.0.4], [], [build_para_krell="no"])
 PKG_CHECK_MODULES(GTK, [$pkg_modules], [], [build_para_krell="no"])
+CPPFLAGS="$GTK_CFLAGS $GLIB_CFLAGS"
+LDFLAGS="$LDFLAGS $GTK_LIBS"
 AC_CHECK_HEADER(gkrellm2/gkrellm.h, [], [build_para_krell="no"])
-if test build_para_krell = "yes"; then
+if test "$build_para_krell" = "yes"; then
        AC_SUBST(GTK_CFLAGS)
        AC_SUBST(GTK_LIBS)
        extras="$extras para_krell.so"
 else
        AC_MSG_WARN([can not build para_krell])
 fi
+CPPFLAGS="$OLD_CPPFLAGS"
+LDFLAGS="$OLD_LDFLAGS"
+LIBS="$OLD_LIBS"
 ########################################################################### sdl
 # FIXME
 AC_CHECK_LIB([SDL_image], [SDL_Init], [extras="$extras para_sdl_gui"], [
@@ -231,6 +242,7 @@ if test "$have_mysql" = "yes"; then
        selectors="$selectors mysql"
        server_ldflags="$server_ldflags $mysql_libs -lmysqlclient"
        server_errlist_objs="$server_errlist_objs mysql_selector"
+       server_cmdline_objs="$server_cmdline_objs mysql_selector_command_list"
        AC_SUBST(mysql_cppflags)
        AC_SUBST(mysql_libs)
        AC_DEFINE(HAVE_MYSQL, 1, [define to 1 to turn on mysql support])
@@ -445,6 +457,7 @@ build_slider="yes"
 OLD_CPPFLAGS="$CPPFLAGS"
 OLD_LD_FLAGS="$LDFLAGS"
 OLD_LIBS="$LIBS"
+PKG_CHECK_MODULES(GTK, [$pkg_modules], [], [build_para_slider="no"])
 PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.0.4], [], [build_slider="no"])
 CPPFLAGS="$GTK_CFLAGS $GLIB_CFLAGS"
 LDFLAGS="$LDFLAGS $GTK_LIBS"
index a2a5bcd..e2812fd 100644 (file)
 #include "net.h"
 #include "string.h"
 #include "user_list.h"
+#include "mysql_selector_command_list.h"
 
 /** pointer to the shared memory area */
 extern struct misc_meta_data *mmd;
 
 static void *mysql_ptr = NULL;
 
-static int com_cam(int, int, char **);
-static int com_cdb(int, int, char **);
-static int com_cs(int, int, char **);
-static int com_da(int, int, char **);
-static int com_hist(int, int, char **);
-static int com_info(int, int, char **);
-static int com_laa(int, int, char **);
-static int com_last(int, int, char **);
-static int com_ls(int, int, char **);
-static int com_mbox(int, int, char **);
-static int com_mv(int, int, char **);
-static int com_na(int, int, char **);
-static int com_pic(int, int, char **);
-static int com_picch(int, int, char **);
-static int com_picdel(int, int, char **);
-static int com_piclist(int, int, char **);
-static int com_ps(int, int, char **);
-static int com_rm_ne(int, int, char **);
-static int com_sa(int, int, char **);
-static int com_set(int, int, char **);
-static int com_sl(int, int, char **);
-static int com_stradd_picadd(int, int, char **);
-static int com_streams(int, int, char **);
-static int com_strdel(int, int, char **);
-static int com_strq(int, int, char **);
-static int com_summary(int, int, char **);
-static int com_upd(int, int, char **);
-static int com_us(int, int, char **);
-static int com_verb(int, int, char **);
-static int com_vrfy(int, int, char **);
-
-static struct server_command cmds[] = {
-{
-.name = "cam",
-.handler = com_cam,
-.perms = DB_READ|DB_WRITE,
-.description = "copy all metadata",
-.synopsis = "cam source dest1 [dest2 ...]",
-.help =
-
-"Copy attributes and other meta data from source file to destination\n"
-"file(s). Useful for files that have been renamed.\n"
-
-},
-{
-.name = "cdb",
-.handler = com_cdb,
-.perms = DB_READ|DB_WRITE,
-.description = "create database",
-.synopsis = "cdb [name]",
-.help =
-
-"\tCreate database name containing the initial columns for basic\n"
-"\tinteroperation with server. This command has to be used only once\n"
-"\twhen you use the mysql audio file selector for the very first time.\n"
-"\n"
-"\tThe optional name defaults to 'paraslash' if not given.\n"
-
-},
-{
-.name = "clean",
-.handler = com_vrfy,
-.perms = DB_READ | DB_WRITE,
-.description = "nuke invalid entries in database",
-.synopsis = "clean",
-.help =
-
-"If the vrfy command shows you any invalid entries in your database,\n"
-"you can get rid of them with clean. Always run 'upd' and 'vrfy'\n"
-"before running this command. Use with caution!\n"
-
-},
-{
-.name = "cs",
-.handler = com_cs,
-.perms = VSS_WRITE | DB_READ | DB_WRITE,
-.description = "change stream",
-.synopsis = "cs [s]",
-.help =
-
-"Selects stream s or prints current stream when s was not given.\n"
-
-},
-{
-.name = "csp",
-.handler = com_cs,
-.perms = VSS_WRITE | DB_READ,
-.description = "change stream and play",
-.synopsis = "csp s",
-.help =
-
-"Select stream s and start playing. If this results in a stream-change,\n"
-"skip rest of current audio file.\n"
-
-},
-{
-.name = "da",
-.handler = com_da,
-.perms = DB_READ | DB_WRITE,
-.description  = "drop attribute from database",
-.synopsis = "da att",
-.help =
-
-"Use with caution. All info on attribute att will be lost.\n"
-
-},
-{
-.name = "hist",
-.handler = com_hist,
-.perms = DB_READ,
-.description = "print history",
-.synopsis = "hist",
-.help =
-
-"Print list of all audio files together with number of days since each\n"
-"file was last played.\n"
-
-},
-{
-.name = "info",
-.handler = com_info,
-.perms = DB_READ,
-.description = "print database info",
-.synopsis = "info [af]",
-.help =
-
-"print database informations for audio file af. Current audio file is\n"
-"used if af is not given.\n"
-
-},
-{
-.name = "la",
-.handler = com_info,
-.perms = DB_READ,
-.description = "list attributes",
-.synopsis = "la [af]",
-.help =
-
-"List attributes of audio file af or of current audio file when invoked\n"
-"without arguments.\n"
-
-},
-{
-.name = "laa",
-.handler = com_laa,
-.perms = DB_READ,
-.description = "list available attributes",
-.synopsis = "laa",
-.help = 
-
-"What should I say more?\n"
-
-},
-{
-.name = "last",
-.handler = com_last,
-.perms = DB_READ,
-.description = "print list of audio files, ordered by lastplayed time",
-.synopsis = "last [n]",
-.help =
-
-"The optional number n defaults to 10 if not specified.\n"
-
-},
-{
-.name = "ls",
-.handler = com_ls,
-.perms = DB_READ,
-.description = "list all audio files that match a LIKE pattern",
-.synopsis = "ls [pattern]",
-.help =
-
-"\tIf pattern was not given, print list of all audio files known\n"
-"\tto the mysql selector. See the documentation of mysql\n"
-"\tfor the definition of LIKE patterns.\n"
-
-},
-{
-.name = "mbox",
-.handler = com_mbox,
-.perms = DB_READ,
-.description = "dump audio file list in mbox format",
-.synopsis = "mbox [p]",
-.help =
-
-"\tDump list of audio files in mbox format (email) to stdout. If\n"
-"\tthe optional pattern p is given, only those audio files,\n"
-"\twhose basename match p are going to be included. Otherwise,\n"
-"\tall files are selected.\n"
-"\n"
-"EXAMPLE\n"
-"\tThe mbox command can be used together with your favorite\n"
-"\tmailer (this example uses mutt) for browsing the audio file\n"
-"\tcollection:\n"
-"\n"
-"\t\tpara_client mbox > ~/para_mbox\n"
-"\n"
-"\t\tmutt -F ~/.muttrc.para -f ~/para_mbox\n"
-"\n"
-"\tFor playlists, you can use mutt's powerful pattern matching\n"
-"\tlanguage to select files. If you like to tag all files\n"
-"\tcontaining the pattern 'foo', type 'T', then '~s foo'.\n"
-"\n"
-"\tWhen ready with the list, type ';|' (i.e., hit the semicolon\n"
-"\tkey to apply the next mutt command to all tagged messages,\n"
-"\tthen the pipe key) to pipe the selected \"mails\" to a\n"
-"\tsuitable script which adds a paraslash stream where exactly\n"
-"\tthese files are admissable or does whatever thou wilt.\n"
-
-},
-{
-.name = "mv",
-.handler = com_mv,
-.perms = DB_READ | DB_WRITE,
-.description = "rename entry in database",
-.synopsis = "mv oldname newname",
-.help =
-
-"Rename oldname to newname. This updates the data table to reflect the\n"
-"new name. All internal data (numplayed, lastplayed, picid,..) is kept.\n"
-"If newname is a full path, the dir table is updated as well.\n"
-
-},
-{
-.name = "na",
-.handler = com_na,
-.perms = DB_READ | DB_WRITE,
-.description = "add new attribute to database",
-.synopsis = "na att",
-.help =
-
-"This adds a column named att to your mysql database. att should only\n"
-"contain letters and numbers, in paricular, '+' and '-' are not allowed.\n"
-
-},
-{
-.name = "ne",
-.handler = com_rm_ne,
-.perms = DB_READ | DB_WRITE,
-.description = "add new database entries",
-.synopsis = "ne file1 [file2 [...]]",
-.help =
-
-"Add the given filename(s) to the database, where file1,... must\n"
-"be full path names. This command might be much faster than 'upd'\n"
-"if the number of given files is small.\n"
-
-},
-{
-.name = "ns",
-.handler = com_ps,
-.perms = VSS_WRITE | DB_READ | DB_WRITE,
-.description = "change to next stream",
-.synopsis = "ns",
-.help =
-
-"Cycle forwards through stream list.\n"
-
-},
-{
-.name = "pic",
-.handler = com_pic,
-.perms = DB_READ,
-.description = "get picture by name or by identifier",
-.synopsis = "pic [name]",
-.help =
-
-"\tDump jpg image that is associated to given audio file (current\n"
-"\taudio file if not specified) to stdout. If name starts with\n"
-"\t'#' it is interpreted as an identifier instead and the picture\n"
-"\thaving that identifier is dumped to stdout.\n"
-"\n"
-"EXAMPLE\n"
-"\n"
-"\tpara_client pic '#123' > pic123.jpg\n"
-
-},
-{
-.name = "picadd",
-.handler = com_stradd_picadd,
-.perms = DB_READ | DB_WRITE,
-.description = "add picture to database",
-.synopsis = "picadd [picname]",
-.help =
-
-"\tRead jpeg file from stdin and store it as picname in database.\n"
-"\n"
-"EXAMPLE\n"
-"\n"
-"\tpara_client picadd foo.jpg < foo.jpg\n"
-
-},
-{
-.name = "picass",
-.handler = com_set,
-.perms = DB_READ | DB_WRITE,
-.description = "associate a picture to file(s)",
-.synopsis = "picass pic_id file1 [file2...]",
-.help =
-
-"Associate the picture given by pic_id to all given files.\n"
-
-},
-{
-.name = "picch",
-.handler = com_picch,
-.perms = DB_READ | DB_WRITE,
-.description = "change name of picture",
-.synopsis = "picch id new_name",
-.help =
-
-"Asign new_name to picture with identifier id.\n"
-
-},
-{
-.name = "picdel",
-.handler = com_picdel,
-.perms = DB_READ | DB_WRITE,
-.description = "delete picture from database",
-.synopsis = "picdel id1 [id2...]",
-.help =
-
-"Delete each given picture from database.\n"
-
-},
-{
-.name = "piclist",
-.handler = com_piclist,
-.perms = DB_READ,
-.description = "print list of pictures",
-.synopsis = "piclist",
-.help =
-
-"Print id, name and length of each picture contained in the database.\n"
-
-},
-{
-.name = "ps",
-.handler = com_ps,
-.perms = VSS_WRITE | DB_READ | DB_WRITE,
-.description = "change to previous stream",
-.synopsis = "ps",
-.help =
-
-"Cycle backwards through stream list.\n"
-
-},
-{
-.name = "rm",
-.handler = com_rm_ne,
-.perms = DB_READ | DB_WRITE,
-.description = "remove entries from database",
-.synopsis = "rm name1 [name2 [...]]",
-.help =
-
-"Remove name1, name2, ... from the data table. Use with caution\n"
-
-},
-{
-.name = "sa",
-.handler = com_sa,
-.perms = DB_READ | DB_WRITE,
-.description = "set/unset attributes",
-.synopsis = "sa at1<'+' | '-'> [at2<'+' | '-'> ] [af1 ...]",
-//.synopsis = "foo",
-.help =
-
-"Set ('+') or unset ('-') attribute at1, at2 etc. for given list of\n"
-"audio files. If no audio files were given the current audio file is\n"
-"used. Example:\n"
-"\n"
-"sa rock+ punk+ classic- LZ__Waldsterben.mp3\n"
-"\n"
-"sets the 'rock' and the 'punk' attribute but unsets the 'classic'\n"
-"attribute.\n"
-
-},
-{
-.name = "skip",
-.handler = com_sl,
-.perms = DB_READ | DB_WRITE,
-.description = "skip subsequent audio files(s)",
-.synopsis = "skip n [s]",
-.help =
-
-"Skip the next n audio files of stream s. This is equivalent to the\n"
-"command 'sl n s', followed by 'us name' for each name the output of sl.\n"
-
-},
-{
-.name = "sl",
-.handler = com_sl,
-.perms = DB_READ,
-.description = "print score list",
-.synopsis = "sl n [s]",
-.help =
-
-"Print sorted list of maximal n lines. Each line is an admissible entry\n"
-"with respect to stream s. The list is sorted by score-value which is\n"
-"given by the definition of s. If s is not given, the current stream\n"
-"is used. Example:\n"
-"\n"
-"      sl 1\n"
-"\n"
-"shows you the audio file the server would select right now.\n"
-
-},
-{
-.name = "snp",
-.handler = com_set,
-.perms = DB_READ | DB_WRITE,
-.description = "set numplayed",
-.synopsis = "snp number af1 [af2 ...]",
-.help =
-
-"Update the numplayed field in the data table for all given audio files.\n"
-
-},
-{
-.name = "stradd",
-.handler = com_stradd_picadd,
-.perms = DB_READ | DB_WRITE,
-.description = "add stream",
-.synopsis = "stradd s",
-.help =
-
-"Add stream s to the list of available streams. The stream definition\n"
-"for s is read from stdin and is then sent to para_server. Example:\n"
-"\n"
-"      echo 'deny: NAME_LIKE(%Madonna%)' | para_client stradd no_madonna\n"
-"\n"
-"adds the new stream 'no_madonna' to the list of available streams. A given\n"
-"audio file is admissible for this stream iff its basename does not contain the\n"
-"string 'Madonna'.\n"
-
-
-},
-{
-.name = "strdel",
-.handler = com_strdel,
-.perms = DB_READ | DB_WRITE,
-.description = "delete stream",
-.synopsis = "strdel s",
-.help =
-
-"Remove stream s from database.\n"
-
-},
-{
-.name = "streams",
-.handler = com_streams,
-.perms = DB_READ,
-.description = "list streams",
-.synopsis = "streams",
-.help =
-
-"Print list of available streams. Use 'cs' to switch to any of these.\n"
-
-},
-{
-.name = "strq",
-.handler = com_strq,
-.perms = DB_READ,
-.description = "query stream definition",
-.synopsis = "strq [s]",
-.help =
-
-"Print definition of stream s to stdout. Use current stream if s was\n"
-"not given.\n"
-
-},
-{
-.name = "summary",
-.handler = com_summary,
-.perms = DB_READ,
-.description = "list attributes",
-.synopsis = "summary",
-.help =
-
-"\tPrint a list of attributes together with number of audio\n"
-"\tfiles having that attribute set.\n"
-
-},
-{
-.name = "upd",
-.handler = com_upd,
-.perms = DB_READ | DB_WRITE,
-.description = "update database",
-.synopsis = "upd",
-.help =
-
-"This command uses the --audio_file_dir option of para_server to locate\n"
-"your audio files. New files are then added to the mysql database. Use\n"
-"this command if you got new files or if you have moved some files\n"
-"around.\n"
-
-},
-{
-.name = "us",
-.handler = com_us,
-.perms = DB_READ | DB_WRITE,
-.description = "update lastplayed time",
-.synopsis = "us name",
-.help =
-
-"Update lastplayed time without actually playing the thing.\n"
-
-},
-{
-.name = "verb",
-.handler = com_verb,
-.perms = DB_READ | DB_WRITE,
-.description = "send verbatim sql query",
-.synopsis = "verb cmd",
-.help =
-
-"Send cmd to mysql server. For expert/debugging only. Note that cmd\n"
-"usually must be escaped. Use only if you know what you are doing!\n"
-
-},
-{
-.name = "vrfy",
-.handler = com_vrfy,
-.perms = DB_READ,
-.description = "list invalid entries in database",
-.synopsis = "vrfy",
-.help =
-
-"Show what clean would delete. Run 'upd' before this command to make\n"
-"sure your database is up to date.\n"
-
-},
-{
-.name = NULL,
-}
-};
-
 static struct para_macro macro_list[] = {
        {       .name = "IS_N_SET",
                .replacement = "(data.%s != '1')"
@@ -693,7 +157,7 @@ static char *escaped_basename(const char *name)
 /*
  * new attribute
  */
-static int com_na(__a_unused int fd, int argc, char *argv[])
+int com_na(__a_unused int fd, int argc, char *argv[])
 {
        char *q, *tmp;
        int ret;
@@ -714,7 +178,7 @@ static int com_na(__a_unused int fd, int argc, char *argv[])
 /*
  * delete attribute
  */
-static int com_da(__a_unused int fd, int argc, char *argv[])
+int com_da(__a_unused int fd, int argc, char *argv[])
 {
        char *q, *tmp;
        int ret;
@@ -787,6 +251,18 @@ out:
        return ret;
 }
 
+/* stradd */
+int com_stradd(int fd, int argc, char *argv[])
+{
+       return com_stradd_picadd(fd, argc, argv);
+}
+
+/* pic_add */
+int com_picadd(int fd, int argc, char *argv[])
+{
+       return com_stradd_picadd(fd, argc, argv);
+}
+
 /*
  * print results to fd
  */
@@ -818,7 +294,7 @@ static int print_results(int fd, void *result,
 /*
  * verbatim
  */
-static int com_verb(int fd, int argc, char *argv[])
+int com_verb(int fd, int argc, char *argv[])
 {
        void *result = NULL;
        int ret;
@@ -865,7 +341,7 @@ static void *get_all_attributes(void)
 /*
  * list all attributes
  */
-static int com_laa(int fd, int argc, __a_unused char *argv[])
+int com_laa(int fd, int argc, __a_unused char *argv[])
 {
        void *result;
        int ret;
@@ -883,7 +359,7 @@ static int com_laa(int fd, int argc, __a_unused char *argv[])
 /*
  * history
  */
-static int com_hist(int fd, int argc, char *argv[]) {
+int com_hist(int fd, int argc, char *argv[]) {
        int ret;
        void *result = NULL;
        char *q, *atts;
@@ -918,7 +394,7 @@ static int com_hist(int fd, int argc, char *argv[]) {
 /*
  * get last num audio files
  */
-static int com_last(int fd, int argc, char *argv[])
+int com_last(int fd, int argc, char *argv[])
 {
        void *result = NULL;
        char *q;
@@ -941,7 +417,7 @@ static int com_last(int fd, int argc, char *argv[])
        return ret;
 }
 
-static int com_mbox(int fd, int argc, char *argv[])
+int com_mbox(int fd, int argc, char *argv[])
 {
        void *result;
        MYSQL_ROW row;
@@ -1340,9 +816,8 @@ static char *get_current_audio_file(void)
        return name;
 }
 
-
-/* print database info */
-static int com_info(int fd, int argc, char *argv[])
+/* list attributes / print database info */
+static int com_la_info(int fd, int argc, char *argv[])
 {
        char *name = NULL, *meta = NULL, *atts = NULL, *dir = NULL;
        int ret, com_la = strcmp(argv[0], "info");
@@ -1375,6 +850,18 @@ out:
        return ret;
 }
 
+/* list attributes */
+int com_la(int fd, int argc, char *argv[])
+{
+       return com_la_info(fd, argc, argv);
+}
+
+/* print database info */
+int com_info(int fd, int argc, char *argv[])
+{
+       return com_la_info(fd, argc, argv);
+}
+
 static int change_stream(const char *stream)
 {
        char *query;
@@ -1489,10 +976,26 @@ static int com_rm_ne(__a_unused int fd, int argc, char *argv[])
        return 1;
 }
 
+/*
+ * rm
+ */
+int com_rm(int fd, int argc, char *argv[])
+{
+       return com_rm_ne(fd, argc, argv);
+}
+
+/*
+ * ne
+ */
+int com_ne(int fd, int argc, char *argv[])
+{
+       return com_ne(fd, argc, argv);
+}
+
 /*
  * mv: rename entry
  */
-static int com_mv(__a_unused int fd, int argc, char *argv[])
+int com_mv(__a_unused int fd, int argc, char *argv[])
 {
        char *q, *dn, *ebn1 = NULL, *ebn2 = NULL, *edn = NULL;
        int ret;
@@ -1548,8 +1051,7 @@ out:
 }
 
 /*
- * picass: associate pic to audio file
- * snp: set numplayed
+ * set field
  */
 static int com_set(__a_unused int fd, int argc, char *argv[])
 {
@@ -1576,10 +1078,26 @@ static int com_set(__a_unused int fd, int argc, char *argv[])
        return 1;
 }
 
+/*
+ * snp: set numplayed
+ */
+int com_picass(int fd, int argc, char *argv[])
+{
+       return com_set(fd, argc, argv);
+}
+
+/*
+ * snp: set numplayed
+ */
+int com_snp(int fd, int argc, char *argv[])
+{
+       return com_set(fd, argc, argv);
+}
+
 /*
  * picch: change entry's name in pics table
  */
-static int com_picch(__a_unused int fd, int argc, char *argv[])
+int com_picch(__a_unused int fd, int argc, char *argv[])
 {
        int ret;
        long unsigned id;
@@ -1602,7 +1120,7 @@ static int com_picch(__a_unused int fd, int argc, char *argv[])
 /*
  * piclist: print list of pics in db
  */
-static int com_piclist(__a_unused int fd, int argc, __a_unused char *argv[])
+int com_piclist(__a_unused int fd, int argc, __a_unused char *argv[])
 {
        void *result = NULL;
        MYSQL_ROW row;
@@ -1631,7 +1149,7 @@ out:
 /*
  * picdel: delete picture from database
  */
-static int com_picdel(int fd, int argc, char *argv[])
+int com_picdel(int fd, int argc, char *argv[])
 {
        char *q;
        long unsigned id;
@@ -1663,7 +1181,7 @@ static int com_picdel(int fd, int argc, char *argv[])
 /*
  * pic: get picture by name or by number
  */
-static int com_pic(int fd, int argc, char *argv[])
+int com_pic(int fd, int argc, char *argv[])
 {
        void *result = NULL;
        MYSQL_ROW row;
@@ -1704,7 +1222,7 @@ out:
 }
 
 /* strdel */
-static int com_strdel(__a_unused int fd, int argc, char *argv[])
+int com_strdel(__a_unused int fd, int argc, char *argv[])
 {
        char *q, *tmp;
        int ret;
@@ -1724,7 +1242,7 @@ static int com_strdel(__a_unused int fd, int argc, char *argv[])
 /*
  * ls
  */
-static int com_ls(int fd, int argc, char *argv[])
+int com_ls(int fd, int argc, char *argv[])
 {
        char *q;
        void *result;
@@ -1757,7 +1275,7 @@ static int com_ls(int fd, int argc, char *argv[])
 /*
  * summary
  */
-static int com_summary(__a_unused int fd, int argc, __a_unused char *argv[])
+int com_summary(__a_unused int fd, int argc, __a_unused char *argv[])
 {
        MYSQL_ROW row;
        MYSQL_ROW row2;
@@ -1867,7 +1385,7 @@ static void update_audio_file_server_handler(char *name)
        update_audio_file(name);
 }
 
-static int com_us(__a_unused int fd, int argc, char *argv[])
+int com_us(__a_unused int fd, int argc, char *argv[])
 {
        char *tmp;
        int ret;
@@ -1897,8 +1415,8 @@ static void refresh_selector_info(void)
        free(info);
 }
 
-/* select previous/next stream */
-static int com_ps(__a_unused int fd, int argc, char *argv[])
+/* select previous / next stream */
+static int com_ps_ns(__a_unused int fd, int argc, char *argv[])
 {
        char *query, *stream = get_current_stream();
        void *result = get_result("select name from streams");
@@ -1964,8 +1482,20 @@ out:
        return ret;
 }
 
+/* select previous stream */
+int com_ps(int fd, int argc, char *argv[])
+{
+       return com_ps_ns(fd, argc, argv);
+}
+
+/* select next stream */
+int com_ns(int fd, int argc, char *argv[])
+{
+       return com_ps_ns(fd, argc, argv);
+}
+
 /* streams */
-static int com_streams(int fd, int argc, __a_unused char *argv[])
+int com_streams(int fd, int argc, __a_unused char *argv[])
 {
        unsigned int num_rows;
        int i, ret = -E_NORESULT;
@@ -2003,7 +1533,7 @@ out:
 }
 
 /* query stream definition */
-static int com_strq(int fd, int argc, char *argv[])
+int com_strq(int fd, int argc, char *argv[])
 {
        MYSQL_ROW row;
        char *query, *name;
@@ -2039,7 +1569,7 @@ out:
 }
 
 /* change stream / change stream and play */
-static int com_cs(int fd, int argc, char *argv[])
+static int com_cs_csp(int fd, int argc, char *argv[])
 {
        int ret, stream_change;
        char *query, *stream = NULL;
@@ -2086,10 +1616,20 @@ out:
        return ret;
 }
 
-/*
- * sl/skip
- */
-static int com_sl(int fd, int argc, char *argv[])
+/* change stream */
+int com_cs(int fd, int argc, char *argv[])
+{
+       return com_cs_csp(fd, argc, argv);
+}
+
+/* change stream and play */
+int com_csp(int fd, int argc, char *argv[])
+{
+       return com_cs_csp(fd, argc, argv);
+}
+
+/* score list / skip */
+static int com_sl_skip(int fd, int argc, char *argv[])
 {
        void *result = NULL;
        MYSQL_ROW row;
@@ -2141,6 +1681,18 @@ out:
        return ret;
 }
 
+/* score list */
+int com_sl(int fd, int argc, char *argv[])
+{
+       return com_sl_skip(fd, argc, argv);
+}
+
+/* skip */
+int com_skip(int fd, int argc, char *argv[])
+{
+       return com_sl_skip(fd, argc, argv);
+}
+
 /*
  * update attributes of name
  */
@@ -2173,7 +1725,7 @@ out:
 /*
  * set attributes
  */
-static int com_sa(int fd, int argc, char *argv[])
+int com_sa(int fd, int argc, char *argv[])
 {
        int i, ret;
        char *atts = NULL, *name;
@@ -2230,7 +1782,7 @@ out:
 /*
  * copy attributes
  */
-static int com_cam(int fd, int argc, char *argv[])
+int com_cam(int fd, int argc, char *argv[])
 {
        char *name = NULL, *meta = NULL, *atts = NULL;
        int i, ret;
@@ -2278,7 +1830,7 @@ out:
 /*
  * verify / clean
  */
-static int com_vrfy(int fd, int argc, __a_unused char *argv[])
+static int com_vrfy_clean(int fd, int argc, __a_unused char *argv[])
 {
        char *query;
        int ret, vrfy_mode = strcmp(argv[0], "clean");
@@ -2328,6 +1880,22 @@ out:
        return ret;
 }
 
+/*
+ * verify
+ */
+int com_vrfy(int fd, int argc, char **argv)
+{
+       return com_vrfy_clean(fd, argc, argv);
+}
+
+/*
+ * clean
+ */
+int com_clean(int fd, int argc, char **argv)
+{
+       return com_vrfy_clean(fd, argc, argv);
+}
+
 static FILE *out_file;
 
 static int mysql_write_tmp_file(const char *dir, const char *name)
@@ -2343,7 +1911,7 @@ static int mysql_write_tmp_file(const char *dir, const char *name)
 /*
  * update database
  */
-static int com_upd(int fd, int argc, __a_unused char *argv[])
+int com_upd(int fd, int argc, __a_unused char *argv[])
 {
        char *tempname = NULL, *query = NULL;
        int ret, out_fd = -1, num = 0;
@@ -2511,7 +2079,7 @@ static void write_msg2mmd(int success)
 }
 
 /* create database */
-static int com_cdb(int fd, int argc, char *argv[])
+int com_cdb(int fd, int argc, char *argv[])
 {
        char *query;
        int ret;
@@ -2603,7 +2171,7 @@ int mysql_selector_init(struct audio_file_selector *db)
        if (!conf.mysql_audio_file_dir_given)
                return -E_NO_AF_DIR;
        db->name = "mysql";
-       db->cmd_list = cmds;
+       db->cmd_list = mysql_selector_cmds;
        db->get_audio_file_list = server_get_audio_file_list;
        db->update_audio_file = update_audio_file_server_handler;
        db->shutdown = shutdown_connection;
diff --git a/mysql_selector.cmd b/mysql_selector.cmd
new file mode 100644 (file)
index 0000000..df88a22
--- /dev/null
@@ -0,0 +1,323 @@
+FN: mysql_selector_command_list
+HC: prototypes for the commands of the mysql audio file selector
+CC: array of commands for the mysql audio file selector
+AT: server_command
+IN: server user_list
+SN: list of mysql selector commands
+---
+N: cam
+P: DB_READ | DB_WRITE
+D: copy all metadata
+U: cam source dest1 [dest2 ...]
+H: Copy attributes and other meta data from source file to destination
+H: file(s). Useful for files that have been renamed.
+---
+N: cdb
+P: DB_READ | DB_WRITE
+D: create database
+U: cdb [name]
+H:
+H: Create database name containing the initial columns for basic
+H: interoperation with server. This command has to be used only once
+H: when you use the mysql audio file selector for the very first time.
+H:
+H: The optional name defaults to 'paraslash' if not given.
+---
+N: clean
+P: DB_READ | DB_WRITE
+D: nuke invalid entries in database
+U: clean
+H: If the vrfy command shows you any invalid entries in your database,
+H: you can get rid of them with clean. Always run 'upd' and 'vrfy'
+H: before running this command. Use with caution!
+---
+N: cs
+P: VSS_WRITE | DB_READ | DB_WRITE
+D: change stream
+U: cs [s]
+H: Selects stream s or prints current stream when s was not given.
+---
+N: csp
+P: VSS_WRITE | DB_READ
+D: change stream and play
+U: csp s
+H: Select stream s and start playing. If this results in a
+H: stream-change, skip rest of current audio file.
+---
+N: da
+P: DB_READ | DB_WRITE
+D: drop attribute from database
+U: da att
+H: Use with caution. All info on attribute att will be lost.
+---
+N: hist
+P: DB_READ
+D: print history
+U: hist
+H: Print list of all audio files together with number of days since
+H: each file was last played.
+---
+N: info
+P: DB_READ
+D: print database info
+U: info [af]
+H: print database informations for audio file af. Current audio file
+H: is used if af is not given.
+---
+N: la
+P: DB_READ
+D: list attributes
+U: la [af]
+H: List attributes of audio file af or of current audio file when
+H: invoked without arguments.
+---
+N: laa
+P: DB_READ
+D: list available attributes
+U: laa
+H: print list of all attributes defined in the database
+---
+N: last
+P: DB_READ
+D: print list of audio files, ordered by lastplayed time
+U: last [n]
+H: The optional number n defaults to 10 if not specified.
+---
+N: ls
+P: DB_READ
+D: list all audio files that match a LIKE pattern
+U: ls [pattern]
+H: If pattern was not given, print list of all audio files known
+H: to the mysql selector. See the documentation of mysql
+H: for the definition of LIKE patterns.
+---
+N: mbox
+P: DB_READ
+D: dump audio file list in mbox format
+U: mbox [p]
+H: Dump list of audio files in mbox format (email) to stdout. If
+H: the optional pattern p is given, only those audio files,
+H: whose basename match p are going to be included. Otherwise,
+H: all files are selected.
+H:
+H: EXAMPLE
+H: The mbox command can be used together with your favorite
+H: mailer (this example uses mutt) for browsing the audio file
+H: collection:
+H:
+H:     para_client mbox > ~/para_mbox
+H:
+H:     mutt -F ~/.muttrc.para -f ~/para_mbox
+H:
+H: For playlists, you can use mutt's powerful pattern matching
+H: language to select files. If you like to tag all files
+H: containing the pattern 'foo', type 'T', then '~s foo'.
+H:
+H: When ready with the list, type ';|' (i.e., hit the semicolon
+H: key to apply the next mutt command to all tagged messages,
+H: then the pipe key) to pipe the selected mails to a
+H: suitable script which adds a paraslash stream where exactly
+H: these files are admissable or does whatever thou wilt.
+---
+N: mv
+P: DB_READ | DB_WRITE
+D: rename entry in database
+U: mv oldname newname
+H: Rename oldname to newname. This updates the data table to reflect
+H: the new name. All internal data (numplayed, lastplayed, picid,..)
+H: is kept.  If newname is a full path, the dir table is updated as
+H: well.
+---
+N: na
+P: DB_READ | DB_WRITE
+D: add new attribute to database
+U: na att
+H: This adds a column named att to your mysql database. att should
+H: only contain letters and numbers, in paricular, '+' and '-' are
+H: not allowed.
+---
+N: ne
+P: DB_READ | DB_WRITE
+D: add new database entries
+U: ne file1 [file2 [...]]
+H: Add the given filename(s) to the database, where file1,... must
+H: be full path names. This command might be much faster than 'upd'
+H: if the number of given files is small.
+---
+N: ns
+P: VSS_WRITE | DB_READ | DB_WRITE
+D: change to next stream
+U: ns
+H: Cycle forwards through stream list.
+---
+N: pic
+P: DB_READ
+D: get picture by name or by identifier
+U: pic [name]
+H: Dump jpg image that is associated to given audio file (current
+H: audio file if not specified) to stdout. If name starts with
+H: '#' it is interpreted as an identifier instead and the picture
+H: having that identifier is dumped to stdout.
+H:
+H: EXAMPLE
+H:
+H:     para_client pic '#123' > pic123.jpg
+---
+N: picadd
+P: DB_READ | DB_WRITE
+D: add picture to database
+U: picadd [picname]
+H: Read jpeg file from stdin and store it as picname in database.
+H:
+H: EXAMPLE
+H:
+H:     para_client picadd foo.jpg < foo.jpg
+---
+N: picass
+P: DB_READ | DB_WRITE
+D: associate a picture to file(s)
+U: picass pic_id file1 [file2...]
+H: Associate the picture given by pic_id to all given files.
+---
+N: picch
+P: DB_READ | DB_WRITE
+D: change name of picture
+U: picch id new_name
+H: Asign new_name to picture with identifier id.
+---
+N: picdel
+P: DB_READ | DB_WRITE
+D: delete picture from database
+U: picdel id1 [id2...]
+H: Delete each given picture from database.
+---
+N: piclist
+P: DB_READ
+D: print list of pictures
+U: piclist
+H: Print id, name and length of each picture contained in the
+H: database.
+---
+N: ps
+P: VSS_WRITE | DB_READ | DB_WRITE
+D: change to previous stream
+U: ps
+H: Cycle backwards through stream list.
+---
+N: rm
+P: DB_READ | DB_WRITE
+D: remove entries from database
+U: rm name1 [name2 [...]]
+H: Remove name1, name2, ... from the data table. Use with caution.
+---
+N: sa
+P: DB_READ | DB_WRITE
+D: set/unset attributes
+U: sa at1<'+' | '-'> [at2<'+' | '-'> ] [af1 ...]
+H: Set ('+') or unset ('-') attribute at1, at2 etc. for given list of
+H: audio files. If no audio files were given the current audio file is
+H: used. Example:
+H:
+H:     sa rock+ punk+ classic- LZ__Waldsterben.mp3
+H:
+H: sets the 'rock' and the 'punk' attribute but unsets the 'classic'
+H: attribute.
+---
+N: skip
+P: DB_READ | DB_WRITE
+D: skip subsequent audio files(s)
+U: skip n [s]
+H: Skip the next n audio files of stream s. This is equivalent to the
+H: command 'sl n s', followed by 'us name' for each name the output of
+H: sl.
+---
+N: sl
+P: DB_READ
+D: print score list
+U: sl n [s]
+H: Print sorted list of maximal n lines. Each line is an admissible
+H: entry with respect to stream s. The list is sorted by score-value
+H: which is given by the definition of s. If s is not given, the
+H: current stream is used. Example:
+H:
+H:     sl 1
+H:
+H: shows you the audio file the server would select right now.
+---
+N: snp
+P: DB_READ | DB_WRITE
+D: set numplayed
+U: snp number af1 [af2 ...]
+H: Update the numplayed field in the data table for all given audio
+H: files.
+---
+N: stradd
+P: DB_READ | DB_WRITE
+D: add stream
+U: stradd s
+H: Add stream s to the list of available streams. The stream
+H: definition for s is read from stdin and is then sent to
+H: para_server. Example:
+H:
+H:     echo 'deny: NAME_LIKE(%Madonna%)' | para_client stradd no_madonna
+H:
+H: adds the new stream 'no_madonna' to the list of available streams.
+H: A given audio file is admissible for this stream iff its basename
+H: does not contain the string 'Madonna'.
+---
+N: strdel
+P: DB_READ | DB_WRITE
+D: delete stream
+U: strdel s
+H: Remove stream s from database.
+---
+N: streams
+P: DB_READ
+D: list streams
+U: streams
+H: Print list of available streams. Use 'cs' to switch to any of
+H: these.
+---
+N: strq
+P: DB_READ
+D: query stream definition
+U: strq [s]
+H: Print definition of stream s to stdout. Use current stream if s was
+H: not given.
+---
+N: summary
+P: DB_READ
+D: list attributes
+U: summary
+H: Print a list of attributes together with number of audio
+H: files having that attribute set.
+---
+N: upd
+P: DB_READ | DB_WRITE
+D: update database
+U: upd
+H: This command uses the --audio_file_dir option of para_server to
+H: locate your audio files. New files are then added to the mysql
+H: database. Use this command if you got new files or if you have
+H: moved some files around.
+---
+N: us
+P: DB_READ | DB_WRITE
+D: update lastplayed time
+U: us name
+H: Update lastplayed time without actually playing the thing.
+---
+N: verb
+P: DB_READ | DB_WRITE
+D: send verbatim sql query
+U: verb cmd
+H: Send cmd to mysql server. For expert/debugging only. Note that cmd
+H: usually must be escaped. Use only if you know what you are doing!
+---
+N: vrfy
+P: DB_READ
+D: list invalid entries in database
+U: vrfy
+H: Show what clean would delete. Run 'upd' before this command to make
+H: sure your database is up to date.
+---
index 010c9d2..c40976d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006-2007 Andre Noll <maan@systemlinux.org>
  *
  *     This program is free software; you can redistribute it and/or modify
  *     it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
 #include "string.h"
 #include "ipc.h"
 #include "user_list.h"
+#include "playlist_selector_command_list.h"
 
 /**
  * structure used for transmission of the playlist
@@ -62,34 +63,8 @@ static unsigned playlist_len, playlist_size, current_playlist_entry;
 static char **playlist;
 static struct audio_file_selector *self;
 
-static int com_ppl(int, int, char **);
-static int com_lpl(int, int, char **);
 extern struct misc_meta_data *mmd;
 
-/* array of supported commands */
-static struct server_command cmds[] = {
-{
-.name = "ppl",
-.handler = com_ppl,
-.perms = DB_READ,
-.description = "print playlist",
-.synopsis = "ppl",
-.help =
-"Print out the current playlist"
-}, {
-.name = "lpl",
-.handler = com_lpl,
-.perms = DB_WRITE,
-.description = "load playlist",
-.synopsis = "lpl",
-.help =
-"Read a new playlist from stdin. Example:\n"
-"\tfind /audio -name '*.mp3' | para_client lpl"
-}, {
-.name = NULL,
-}
-};
-
 static void playlist_add(char *path)
 {
        if (playlist_len >= playlist_size) {
@@ -143,7 +118,7 @@ out:
        return ret;
 }
 
-static int com_lpl(int fd, __a_unused int argc, __a_unused char *argv[])
+int com_lpl(int fd, __a_unused int argc, __a_unused char *argv[])
 {
        unsigned loaded = 0;
        size_t bufsize = 4096; /* guess that's enough */
@@ -174,7 +149,7 @@ out:
        return ret;
 }
 
-static int com_ppl(int fd, __a_unused int argc, __a_unused char *argv[])
+int com_ppl(int fd, __a_unused int argc, __a_unused char *argv[])
 {
        unsigned i;
 
@@ -316,7 +291,7 @@ int playlist_selector_init(struct audio_file_selector *db)
        void *shm = NULL;
 
        self = db;
-       db->cmd_list = cmds;
+       db->cmd_list = playlist_selector_cmds;
        db->get_audio_file_list = pls_get_audio_file_list;
        db->shutdown = pls_shutdown;
        db->post_select = pls_post_select;
diff --git a/playlist_selector.cmd b/playlist_selector.cmd
new file mode 100644 (file)
index 0000000..f829028
--- /dev/null
@@ -0,0 +1,20 @@
+FN: playlist_selector_command_list
+HC: prototypes for the commands of the playlist audio file selector
+CC: array of commands for the playlist audio file selector
+AT: server_command
+IN: server user_list
+SN: list of playlist selector commands
+---
+N: ppl
+P: DB_READ
+D: print playlist
+U: ppl
+H: Print out the current playlist
+---
+N: lpl
+P: DB_WRITE
+D: load playlist
+U: lpl
+H: Read a new playlist from stdin. Example:
+H: find /audio -name '*.mp3' | para_client lpl
+---
index 7bf3402..4c803d8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2006 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2004-2007 Andre Noll <maan@systemlinux.org>
  *
  *     This program is free software; you can redistribute it and/or modify
  *     it under the terms of the GNU General Public License as published by
@@ -25,8 +25,8 @@
 #include "error.h"
 #include "net.h"
 #include "string.h"
+#include "random_selector_command_list.h"
 
-static int com_random_info(int, int, char **);
 extern struct misc_meta_data *mmd;
 
 static unsigned int num_audio_files, audio_file_count;
@@ -48,23 +48,7 @@ static int remember_file(const char *dir, const char *name)
        return 1;
 }
 
-/* array of commands that are supported by this selector */
-static struct server_command cmds[] = {
-{
-.name = "random_info",
-.handler = com_random_info,
-.perms = 0,
-.description = "about the random audio file selector",
-.synopsis = "random_info",
-.help =
-
-"Select a random file under the given directory"
-}, {
-.name = NULL,
-}
-};
-
-static int com_random_info(int fd, __a_unused int argc, __a_unused char *argv[])
+int com_random_info(int fd, __a_unused int argc, __a_unused char *argv[])
 {
        return send_buffer(fd, "Don't use for huge directories as it is "
                "very inefficient in this case.\n");
@@ -152,7 +136,7 @@ int random_selector_init(struct audio_file_selector *s)
        PARA_INFO_LOG("%s", "registering random handlers ;)\n");
        gettimeofday(&now, NULL);
        srand(now.tv_usec);
-       s->cmd_list = cmds;
+       s->cmd_list = random_selector_cmds;
        s->get_audio_file_list = random_get_audio_file_list;
        s->shutdown = random_shutdown;
        s->update_audio_file = random_update_audio_file;
diff --git a/random_selector.cmd b/random_selector.cmd
new file mode 100644 (file)
index 0000000..fe3ef72
--- /dev/null
@@ -0,0 +1,12 @@
+FN: random_selector_command_list
+HC: prototypes for the commands of the random audio file selector
+CC: array of commands for the random audio file selector
+AT: server_command
+IN: server user_list
+SN: list of random selector commands
+---
+N: random_info
+P: 0
+D: about the random audio file selector
+U: random_info
+H: The random selector chooses files randomly out of the given directory.
diff --git a/server.cmd b/server.cmd
new file mode 100644 (file)
index 0000000..71ed6d9
--- /dev/null
@@ -0,0 +1,146 @@
+FN: server_command_list
+HC: prototypes for the server command handlers
+CC: array of server commands
+AT: server_command
+IN: server user_list
+SN: list of server commands
+---
+N: chs
+P: DB_READ | DB_WRITE
+D: change the current audio file selector
+U: chs [new_selector]
+H: Shutdown the current selector and activate new_selector. If no
+H: argument was given, print the name of the current selector.
+---
+N: ff
+P: VSS_READ | VSS_WRITE
+D: jump amount of time forwards or backwards in current audio file
+U: ff n[-]
+H: Set the 'R' (reposition request) bit of the vss status flags
+H: and enqueue a request to jump n seconds forwards or backwards
+H: in the current audio file.
+H:
+H: EXAMPLE
+H:
+H:     ff 30-
+H:
+H: jumps 30 seconds backwards.
+---
+N: help
+P: 0
+D: print help text
+U: help [command]
+H: Without any arguments, help prints a list of availible commands. When
+H: issued with a command name as first argument, print out a description
+H: for that command.
+---
+N: hup
+P: VSS_WRITE
+D: force reload of config file, log file and user list
+U: hup
+H: Reread the config file and the user list file, close and reopen the log
+H: file, and tell all children to do the same.
+---
+N: jmp
+P: VSS_READ | VSS_WRITE
+D: jump to given position in current audio file
+U: jmp [n]
+H: Set the 'R' (reposition request) bit of the vss status flags
+H: and enqueue a request to jump to n% of the current audio file,
+H: where 0 <= n <= 100.
+---
+N: next
+P: VSS_READ | VSS_WRITE
+D: skip rest of current audio file
+U: next
+H: Set the 'N' (next audio file) bit of the vss status flags. When
+H: playing, change audio file immediately. Equivalent to stop
+H: if paused, NOP if stopped.
+---
+N: nomore
+P: VSS_READ | VSS_WRITE
+D: stop playing after current audio file
+U: nomore
+H: Set the 'O' (no more) bit of the vss status flags. This instructs
+H: para_server to clear the 'P' (playing) bit as soon as it encounters
+H: the 'N' (next audio file) bit being set.
+H: Use this command instead of stop if you don't like
+H: sudden endings.
+---
+N: pause
+P: VSS_READ | VSS_WRITE
+D: pause current audio file
+U: pause
+H: Clear the 'P' (playing) bit of the vss status flags.
+---
+N: play
+P: VSS_READ | VSS_WRITE
+D: start playing or resume playing when paused
+U: play
+H: Set the 'P' (playing) bit of the vss status flags. This
+H: results in starting/continuing to stream.
+---
+N: sb
+P: VSS_READ
+D: print status bar for current audio file
+U: sb [n]
+H: Without any arguments, sb continuously prints a status bar of the
+H: form
+H:
+H:     12:34 [56:12] (56%) filename
+H:
+H: indicating playing time, remaining time, percentage and the name of
+H: the file being streamed. Use the optional number n to let stat exit
+H: after having displayed the status bar n times.
+---
+N: sc
+P: VSS_READ
+D: print name of audio file whenever it changes
+U: sc [n]
+H: sc prints exactly one line (the filename of the audio file
+H: being played) whenever the audio file changes. Stops after
+H: n iterations, or never if n is not specified.
+---
+N: sender
+P: VSS_READ | VSS_WRITE
+D: control paraslash internal senders
+U: sender [s cmd [arguments]]
+H: send command cmd to sender s. cmd may be one of the following:
+H: help, on, off, add, delete, allow, or deny. Note that not all senders
+H: support each command. Try e.g. 'para_client sender http help' for
+H: more information about the http sender. If no argument is given,
+H: print out a list of all senders that are compiled in.
+---
+N: si
+P: 0
+D: print server info
+U: si
+H: Print server uptime and other information.
+---
+N: stat
+P: VSS_READ
+D: print status info for current audio file
+U: stat [n]
+H: Without any arguments, stat continuously prints status messages
+H: about the audio file being streamed. Use the optional number n
+H: to let stat exit after having displayed status n times.
+---
+N: stop
+P: VSS_READ | VSS_WRITE
+D: stop playing
+U: stop
+H: Clear the 'P' (play) bit and set the 'N' bit of the vss status
+H: flags.
+---
+N: term
+P: VSS_READ | VSS_WRITE
+D: terminate para_server
+U: term
+H: Shuts down the server. Instead of this command, you can also send
+H: SIGINT or SIGTERM. It should never be necessary to send SIGKILL.
+---
+N: version
+P: 0
+D: print server's version
+U: version
+H: Show version and other info
index bd2b050..dd5184f 100644 (file)
--- a/server.h
+++ b/server.h
@@ -37,7 +37,7 @@ struct server_command {
 /** one-line description of the command */
        const char *description;
 /** summary of the command line options */
-       const char *synopsis;
+       const char *usage;
 /** the long help text */
        const char *help;
 };
index bd522d3..47e5cd2 100644 (file)
@@ -13,12 +13,26 @@ for instructions on how to use the mysql audio file selector
 shipped with paraslash.
 <p>
 The various commands of para_server and para_audiod are explained in
-paraslash's
-       <a href="doc/html/index.html">manual pages</a>.
+the corresponding manual pages:
+<ul>
+       <li> <a href="man/para_server.html">para_server</a>. </li>
+       <li> <a href="man/para_audiod.html">para_audiod</a>. </li>
+</ul>
+Further manual pages:
+<ul>
+       <li> <a href="man/para_audioc.html">para_audioc</a> </li>
+       <li> <a href="man/para_client.html">para_client</a> </li>
+       <li> <a href="man/para_fade.html">para_fade</a> </li>
+       <li> <a href="man/para_filter.html">para_filter</a> </li>
+       <li> <a href="man/para_gui.html">para_gui</a> </li>
+       <li> <a href="man/para_recv.html">para_recv</a> </li>
+       <li> <a href="man/para_sdl_gui.html">para_sdl_gui</a> </li>
+       <li> <a href="man/para_write.html">para_write</a> </li>
+</ul>
 </p>
 <p>
-As of version 0.2.10, the source of para_server and para_audiod is fully documented.
-Have a look at the
+As of version 0.2.10, the source code of paraslash's core programs is fully
+documented.  Have a look at the
        <a href="doxygen/html/index.html">Paraslash API Reference</a>.
 </p>
 <p> Finally, you can <a href="HTML/index.html">RTFS online</a>.