X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=mixer.c;h=b14bb76ebe150864ae261da3c668c0be885e2f74;hp=52af25f9c22ae5397f03c5bf61daaae0f1bb67bd;hb=HEAD;hpb=2031b9cab9304b02c0372f73eef54d9501277031 diff --git a/mixer.c b/mixer.c index 52af25f9..dda7fc1d 100644 --- a/mixer.c +++ b/mixer.c @@ -1,6 +1,6 @@ /* Copyright (C) 1998 Andre Noll , see file COPYING. */ -/** \file mixer.c A volume fader and alarm clock for OSS. */ +/** \file mixer.c A volume fader and alarm clock. */ #include #include @@ -8,6 +8,7 @@ #include "mixer.lsg.h" #include "para.h" +#include "lsu.h" #include "fd.h" #include "string.h" #include "mix.h" @@ -39,7 +40,7 @@ static struct lls_parse_result *lpr, *sub_lpr; #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)(const struct mixer *, struct mixer_handle *); +typedef int (*mixer_subcommand_handler_t)(const struct mixer *); #define EXPORT_CMD(_cmd) const mixer_subcommand_handler_t \ lsg_mixer_com_ ## _cmd ## _user_data = &com_ ## _cmd; @@ -152,19 +153,45 @@ sleep: return ret; } -static int com_fade(const struct mixer *m, struct mixer_handle *h) +static int open_mixer_and_set_channel(const struct mixer *m, struct mixer_handle **h) +{ + int ret; + + ret = m->open(OPT_STRING_VAL(PARA_MIXER, MIXER_DEVICE), h); + if (ret < 0) + return ret; + 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); + free(channels); + } + if (ret < 0) + m->close(h); + return ret; +} + +static int com_fade(const struct mixer *m) { 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); + struct mixer_handle *h; + int ret; + + ret = open_mixer_and_set_channel(m, &h); + if (ret < 0) + return ret; + ret = fade(m, h, new_vol, fade_time); + m->close(&h); + return ret; } EXPORT_CMD(fade); -static void client_cmd(const char *cmd) +static void run(const char *exe, const char *cmd) { int ret, status, fds[3] = {0, 0, 0}; pid_t pid; - char *cmdline = make_message(BINDIR "/para_client %s", cmd); + char *cmdline = make_message("%s %s", exe, cmd); PARA_NOTICE_LOG("%s\n", cmdline); ret = para_exec_cmdline_pid(&pid, cmdline, fds); @@ -188,6 +215,16 @@ fail: exit(EXIT_FAILURE); } +static void client_cmd(const char *cmd) +{ + run(BINDIR "/para_client", cmd); +} + +static void audioc_cmd(const char *cmd) +{ + run(BINDIR "/para_audioc", cmd); +} + static void change_afs_mode(const char *afs_mode) { char *cmd; @@ -236,13 +273,28 @@ static int set_initial_volume(const struct mixer *m, struct mixer_handle *h) return 1; } -static int com_sleep(const struct mixer *m, struct mixer_handle *h) +static void stop(const struct mixer *m, struct mixer_handle *h) +{ + int ret, old_vol = 0; + + ret = m->get(h); + if (ret > 0) + old_vol = ret; + fade(m, h, 0, 3); + audioc_cmd("off"); + client_cmd("stop"); + audioc_cmd("on"); + m->set(h, old_vol); +} + +static int com_sleep(const struct mixer *m) { time_t t1, wake_time_epoch; unsigned int delay; struct tm *tm; int ret; const char *wake_time = OPT_STRING_VAL(SLEEP, WAKE_TIME); + const char *initial_mood = OPT_STRING_VAL(SLEEP, INITIAL_MOOD); 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); @@ -251,9 +303,13 @@ static int com_sleep(const struct mixer *m, struct mixer_handle *h) int fiv = OPT_UINT32_VAL(SLEEP, FI_VOL); int fov = OPT_UINT32_VAL(SLEEP, FO_VOL); int32_t hour, min = 0; - char *tmp; - char *wt = para_strdup(wake_time + (wake_time[0] == '+')); + char *tmp, *wt; + struct mixer_handle *h; + ret = open_mixer_and_set_channel(m, &h); + if (ret < 0) + return ret; + wt = para_strdup(wake_time + (wake_time[0] == '+')); /* calculate wake time */ time(&t1); tmp = strchr(wt, ':'); @@ -263,13 +319,13 @@ static int com_sleep(const struct mixer *m, struct mixer_handle *h) ret = para_atoi32(tmp, &min); if (ret < 0) { free(wt); - return ret; + goto close_mixer; } } ret = para_atoi32(wt, &hour); free(wt); if (ret < 0) - return ret; + goto close_mixer; if (wake_time[0] == '+') { /* relative */ t1 += hour * 60 * 60 + min * 60; tm = localtime(&t1); @@ -285,34 +341,44 @@ static int com_sleep(const struct mixer *m, struct mixer_handle *h) } wake_time_epoch = mktime(tm); PARA_INFO_LOG("waketime: %d:%02d\n", tm->tm_hour, tm->tm_min); - client_cmd("stop"); - sleep(1); - if (fot && fo_mood) { - ret = set_initial_volume(m, h); - if (ret < 0) - return ret; + stop(m, h); + ret = set_initial_volume(m, h); + if (ret < 0) + goto close_mixer; + /* + * Setting the volume invalidates the current channel setting, so we + * have to set it again. + */ + ret = set_channel(m, h, OPT_STRING_VAL(PARA_MIXER, MIXER_CHANNEL)); + if (ret < 0) + goto close_mixer; + delay = OPT_UINT32_VAL(SLEEP, INITIAL_DELAY); + if (delay > 0 && initial_mood && *initial_mood) { + change_afs_mode(initial_mood); + client_cmd("play"); + sleep(delay); + stop(m, h); + } + if (fot && fo_mood && *fo_mood) { change_afs_mode(fo_mood); client_cmd("play"); - ret = set_channel(m, h, OPT_STRING_VAL(PARA_MIXER, MIXER_CHANNEL)); - if (ret < 0) - return ret; ret = fade(m, h, fov, fot); if (ret < 0) - return ret; + goto close_mixer; } else { ret = m->set(h, fov); if (ret < 0) - return ret; + goto close_mixer; } - if (sleep_mood) { + if (sleep_mood && *sleep_mood) { change_afs_mode(sleep_mood); if (!fot || !fo_mood) /* currently stopped */ client_cmd("play"); - } else if (fot && fo_mood) /* currently playing */ - client_cmd("stop"); - if (!fit || !fi_mood) /* nothing to do */ + } else if (fot && fo_mood && *fo_mood) /* currently playing */ + stop(m, h); + m->close(&h); + if (!fit || !fi_mood || !*fi_mood) /* nothing to do */ return 1; - change_afs_mode(fi_mood); for (;;) { time(&t1); if (wake_time_epoch <= t1 + fit) @@ -323,22 +389,34 @@ static int com_sleep(const struct mixer *m, struct mixer_handle *h) (delay % 3600) / 60); sleep(delay); } + change_afs_mode(fi_mood); + ret = open_mixer_and_set_channel(m, &h); + if (ret < 0) + return ret; + if (sleep_mood && *sleep_mood) /* currently playing */ + stop(m, h); client_cmd("play"); ret = fade(m, h, fiv, fit); - PARA_INFO_LOG("fade complete, returning\n"); +close_mixer: + m->close(&h); return ret; } EXPORT_CMD(sleep); -static int com_snooze(const struct mixer *m, struct mixer_handle *h) +static int com_snooze(const struct mixer *m) { int ret, val; + struct mixer_handle *h; + ret = open_mixer_and_set_channel(m, &h); + if (ret < 0) + return ret; + ret = 1; if (OPT_UINT32_VAL(SNOOZE, SO_TIME) == 0) - return 1; + goto close_mixer; ret = m->get(h); if (ret < 0) - return ret; + goto close_mixer; val = ret; if (val < OPT_UINT32_VAL(SNOOZE, SO_VOL)) ret = m->set(h, OPT_UINT32_VAL(SNOOZE, SO_VOL)); @@ -346,20 +424,35 @@ static int com_snooze(const struct mixer *m, struct mixer_handle *h) ret = fade(m, h, OPT_UINT32_VAL(SNOOZE, SO_VOL), OPT_UINT32_VAL(SNOOZE, SO_TIME)); if (ret < 0) - return ret; + goto close_mixer; client_cmd("pause"); PARA_NOTICE_LOG("%" PRIu32 " seconds snooze time...\n", OPT_UINT32_VAL(SNOOZE, SNOOZE_TIME)); + m->close(&h); sleep(OPT_UINT32_VAL(SNOOZE, SNOOZE_TIME)); client_cmd("play"); - return fade(m, h, OPT_UINT32_VAL(SNOOZE, SI_VOL), + ret = open_mixer_and_set_channel(m, &h); + if (ret < 0) + goto close_mixer; + ret = fade(m, h, OPT_UINT32_VAL(SNOOZE, SI_VOL), OPT_UINT32_VAL(SNOOZE, SI_TIME)); +close_mixer: + m->close(&h); + return ret; } EXPORT_CMD(snooze); -static int com_set(const struct mixer *m, struct mixer_handle *h) +static int com_set(const struct mixer *m) { - return m->set(h, OPT_UINT32_VAL(SET, VAL)); + struct mixer_handle *h; + int ret; + + ret = open_mixer_and_set_channel(m, &h); + if (ret < 0) + return ret; + ret = m->set(h, OPT_UINT32_VAL(SET, VAL)); + m->close(&h); + return ret; } EXPORT_CMD(set); @@ -398,9 +491,7 @@ static void show_subcommands(void) } } - -static int com_help(__a_unused const struct mixer *m, - __a_unused struct mixer_handle *h) +static int com_help(__a_unused const struct mixer *m) { const struct lls_command *cmd; const struct lls_opt_result *r_l = OPT_RESULT(HELP, LONG); @@ -453,60 +544,16 @@ static void handle_help_flags(void) static int parse_and_merge_config_file(const struct lls_command *cmd) { int ret; - 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; - - 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/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(PARA_MIXER, CONFIG_FILE)) - goto free_cf; - } else { - 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, &cf_lpr, &errctx)); - lls_free_argv(cf_argv); - if (ret < 0) - goto free_cf; - 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(*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; + struct lls_parse_result **lprp = (cmd == lls_cmd(0, mixer_suite))? + &lpr : &sub_lpr; + + ret = lsu_merge_config_file_options(OPT_STRING_VAL(PARA_MIXER, + CONFIG_FILE), "mixer.conf", lprp, cmd, mixer_suite, + 0 /* flags */); + if (ret < 0) + return ret; + loglevel = OPT_UINT32_VAL(PARA_MIXER, LOGLEVEL); + return 1; } /** @@ -527,7 +574,6 @@ int main(int argc, char *argv[]) char *errctx; const char *subcmd; const struct mixer *m; - struct mixer_handle *h; unsigned n; ret = lls(lls_parse(argc, argv, cmd, &lpr, &errctx)); @@ -555,23 +601,10 @@ int main(int argc, char *argv[]) if (ret < 0) goto free_lpr; ret = parse_and_merge_config_file(cmd); - if (ret < 0) - goto free_lpr; - m = get_mixer_or_die(); - ret = m->open(OPT_STRING_VAL(PARA_MIXER, MIXER_DEVICE), &h); if (ret < 0) 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); - free(channels); - } - if (ret < 0) - goto close_mixer; - ret = (*(mixer_subcommand_handler_t *)(lls_user_data(cmd)))(m ,h); -close_mixer: - m->close(&h); + m = get_mixer_or_die(); + ret = (*(mixer_subcommand_handler_t *)(lls_user_data(cmd)))(m); free_sub_lpr: lls_free_parse_result(sub_lpr, cmd); free_lpr: