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"
--------------------------------------
#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;
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);
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);
}
}
-
- 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);
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: