From 7031f4e380b429e9c0eea1b8e5484dabdbb12ae5 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Tue, 27 Dec 2016 22:19:03 +0100 Subject: [PATCH] Convert para_fade to subcommands, rename it to para_mixer. para_fade operates in one of several modes, but the command line options are shared. So most of the options are ignored for any particular mode. With lopsub we can do better and define one subcommand per mode so that options which are only relevant to one subcommand can be made local to that subcommand. With subcommands the syntax of the command changes, which breaks existing scripts. So it seems to be prudent to rename the executable from para_fade to para_mixer. The old name was a bit misleading anyway since the command can do much more than just fade the volume. --- Makefile.in | 2 +- Makefile.real | 10 +- configure.ac | 20 +- m4/lls/{fade.suite.m4 => mixer.suite.m4} | 177 +++++++------ mix.h | 2 +- fade.c => mixer.c | 302 +++++++++++++++-------- t/test-lib.sh | 2 +- web/documentation.in.html | 2 +- web/manual.md | 2 +- 9 files changed, 307 insertions(+), 212 deletions(-) rename m4/lls/{fade.suite.m4 => mixer.suite.m4} (79%) rename fade.c => mixer.c (53%) diff --git a/Makefile.in b/Makefile.in index 2fee61cb..e1f7634e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -19,7 +19,7 @@ client_objs := @client_objs@ gui_objs := @gui_objs@ audiod_objs := @audiod_objs@ audioc_objs := @audioc_objs@ -fade_objs := @fade_objs@ +mixer_objs := @mixer_objs@ server_objs := @server_objs@ write_objs := @write_objs@ afh_objs := @afh_objs@ diff --git a/Makefile.real b/Makefile.real index 669a469f..1fe29d46 100644 --- a/Makefile.real +++ b/Makefile.real @@ -36,7 +36,7 @@ test_dir := t # sort removes duplicate words, which is all we need here all_objs := $(sort $(recv_objs) $(filter_objs) $(client_objs) $(gui_objs) \ - $(audiod_objs) $(audioc_objs) $(fade_objs) $(server_objs) \ + $(audiod_objs) $(audioc_objs) $(mixer_objs) $(server_objs) \ $(write_objs) $(afh_objs) $(play_objs)) deps := $(addprefix $(dep_dir)/, $(all_objs:.o=.d)) @@ -45,7 +45,7 @@ audioc_objs += audioc.lsg.o audiod_objs += $(addsuffix _cmd.lsg.o, recv filter audiod write) \ client.lsg.o audiod.lsg.o client_objs += client.lsg.o -fade_objs += fade.lsg.o +mixer_objs += mixer.lsg.o filter_objs += filter_cmd.lsg.o filter.lsg.o gui_objs += gui.lsg.o play_objs += $(addsuffix _cmd.lsg.o, recv filter play write) play.lsg.o @@ -65,7 +65,7 @@ client_objs := $(addprefix $(object_dir)/, $(client_objs)) gui_objs := $(addprefix $(object_dir)/, $(gui_objs)) audiod_objs := $(addprefix $(object_dir)/, $(audiod_objs)) audioc_objs := $(addprefix $(object_dir)/, $(audioc_objs)) -fade_objs := $(addprefix $(object_dir)/, $(fade_objs)) +mixer_objs := $(addprefix $(object_dir)/, $(mixer_objs)) server_objs := $(addprefix $(object_dir)/, $(server_objs)) write_objs := $(addprefix $(object_dir)/, $(write_objs)) afh_objs := $(addprefix $(object_dir)/, $(afh_objs)) @@ -267,7 +267,7 @@ para_play \ para_write \ para_play \ para_audiod \ -para_fade \ +para_mixer \ : LDFLAGS += \ $(oss_ldflags) \ $(alsa_ldflags) @@ -276,7 +276,7 @@ para_afh \ para_audioc \ para_audiod \ para_client \ -para_fade \ +para_mixer \ para_filter \ para_gui \ para_play \ diff --git a/configure.ac b/configure.ac index 54a313ad..4fe45795 100644 --- a/configure.ac +++ b/configure.ac @@ -580,23 +580,23 @@ if test -n "$CRYPTOLIB"; then else build_audiod="no" fi -########################################################################### fade +########################################################################### mixer if test $HAVE_OSS = yes -o $HAVE_ALSA = yes; then - build_fade="yes" - executables="$executables fade" - fade_errlist_objs="fade exec string fd version" + build_mixer="yes" + executables="$executables mixer" + mixer_errlist_objs="mixer exec string fd version" if test $HAVE_OSS = yes; then - fade_errlist_objs="$fade_errlist_objs oss_mix" + mixer_errlist_objs="$mixer_errlist_objs oss_mix" mixers="${mixers}oss " default_mixer="OSS_MIX" fi if test $HAVE_ALSA = yes; then - fade_errlist_objs="$fade_errlist_objs alsa_mix" + mixer_errlist_objs="$mixer_errlist_objs alsa_mix" mixers="${mixers}alsa " default_mixer="ALSA_MIX" fi - fade_objs="$fade_errlist_objs" - AC_SUBST(fade_objs, add_dot_o($fade_objs)) + mixer_objs="$mixer_errlist_objs" + AC_SUBST(mixer_objs, add_dot_o($mixer_objs)) enum="$( for i in $mixers; do printf "${i}_MIX, " | tr '[a-z]' '[A-Z]' @@ -618,7 +618,7 @@ if test $HAVE_OSS = yes -o $HAVE_ALSA = yes; then array="$(for i in $mixers; do printf '{.init = '$i'_mix_init},'; done)" AC_DEFINE_UNQUOTED(MIXER_ARRAY, $array, array of supported mixers) else - build_fade="no" + build_mixer="no" AC_MSG_WARN([no mixer support]) fi ########################################################################### gui @@ -927,7 +927,7 @@ audio format handlers: $audio_format_handlers para_server: $build_server para_gui: $build_gui -para_fade: $build_fade +para_mixer: $build_mixer para_client: $build_client para_audiod: $build_audiod ]) diff --git a/m4/lls/fade.suite.m4 b/m4/lls/mixer.suite.m4 similarity index 79% rename from m4/lls/fade.suite.m4 rename to m4/lls/mixer.suite.m4 index 5e0eee2a..83d6ad95 100644 --- a/m4/lls/fade.suite.m4 +++ b/m4/lls/mixer.suite.m4 @@ -1,14 +1,16 @@ -m4_define(PROGRAM, para_fade) -m4_define(DEFAULT_CONFIG_FILE, ~/.paraslash/fade.conf) -[suite fade] +m4_define(PROGRAM, para_mixer) +m4_define(DEFAULT_CONFIG_FILE, ~/.paraslash/mixer.conf) +[suite mixer] version-string = GIT_VERSION() -[supercommand para_fade] +caption = List of subcommands +[supercommand para_mixer] purpose = alarm clock and volume-fader for OSS and ALSA + synopsis = [] -- [] [] [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. + para_mixer 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. The sleep and snooze subcommands + contact para_server to start or stop streaming. [/description] m4_include(common-option-section.m4) m4_include(help.m4) @@ -17,26 +19,9 @@ version-string = GIT_VERSION() 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] + [help] + These options apply to several subcommands. + [/help] [option mixer-api] short_opt = a summary = select alternative mixer API @@ -62,7 +47,7 @@ version-string = GIT_VERSION() [/help] [option mixer-channel] short_opt = C - summary = select the analog mixer channel + summary = select a mixer channel arg_info = required_arg arg_type = string typestr = channel @@ -77,9 +62,78 @@ version-string = GIT_VERSION() '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 +[subcommand help] + purpose = print subcommand help + non-opts-name = [] + [option long] + summary = print the long help text + short_opt = l + +[subcommand set] + purpose = set a channel to the given value and exit + [option val] + summary = mixer channel value to set + arg_info = required_arg + arg_type = uint32 + typestr = value + default_val = 10 +[subcommand fade] + purpose = fade a channel to the given value in the given time + [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 +[subcommand snooze] + purpose = fade out, pause, sleep, play, fade in + [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 +[subcommand sleep] + purpose = stream, fade out, sleep, fade in + [description] + Change to the initial volume and select the initial mood/playlist. + Fade out to the given fade-out volume in the specified time. Switch + to the sleep mood/playlist and wait until wake time minus fade-in + time. Finally, switch to the wake mood/playlist and fade in to the + fade-in volume. + [/description] [option ivol] summary = set initial volume arg_info = required_arg @@ -166,62 +220,3 @@ version-string = GIT_VERSION() 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 diff --git a/mix.h b/mix.h index 60c4392f..fe85d746 100644 --- a/mix.h +++ b/mix.h @@ -4,7 +4,7 @@ * Licensed under the GPL v2. For licencing details see COPYING. */ -/** \file mix.h Mixer API (used by para_fade). */ +/** \file mix.h Mixer API for para_mixer. */ /** * Opaque structure which corresponds to an instance of a mixer. diff --git a/fade.c b/mixer.c similarity index 53% rename from fade.c rename to mixer.c index 34237c6b..2089c5b1 100644 --- a/fade.c +++ b/mixer.c @@ -4,12 +4,12 @@ * Licensed under the GPL v2. For licencing details see COPYING. */ -/** \file fade.c A volume fader and alarm clock for OSS. */ +/** \file mixer.c A volume fader and alarm clock for OSS. */ #include #include -#include "fade.lsg.h" +#include "mixer.lsg.h" #include "para.h" #include "fd.h" #include "string.h" @@ -26,13 +26,19 @@ 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; +static struct lls_parse_result *lpr, *sub_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))) +#define CMD_PTR(_cmd) (lls_cmd(LSG_MIXER_CMD_ ## _cmd, mixer_suite)) +#define OPT_RESULT(_cmd, _opt) (lls_opt_result( \ + LSG_MIXER_ ## _cmd ## _OPT_ ## _opt, (LSG_MIXER_CMD_ ## _cmd == 0)? lpr : sub_lpr)) +#define OPT_GIVEN(_cmd, _opt) (lls_opt_given(OPT_RESULT(_cmd, _opt))) +#define OPT_STRING_VAL(_cmd, _opt) (lls_string_val(0, OPT_RESULT(_cmd, _opt))) +#define OPT_UINT32_VAL(_cmd, _opt) (lls_uint32_val(0, OPT_RESULT(_cmd, _opt))) + +typedef int (*mixer_subcommand_handler_t)(struct mixer *, struct mixer_handle *); + +#define EXPORT_CMD(_cmd) const mixer_subcommand_handler_t \ + lsg_mixer_com_ ## _cmd ## _user_data = &com_ ## _cmd; static int loglevel; static __printf_2_3 void date_log(int ll, const char *fmt, ...) @@ -61,7 +67,8 @@ static int set_channel(struct mixer *m, struct mixer_handle *h, const char *chan } /* Fade to new volume in fade_time seconds. */ -static int fade(struct mixer *m, struct mixer_handle *h, int new_vol, int fade_time) +static int fade(struct mixer *m, struct mixer_handle *h, uint32_t new_vol, + uint32_t fade_time) { int vol, diff, incr, ret; unsigned secs; @@ -75,8 +82,8 @@ static int fade(struct mixer *m, struct mixer_handle *h, int new_vol, int fade_t if (ret < 0) goto out; vol = ret; - PARA_NOTICE_LOG("fading %s from %d to %d in %u seconds\n", - OPT_STRING_VAL(MIXER_CHANNEL), vol, new_vol, secs); + PARA_NOTICE_LOG("fading %s from %d to %u in %u seconds\n", + OPT_STRING_VAL(PARA_MIXER, MIXER_CHANNEL), vol, new_vol, secs); diff = new_vol - vol; if (!diff) { sleep(secs); @@ -100,6 +107,13 @@ static int fade(struct mixer *m, struct mixer_handle *h, int new_vol, int fade_t out: return ret; } +static int com_fade(struct mixer *m, struct mixer_handle *h) +{ + uint32_t new_vol = OPT_UINT32_VAL(FADE, FADE_VOL); + uint32_t fade_time = OPT_UINT32_VAL(FADE, FADE_TIME); + return fade(m, h, new_vol, fade_time); +} +EXPORT_CMD(fade); static void client_cmd(const char *cmd) { @@ -145,8 +159,8 @@ static int set_initial_volume(struct mixer *m, struct mixer_handle *h) { int i, ret; - for (i = 0; i < OPT_GIVEN(IVOL); i++) { - const char *val = lls_string_val(i, OPT_RESULT(IVOL)); + for (i = 0; i < OPT_GIVEN(SLEEP, IVOL); i++) { + const char *val = lls_string_val(i, OPT_RESULT(SLEEP, IVOL)); char *p, *ch, *arg = para_strdup(val); int32_t iv; p = strchr(arg, ':'); @@ -180,24 +194,24 @@ static int set_initial_volume(struct mixer *m, struct mixer_handle *h) return 1; } -static int sweet_dreams(struct mixer *m, struct mixer_handle *h) +static int com_sleep(struct mixer *m, struct mixer_handle *h) { time_t t1, wake_time_epoch; unsigned int delay; struct tm *tm; - 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); + int ret, min = OPT_UINT32_VAL(SLEEP, WAKE_MIN); + const char *fo_mood = OPT_STRING_VAL(SLEEP, FO_MOOD); + const char *fi_mood = OPT_STRING_VAL(SLEEP, FI_MOOD); + const char *sleep_mood = OPT_STRING_VAL(SLEEP, SLEEP_MOOD); + int fit = OPT_UINT32_VAL(SLEEP, FI_TIME); + int fot = OPT_UINT32_VAL(SLEEP, FO_TIME); + int fiv = OPT_UINT32_VAL(SLEEP, FI_VOL); + int fov = OPT_UINT32_VAL(SLEEP, FO_VOL); /* calculate wake time */ time(&t1); - if (OPT_GIVEN(WAKE_HOUR)) { - int hour = OPT_UINT32_VAL(WAKE_HOUR); + if (OPT_GIVEN(SLEEP, WAKE_HOUR)) { + int hour = OPT_UINT32_VAL(SLEEP, WAKE_HOUR); tm = localtime(&t1); if (tm->tm_hour > hour || (tm->tm_hour == hour && tm->tm_min> min)) { t1 += 86400; /* wake time is tomorrow */ @@ -221,7 +235,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, OPT_STRING_VAL(MIXER_CHANNEL)); + ret = set_channel(m, h, OPT_STRING_VAL(PARA_MIXER, MIXER_CHANNEL)); if (ret < 0) return ret; ret = fade(m, h, fov, fot); @@ -232,7 +246,7 @@ static int sweet_dreams(struct mixer *m, struct mixer_handle *h) if (ret < 0) return ret; } - if (OPT_GIVEN(SLEEP_MOOD)) { + if (OPT_GIVEN(SLEEP, SLEEP_MOOD)) { change_afs_mode(sleep_mood); client_cmd("play"); } else @@ -255,31 +269,34 @@ static int sweet_dreams(struct mixer *m, struct mixer_handle *h) PARA_INFO_LOG("fade complete, returning\n"); return ret; } +EXPORT_CMD(sleep); -static int snooze(struct mixer *m, struct mixer_handle *h) +static int com_snooze(struct mixer *m, struct mixer_handle *h) { int ret, val; - if (OPT_UINT32_VAL(SO_TIME) == 0) + if (OPT_UINT32_VAL(SNOOZE, SO_TIME) == 0) return 1; ret = m->get(h); if (ret < 0) return ret; val = ret; - if (val < OPT_UINT32_VAL(SO_VOL)) - ret = m->set(h, OPT_UINT32_VAL(SO_VOL)); + if (val < OPT_UINT32_VAL(SNOOZE, SO_VOL)) + ret = m->set(h, OPT_UINT32_VAL(SNOOZE, SO_VOL)); else - ret = fade(m, h, OPT_UINT32_VAL(SO_VOL), - OPT_UINT32_VAL(SO_TIME)); + ret = fade(m, h, OPT_UINT32_VAL(SNOOZE, SO_VOL), + OPT_UINT32_VAL(SNOOZE, SO_TIME)); if (ret < 0) return ret; client_cmd("pause"); PARA_NOTICE_LOG("%" PRIu32 " seconds snooze time...\n", - OPT_UINT32_VAL(SNOOZE_TIME)); - sleep(OPT_UINT32_VAL(SNOOZE_TIME)); + OPT_UINT32_VAL(SNOOZE, SNOOZE_TIME)); + sleep(OPT_UINT32_VAL(SNOOZE, SNOOZE_TIME)); client_cmd("play"); - return fade(m, h, OPT_UINT32_VAL(SI_VOL), OPT_UINT32_VAL(SI_TIME)); + return fade(m, h, OPT_UINT32_VAL(SNOOZE, SI_VOL), + OPT_UINT32_VAL(SNOOZE, SI_TIME)); } +EXPORT_CMD(snooze); static void init_mixers(void) { @@ -293,20 +310,22 @@ static void init_mixers(void) } } -static int set_val(struct mixer *m, struct mixer_handle *h) +static int com_set(struct mixer *m, struct mixer_handle *h) { - return m->set(h, OPT_UINT32_VAL(VAL)); + return m->set(h, OPT_UINT32_VAL(SET, VAL)); } +EXPORT_CMD(set); static struct mixer *get_mixer_or_die(void) { int i; - if (!OPT_GIVEN(MIXER_API)) + if (!OPT_GIVEN(PARA_MIXER, MIXER_API)) i = DEFAULT_MIXER; else FOR_EACH_MIXER(i) - if (!strcmp(mixer_name[i], OPT_STRING_VAL(MIXER_API))) + if (!strcmp(mixer_name[i], + OPT_STRING_VAL(PARA_MIXER, MIXER_API))) break; if (i < NUM_SUPPORTED_MIXERS) { PARA_NOTICE_LOG("using %s mixer API\n", mixer_name[i]); @@ -321,90 +340,182 @@ static struct mixer *get_mixer_or_die(void) exit(EXIT_FAILURE); } +static void show_subcommands(void) +{ + const struct lls_command *cmd; + int i; + printf("Subcommands:\n"); + for (i = 1; (cmd = lls_cmd(i, mixer_suite)); i++) { + const char *name = lls_command_name(cmd); + const char *purpose = lls_purpose(cmd); + printf("%-20s%s\n", name, purpose); + } +} + + +static int com_help(__a_unused struct mixer *m, __a_unused struct mixer_handle *h) +{ + const struct lls_command *cmd; + const struct lls_opt_result *r_l = OPT_RESULT(HELP, LONG); + char *txt, *errctx; + const char *name; + int ret; + + ret = lls_check_arg_count(sub_lpr, 0, 1, NULL); + if (ret < 0) + return ret; + if (lls_num_inputs(sub_lpr) == 0) { + show_subcommands(); + return 0; + } + name = lls_input(0, sub_lpr); + ret = lls(lls_lookup_subcmd(name, mixer_suite, &errctx)); + if (ret < 0) { + if (errctx) + PARA_ERROR_LOG("%s\n", errctx); + free(errctx); + return ret; + } + cmd = lls_cmd(ret, mixer_suite); + if (lls_opt_given(r_l)) + txt = lls_long_help(cmd); + else + txt = lls_short_help(cmd); + printf("%s", txt); + free(txt); + return 0; +} +EXPORT_CMD(help); + static void handle_help_flags(void) { char *help; - if (OPT_GIVEN(DETAILED_HELP)) - help = lls_long_help(CMD_PTR); - else if (OPT_GIVEN(HELP)) - help = lls_short_help(CMD_PTR); + if (OPT_GIVEN(PARA_MIXER, DETAILED_HELP)) + help = lls_long_help(CMD_PTR(PARA_MIXER)); + else if (OPT_GIVEN(PARA_MIXER, HELP)) + help = lls_short_help(CMD_PTR(PARA_MIXER)); else return; - printf("%s\n", help); + printf("%s", help); free(help); + show_subcommands(); exit(EXIT_SUCCESS); } -/** - * The main function of para_fade. - * - * The executable is linked with the alsa or the oss mixer API, or both. It has - * a custom log function which prefixes log messages with the current date. - * - * \param argc Argument counter. - * \param argv Argument vector. - * - * \return EXIT_SUCCESS or EXIT_FAILURE. - */ -int main(int argc, char *argv[]) +static int parse_and_merge_config_file(const struct lls_command *cmd) { - const struct lls_command *cmd = CMD_PTR; int ret; - char *cf, *errctx; - struct mixer *m; - struct mixer_handle *h; + int cf_argc; + char **cf_argv; + char *cf, *errctx = NULL; + struct lls_parse_result **lprp, *cf_lpr, *merged_lpr; void *map; size_t sz; + const char *subcmd_name; - 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)); + if (cmd == lls_cmd(0, mixer_suite)) { + lprp = &lpr; + subcmd_name = NULL; + } else { + lprp = &sub_lpr; + subcmd_name = lls_command_name(cmd); + } + if (OPT_GIVEN(PARA_MIXER, CONFIG_FILE)) + cf = para_strdup(OPT_STRING_VAL(PARA_MIXER, CONFIG_FILE)); else { char *home = para_homedir(); - cf = make_message("%s/.paraslash/fade.conf", home); + cf = make_message("%s/.paraslash/mixer.conf", home); free(home); } 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)) + if (ret == -ERRNO_TO_PARA_ERROR(ENOENT) && + OPT_GIVEN(PARA_MIXER, 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)); + ret = lls(lls_convert_config(map, sz, subcmd_name, &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)); + ret = lls(lls_parse(cf_argc, cf_argv, cmd, &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); + ret = lls(lls_merge(*lprp, cf_lpr, cmd, &merged_lpr, &errctx)); + lls_free_parse_result(cf_lpr, cmd); if (ret < 0) goto free_cf; - lls_free_parse_result(lpr, CMD_PTR); - lpr = merged_lpr; - loglevel = OPT_UINT32_VAL(LOGLEVEL); + lls_free_parse_result(*lprp, cmd); + *lprp = merged_lpr; + loglevel = OPT_UINT32_VAL(PARA_MIXER, LOGLEVEL); + } + ret = 1; +free_cf: + free(cf); + if (errctx) + PARA_ERROR_LOG("%s\n", errctx); + free(errctx); + return ret; +} + +/** + * The main function of para_mixer. + * + * The executable is linked with the alsa or the oss mixer API, or both. It has + * a custom log function which prefixes log messages with the current date. + * + * \param argc Argument counter. + * \param argv Argument vector. + * + * \return EXIT_SUCCESS or EXIT_FAILURE. + */ +int main(int argc, char *argv[]) +{ + const struct lls_command *cmd = CMD_PTR(PARA_MIXER); + int ret; + char *errctx; + const char *subcmd; + struct mixer *m; + struct mixer_handle *h; + unsigned n; + + ret = lls(lls_parse(argc, argv, cmd, &lpr, &errctx)); + if (ret < 0) + goto fail; + loglevel = OPT_UINT32_VAL(PARA_MIXER, LOGLEVEL); + version_handle_flag("mixer", OPT_GIVEN(PARA_MIXER, VERSION)); + handle_help_flags(); + + n = lls_num_inputs(lpr); + if (n == 0) { + show_subcommands(); + ret = 0; + goto free_lpr; } + ret = parse_and_merge_config_file(cmd); + if (ret < 0) + goto free_lpr; + subcmd = lls_input(0, lpr); + ret = lls(lls_lookup_subcmd(subcmd, mixer_suite, &errctx)); + if (ret < 0) + goto fail; + cmd = lls_cmd(ret, mixer_suite); + ret = lls(lls_parse(n, argv + argc - n, cmd, &sub_lpr, &errctx)); + if (ret < 0) + goto free_lpr; + ret = parse_and_merge_config_file(cmd); + if (ret < 0) + goto free_lpr; init_mixers(); m = get_mixer_or_die(); - ret = m->open(OPT_STRING_VAL(MIXER_DEVICE), &h); + ret = m->open(OPT_STRING_VAL(PARA_MIXER, MIXER_DEVICE), &h); if (ret < 0) - goto free_cf; - ret = set_channel(m, h, OPT_STRING_VAL(MIXER_CHANNEL)); + goto free_sub_lpr; + ret = set_channel(m, h, OPT_STRING_VAL(PARA_MIXER, MIXER_CHANNEL)); if (ret == -E_BAD_CHANNEL) { char *channels = m->get_channels(h); printf("Available channels: %s\n", channels); @@ -412,24 +523,13 @@ int main(int argc, char *argv[]) } if (ret < 0) 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); - else if (strcmp(OPT_STRING_VAL(MODE), "set") == 0) - ret = set_val(m, h); - else if (strcmp(OPT_STRING_VAL(MODE), "sleep") == 0) - ret = sweet_dreams(m, h); - else { - PARA_ERROR_LOG("invalid mode: %s\n", OPT_STRING_VAL(MODE)); - ret = -ERRNO_TO_PARA_ERROR(EINVAL); - } + ret = (*(mixer_subcommand_handler_t *)(lls_user_data(cmd)))(m ,h); close_mixer: m->close(&h); -free_cf: - free(cf); - lls_free_parse_result(lpr, CMD_PTR); +free_sub_lpr: + lls_free_parse_result(sub_lpr, cmd); +free_lpr: + lls_free_parse_result(lpr, CMD_PTR(PARA_MIXER)); if (ret >= 0) return EXIT_SUCCESS; fail: diff --git a/t/test-lib.sh b/t/test-lib.sh index 1f9913e3..9c6516e2 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -311,7 +311,7 @@ fi fixup_dirs [[ -z "$o_executables" ]] && o_executables="para_afh para_audioc para_audiod - para_client para_fade para_filter para_gui para_recv para_server + para_client para_mixer para_filter para_gui para_recv para_server para_write" for exe in $o_executables; do export $(tr 'a-z' 'A-Z' <<< $exe)="$o_executables_dir/$exe" diff --git a/web/documentation.in.html b/web/documentation.in.html index b226943b..9e8b59ce 100644 --- a/web/documentation.in.html +++ b/web/documentation.in.html @@ -29,7 +29,7 @@ [para_filter] [para_write] [para_gui] - [para_fade] + [para_mixere] [para_play]

diff --git a/web/manual.md b/web/manual.md index 9bc86016..1fde2953 100644 --- a/web/manual.md +++ b/web/manual.md @@ -167,7 +167,7 @@ window. Appearance can be customized via themes. para_gui provides key-bindings for the most common server commands and new key-bindings can be added easily. -### para_fade ### +### para_mixer ### An alarm clock and volume-fader for OSS and ALSA. -- 2.39.2