Convert para_fade to lopsub.
authorAndre Noll <maan@tuebingen.mpg.de>
Sun, 10 Apr 2016 20:31:11 +0000 (22:31 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Sun, 26 Mar 2017 09:02:28 +0000 (11:02 +0200)
This replaces the ggo file for the command line and config file parser
of para_fade by a lopsub suite file and links para_fade against the
lopsub library.

As there are no subcommands, the conversion is straight forward and
the bulk of the patch are simple changes which replace access to the
gengetopt structure by equivalent lopsub constructs.

Makefile.real
configure.ac
fade.c
m4/gengetopt/fade.m4 [deleted file]
m4/lls/fade.suite.m4 [new file with mode: 0644]

index ee60363..84872be 100644 (file)
@@ -43,11 +43,12 @@ all_objs := $(sort $(recv_objs) $(filter_objs) $(client_objs) $(gui_objs) \
        $(audiod_objs) $(audioc_objs) $(fade_objs) $(server_objs) \
        $(write_objs) $(afh_objs) $(play_objs))
 deps := $(addprefix $(dep_dir)/, $(filter-out %.cmdline.d, $(all_objs:.o=.d)))
-converted_executables := audioc client
+converted_executables := audioc client fade
 unconverted_executables := $(filter-out $(converted_executables), $(executables))
 
 audioc_objs += audioc.lsg.o
 audiod_objs += audiod_cmd.lsg.o recv_cmd.lsg.o client.lsg.o
+fade_objs += fade.lsg.o
 server_objs += server_cmd.lsg.o
 play_objs += play_cmd.lsg.o recv_cmd.lsg.o
 recv_objs += recv_cmd.lsg.o
@@ -305,6 +306,7 @@ para_fade \
 para_audioc \
 para_audiod \
 para_client \
+para_fade \
 para_play \
 para_recv \
 para_server \
index a22c5f1..909205e 100644 (file)
@@ -618,8 +618,7 @@ fi
 if test $HAVE_OSS = yes -o $HAVE_ALSA = yes; then
        build_fade="yes"
        executables="$executables fade"
-       fade_cmdline_objs="fade"
-       fade_errlist_objs="fade exec string fd version ggo"
+       fade_errlist_objs="fade exec string fd version"
        if test $HAVE_OSS = yes; then
                fade_errlist_objs="$fade_errlist_objs oss_mix"
                mixers="${mixers}oss "
@@ -630,7 +629,7 @@ if test $HAVE_OSS = yes -o $HAVE_ALSA = yes; then
                mixers="${mixers}alsa "
                default_mixer="ALSA_MIX"
        fi
-       fade_objs="add_cmdline($fade_cmdline_objs) $fade_errlist_objs"
+       fade_objs="$fade_errlist_objs"
        AC_SUBST(fade_objs, add_dot_o($fade_objs))
        enum="$(
                for i in $mixers; do
diff --git a/fade.c b/fade.c
index 67dc4d5..34237c6 100644 (file)
--- a/fade.c
+++ b/fade.c
@@ -7,27 +7,33 @@
 /** \file fade.c A volume fader and alarm clock for OSS. */
 
 #include <regex.h>
+#include <lopsub.h>
 
-#include "fade.cmdline.h"
+#include "fade.lsg.h"
 #include "para.h"
 #include "fd.h"
 #include "string.h"
 #include "mix.h"
 #include "error.h"
-#include "ggo.h"
 #include "version.h"
 
 /** Array of error strings. */
 DEFINE_PARA_ERRLIST;
 
-static struct fade_args_info conf;
-
 enum mixer_id {MIXER_ENUM};
 static char *mixer_name[] = {MIXER_NAMES};
 DECLARE_MIXER_INITS;
 static struct mixer supported_mixer[] = {MIXER_ARRAY};
 #define FOR_EACH_MIXER(i) for ((i) = 0; (i) < NUM_SUPPORTED_MIXERS; (i)++)
 
+static struct lls_parse_result *lpr;
+
+#define CMD_PTR (lls_cmd(0, fade_suite))
+#define OPT_RESULT(_name) (lls_opt_result(LSG_FADE_PARA_FADE_OPT_ ## _name, lpr))
+#define OPT_GIVEN(_name) (lls_opt_given(OPT_RESULT(_name)))
+#define OPT_STRING_VAL(_name) (lls_string_val(0, OPT_RESULT(_name)))
+#define OPT_UINT32_VAL(_name) (lls_uint32_val(0, OPT_RESULT(_name)))
+
 static int loglevel;
 static __printf_2_3 void date_log(int ll, const char *fmt, ...)
 {
@@ -70,7 +76,7 @@ static int fade(struct mixer *m, struct mixer_handle *h, int new_vol, int fade_t
                goto out;
        vol = ret;
        PARA_NOTICE_LOG("fading %s from %d to %d in %u seconds\n",
-               conf.mixer_channel_arg, vol, new_vol, secs);
+               OPT_STRING_VAL(MIXER_CHANNEL), vol, new_vol, secs);
        diff = new_vol - vol;
        if (!diff) {
                sleep(secs);
@@ -123,7 +129,7 @@ fail:
        exit(EXIT_FAILURE);
 }
 
-static void change_afs_mode(char *afs_mode)
+static void change_afs_mode(const char *afs_mode)
 {
        char *cmd;
 
@@ -139,8 +145,9 @@ static int set_initial_volume(struct mixer *m, struct mixer_handle *h)
 {
        int i, ret;
 
-       for (i = 0; i < conf.ivol_given; i++) {
-               char *p, *ch, *arg = para_strdup(conf.ivol_arg[i]);
+       for (i = 0; i < OPT_GIVEN(IVOL); i++) {
+               const char *val = lls_string_val(i, OPT_RESULT(IVOL));
+               char *p, *ch, *arg = para_strdup(val);
                int32_t iv;
                p = strchr(arg, ':');
                if (p) {
@@ -178,19 +185,19 @@ static int sweet_dreams(struct mixer *m, struct mixer_handle *h)
        time_t t1, wake_time_epoch;
        unsigned int delay;
        struct tm *tm;
-       int ret, min = conf.wake_min_arg;
-       char *fo_mood = conf.fo_mood_arg;
-       char *fi_mood = conf.fi_mood_arg;
-       char *sleep_mood = conf.sleep_mood_arg;
-       int fit = conf.fi_time_arg;
-       int fot = conf.fo_time_arg;
-       int fiv = conf.fi_vol_arg;
-       int fov = conf.fo_vol_arg;
+       int ret, min = OPT_UINT32_VAL(WAKE_MIN);
+       const char *fo_mood = OPT_STRING_VAL(FO_MOOD);
+       const char *fi_mood = OPT_STRING_VAL(FI_MOOD);
+       const char *sleep_mood = OPT_STRING_VAL(SLEEP_MOOD);
+       int fit = OPT_UINT32_VAL(FI_TIME);
+       int fot = OPT_UINT32_VAL(FO_TIME);
+       int fiv = OPT_UINT32_VAL(FI_VOL);
+       int fov = OPT_UINT32_VAL(FO_VOL);
 
        /* calculate wake time */
        time(&t1);
-       if (conf.wake_hour_given) {
-               int hour = conf.wake_hour_arg;
+       if (OPT_GIVEN(WAKE_HOUR)) {
+               int hour = OPT_UINT32_VAL(WAKE_HOUR);
                tm = localtime(&t1);
                if (tm->tm_hour > hour || (tm->tm_hour == hour && tm->tm_min> min)) {
                        t1 += 86400; /* wake time is tomorrow */
@@ -214,7 +221,7 @@ static int sweet_dreams(struct mixer *m, struct mixer_handle *h)
                        return ret;
                change_afs_mode(fo_mood);
                client_cmd("play");
-               ret = set_channel(m, h, conf.mixer_channel_arg);
+               ret = set_channel(m, h, OPT_STRING_VAL(MIXER_CHANNEL));
                if (ret < 0)
                        return ret;
                ret = fade(m, h, fov, fot);
@@ -225,7 +232,7 @@ static int sweet_dreams(struct mixer *m, struct mixer_handle *h)
                if (ret < 0)
                        return ret;
        }
-       if (conf.sleep_mood_given) {
+       if (OPT_GIVEN(SLEEP_MOOD)) {
                change_afs_mode(sleep_mood);
                client_cmd("play");
        } else
@@ -253,37 +260,25 @@ static int snooze(struct mixer *m, struct mixer_handle *h)
 {
        int ret, val;
 
-       if (conf.so_time_arg <= 0)
+       if (OPT_UINT32_VAL(SO_TIME) == 0)
                return 1;
        ret = m->get(h);
        if (ret < 0)
                return ret;
        val = ret;
-       if (val < conf.so_vol_arg)
-               ret = m->set(h, conf.so_vol_arg);
+       if (val < OPT_UINT32_VAL(SO_VOL))
+               ret = m->set(h, OPT_UINT32_VAL(SO_VOL));
        else
-               ret = fade(m, h, conf.so_vol_arg, conf.so_time_arg);
+               ret = fade(m, h, OPT_UINT32_VAL(SO_VOL),
+                       OPT_UINT32_VAL(SO_TIME));
        if (ret < 0)
                return ret;
        client_cmd("pause");
-       PARA_NOTICE_LOG("%d seconds snooze time...\n", conf.snooze_time_arg);
-       sleep(conf.snooze_time_arg);
+       PARA_NOTICE_LOG("%" PRIu32 " seconds snooze time...\n",
+               OPT_UINT32_VAL(SNOOZE_TIME));
+       sleep(OPT_UINT32_VAL(SNOOZE_TIME));
        client_cmd("play");
-       return fade(m, h, conf.si_vol_arg, conf.si_time_arg);
-}
-
-static int configfile_exists(void)
-{
-       static char *config_file;
-
-       if (!conf.config_file_given) {
-               char *home = para_homedir();
-               free(config_file);
-               config_file = make_message("%s/.paraslash/fade.conf", home);
-               free(home);
-               conf.config_file_arg = config_file;
-       }
-       return file_exists(conf.config_file_arg);
+       return fade(m, h, OPT_UINT32_VAL(SI_VOL), OPT_UINT32_VAL(SI_TIME));
 }
 
 static void init_mixers(void)
@@ -300,18 +295,18 @@ static void init_mixers(void)
 
 static int set_val(struct mixer *m, struct mixer_handle *h)
 {
-       return m->set(h, conf.val_arg);
+       return m->set(h, OPT_UINT32_VAL(VAL));
 }
 
 static struct mixer *get_mixer_or_die(void)
 {
        int i;
 
-       if (!conf.mixer_api_given)
+       if (!OPT_GIVEN(MIXER_API))
                i = DEFAULT_MIXER;
        else
                FOR_EACH_MIXER(i)
-                       if (!strcmp(mixer_name[i], conf.mixer_api_arg))
+                       if (!strcmp(mixer_name[i], OPT_STRING_VAL(MIXER_API)))
                                break;
        if (i < NUM_SUPPORTED_MIXERS) {
                PARA_NOTICE_LOG("using %s mixer API\n", mixer_name[i]);
@@ -326,13 +321,19 @@ static struct mixer *get_mixer_or_die(void)
        exit(EXIT_FAILURE);
 }
 
-__noreturn static void print_help_and_die(void)
+static void handle_help_flags(void)
 {
-       struct ggo_help h = DEFINE_GGO_HELP(fade);
-       bool d = conf.detailed_help_given;
+       char *help;
 
-       ggo_print_help(&h, d? GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS);
-       exit(0);
+       if (OPT_GIVEN(DETAILED_HELP))
+               help = lls_long_help(CMD_PTR);
+       else if (OPT_GIVEN(HELP))
+               help = lls_short_help(CMD_PTR);
+       else
+               return;
+       printf("%s\n", help);
+       free(help);
+       exit(EXIT_SUCCESS);
 }
 
 /**
@@ -348,63 +349,93 @@ __noreturn static void print_help_and_die(void)
  */
 int main(int argc, char *argv[])
 {
+       const struct lls_command *cmd = CMD_PTR;
        int ret;
+       char *cf, *errctx;
        struct mixer *m;
-       struct mixer_handle *h = NULL;
-
-       fade_cmdline_parser(argc, argv, &conf);
-       loglevel = get_loglevel_by_name(conf.loglevel_arg);
-       version_handle_flag("fade", conf.version_given);
-       if (conf.help_given || conf.detailed_help_given)
-               print_help_and_die();
-       ret = configfile_exists();
-       if (!ret && conf.config_file_given) {
-               PARA_EMERG_LOG("can not read config file %s\n",
-                       conf.config_file_arg);
-               exit(EXIT_FAILURE);
+       struct mixer_handle *h;
+       void *map;
+       size_t sz;
+
+       ret = lls(lls_parse(argc, argv, cmd, &lpr, &errctx));
+       if (ret < 0)
+               goto fail;
+       loglevel = OPT_UINT32_VAL(LOGLEVEL);
+       version_handle_flag("fade", OPT_GIVEN(VERSION));
+       handle_help_flags();
+
+       if (OPT_GIVEN(CONFIG_FILE))
+               cf = para_strdup(OPT_STRING_VAL(CONFIG_FILE));
+       else {
+               char *home = para_homedir();
+               cf = make_message("%s/.paraslash/fade.conf", home);
+               free(home);
        }
-       if (ret) {
-               struct fade_cmdline_parser_params params = {
-                       .override = 0,
-                       .initialize = 0,
-                       .check_required = 0,
-                       .check_ambiguity = 0,
-                       .print_errors = 1
-               };
-               fade_cmdline_parser_config_file(conf.config_file_arg,
-                       &conf, &params);
-               loglevel = get_loglevel_by_name(conf.loglevel_arg);
+       ret = mmap_full_file(cf, O_RDONLY, &map, &sz, NULL);
+       if (ret < 0) {
+               if (ret != -E_EMPTY && ret != -ERRNO_TO_PARA_ERROR(ENOENT))
+                       goto free_cf;
+               if (ret == -ERRNO_TO_PARA_ERROR(ENOENT) && OPT_GIVEN(CONFIG_FILE))
+                       goto free_cf;
+       } else {
+               int cf_argc;
+               char **cf_argv;
+               struct lls_parse_result *cf_lpr, *merged_lpr;
+               ret = lls(lls_convert_config(map, sz, NULL, &cf_argv, &errctx));
+               para_munmap(map, sz);
+               if (ret < 0)
+                       goto free_cf;
+               cf_argc = ret;
+               ret = lls(lls_parse(cf_argc, cf_argv, CMD_PTR, &cf_lpr, &errctx));
+               lls_free_argv(cf_argv);
+               if (ret < 0)
+                       goto free_cf;
+               ret = lls(lls_merge(lpr, cf_lpr, CMD_PTR, &merged_lpr,
+                       &errctx));
+               lls_free_parse_result(cf_lpr, CMD_PTR);
+               if (ret < 0)
+                       goto free_cf;
+               lls_free_parse_result(lpr, CMD_PTR);
+               lpr = merged_lpr;
+               loglevel = OPT_UINT32_VAL(LOGLEVEL);
        }
        init_mixers();
        m = get_mixer_or_die();
-       ret = m->open(conf.mixer_device_arg, &h);
+       ret = m->open(OPT_STRING_VAL(MIXER_DEVICE), &h);
        if (ret < 0)
-               goto out;
-       ret = set_channel(m, h, conf.mixer_channel_arg);
+               goto free_cf;
+       ret = set_channel(m, h, OPT_STRING_VAL(MIXER_CHANNEL));
        if (ret == -E_BAD_CHANNEL) {
                char *channels = m->get_channels(h);
                printf("Available channels: %s\n", channels);
                free(channels);
        }
        if (ret < 0)
-               goto out;
-       switch (conf.mode_arg) {
-       case mode_arg_fade:
-               ret = fade(m, h, conf.fade_vol_arg, conf.fade_time_arg);
-               break;
-       case mode_arg_snooze:
+               goto close_mixer;
+       if (strcmp(OPT_STRING_VAL(MODE), "fade") == 0)
+               ret = fade(m, h, OPT_UINT32_VAL(FADE_VOL),
+                       OPT_UINT32_VAL(FADE_TIME));
+       else if (strcmp(OPT_STRING_VAL(MODE), "snooze") == 0)
                ret = snooze(m, h);
-               break;
-       case mode_arg_set:
+       else if (strcmp(OPT_STRING_VAL(MODE), "set") == 0)
                ret = set_val(m, h);
-               break;
-       default: /* sleep mode */
+       else if (strcmp(OPT_STRING_VAL(MODE), "sleep") == 0)
                ret = sweet_dreams(m, h);
-               break;
+       else {
+               PARA_ERROR_LOG("invalid mode: %s\n", OPT_STRING_VAL(MODE));
+               ret = -ERRNO_TO_PARA_ERROR(EINVAL);
        }
-out:
+close_mixer:
        m->close(&h);
-       if (ret < 0)
-               PARA_EMERG_LOG("%s\n", para_strerror(-ret));
-       return ret < 0? EXIT_FAILURE : EXIT_SUCCESS;
+free_cf:
+       free(cf);
+       lls_free_parse_result(lpr, CMD_PTR);
+       if (ret >= 0)
+               return EXIT_SUCCESS;
+fail:
+       if (errctx)
+               PARA_ERROR_LOG("%s\n", errctx);
+       free(errctx);
+       PARA_EMERG_LOG("%s\n", para_strerror(-ret));
+       return EXIT_FAILURE;
 }
diff --git a/m4/gengetopt/fade.m4 b/m4/gengetopt/fade.m4
deleted file mode 100644 (file)
index 59389ff..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-args "--conf-parser --no-handle-version --no-handle-help"
-
-purpose "An alarm clock and volume-fader for OSS and ALSA"
-
-include(header.m4)
-define(CURRENT_PROGRAM,para_fade)
-define(DEFAULT_CONFIG_FILE,~/.paraslash/fade.conf)
-<qu>
-section "General options"
-#########################
-
-</qu>
-include(config_file.m4)
-include(loglevel.m4)
-<qu>
-option "mode" o
-#~~~~~~~~~~~~~~
-"how to fade volume"
-       enum typestr = "mode"
-       values = "sleep", "fade", "set", "snooze"
-       default = "sleep"
-       optional
-       details="
-               para_fade knows the following modes:
-
-               sleep mode: Change to the initial volume and select
-               the initial afs mood/playlist. Then fade out until
-               the fade-out volume is reached. Switch to the
-               sleep mood/playlist until wake time minus fade-in
-               time. Finally switch to the wake mood/playlist and
-               fade to the fade-in volume.
-
-               fade: Fade the volume to the given value in the
-               given time.
-
-               set: Just set the value and exit.
-
-               snooze: Fade out, sleep a bit and fade in.
-"
-
-option "mixer-api" a
-#~~~~~~~~~~~~~~~~~~~
-"choose the mixer API"
-       string typestr = "api"
-       optional
-       details = "
-               ALSA is preferred over OSS if both APIs are supported
-               and this option is not given. To see the supported
-               mixer APIs, use this option with an invalid string
-               as the mixer API, e.g. --mixer-api help.
-       "
-
-option "mixer-device" m
-#~~~~~~~~~~~~~~~~~~~~~~
-"choose mixer device"
-       string typestr = "device"
-       optional
-       details = "
-               The default device (used if this option is not given)
-               depends on the selected mixer API. For ALSA, the
-               default is 'hw:0' which corresponds to the first sound
-               device. For OSS, '/dev/mixer' is used as the default.
-       "
-
-option "mixer-channel" C
-#~~~~~~~~~~~~~~~~~~~~~~~
-"select the analog mixer channel"
-       string typestr = "channel"
-       optional
-       details = "
-               For the ALSA mixer API, the possible values are
-               determined at runtime depending on the hardware and
-               can be printed by specifying an invalid mixer channel,
-               for example --mixer-channel help. The default channel
-               is 'Master'.
-
-               For OSS the possible values are invariably 'volume',
-               'bass', 'treble', 'synth', 'pcm', 'speaker', 'line',
-               'mic', 'cd', 'imix', 'altpcm', 'reclev', 'igain',
-               'ogain'. However, not all listed channels might be
-               supported on any particular hardware. The default
-               channel is 'volume'.
-       "
-
-section "Options for sleep mode"
-################################
-
-option "ivol" -
-#~~~~~~~~~~~~~~
-"set initial volume"
-       string typestr = "[channel:]volume"
-       default = "60"
-       optional
-       multiple
-       details = "
-               Used as the start volume, before fading out to the
-               fade out volume. The channel part may be omitted, in
-               which case the default channel is used. This option
-               may be given multiple times.
-       "
-
-option "fo-mood" -
-#~~~~~~~~~~~~~~~~~
-"afs mood/playlist during fade out"
-       string typestr = "mood_spec"
-       default = "m/fade"
-       optional
-       details = "
-               Select this mood right after setting the
-               volume. Example: --fo-mood m/sleep
-"
-
-option "fo-time" -
-#~~~~~~~~~~~~~~~~~
-"fall asleep fade out time"
-       int typestr = "seconds"
-       default = "1800"
-       optional
-       details = "
-               No fading if set to 0.
-       "
-
-option "fo-vol" -
-#~~~~~~~~~~~~~~~~
-"volume to fade out to"
-       int typestr = "volume"
-       default = "20"
-       optional
-
-option "sleep-mood" -
-#~~~~~~~~~~~~~~~~~~~~
-"sleep time afs mood/playlist"
-       string typestr = "mood_spec"
-       default = "m/sleep"
-       optional
-       details = "
-               Select the given afs mood/playlist after the fade
-               out is complete. If unset, the \"stop\" command is
-               sent to para_server.
-       "
-
-option "wake-hour" H
-#~~~~~~~~~~~~~~~~~~~
-"(0-23) (default: now + 9 hours)"
-       int typestr = "hour"
-       optional
-
-option "wake-min" M
-#~~~~~~~~~~~~~~~~~~
-"(0-59)"
-       int typestr = "minutes"
-       default = "0"
-       optional
-
-option "fi-mood" -
-#~~~~~~~~~~~~~~~~~
-"afs mood/playlist during fade in"
-       string typestr = "mood_spec"
-       default = "m/wake"
-       optional
-       details = "
-               Change to this afs mood/playlist on wake time.
-       "
-
-option "fi-time" -
-#~~~~~~~~~~~~~~~~~
-"wake up fade in time"
-       int typestr="seconds"
-       default="1200"
-       optional
-       details = "
-               No fading in if set to 0.
-       "
-
-option "fi-vol" -
-#~~~~~~~~~~~~~~~~
-"volume to fade to at wake time"
-       int typestr = "volume"
-       default = "80"
-       optional
-
-section "Options for snooze mode"
-#################################
-
-option "so-time" -
-#~~~~~~~~~~~~~~~~~
-"snooze-out time"
-       int typestr = "seconds"
-       default = "30"
-       optional
-
-option "so-vol" -
-#~~~~~~~~~~~~~~~~
-"volume to fade to before snooze"
-       int typestr = "volume"
-       default = "20"
-       optional
-
-option "snooze-time" -
-#~~~~~~~~~~~~~~~~~~~~~
-"delay"
-       int typestr = "seconds"
-       default = "600"
-       optional
-
-option "si-time" -
-#~~~~~~~~~~~~~~~~~
-"snooze-in time"
-       int typestr = "seconds"
-       default = "180"
-       optional
-
-option "si-vol" -
-#~~~~~~~~~~~~~~~~
-"volume to fade to after snooze"
-       int typestr = "volume"
-       default = "80"
-       optional
-
-section "Options for fade mode"
-###############################
-
-option "fade-vol" f
-#~~~~~~~~~~~~~~~~~~
-"volume to fade to"
-       int typestr = "volume"
-       default = "50"
-       optional
-
-option "fade-time" t
-#~~~~~~~~~~~~~~~~~~~
-"fading time"
-       int typestr = "seconds"
-       default = "5"
-       optional
-
-section "Options for set mode"
-##############################
-
-option "val" -
-"value to set"
-       int typestr = "value"
-       default = "0"
-       optional
-
-</qu>
diff --git a/m4/lls/fade.suite.m4 b/m4/lls/fade.suite.m4
new file mode 100644 (file)
index 0000000..5e0eee2
--- /dev/null
@@ -0,0 +1,227 @@
+m4_define(PROGRAM, para_fade)
+m4_define(DEFAULT_CONFIG_FILE, ~/.paraslash/fade.conf)
+[suite fade]
+version-string = GIT_VERSION()
+[supercommand para_fade]
+       purpose = alarm clock and volume-fader for OSS and ALSA
+       [description]
+               para_fade is a simple program which adjusts the settings of an audio
+               mixing device. It can set the level of a mixer channel, or fade the
+               level from one value to another in a given time period. In sleep and
+               snooze mode, it contacts para_server to start or stop streaming.
+       [/description]
+       m4_include(common-option-section.m4)
+       m4_include(help.m4)
+       m4_include(detailed-help.m4)
+       m4_include(version.m4)
+       m4_include(config-file.m4)
+       m4_include(loglevel.m4)
+       m4_include(per-command-options-section.m4)
+       [option mode]
+               short_opt = o
+               summary = select mode of operation (sleep, fade, set or snooze)
+               arg_info = required_arg
+               arg_type = string
+               default_val = sleep
+               typestr = mode
+               [help]
+                       sleep: Change to the initial volume and select the initial
+                       afs mood/playlist. Then fade out until the fade-out volume is
+                       reached. Switch to the sleep mood/playlist until wake time minus
+                       fade-in time. Finally switch to the wake mood/playlist and fade to
+                       the fade-in volume.
+
+                       fade: Fade the volume to the given value in the given time.
+
+                       set: Just set the value and exit.
+
+                       snooze: Fade out, sleep a bit, and fade in.
+               [/help]
+       [option mixer-api]
+               short_opt = a
+               summary = select alternative mixer API
+               arg_info = required_arg
+               arg_type = string
+               typestr = api
+               [help]
+                       ALSA is preferred over OSS if both APIs are supported and this option
+                       is not given. To see the supported mixer APIs, use this option with
+                       an invalid string as the mixer API, e.g. --mixer-api help.
+               [/help]
+       [option mixer-device]
+               short_opt = m
+               summary = set mixer device
+               arg_info = required_arg
+               arg_type = string
+               typestr = device
+               [help]
+                       The default device (used if this option is not given) depends
+                       on the selected mixer API. For ALSA, the default is 'hw:0' which
+                       corresponds to the first sound device. For OSS, '/dev/mixer' is used
+                       as the default.
+               [/help]
+       [option mixer-channel]
+               short_opt = C
+               summary = select the analog mixer channel
+               arg_info = required_arg
+               arg_type = string
+               typestr = channel
+               [help]
+                       For the ALSA mixer API, the possible values are determined at runtime
+                       depending on the hardware and can be printed by specifying an invalid
+                       mixer channel, for example --mixer-channel help. The default channel is
+                       'Master'.
+
+                       For OSS the possible values are invariably 'volume', 'bass', 'treble',
+                       'synth', 'pcm', 'speaker', 'line', 'mic', 'cd', 'imix', 'altpcm',
+                       'reclev', 'igain', 'ogain'. However, not all listed channels might be
+                       supported on any particular hardware. The default channel is 'volume'.
+               [/help]
+       [option ignored]
+               summary = Options for sleep mode
+               flag ignored
+       [option ivol]
+               summary = set initial volume
+               arg_info = required_arg
+               arg_type = string
+               default_val = 60
+               flag multiple
+               typestr = [channel:]volume
+               [help]
+                       Used as the start volume, before fading out to the fade-out volume. The
+                       channel part may be omitted, in which case the default channel is
+                       used. This option may be given multiple times.
+               [/help]
+       [option fo-mood]
+               summary = mood or playlist for fade-out
+               arg_info = required_arg
+               arg_type = string
+               typestr = mood_spec
+               default_val = m/fade
+               [help]
+                       This mood (or playlist) is selected right after setting the initial
+                       volume.
+               [/help]
+       [option fo-time]
+               summary = duration of fade-out period
+               arg_info = required_arg
+               arg_type = uint32
+               typestr = seconds
+               default_val = 1800
+               [help]
+                       No fading if this is set to 0.
+               [/help]
+       [option fo-vol]
+               summary = destination volume for fade-out
+               arg_info = required_arg
+               arg_type = uint32
+               typestr = volume
+               default_val = 20
+       [option sleep-mood]
+               summary = mood/playlist between fade-out and fade-in
+               arg_info = required_arg
+               arg_type = string
+               typestr = mood_spec
+               default_val = m/sleep
+               [help]
+                       Select the given mood or playlist after the fade-out. If unset,
+                       playback is stopped until fade-in starts.
+               [/help]
+       [option wake-hour]
+               short_opt = H
+               summary = A number between 0 and 23
+               arg_info = required_arg
+               arg_type = uint32
+               typestr = hour
+               [help]
+                       If this is not given, the default is computed as now + 9 hours.
+               [/help]
+       [option wake-min]
+               short_opt = M
+               summary = A number between 0 and 59
+               arg_info = required_arg
+               arg_type = uint32
+               typestr = minutes
+       [option fi-mood]
+               summary = mood or playlist for fade-in
+               arg_info = required_arg
+               arg_type = string
+               typestr = mood_spec
+               default_val = m/wake
+               [help]
+                       This mood or playlist is selected right before fade-in begins.
+               [/help]
+       [option fi-time]
+               summary = duration of fade-in period
+               arg_info = required_arg
+               arg_type = uint32
+               typestr = seconds
+               default_val = 1200
+               [help]
+                       No fading if this is set to 0.
+               [/help]
+       [option fi-vol]
+               summary = destination volume for fade-in
+               arg_info = required_arg
+               arg_type = uint32
+               typestr = volume
+               default_val = 80
+       [option ignored]
+               summary = Options for snooze mode
+               flag ignored
+       [option so-time]
+               summary = duration of fade-out period
+               arg_info = required_arg
+               arg_type = uint32
+               typestr = seconds
+               default_val = 30
+       [option so-vol]
+               summary = destination volume for fade-out
+               arg_info = required_arg
+               arg_type = uint32
+               typestr = volume
+               default_val = 20
+       [option snooze-time]
+               summary = delay between end of fade-out and begin of fade-in
+               arg_info = required_arg
+               arg_type = uint32
+               typestr = seconds
+               default_val = 600
+       [option si-time]
+               summary = duration of fade-in period
+               arg_info = required_arg
+               arg_type = uint32
+               typestr = seconds
+               default_val = 180
+       [option si-vol]
+               summary = destination volume for fade-in
+               arg_info = required_arg
+               arg_type = uint32
+               typestr = volume
+               default_val = 80
+       [option ignored]
+               summary = Options for fade mode
+               flag ignored
+       [option fade-vol]
+               short_opt = f
+               summary = destination volume for fading
+               arg_info = required_arg
+               arg_type = uint32
+               typestr = volume
+               default_val = 50
+       [option fade-time]
+               short_opt = t
+               summary = duration of fade period
+               arg_info = required_arg
+               arg_type = uint32
+               typestr = seconds
+               default_val = 5
+       [option ignored]
+               summary = Options for set mode
+               flag ignored
+       [option val]
+               summary = mixer channel value to set
+               arg_info = required_arg
+               arg_type = uint32
+               typestr = value
+               default_val = 10