Merge branch 'refs/heads/t/mixer'
authorAndre Noll <maan@tuebingen.mpg.de>
Sun, 15 Mar 2020 14:51:20 +0000 (15:51 +0100)
committerAndre Noll <maan@tuebingen.mpg.de>
Sun, 15 Mar 2020 14:56:36 +0000 (15:56 +0100)
A single patch for para_mixer which makes the subcommands which
sleep a bit more robust.

The merge conflicted due to commit d6b25bf854c1 (mixer: fade: Handle
empty mood strings gracefully) from half a year ago, but the resolution
was obvious.

Cooking for nine months.

* refs/heads/t/mixer:
  mixer: sleep/snooze: Close mixer during sleep.

1  2 
NEWS.md
mixer.c

diff --combined NEWS.md
+++ b/NEWS.md
@@@ -1,31 -1,6 +1,32 @@@
  NEWS
  ====
  
 +----------------------------------------------
 +0.6.3 (to be announced) "generalized activity"
 +----------------------------------------------
 +
 +- The ff command now accepts a negative argument to instruct the
 +  virtual streaming system to jump backwards in the current audio
 +  stream. The old syntax (e.g., "ff 30-") is still supported but it
 +  is deprecated and no longer documented. The compatibility code is
 +  sheduled for removal after 0.7.0.
 +- para_afh: New option: --preserve to reset the modification time to
 +  the value of the original file after meta data modification.
 +- Overhaul of the compress filter code. The refined algorithm should
 +  reduce clipping. The meaning of --aggressiveness has changed, see the
 +  updated and extended documentation of the compress filter for details.
 +- Cleanup of the audio format handler code.
 +- We now build the tree using the .ONESHELL feature of GNU make,
 +  which results in a significant speedup.
 +- Two robustness fixes for FreeBSD.
 +- para_client now supports RFC4716 private keys as generated with
 +  ssh-keygen -m RFC4716. In fact, this key format has been made the
 +  default, and the former PEM keys will be depreciated at some point.
 +- The ogg audio format handlers learned to detect holes and now report
 +  the correct duration also if ogg pages are missing in the file. This
 +  affects ogg/vorbis ogg/speex and ogg/opus.
++- Robustness improvements for para_mixer.
 +
  --------------------------------------
  0.6.2 (2018-06-30) "elastic diversity"
  --------------------------------------
diff --combined mixer.c
+++ b/mixer.c
@@@ -40,7 -40,7 +40,7 @@@ static struct lls_parse_result *lpr, *s
  #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;
@@@ -153,11 -153,37 +153,37 @@@ 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);
  
@@@ -237,7 -263,7 +263,7 @@@ static int set_initial_volume(const str
        return 1;
  }
  
- static int com_sleep(const struct mixer *m, struct mixer_handle *h)
+ static int com_sleep(const struct mixer *m)
  {
        time_t t1, wake_time_epoch;
        unsigned int delay;
        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, ':');
                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);
        PARA_INFO_LOG("waketime: %d:%02d\n", tm->tm_hour, tm->tm_min);
        client_cmd("stop");
        sleep(1);
 -      if (fot && fo_mood) {
 +      if (fot && fo_mood && *fo_mood) {
                ret = set_initial_volume(m, h);
                if (ret < 0)
-                       return ret;
+                       goto close_mixer;
                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;
+                       goto close_mixer;
                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 */
 +      } else if (fot && fo_mood && *fo_mood) /* currently playing */
                client_cmd("stop");
 -      if (!fit || !fi_mood) /* nothing to do */
+       m->close(&h);
 +      if (!fit || !fi_mood || !*fi_mood) /* nothing to do */
                return 1;
        for (;;) {
                time(&t1);
                sleep(delay);
        }
        change_afs_mode(fi_mood);
 -      if (sleep_mood) /* currently playing */
 +      if (sleep_mood && *sleep_mood) /* currently playing */
                client_cmd("next");
        else /* currently stopped */
                client_cmd("play");
+       ret = open_mixer_and_set_channel(m, &h);
+       if (ret < 0)
+               return ret;
        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));
                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);
  
@@@ -402,9 -457,7 +457,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);
@@@ -487,7 -540,6 +540,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));
        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: