diff -r 3b8e4ee4363e alsactl/alsactl.1 --- a/alsactl/alsactl.1 Mon Oct 15 10:36:47 2007 +0200 +++ b/alsactl/alsactl.1 Fri Dec 14 15:35:34 2007 +0100 @@ -41,7 +41,12 @@ Select the configuration file to use. Th .TP \fI\-F, \-\-force\fP Used with restore command. Try to restore the matching control elements -as much as possible. +as much as possible. This option is set as default now. + +.TP +\fI\-P, \-\-pedantic\fP +Used with restore command. Don't restore mismatching control elements. +This option was the old default behavior. .TP \fI\-d, \-\-debug\fP diff -r 3b8e4ee4363e alsactl/alsactl.c --- a/alsactl/alsactl.c Mon Oct 15 10:36:47 2007 +0200 +++ b/alsactl/alsactl.c Fri Dec 14 15:35:34 2007 +0100 @@ -34,7 +34,7 @@ #define SYS_ASOUNDNAMES "/etc/asound.names" int debugflag = 0; -int force_restore = 0; +int force_restore = 1; char *command; static void help(void) @@ -44,6 +44,8 @@ static void help(void) printf(" -h,--help this help\n"); printf(" -f,--file # configuration file (default " SYS_ASOUNDRC " or " SYS_ASOUNDNAMES ")\n"); printf(" -F,--force try to restore the matching controls as much as possible\n"); + printf(" (default mode)\n"); + printf(" -P,--pedantic don't restore mismatching controls (old default)\n"); printf(" -d,--debug debug mode\n"); printf(" -v,--version print version of this program\n"); printf("\nAvailable commands:\n"); @@ -62,6 +64,7 @@ int main(int argc, char *argv[]) {"help", 0, NULL, 'h'}, {"file", 1, NULL, 'f'}, {"force", 0, NULL, 'F'}, + {"pedantic", 0, NULL, 'P'}, {"debug", 0, NULL, 'd'}, {"version", 0, NULL, 'v'}, {NULL, 0, NULL, 0}, @@ -84,6 +87,9 @@ int main(int argc, char *argv[]) break; case 'F': force_restore = 1; + break; + case 'P': + force_restore = 0; break; case 'd': debugflag = 1; diff -r 3b8e4ee4363e alsactl/state.c --- a/alsactl/state.c Mon Oct 15 10:36:47 2007 +0200 +++ b/alsactl/state.c Fri Dec 14 15:35:34 2007 +0100 @@ -188,6 +188,46 @@ static unsigned int *str_to_tlv(const ch return tlv; } +/* + * add the TLV string and dB ranges to comment fields + */ +static int add_tlv_comments(snd_ctl_t *handle, snd_ctl_elem_id_t *id, + snd_ctl_elem_info_t *info, snd_config_t *comment) +{ + unsigned int tlv[MAX_USER_TLV_SIZE]; + unsigned int *db; + long dbmin, dbmax; + int err; + + if (snd_ctl_elem_tlv_read(handle, id, tlv, sizeof(tlv)) < 0) + return 0; /* ignore error */ + + if (snd_ctl_elem_info_is_tlv_writable(info)) { + char *s = tlv_to_str(tlv); + if (s) { + err = snd_config_string_add(comment, "tlv", s); + if (err < 0) { + error("snd_config_string_add: %s", snd_strerror(err)); + return err; + } + free(s); + } + } + + err = snd_tlv_parse_dB_info(tlv, sizeof(tlv), &db); + if (err <= 0) + return 0; + + snd_tlv_get_dB_range(db, snd_ctl_elem_info_get_min(info), + snd_ctl_elem_info_get_max(info), + &dbmin, &dbmax); + if (err < 0) + return err; + snd_config_integer_add(comment, "dbmin", dbmin); + snd_config_integer_add(comment, "dbmax", dbmax); + return 0; +} + static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id, snd_config_t *top) { snd_ctl_elem_value_t *ctl; @@ -285,23 +325,11 @@ static int get_control(snd_ctl_t *handle error("snd_config_string_add: %s", snd_strerror(err)); return err; } - if (snd_ctl_elem_info_is_tlv_readable(info) && - snd_ctl_elem_info_is_tlv_writable(info)) { - unsigned int tlv[MAX_USER_TLV_SIZE]; - err = snd_ctl_elem_tlv_read(handle, id, tlv, sizeof(tlv)); - if (err >= 0) { - char *s = tlv_to_str(tlv); - if (s) { - err = snd_config_string_add(comment, "tlv", s); - if (err < 0) { - error("snd_config_string_add: %s", snd_strerror(err)); - return err; - } - free(s); - } - } + if (snd_ctl_elem_info_is_tlv_readable(info)) { + err = add_tlv_comments(handle, id, info, comment); + if (err < 0) + return err; } - break; } case SND_CTL_ELEM_TYPE_INTEGER64: @@ -651,6 +679,7 @@ static int config_bool(snd_config_t *n) const char *str; long val; long long lval; + switch (snd_config_get_type(n)) { case SND_CONFIG_TYPE_INTEGER: snd_config_get_integer(n, &val); @@ -665,6 +694,11 @@ static int config_bool(snd_config_t *n) case SND_CONFIG_TYPE_STRING: snd_config_get_string(n, &str); break; + case SND_CONFIG_TYPE_COMPOUND: + if (!force_restore) + return -1; + n = snd_config_iterator_entry(snd_config_iterator_first(n)); + return config_bool(n); default: return -1; } @@ -682,6 +716,7 @@ static int config_enumerated(snd_config_ long val; long long lval; unsigned int idx, items; + switch (snd_config_get_type(n)) { case SND_CONFIG_TYPE_INTEGER: snd_config_get_integer(n, &val); @@ -692,6 +727,11 @@ static int config_enumerated(snd_config_ case SND_CONFIG_TYPE_STRING: snd_config_get_string(n, &str); break; + case SND_CONFIG_TYPE_COMPOUND: + if (!force_restore) + return -1; + n = snd_config_iterator_entry(snd_config_iterator_first(n)); + return config_enumerated(n, handle, info); default: return -1; } @@ -708,6 +748,30 @@ static int config_enumerated(snd_config_ return idx; } return -1; +} + +static int config_integer(snd_config_t *n, long *val) +{ + int err = snd_config_get_integer(n, val); + if (err < 0 && force_restore) { + if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) + return err; + n = snd_config_iterator_entry(snd_config_iterator_first(n)); + return config_integer(n, val); + } + return err; +} + +static int config_integer64(snd_config_t *n, long long *val) +{ + int err = snd_config_get_integer64(n, val); + if (err < 0 && force_restore) { + if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) + return err; + n = snd_config_iterator_entry(snd_config_iterator_first(n)); + return config_integer64(n, val); + } + return err; } static int is_user_control(snd_config_t *conf) @@ -729,6 +793,56 @@ static int is_user_control(snd_config_t return 0; } +/* + * get the item type from the given comment config + */ +static int get_comment_type(snd_config_t *n) +{ + const char *type; + + if (snd_config_get_string(n, &type) < 0) + return -EINVAL; + if (strcmp(type, "BOOLEAN") == 0) + return SND_CTL_ELEM_TYPE_BOOLEAN; + else if (strcmp(type, "INTEGER") == 0) + return SND_CTL_ELEM_TYPE_INTEGER; + else if (strcmp(type, "ENUMERATED") == 0) + return SND_CTL_ELEM_TYPE_ENUMERATED; + else if (strcmp(type, "INTEGER64") == 0) + return SND_CTL_ELEM_TYPE_INTEGER; + else if (strcmp(type, "IEC958") == 0) + return SND_CTL_ELEM_TYPE_IEC958; + else + return -EINVAL; +} + +/* + * get the value range from the given comment config + */ +static int get_comment_range(snd_config_t *n, int ctype, + long *imin, long *imax, long *istep) +{ + const char *s; + int err; + + if (snd_config_get_string(n, &s) < 0) + return -EINVAL; + switch (ctype) { + case SND_CTL_ELEM_TYPE_INTEGER: + err = sscanf(s, "%li - %li (step %li)", imin, imax, istep); + if (err != 3) { + istep = 0; + err = sscanf(s, "%li - %li", imin, imax); + if (err != 2) + return -EINVAL; + } + break; + default: + return -EINVAL; + } + return 0; +} + static int add_user_control(snd_ctl_t *handle, snd_ctl_elem_info_t *info, snd_config_t *conf) { snd_ctl_elem_id_t *id; @@ -745,39 +859,20 @@ static int add_user_control(snd_ctl_t *h tlv = NULL; snd_config_for_each(i, next, conf) { snd_config_t *n = snd_config_iterator_entry(i); - const char *id, *type; + const char *id; if (snd_config_get_id(n, &id) < 0) continue; if (strcmp(id, "type") == 0) { - if ((err = snd_config_get_string(n, &type)) < 0) - return -EINVAL; - if (strcmp(type, "BOOLEAN") == 0) - ctype = SND_CTL_ELEM_TYPE_BOOLEAN; - else if (strcmp(type, "INTEGER") == 0) - ctype = SND_CTL_ELEM_TYPE_INTEGER; - else if (strcmp(type, "IEC958") == 0) - ctype = SND_CTL_ELEM_TYPE_IEC958; - else - return -EINVAL; + err = get_comment_type(n); + if (err < 0) + return err; + ctype = err; continue; } if (strcmp(id, "range") == 0) { - const char *s; - if ((err = snd_config_get_string(n, &s)) < 0) - return -EINVAL; - switch (ctype) { - case SND_CTL_ELEM_TYPE_INTEGER: - err = sscanf(s, "%li - %li (step %li)", &imin, &imax, &istep); - if (err != 3) { - istep = 0; - err = sscanf(s, "%li - %li", &imin, &imax); - if (err != 2) - return -EINVAL; - } - break; - default: - return -EINVAL; - } + err = get_comment_range(n, ctype, &imin, &imax, &istep); + if (err < 0) + return err; continue; } if (strcmp(id, "count") == 0) { @@ -831,6 +926,213 @@ static int add_user_control(snd_ctl_t *h return snd_ctl_elem_info(handle, info); } +/* + * look for a config node with the given item name + */ +static snd_config_t *search_comment_item(snd_config_t *conf, const char *name) +{ + snd_config_iterator_t i, next; + snd_config_for_each(i, next, conf) { + snd_config_t *n = snd_config_iterator_entry(i); + const char *id; + if (snd_config_get_id(n, &id) < 0) + continue; + if (strcmp(id, name) == 0) + return n; + } + return NULL; +} + +/* + * check whether the config item has the same of compatible type + */ +static int check_comment_type(snd_config_t *conf, int type) +{ + snd_config_t *n = search_comment_item(conf, "type"); + int ctype; + + if (!n) + return 0; /* not defined */ + ctype = get_comment_type(n); + if (ctype == type) + return 0; + if ((ctype == SND_CTL_ELEM_TYPE_BOOLEAN || + ctype == SND_CTL_ELEM_TYPE_INTEGER || + ctype == SND_CTL_ELEM_TYPE_INTEGER64 || + ctype == SND_CTL_ELEM_TYPE_ENUMERATED) && + (type == SND_CTL_ELEM_TYPE_BOOLEAN || + type == SND_CTL_ELEM_TYPE_INTEGER || + type == SND_CTL_ELEM_TYPE_INTEGER64 || + type == SND_CTL_ELEM_TYPE_ENUMERATED)) + return 0; /* OK, compatible */ + return -EINVAL; +} + +/* + * convert from an old value to a new value with the same dB level + */ +static int convert_to_new_db(snd_config_t *value, long omin, long omax, + long nmin, long nmax, + long odbmin, long odbmax, + long ndbmin, long ndbmax) +{ + long val; + if (config_integer(value, &val) < 0) + return -EINVAL; + if (val < omin || val > omax) + return -EINVAL; + val = ((val - omin) * (odbmax - odbmin)) / (omax - omin) + odbmin; + if (val < ndbmin) + val = ndbmin; + else if (val > ndbmax) + val = ndbmax; + val = ((val - ndbmin) * (nmax - nmin)) / (ndbmax - ndbmin) + nmin; + return snd_config_set_integer(value, val); +} + +/* + * compare the current value range with the old range in comments. + * also, if dB information is available, try to compare them. + * if any change occurs, try to keep the same dB level. + */ +static int check_comment_range(snd_ctl_t *handle, snd_config_t *conf, + snd_ctl_elem_info_t *info, snd_config_t *value) +{ + snd_config_t *n; + long omin, omax, ostep; + long nmin, nmax; + long odbmin, odbmax; + long ndbmin, ndbmax; + snd_ctl_elem_id_t *id; + + n = search_comment_item(conf, "range"); + if (!n) + return 0; + if (get_comment_range(n, SND_CTL_ELEM_TYPE_INTEGER, + &omin, &omax, &ostep) < 0) + return 0; + nmin = snd_ctl_elem_info_get_min(info); + nmax = snd_ctl_elem_info_get_max(info); + if (omin != nmin && omax != nmax) { + /* Hey, the range mismatches */ + if (!force_restore) + return -EINVAL; + } + if (omin >= omax || nmin >= nmax) + return 0; /* invalid values */ + + n = search_comment_item(conf, "dbmin"); + if (!n) + return 0; + if (config_integer(n, &odbmin) < 0) + return 0; + n = search_comment_item(conf, "dbmax"); + if (!n) + return 0; + if (config_integer(n, &odbmax) < 0) + return 0; + if (odbmin >= odbmax) + return 0; /* invalid values */ + snd_ctl_elem_id_alloca(&id); + snd_ctl_elem_info_get_id(info, id); + if (snd_ctl_get_dB_range(handle, id, &ndbmin, &ndbmax) < 0) + return 0; + if (ndbmin >= ndbmax) + return 0; /* invalid values */ + if (omin == nmin && omax == nmax && + odbmin == ndbmin && odbmax == ndbmax) + return 0; /* OK, identical one */ + + /* Let's guess the current value from dB range */ + if (snd_config_get_type(value) == SND_CONFIG_TYPE_COMPOUND) { + snd_config_iterator_t i, next; + snd_config_for_each(i, next, value) { + snd_config_t *n = snd_config_iterator_entry(i); + convert_to_new_db(n, omin, omax, nmin, nmax, + odbmin, odbmax, ndbmin, ndbmax); + } + } else + convert_to_new_db(value, omin, omax, nmin, nmax, + odbmin, odbmax, ndbmin, ndbmax); + return 0; +} + +static int restore_config_value(snd_ctl_t *handle, snd_ctl_elem_info_t *info, + snd_ctl_elem_iface_t type, + snd_config_t *value, + snd_ctl_elem_value_t *ctl, int idx) +{ + long val; + long long lval; + int err; + + switch (type) { + case SND_CTL_ELEM_TYPE_BOOLEAN: + val = config_bool(value); + if (val >= 0) { + snd_ctl_elem_value_set_boolean(ctl, idx, val); + return 1; + } + break; + case SND_CTL_ELEM_TYPE_INTEGER: + err = config_integer(value, &val); + if (err == 0) { + snd_ctl_elem_value_set_integer(ctl, idx, val); + return 1; + } + break; + case SND_CTL_ELEM_TYPE_INTEGER64: + err = config_integer64(value, &lval); + if (err == 0) { + snd_ctl_elem_value_set_integer64(ctl, idx, lval); + return 1; + } + break; + case SND_CTL_ELEM_TYPE_ENUMERATED: + val = config_enumerated(value, handle, info); + if (val >= 0) { + snd_ctl_elem_value_set_enumerated(ctl, idx, val); + return 1; + } + break; + case SND_CTL_ELEM_TYPE_BYTES: + case SND_CTL_ELEM_TYPE_IEC958: + break; + default: + error("Unknow control type: %d", type); + return -EINVAL; + } + return 0; +} + +static int restore_config_value2(snd_ctl_t *handle, snd_ctl_elem_info_t *info, + snd_ctl_elem_iface_t type, + snd_config_t *value, + snd_ctl_elem_value_t *ctl, int idx, + unsigned int numid) +{ + int err = restore_config_value(handle, info, type, value, ctl, idx); + long val; + + if (err != 0) + return err; + switch (type) { + case SND_CTL_ELEM_TYPE_BYTES: + case SND_CTL_ELEM_TYPE_IEC958: + err = snd_config_get_integer(value, &val); + if (err < 0 || val < 0 || val > 255) { + error("bad control.%d.value.%d content", numid, idx); + return force_restore ? 0 : -EINVAL; + } + snd_ctl_elem_value_set_byte(ctl, idx, val); + return 1; + break; + default: + break; + } + return 0; +} + static int set_control(snd_ctl_t *handle, snd_config_t *control) { snd_ctl_elem_value_t *ctl; @@ -852,8 +1154,6 @@ static int set_control(snd_ctl_t *handle long index = -1; snd_config_t *value = NULL; snd_config_t *comment = NULL; - long val; - long long lval; unsigned int idx; int err; char *set; @@ -994,56 +1294,28 @@ static int set_control(snd_ctl_t *handle return -ENOENT; } -#if 0 if (comment) { - check_comment_type(comment, type); - if (type == SND_CTL_ELEM_TYPE_INTEGER || - type == SND_CTL_ELEM_TYPE_INTEGER64) - check_comment_range(comment, info); + if (check_comment_type(comment, type) < 0) + error("incompatible field type for control #%d", numid); + if (type == SND_CTL_ELEM_TYPE_INTEGER) { + if (check_comment_range(handle, comment, info, value) < 0) { + error("value range mismatch for control #%d", + numid); + return -EINVAL; + } + } } -#endif if (!snd_ctl_elem_info_is_writable(info)) return 0; snd_ctl_elem_value_set_numid(ctl, numid1); if (count == 1) { - switch (type) { - case SND_CTL_ELEM_TYPE_BOOLEAN: - val = config_bool(value); - if (val >= 0) { - snd_ctl_elem_value_set_boolean(ctl, 0, val); - goto _ok; - } - break; - case SND_CTL_ELEM_TYPE_INTEGER: - err = snd_config_get_integer(value, &val); - if (err == 0) { - snd_ctl_elem_value_set_integer(ctl, 0, val); - goto _ok; - } - break; - case SND_CTL_ELEM_TYPE_INTEGER64: - err = snd_config_get_integer64(value, &lval); - if (err == 0) { - snd_ctl_elem_value_set_integer64(ctl, 0, lval); - goto _ok; - } - break; - case SND_CTL_ELEM_TYPE_ENUMERATED: - val = config_enumerated(value, handle, info); - if (val >= 0) { - snd_ctl_elem_value_set_enumerated(ctl, 0, val); - goto _ok; - } - break; - case SND_CTL_ELEM_TYPE_BYTES: - case SND_CTL_ELEM_TYPE_IEC958: - break; - default: - error("Unknow control type: %d", type); - return -EINVAL; - } + err = restore_config_value(handle, info, type, value, ctl, 0); + if (err < 0) + return err; + if (err > 0) + goto _ok; } switch (type) { case SND_CTL_ELEM_TYPE_BYTES: @@ -1080,8 +1352,17 @@ static int set_control(snd_ctl_t *handle break; } if (snd_config_get_type(value) != SND_CONFIG_TYPE_COMPOUND) { - error("bad control.%d.value type", numid); - return -EINVAL; + if (!force_restore) { + error("bad control.%d.value type", numid); + return -EINVAL; + } + for (idx = 0; idx < count; ++idx) { + err = restore_config_value2(handle, info, type, value, + ctl, idx, numid); + if (err < 0) + return err; + } + goto _ok; } set = (char*) alloca(count); @@ -1095,59 +1376,22 @@ static int set_control(snd_ctl_t *handle if (idx < 0 || idx >= count || set[idx]) { error("bad control.%d.value index", numid); - return -EINVAL; + if (!force_restore) + return -EINVAL; + continue; } - switch (type) { - case SND_CTL_ELEM_TYPE_BOOLEAN: - val = config_bool(n); - if (val < 0) { - error("bad control.%d.value.%d content", numid, idx); - return -EINVAL; - } - snd_ctl_elem_value_set_boolean(ctl, idx, val); - break; - case SND_CTL_ELEM_TYPE_INTEGER: - err = snd_config_get_integer(n, &val); - if (err < 0) { - error("bad control.%d.value.%d content", numid, idx); - return -EINVAL; - } - snd_ctl_elem_value_set_integer(ctl, idx, val); - break; - case SND_CTL_ELEM_TYPE_INTEGER64: - err = snd_config_get_integer64(n, &lval); - if (err < 0) { - error("bad control.%d.value.%d content", numid, idx); - return -EINVAL; - } - snd_ctl_elem_value_set_integer64(ctl, idx, lval); - break; - case SND_CTL_ELEM_TYPE_ENUMERATED: - val = config_enumerated(n, handle, info); - if (val < 0) { - error("bad control.%d.value.%d content", numid, idx); - return -EINVAL; - } - snd_ctl_elem_value_set_enumerated(ctl, idx, val); - break; - case SND_CTL_ELEM_TYPE_BYTES: - case SND_CTL_ELEM_TYPE_IEC958: - err = snd_config_get_integer(n, &val); - if (err < 0 || val < 0 || val > 255) { - error("bad control.%d.value.%d content", numid, idx); - return -EINVAL; - } - snd_ctl_elem_value_set_byte(ctl, idx, val); - break; - default: - break; - } - set[idx] = 1; + err = restore_config_value2(handle, info, type, n, + ctl, idx, numid); + if (err < 0) + return err; + if (err > 0) + set[idx] = 1; } for (idx = 0; idx < count; ++idx) { if (!set[idx]) { error("control.%d.value.%d is not specified", numid, idx); - return -EINVAL; + if (!force_restore) + return -EINVAL; } } diff -r 3b8e4ee4363e aplay/aplay.c --- a/aplay/aplay.c Mon Oct 15 10:36:47 2007 +0200 +++ b/aplay/aplay.c Fri Dec 14 15:35:34 2007 +0100 @@ -1462,7 +1462,9 @@ static void voc_pcm_flush(void) if (pcm_write(audiobuf, b) != (ssize_t)b) error(_("voc_pcm_flush error")); } + snd_pcm_nonblock(handle, 0); snd_pcm_drain(handle); + snd_pcm_nonblock(handle, nonblock); } static void voc_play(int fd, int ofs, char *name) @@ -1988,7 +1990,9 @@ void playback_go(int fd, size_t loaded, written += r; l = 0; } + snd_pcm_nonblock(handle, 0); snd_pcm_drain(handle); + snd_pcm_nonblock(handle, nonblock); } @@ -2227,7 +2231,9 @@ void playbackv_go(int* fds, unsigned int r = r * bits_per_frame / 8; count -= r; } + snd_pcm_nonblock(handle, 0); snd_pcm_drain(handle); + snd_pcm_nonblock(handle, nonblock); } void capturev_go(int* fds, unsigned int channels, off64_t count, int rtype, char **names) diff -r 3b8e4ee4363e configure.in --- a/configure.in Mon Oct 15 10:36:47 2007 +0200 +++ b/configure.in Fri Dec 14 15:35:34 2007 +0100 @@ -27,7 +27,9 @@ dnl AC_PROG_CXX dnl AC_PROG_CXX AC_PROG_INSTALL AC_PROG_LN_S -AM_PATH_ALSA(1.0.12) +AM_PATH_ALSA(1.0.15) +AC_CHECK_FUNC(snd_tlv_get_dB_range,, + AC_ERROR([No TLV support code in alsa-lib])) AC_ARG_ENABLE(alsamixer, [ --disable-alsamixer Disable alsamixer compilation], diff -r 3b8e4ee4363e iecset/iecset.c --- a/iecset/iecset.c Mon Oct 15 10:36:47 2007 +0200 +++ b/iecset/iecset.c Fri Dec 14 15:35:34 2007 +0100 @@ -308,7 +308,7 @@ int main(int argc, char **argv) break; case 'c': i = atoi(optarg); - if (i < 0 || i >= 7) { + if (i < 0 || i >= 32) { fprintf(stderr, "invalid card index %d\n", i); return 1; } diff -r 3b8e4ee4363e seq/aseqnet/aseqnet.c --- a/seq/aseqnet/aseqnet.c Mon Oct 15 10:36:47 2007 +0200 +++ b/seq/aseqnet/aseqnet.c Fri Dec 14 15:35:34 2007 +0100 @@ -26,6 +26,7 @@ #include #include #include +#include #include "aconfig.h" #include "gettext.h" diff -r 3b8e4ee4363e speaker-test/speaker-test.c --- a/speaker-test/speaker-test.c Mon Oct 15 10:36:47 2007 +0200 +++ b/speaker-test/speaker-test.c Fri Dec 14 15:35:34 2007 +0100 @@ -276,28 +276,28 @@ static int set_hwparams(snd_pcm_t *handl /* choose all parameters */ err = snd_pcm_hw_params_any(handle, params); if (err < 0) { - printf(_("Broken configuration for playback: no configurations available: %s\n"), snd_strerror(err)); + fprintf(stderr, _("Broken configuration for playback: no configurations available: %s\n"), snd_strerror(err)); return err; } /* set the interleaved read/write format */ err = snd_pcm_hw_params_set_access(handle, params, access); if (err < 0) { - printf(_("Access type not available for playback: %s\n"), snd_strerror(err)); + fprintf(stderr, _("Access type not available for playback: %s\n"), snd_strerror(err)); return err; } /* set the sample format */ err = snd_pcm_hw_params_set_format(handle, params, format); if (err < 0) { - printf(_("Sample format not available for playback: %s\n"), snd_strerror(err)); + fprintf(stderr, _("Sample format not available for playback: %s\n"), snd_strerror(err)); return err; } /* set the count of channels */ err = snd_pcm_hw_params_set_channels(handle, params, channels); if (err < 0) { - printf(_("Channels count (%i) not available for playbacks: %s\n"), channels, snd_strerror(err)); + fprintf(stderr, _("Channels count (%i) not available for playbacks: %s\n"), channels, snd_strerror(err)); return err; } @@ -305,12 +305,12 @@ static int set_hwparams(snd_pcm_t *handl rrate = rate; err = snd_pcm_hw_params_set_rate(handle, params, rate, 0); if (err < 0) { - printf(_("Rate %iHz not available for playback: %s\n"), rate, snd_strerror(err)); + fprintf(stderr, _("Rate %iHz not available for playback: %s\n"), rate, snd_strerror(err)); return err; } if (rrate != rate) { - printf(_("Rate doesn't match (requested %iHz, get %iHz, err %d)\n"), rate, rrate, err); + fprintf(stderr, _("Rate doesn't match (requested %iHz, get %iHz, err %d)\n"), rate, rrate, err); return -EINVAL; } @@ -326,7 +326,7 @@ static int set_hwparams(snd_pcm_t *handl printf(_("Requested period time %u us\n"), period_time); err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, NULL); if (err < 0) { - printf(_("Unable to set period time %u us for playback: %s\n"), + fprintf(stderr, _("Unable to set period time %u us for playback: %s\n"), period_time, snd_strerror(err)); return err; } @@ -335,7 +335,7 @@ static int set_hwparams(snd_pcm_t *handl printf(_("Requested buffer time %u us\n"), buffer_time); err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, NULL); if (err < 0) { - printf(_("Unable to set buffer time %u us for playback: %s\n"), + fprintf(stderr, _("Unable to set buffer time %u us for playback: %s\n"), buffer_time, snd_strerror(err)); return err; } @@ -347,7 +347,7 @@ static int set_hwparams(snd_pcm_t *handl printf(_("Using max buffer size %lu\n"), buffer_size); err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &buffer_size); if (err < 0) { - printf(_("Unable to set buffer size %lu for playback: %s\n"), + fprintf(stderr, _("Unable to set buffer size %lu for playback: %s\n"), buffer_size, snd_strerror(err)); return err; } @@ -356,7 +356,7 @@ static int set_hwparams(snd_pcm_t *handl printf(_("Periods = %u\n"), nperiods); err = snd_pcm_hw_params_set_periods_near(handle, params, &nperiods, NULL); if (err < 0) { - printf(_("Unable to set nperiods %u for playback: %s\n"), + fprintf(stderr, _("Unable to set nperiods %u for playback: %s\n"), nperiods, snd_strerror(err)); return err; } @@ -366,14 +366,14 @@ static int set_hwparams(snd_pcm_t *handl printf(_("was set period_size = %lu\n"),period_size); printf(_("was set buffer_size = %lu\n"),buffer_size); if (2*period_size > buffer_size) { - printf(_("buffer to small, could not use\n")); - return err; + fprintf(stderr, _("buffer to small, could not use\n")); + return -EINVAL; } /* write the parameters to device */ err = snd_pcm_hw_params(handle, params); if (err < 0) { - printf(_("Unable to set hw params for playback: %s\n"), snd_strerror(err)); + fprintf(stderr, _("Unable to set hw params for playback: %s\n"), snd_strerror(err)); return err; } @@ -386,35 +386,35 @@ static int set_swparams(snd_pcm_t *handl /* get the current swparams */ err = snd_pcm_sw_params_current(handle, swparams); if (err < 0) { - printf(_("Unable to determine current swparams for playback: %s\n"), snd_strerror(err)); + fprintf(stderr, _("Unable to determine current swparams for playback: %s\n"), snd_strerror(err)); return err; } /* start the transfer when a buffer is full */ err = snd_pcm_sw_params_set_start_threshold(handle, swparams, buffer_size); if (err < 0) { - printf(_("Unable to set start threshold mode for playback: %s\n"), snd_strerror(err)); + fprintf(stderr, _("Unable to set start threshold mode for playback: %s\n"), snd_strerror(err)); return err; } /* allow the transfer when at least period_size frames can be processed */ err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_size); if (err < 0) { - printf(_("Unable to set avail min for playback: %s\n"), snd_strerror(err)); + fprintf(stderr, _("Unable to set avail min for playback: %s\n"), snd_strerror(err)); return err; } /* align all transfers to 1 sample */ err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1); if (err < 0) { - printf(_("Unable to set transfer align for playback: %s\n"), snd_strerror(err)); + fprintf(stderr, _("Unable to set transfer align for playback: %s\n"), snd_strerror(err)); return err; } /* write the parameters to the playback device */ err = snd_pcm_sw_params(handle, swparams); if (err < 0) { - printf(_("Unable to set sw params for playback: %s\n"), snd_strerror(err)); + fprintf(stderr, _("Unable to set sw params for playback: %s\n"), snd_strerror(err)); return err; } @@ -429,7 +429,7 @@ static int xrun_recovery(snd_pcm_t *hand if (err == -EPIPE) { /* under-run */ err = snd_pcm_prepare(handle); if (err < 0) - printf(_("Can't recovery from underrun, prepare failed: %s\n"), snd_strerror(err)); + fprintf(stderr, _("Can't recovery from underrun, prepare failed: %s\n"), snd_strerror(err)); return 0; } else if (err == -ESTRPIPE) { @@ -440,7 +440,7 @@ static int xrun_recovery(snd_pcm_t *hand if (err < 0) { err = snd_pcm_prepare(handle); if (err < 0) - printf(_("Can't recovery from suspend, prepare failed: %s\n"), snd_strerror(err)); + fprintf(stderr, _("Can't recovery from suspend, prepare failed: %s\n"), snd_strerror(err)); } return 0; @@ -648,9 +648,9 @@ static int write_buffer(snd_pcm_t *handl continue; if (err < 0) { - printf(_("Write error: %d,%s\n"), err, snd_strerror(err)); + fprintf(stderr, _("Write error: %d,%s\n"), err, snd_strerror(err)); if (xrun_recovery(handle, err) < 0) { - printf(_("xrun_recovery failed: %d,%s\n"), err, snd_strerror(err)); + fprintf(stderr, _("xrun_recovery failed: %d,%s\n"), err, snd_strerror(err)); return -1; } break; /* skip one period */ @@ -683,6 +683,9 @@ static int write_loop(snd_pcm_t *handle, return err; } + + if (periods <= 0) + periods = 1; for(n = 0; n < periods; n++) { if (test_type == TEST_PINK_NOISE) @@ -847,7 +850,7 @@ int main(int argc, char *argv[]) { speaker = speaker < 1 ? 0 : speaker; speaker = speaker > channels ? 0 : speaker; if (speaker==0) { - printf(_("Invalid parameter for -s option.\n")); + fprintf(stderr, _("Invalid parameter for -s option.\n")); exit(EXIT_FAILURE); } break; @@ -858,7 +861,7 @@ int main(int argc, char *argv[]) { wav_file_dir = optarg; break; default: - printf(_("Unknown option '%c'\n"), c); + fprintf(stderr, _("Unknown option '%c'\n"), c); exit(EXIT_FAILURE); break; } @@ -908,7 +911,7 @@ int main(int argc, char *argv[]) { initialize_pink_noise(&pink, 16); if (frames == NULL) { - printf(_("No enough memory\n")); + fprintf(stderr, _("No enough memory\n")); exit(EXIT_FAILURE); } if (speaker==0) { @@ -939,7 +942,7 @@ int main(int argc, char *argv[]) { err = write_loop(handle, channel, ((rate*3)/period_size), frames); if (err < 0) { - printf(_("Transfer failed: %s\n"), snd_strerror(err)); + fprintf(stderr, _("Transfer failed: %s\n"), snd_strerror(err)); free(frames); snd_pcm_close(handle); exit(EXIT_SUCCESS); @@ -961,7 +964,7 @@ int main(int argc, char *argv[]) { err = write_loop(handle, speaker-1, ((rate*5)/period_size), frames); if (err < 0) { - printf(_("Transfer failed: %s\n"), snd_strerror(err)); + fprintf(stderr, _("Transfer failed: %s\n"), snd_strerror(err)); } }