Files
alsa/alsa-lib-git-fixes.diff

977 lines
31 KiB
Diff

diff --git a/configure.in b/configure.in
index 9a71d95..ea6a8a0 100644
--- a/configure.in
+++ b/configure.in
@@ -367,6 +367,7 @@ AC_ARG_ENABLE(seq,
AC_ARG_ENABLE(alisp,
AS_HELP_STRING([--disable-alisp], [disable the alisp component]),
[build_alisp="$enableval"], [build_alisp="yes"])
+test "$softfloat" = "yes" && build_alisp="no"
AC_ARG_ENABLE(old-symbols,
AS_HELP_STRING([--disable-old-symbols], [disable old obsoleted symbols]),
[keep_old_symbols="$enableval"], [keep_old_symbols="yes"])
@@ -474,6 +475,7 @@ fi
if test "$softfloat" = "yes"; then
build_pcm_lfloat="no"
+ build_pcm_ladspa="no"
fi
AM_CONDITIONAL(BUILD_PCM_PLUGIN, test x$build_pcm_plugin = xyes)
diff --git a/include/sound/asound.h b/include/sound/asound.h
index 977b2d6..62d1e57 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -402,7 +402,7 @@ struct sndrv_pcm_sw_params {
struct sndrv_pcm_channel_info {
unsigned int channel;
- off_t offset; /* mmap offset */
+ long offset; /* mmap offset */
unsigned int first; /* offset to first sample in bits */
unsigned int step; /* samples distance in bits */
};
diff --git a/modules/mixer/simple/Makefile.am b/modules/mixer/simple/Makefile.am
index f73871f..bad0944 100644
--- a/modules/mixer/simple/Makefile.am
+++ b/modules/mixer/simple/Makefile.am
@@ -21,11 +21,11 @@ smixer_sbase_la_LIBADD = ../../../src/libasound.la
smixer_ac97_la_SOURCES = ac97.c sbasedl.c
smixer_ac97_la_LDFLAGS = -module -avoid-version $(LDFLAGS_NOUNDEFINED)
-smixer_ac97_la_LIBADD = ../../../src/libasound.la
+smixer_ac97_la_LIBADD = ../../../src/libasound.la -ldl
smixer_hda_la_SOURCES = hda.c sbasedl.c
smixer_hda_la_LDFLAGS = -module -avoid-version $(LDFLAGS_NOUNDEFINED)
-smixer_hda_la_LIBADD = ../../../src/libasound.la
+smixer_hda_la_LIBADD = ../../../src/libasound.la -ldl
if BUILD_PYTHON
smixer_python_la_SOURCES = python.c
diff --git a/src/conf/cards/CMI8788.conf b/src/conf/cards/CMI8788.conf
index 26910d5..0ca71e9 100644
--- a/src/conf/cards/CMI8788.conf
+++ b/src/conf/cards/CMI8788.conf
@@ -13,7 +13,7 @@ CMI8788.pcm.front.0 {
card $CARD
}
-# default with dmix+softvol & dsnoop
+# default with dmix & dsnoop
CMI8788.pcm.default {
@args [ CARD ]
@args.CARD {
@@ -23,15 +23,8 @@ CMI8788.pcm.default {
playback.pcm {
type plug
slave.pcm {
- type softvol
- slave.pcm {
- @func concat
- strings [ "dmix:" $CARD ",FORMAT=S32_LE" ]
- }
- control {
- name "PCM Playback Volume"
- card $CARD
- }
+ @func concat
+ strings [ "dmix:" $CARD ",FORMAT=S32_LE" ]
}
}
capture.pcm {
diff --git a/src/conf/cards/GUS.conf b/src/conf/cards/GUS.conf
index 80e3058..d744c54 100644
--- a/src/conf/cards/GUS.conf
+++ b/src/conf/cards/GUS.conf
@@ -17,50 +17,3 @@ GUS.pcm.front.0 {
card $CARD
}
}
-
-#
-# It's a temporary solution.
-#
-
-!pcm.hw {
- @args [ CARD DEV SUBDEV ]
- @args.CARD {
- type string
- default {
- @func getenv
- vars [
- ALSA_PCM_CARD
- ALSA_CARD
- ]
- default {
- @func refer
- name defaults.pcm.card
- }
- }
- }
- @args.DEV {
- type integer
- default {
- @func igetenv
- vars [
- ALSA_PCM_DEVICE
- ]
- default {
- @func refer
- name defaults.pcm.device
- }
- }
- }
- @args.SUBDEV {
- type integer
- default {
- @func refer
- name defaults.pcm.subdevice
- }
- }
- type hw
- card $CARD
- device $DEV
- subdevice $SUBDEV
- mmap_emulation on
-}
diff --git a/src/conf/cards/HDA-Intel.conf b/src/conf/cards/HDA-Intel.conf
index bcbcb9b..800281e 100644
--- a/src/conf/cards/HDA-Intel.conf
+++ b/src/conf/cards/HDA-Intel.conf
@@ -58,6 +58,7 @@ HDA-Intel.pcm.default {
resolution 121
}
}
+ hint.device 0
}
<confdir:pcm/surround40.conf>
diff --git a/src/control/control_ext.c b/src/control/control_ext.c
index a8675c1..d1fe8ea 100644
--- a/src/control/control_ext.c
+++ b/src/control/control_ext.c
@@ -107,6 +107,7 @@ static int snd_ctl_ext_elem_list(snd_ctl_t *handle, snd_ctl_elem_list_t *list)
ret = ext->callback->elem_list(ext, offset, ids);
if (ret < 0)
return ret;
+ ids->numid = offset + 1; /* fake number */
list->used++;
offset++;
ids++;
@@ -114,13 +115,24 @@ static int snd_ctl_ext_elem_list(snd_ctl_t *handle, snd_ctl_elem_list_t *list)
return 0;
}
+static snd_ctl_ext_key_t get_elem(snd_ctl_ext_t *ext, snd_ctl_elem_id_t *id)
+{
+ int numid = id->numid;
+ if (numid > 0) {
+ ext->callback->elem_list(ext, numid - 1, id);
+ id->numid = numid;
+ } else
+ id->numid = 0;
+ return ext->callback->find_elem(ext, id);
+}
+
static int snd_ctl_ext_elem_info(snd_ctl_t *handle, snd_ctl_elem_info_t *info)
{
snd_ctl_ext_t *ext = handle->private_data;
snd_ctl_ext_key_t key;
int type, ret;
- key = ext->callback->find_elem(ext, &info->id);
+ key = get_elem(ext, &info->id);
if (key == SND_CTL_EXT_KEY_NOT_FOUND)
return -ENOENT;
ret = ext->callback->get_attribute(ext, key, &type, &info->access, &info->count);
@@ -200,7 +212,7 @@ static int snd_ctl_ext_elem_read(snd_ctl_t *handle, snd_ctl_elem_value_t *contro
int type, ret;
unsigned int access, count;
- key = ext->callback->find_elem(ext, &control->id);
+ key = get_elem(ext, &control->id);
if (key == SND_CTL_EXT_KEY_NOT_FOUND)
return -ENOENT;
ret = ext->callback->get_attribute(ext, key, &type, &access, &count);
@@ -254,7 +266,7 @@ static int snd_ctl_ext_elem_write(snd_ctl_t *handle, snd_ctl_elem_value_t *contr
int type, ret;
unsigned int access, count;
- key = ext->callback->find_elem(ext, &control->id);
+ key = get_elem(ext, &control->id);
if (key == SND_CTL_EXT_KEY_NOT_FOUND)
return -ENOENT;
ret = ext->callback->get_attribute(ext, key, &type, &access, &count);
diff --git a/src/mixer/simple_none.c b/src/mixer/simple_none.c
index 0f4dd3a..4802200 100644
--- a/src/mixer/simple_none.c
+++ b/src/mixer/simple_none.c
@@ -1450,7 +1450,14 @@ static int simple_add1(snd_mixer_class_t *class, const char *name,
}
if (ctype != SND_CTL_ELEM_TYPE_BOOLEAN)
return 0;
+#ifdef HAVE_SOFT_FLOAT
+ /* up to 256 channels */
+ for (n = 1; n < 256; n++)
+ if (n * n == values)
+ break;
+#else
n = sqrt((double)values);
+#endif
if (n * n != values)
return 0;
values = n;
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index 74d1d1a..209c5bb 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -1430,7 +1430,7 @@ int snd_pcm_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int s
* \param pcm PCM handle
* \param pfds array of poll descriptors
* \param nfds count of poll descriptors
- * \param revents returned events
+ * \param revents pointer to the returned (single) event
* \return zero if success, otherwise a negative error code
*
* This function does "demangling" of the revents mask returned from
@@ -1440,6 +1440,9 @@ int snd_pcm_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int s
* syscall returned that some events are waiting, this function might
* return empty set of events. In this case, application should
* do next event waiting using poll() or select().
+ *
+ * Note: Even if multiple poll descriptors are used (i.e. pfds > 1),
+ * this function returns only a single event.
*/
int snd_pcm_poll_descriptors_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
{
@@ -2338,8 +2341,8 @@ int snd_pcm_wait(snd_pcm_t *pcm, int timeout)
int snd_pcm_wait_nocheck(snd_pcm_t *pcm, int timeout)
{
struct pollfd *pfd;
- unsigned short *revents;
- int i, npfds, pollio, err, err_poll;
+ unsigned short revents = 0;
+ int npfds, err, err_poll;
npfds = snd_pcm_poll_descriptors_count(pcm);
if (npfds <= 0 || npfds >= 16) {
@@ -2347,7 +2350,6 @@ int snd_pcm_wait_nocheck(snd_pcm_t *pcm, int timeout)
return -EIO;
}
pfd = alloca(sizeof(*pfd) * npfds);
- revents = alloca(sizeof(*revents) * npfds);
err = snd_pcm_poll_descriptors(pcm, pfd, npfds);
if (err < 0)
return err;
@@ -2356,7 +2358,6 @@ int snd_pcm_wait_nocheck(snd_pcm_t *pcm, int timeout)
return -EIO;
}
do {
- pollio = 0;
err_poll = poll(pfd, npfds, timeout);
if (err_poll < 0) {
if (errno == EINTR)
@@ -2365,28 +2366,23 @@ int snd_pcm_wait_nocheck(snd_pcm_t *pcm, int timeout)
}
if (! err_poll)
break;
- err = snd_pcm_poll_descriptors_revents(pcm, pfd, npfds, revents);
+ err = snd_pcm_poll_descriptors_revents(pcm, pfd, npfds, &revents);
if (err < 0)
return err;
- for (i = 0; i < npfds; i++) {
- if (revents[i] & (POLLERR | POLLNVAL)) {
- /* check more precisely */
- switch (snd_pcm_state(pcm)) {
- case SND_PCM_STATE_XRUN:
- return -EPIPE;
- case SND_PCM_STATE_SUSPENDED:
- return -ESTRPIPE;
- case SND_PCM_STATE_DISCONNECTED:
- return -ENODEV;
- default:
- return -EIO;
- }
+ if (revents & (POLLERR | POLLNVAL)) {
+ /* check more precisely */
+ switch (snd_pcm_state(pcm)) {
+ case SND_PCM_STATE_XRUN:
+ return -EPIPE;
+ case SND_PCM_STATE_SUSPENDED:
+ return -ESTRPIPE;
+ case SND_PCM_STATE_DISCONNECTED:
+ return -ENODEV;
+ default:
+ return -EIO;
}
- if ((revents[i] & (POLLIN | POLLOUT)) == 0)
- continue;
- pollio++;
}
- } while (! pollio);
+ } while (!(revents & (POLLIN | POLLOUT)));
#if 0 /* very useful code to test poll related problems */
{
snd_pcm_sframes_t avail_update;
@@ -7261,7 +7257,7 @@ int snd_pcm_recover(snd_pcm_t *pcm, int err, int silent)
* \param channels required PCM channels
* \param rate required sample rate in Hz
* \param soft_resample 0 = disallow alsa-lib resample stream, 1 = allow resampling
- * \param latency required overall latency in us (0 = optimum latency for players)
+ * \param latency required overall latency in us
* \return 0 on success otherwise a negative error code
*/
int snd_pcm_set_params(snd_pcm_t *pcm,
diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c
index 82823a0..bfa1cc8 100644
--- a/src/pcm/pcm_file.c
+++ b/src/pcm/pcm_file.c
@@ -29,6 +29,7 @@
#include <endian.h>
#include <byteswap.h>
#include <ctype.h>
+#include <string.h>
#include "pcm_local.h"
#include "pcm_plugin.h"
@@ -39,6 +40,16 @@ const char *_snd_module_pcm_file = "";
#ifndef DOC_HIDDEN
+/* keys to be replaced by real values in the filename */
+#define LEADING_KEY '%' /* i.e. %r, %c, %b ... */
+#define RATE_KEY 'r'
+#define CHANNELS_KEY 'c'
+#define BWIDTH_KEY 'b'
+#define FORMAT_KEY 'f'
+
+/* maximum length of a value */
+#define VALUE_MAXLEN 64
+
typedef enum _snd_pcm_file_format {
SND_PCM_FILE_FORMAT_RAW,
SND_PCM_FILE_FORMAT_WAV
@@ -57,6 +68,9 @@ struct wav_fmt {
typedef struct {
snd_pcm_generic_t gen;
char *fname;
+ char *final_fname;
+ int trunc;
+ int perm;
int fd;
char *ifname;
int ifd;
@@ -84,6 +98,175 @@ typedef struct {
#define TO_LE16(x) bswap_16(x)
#endif
+static int snd_pcm_file_append_value(char **string_p, char **index_ch_p,
+ int *len_p, const char *value)
+{
+ char *string, *index_ch;
+ int index, len, value_len;
+ /* input pointer values */
+ len = *(len_p);
+ string = *(string_p);
+ index_ch = *(index_ch_p);
+
+ value_len = strlen(value);
+ /* reallocation to accommodate the value */
+ index = index_ch - string;
+ len += value_len;
+ string = realloc(string, len + 1);
+ if (!string)
+ return -ENOMEM;
+ index_ch = string + index;
+ /* concatenating the new value */
+ strcpy(index_ch, value);
+ index_ch += value_len;
+ /* return values */
+ *(len_p) = len;
+ *(string_p) = string;
+ *(index_ch_p) = index_ch;
+ return 0;
+}
+
+static int snd_pcm_file_replace_fname(snd_pcm_file_t *file, char **new_fname_p)
+{
+ char value[VALUE_MAXLEN];
+ char *fname = file->fname;
+ char *new_fname = NULL;
+ char *old_last_ch, *old_index_ch, *new_index_ch;
+ int old_len, new_len, err;
+
+ snd_pcm_t *pcm = file->gen.slave;
+
+ /* we want to keep fname, const */
+ old_len = new_len = strlen(fname);
+ old_last_ch = fname + old_len - 1;
+ new_fname = malloc(new_len + 1);
+ if (!new_fname)
+ return -ENOMEM;
+
+ old_index_ch = fname; /* first character of the old name */
+ new_index_ch = new_fname; /* first char of the new name */
+
+ while (old_index_ch <= old_last_ch) {
+ if (*(old_index_ch) == LEADING_KEY &&
+ old_index_ch != old_last_ch) {
+ /* is %, not last char, skipping and checking
+ next char */
+ switch (*(++old_index_ch)) {
+ case RATE_KEY:
+ snprintf(value, sizeof(value), "%d",
+ pcm->rate);
+ err = snd_pcm_file_append_value(&new_fname,
+ &new_index_ch, &new_len, value);
+ if (err < 0)
+ return err;
+ break;
+
+ case CHANNELS_KEY:
+ snprintf(value, sizeof(value), "%d",
+ pcm->channels);
+ err = snd_pcm_file_append_value(&new_fname,
+ &new_index_ch, &new_len, value);
+ if (err < 0)
+ return err;
+ break;
+
+ case BWIDTH_KEY:
+ snprintf(value, sizeof(value), "%d",
+ pcm->frame_bits/pcm->channels);
+ err = snd_pcm_file_append_value(&new_fname,
+ &new_index_ch, &new_len, value);
+ if (err < 0)
+ return err;
+ break;
+
+ case FORMAT_KEY:
+ err = snd_pcm_file_append_value(&new_fname,
+ &new_index_ch, &new_len,
+ snd_pcm_format_name(pcm->format));
+ if (err < 0)
+ return err;
+ break;
+
+ default:
+ /* non-key char, just copying */
+ *(new_index_ch++) = *(old_index_ch);
+ }
+ /* next old char */
+ old_index_ch++;
+ } else {
+ /* plain copying, shifting both strings to next chars */
+ *(new_index_ch++) = *(old_index_ch++);
+ }
+ }
+ /* closing the new string */
+ *(new_index_ch) = '\0';
+ *(new_fname_p) = new_fname;
+ return 0;
+
+}
+
+static int snd_pcm_file_open_output_file(snd_pcm_file_t *file)
+{
+ int err, fd;
+
+ /* fname can contain keys, generating final_fname */
+ err = snd_pcm_file_replace_fname(file, &(file->final_fname));
+ if (err < 0)
+ return err;
+ /*printf("DEBUG - original fname: %s, final fname: %s\n",
+ file->fname, file->final_fname);*/
+
+ if (file->final_fname[0] == '|') {
+ /* pipe mode */
+ FILE *pipe;
+ /* clearing */
+ pipe = popen(file->final_fname + 1, "w");
+ if (!pipe) {
+ SYSERR("running %s for writing failed",
+ file->final_fname);
+ return -errno;
+ }
+ fd = fileno(pipe);
+ } else {
+ if (file->trunc)
+ fd = open(file->final_fname, O_WRONLY|O_CREAT|O_TRUNC,
+ file->perm);
+ else {
+ fd = open(file->final_fname, O_WRONLY|O_CREAT|O_EXCL,
+ file->perm);
+ if (fd < 0) {
+ char *tmpfname = NULL;
+ int idx, len;
+ len = strlen(file->final_fname) + 6;
+ tmpfname = malloc(len);
+ if (!tmpfname)
+ return -ENOMEM;
+ for (idx = 1; idx < 10000; idx++) {
+ snprintf(tmpfname, len,
+ "%s.%04d", file->final_fname,
+ idx);
+ fd = open(tmpfname,
+ O_WRONLY|O_CREAT|O_EXCL,
+ file->perm);
+ if (fd >= 0) {
+ free(file->final_fname);
+ file->final_fname = tmpfname;
+ break;
+ }
+ }
+ if (fd < 0) {
+ SYSERR("open %s for writing failed",
+ file->final_fname);
+ free(tmpfname);
+ return -errno;
+ }
+ }
+ }
+ }
+ file->fd = fd;
+ return 0;
+}
+
static void setup_wav_header(snd_pcm_t *pcm, struct wav_fmt *fmt)
{
fmt->fmt = TO_LE16(0x01);
@@ -152,6 +335,8 @@ static void fixup_wav_header(snd_pcm_t *pcm)
}
#endif /* DOC_HIDDEN */
+
+
static void snd_pcm_file_write_bytes(snd_pcm_t *pcm, size_t bytes)
{
snd_pcm_file_t *file = pcm->private_data;
@@ -442,6 +627,13 @@ static int snd_pcm_file_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
a->first = slave->sample_bits * channel;
a->step = slave->frame_bits;
}
+ if (file->fd < 0) {
+ err = snd_pcm_file_open_output_file(file);
+ if (err < 0) {
+ SYSERR("failed opening output file %s", file->fname);
+ return err;
+ }
+ }
return 0;
}
@@ -452,6 +644,10 @@ static void snd_pcm_file_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_output_printf(out, "File PCM (file=%s)\n", file->fname);
else
snd_output_printf(out, "File PCM (fd=%d)\n", file->fd);
+ if (file->final_fname)
+ snd_output_printf(out, "Final file PCM (file=%s)\n",
+ file->final_fname);
+
if (pcm->setup) {
snd_output_printf(out, "Its setup is:\n");
snd_pcm_dump_setup(pcm, out);
@@ -533,7 +729,6 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
snd_pcm_file_t *file;
snd_pcm_file_format_t format;
struct timespec timespec;
- char *tmpname = NULL;
int err;
assert(pcmp);
@@ -546,58 +741,27 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
SNDERR("file format %s is unknown", fmt);
return -EINVAL;
}
- if (fname) {
- if (trunc)
- fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, perm);
- else {
- fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, perm);
- if (fd < 0) {
- int idx, len;
- len = strlen(fname) + 6;
- tmpname = malloc(len);
- if (!tmpname)
- return -ENOMEM;
- for (idx = 1; idx < 10000; idx++) {
- snprintf(tmpname, len,
- "%s.%04d", fname, idx);
- fd = open(tmpname, O_WRONLY|O_CREAT|O_EXCL, perm);
- if (fd >= 0) {
- fname = tmpname;
- break;
- }
- }
- }
- }
- if (fd < 0) {
- SYSERR("open %s for writing failed", fname);
- free(tmpname);
- return -errno;
- }
- }
file = calloc(1, sizeof(snd_pcm_file_t));
if (!file) {
- if (fname)
- close(fd);
- free(tmpname);
return -ENOMEM;
}
+ /* opening output fname is delayed until writing,
+ when PCM params are known */
+ if (fname)
+ file->fname = strdup(fname);
+ file->trunc = trunc;
+ file->perm = perm;
+
if (ifname) {
ifd = open(ifname, O_RDONLY); /* TODO: mind blocking mode */
if (ifd < 0) {
SYSERR("open %s for reading failed", ifname);
- if (fname)
- close(fd);
free(file);
- free(tmpname);
return -errno;
}
- }
-
- if (fname)
- file->fname = strdup(fname);
- if (ifname)
file->ifname = strdup(ifname);
+ }
file->fd = fd;
file->ifd = ifd;
file->format = format;
@@ -608,7 +772,6 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
if (err < 0) {
free(file->fname);
free(file);
- free(tmpname);
return err;
}
pcm->ops = &snd_pcm_file_ops;
@@ -625,8 +788,6 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
snd_pcm_link_hw_ptr(pcm, slave);
snd_pcm_link_appl_ptr(pcm, slave);
*pcmp = pcm;
-
- free(tmpname);
return 0;
}
@@ -634,8 +795,9 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
\section pcm_plugins_file Plugin: File
-This plugin stores contents of a PCM stream to file, and optionally
-uses an existing file as an input data source (i.e., "virtual mic")
+This plugin stores contents of a PCM stream to file or pipes the stream
+to a command, and optionally uses an existing file as an input data source
+(i.e., "virtual mic")
\code
pcm.name {
@@ -647,7 +809,17 @@ pcm.name {
# or
pcm { } # Slave PCM definition
}
- file STR # Output filename
+ file STR # Output filename (or shell command the stream
+ # will be piped to if STR starts with the pipe
+ # char).
+ # STR can contain format keys, replaced by
+ # real values corresponding to the stream:
+ # %r rate (replaced with: 48000)
+ # %c channels (replaced with: 2)
+ # %b bits per sample (replaced with: 16)
+ # %f sample format string
+ # (replaced with: S16_LE)
+ # %% replaced with %
or
file INT # Output file descriptor number
infile STR # Input filename - only raw format
@@ -773,7 +945,7 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
err = snd_pcm_slave_conf(root, slave, &sconf, 0);
if (err < 0)
return err;
- if (!fname && fd < 0 && !ifname) {
+ if ((!fname || strlen(fname) == 0) && fd < 0 && !ifname) {
snd_config_delete(sconf);
SNDERR("file is not defined");
return -EINVAL;
diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c
index abd3d43..967cf46 100644
--- a/src/pcm/pcm_plug.c
+++ b/src/pcm/pcm_plug.c
@@ -605,7 +605,16 @@ static int snd_pcm_plug_change_mmap(snd_pcm_t *pcm, snd_pcm_t **new,
plug->gen.slave != plug->req_slave);
if (err < 0)
return err;
- slv->access = clt->access;
+ switch (slv->access) {
+ case SND_PCM_ACCESS_RW_INTERLEAVED:
+ slv->access = SND_PCM_ACCESS_MMAP_INTERLEAVED;
+ break;
+ case SND_PCM_ACCESS_RW_NONINTERLEAVED:
+ slv->access = SND_PCM_ACCESS_MMAP_NONINTERLEAVED;
+ break;
+ default:
+ break;
+ }
return 1;
}
#endif
@@ -743,19 +752,29 @@ static int check_access_change(snd_pcm_hw_params_t *cparams,
return 0; /* OK, we have mmap support */
#ifdef BUILD_PCM_PLUGIN_MMAP_EMUL
/* no mmap support - we need mmap emulation */
+
+ if (!snd_pcm_access_mask_test(smask, SND_PCM_ACCESS_RW_INTERLEAVED) &&
+ !snd_pcm_access_mask_test(smask, SND_PCM_ACCESS_RW_NONINTERLEAVED))
+ return -EINVAL; /* even no RW access? no way! */
+
cmask = (const snd_pcm_access_mask_t *)
snd_pcm_hw_param_get_mask(cparams,
SND_PCM_HW_PARAM_ACCESS);
snd_mask_none(&mask);
if (snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_RW_INTERLEAVED) ||
- snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_MMAP_INTERLEAVED))
- snd_pcm_access_mask_set(&mask,
- SND_PCM_ACCESS_RW_INTERLEAVED);
+ snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_MMAP_INTERLEAVED)) {
+ if (snd_pcm_access_mask_test(smask, SND_PCM_ACCESS_RW_INTERLEAVED))
+ snd_pcm_access_mask_set(&mask,
+ SND_PCM_ACCESS_RW_INTERLEAVED);
+ }
if (snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_RW_NONINTERLEAVED) ||
- snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED))
- snd_pcm_access_mask_set(&mask,
- SND_PCM_ACCESS_RW_NONINTERLEAVED);
- *smask = mask;
+ snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) {
+ if (snd_pcm_access_mask_test(smask, SND_PCM_ACCESS_RW_NONINTERLEAVED))
+ snd_pcm_access_mask_set(&mask,
+ SND_PCM_ACCESS_RW_NONINTERLEAVED);
+ }
+ if (!snd_mask_empty(&mask))
+ *smask = mask; /* prefer the straight conversion */
return 0;
#else
return -EINVAL;
diff --git a/src/seq/seq.c b/src/seq/seq.c
index feb9733..7b777a1 100644
--- a/src/seq/seq.c
+++ b/src/seq/seq.c
@@ -30,7 +30,7 @@
/*! \page seq Sequencer interface
-\section seq_general Genral
+\section seq_general General
The ALSA sequencer interface is designed to deliver the MIDI-like
events between clients/ports.
@@ -76,10 +76,10 @@ A client can have one or more <i>ports</i> to communicate between other
clients. A port is corresponding to the MIDI port in the case of MIDI device,
but in general it is nothing but the access point between other clients.
Each port may have capability flags, which specify the read/write
-accessbility and subscription permissions of the port.
+accessibility and subscription permissions of the port.
For creation of a port, call #snd_seq_create_port()
-with the appropirate port attribute specified in #snd_seq_port_info_t
-reocrd.
+with the appropriate port attribute specified in #snd_seq_port_info_t
+record.
For creating a port for the normal use, there is a helper function
#snd_seq_create_simple_port(). An example with this function is like below.
@@ -102,7 +102,7 @@ Here, input and output mean
input (read) from other clients and output (write) to others, respectively.
Since memory pool of each client is independent from others,
it avoids such a situation that a client eats the whole events pool
-and interfere other clients' responce.
+and interfere other clients' response.
The all scheduled output events or input events from dispatcher are stored
on these pools until delivered to other clients or extracted to user space.
@@ -171,7 +171,7 @@ the MIDI events like program, velocity or chorus effects.
This application can accept arbitrary MIDI input
and send to arbitrary port, just like a Unix pipe application using
stdin and stdout files.
-We can even connect several filter applictions which work individually
+We can even connect several filter applications which work individually
in order to process the MIDI events.
Subscription can be used for this purpose.
The connection between ports can be done also by the "third" client.
@@ -199,7 +199,7 @@ All the sequencer events are stored in a sequencer event record,
#snd_seq_event_t type.
Application can send and receive these event records to/from other
clients via sequencer.
-An event has several stroage types according to its usage.
+An event has several storage types according to its usage.
For example, a SYSEX message is stored on the variable length event,
and a large synth sample data is delivered using a user-space data pointer.
@@ -227,7 +227,7 @@ The type field contains the type of the event
(1 byte).
The flags field consists of bit flags which
describe several conditions of the event (1 byte).
-It includes the time-stamp mode, data storage type, and scheduling prority.
+It includes the time-stamp mode, data storage type, and scheduling priority.
The tag field is an arbitrary tag.
This tag can used for removing a distinct event from the event queue
via #snd_seq_remove_events().
@@ -240,7 +240,7 @@ The data field is a union of event data.
An event can be delivered either on scheduled or direct dispatch mode.
On the scheduling mode, an event is once stored on the priority queue
and delivered later (or even immediately) to the destination,
-whereas on the direct disatch mode, an event is passed to the destination
+whereas on the direct dispatch mode, an event is passed to the destination
without any queue.
For a scheduled delivery, a queue to process the event must exist.
@@ -284,7 +284,7 @@ The time stored in an event record is a union of these two different
time values.
Note that the time format used for real time events is very similar to
-timeval struct used for unix system time.
+timeval struct used for Unix system time.
The absurd resolution of the timestamps allows us to perform very accurate
conversions between songposition and real time. Round-off errors can be
neglected.
@@ -299,7 +299,7 @@ counted from the moment when the queue started.
An client that relies on these relative timestamps is the MIDI input port.
As each sequencer queue has it's own clock the only way to deliver events at
the right time is by using the relative timestamp format. When the event
-arrives at the queue it is normalised to absolute format.
+arrives at the queue it is normalized to absolute format.
The timestamp format is specified in the flag bitfield masked by
#SND_SEQ_TIME_STAMP_MASK.
@@ -320,7 +320,7 @@ fill the port id of source.port and
both client and port of dest field.
If an existing address is set to the destination,
-the event is simplly delivered to it.
+the event is simply delivered to it.
When #SND_SEQ_ADDRESS_SUBSCRIBERS is set to the destination client id,
the event is delivered to all the clients connected to the source port.
@@ -346,7 +346,7 @@ an announcement is sent to subscribers from this port.
Some events like SYSEX message, however, need larger data space
than the standard data.
-For such events, ALSA sequencer provides seveal different data storage types.
+For such events, ALSA sequencer provides several different data storage types.
The data type is specified in the flag bits masked by #SND_SEQ_EVENT_LENGTH_MASK.
The following data types are available:
@@ -359,7 +359,7 @@ A macro #snd_seq_ev_set_fixed() is provided to set this type.
\par Variable length data
SYSEX or a returned error use this type.
The actual data is stored on an extra allocated space.
-On sequecer kernel, the whole extra-data is duplicated, so that the event
+On sequencer kernel, the whole extra-data is duplicated, so that the event
can be scheduled on queue.
The data contains only the length and the
pointer of extra-data.
@@ -430,7 +430,7 @@ Note that PPQ cannot be changed while the queue is running.
It must be set before the queue is started.
On the other hand, in the case of <i>realtime</i> queue, the
-time resolution is fixed to nanosecononds. There is, however,
+time resolution is fixed to nanoseconds. There is, however,
a parameter to change the speed of this queue, called <i>skew</i>.
You can make the queue faster or slower by setting the skew value
bigger or smaller. In the API, the skew is defined by two values,
@@ -488,7 +488,7 @@ special settings.
In the above example, the tempo is changed immediately after
the buffer is flushed by #snd_seq_drain_output() call.
You can schedule the event in a certain queue so that the tempo
-change happes at the scheduled time, too.
+change happens at the scheduled time, too.
\subsection seq_ev_start Starting and stopping a queue
@@ -515,7 +515,7 @@ Each ALSA port can have capability flags.
The most basic capability flags are
#SND_SEQ_PORT_CAP_READ and #SND_SEQ_PORT_CAP_WRITE.
The former means that the port allows to send events to other ports,
-whereas the latter capability menas
+whereas the latter capability means
that the port allows to receive events from other ports.
You may have noticed that meanings of \c READ and \c WRITE
are permissions of the port from the viewpoint of other ports.
@@ -536,7 +536,7 @@ Obviously, these flags have no influence
if \c READ or \c WRITE> capability is not set.
Note that these flags are not necessary if the client subscribes itself
-to the spcified port.
+to the specified port.
For example, when a port makes READ subscription
to MIDI input port, this port must have #SND_SEQ_PORT_CAP_WRITE capability,
but no #SND_SEQ_PORT_CAP_SUBS_WRITE capability is required.
@@ -610,7 +610,7 @@ if #SND_SEQ_PORT_CAP_NO_EXPORT capability is set in either sender or receiver po
Assume MIDI input port = 64:0, application port = 128:0, and
queue for timestamp = 1 with real-time stamp.
-The application port must have capabilty #SND_SEQ_PORT_CAP_WRITE.
+The application port must have capability #SND_SEQ_PORT_CAP_WRITE.
\code
void capture_keyboard(snd_seq_t *seq)
{
@@ -633,7 +633,7 @@ void capture_keyboard(snd_seq_t *seq)
\subsection seq_subs_ex_out Output to MIDI device
Assume MIDI output port = 65:1 and application port = 128:0.
-The application port must have capabilty #SND_SEQ_PORT_CAP_READ.
+The application port must have capability #SND_SEQ_PORT_CAP_READ.
\code
void subscribe_output(snd_seq_t *seq)
{
@@ -790,7 +790,7 @@ void event_filter(snd_seq_t *seq, snd_seq_event_t *ev)
/**
* \brief get identifier of sequencer handle
* \param seq sequencer handle
- * \return ascii identifier of sequencer handle
+ * \return ASCII identifier of sequencer handle
*
* Returns the ASCII identifier of the given sequencer handle. It's the same
* identifier specified in snd_seq_open().
@@ -1610,7 +1610,7 @@ void snd_seq_client_info_event_filter_del(snd_seq_client_info_t *info, int event
* \param event_type event type to be checked
* \return 1 if the event type is present, 0 otherwise
*
- * Test if the event type is in the filter bitamp of this client_info container.
+ * Test if the event type is in the filter bitmap of this client_info container.
*
* \sa snd_seq_get_client_info(),
* snd_seq_set_client_info(),
diff --git a/src/seq/seqmid.c b/src/seq/seqmid.c
index 3b0960d..86a4970 100644
--- a/src/seq/seqmid.c
+++ b/src/seq/seqmid.c
@@ -317,7 +317,7 @@ int snd_seq_set_client_pool_input(snd_seq_t *seq, size_t size)
* \param seq sequencer handle
* \return 0 on success or negative error code
*
- * So far, this works ideically like #snd_seq_drop_output().
+ * So far, this works identically like #snd_seq_drop_output().
*/
int snd_seq_reset_pool_output(snd_seq_t *seq)
{
@@ -329,7 +329,7 @@ int snd_seq_reset_pool_output(snd_seq_t *seq)
* \param seq sequencer handle
* \return 0 on success or negative error code
*
- * So far, this works ideically like #snd_seq_drop_input().
+ * So far, this works identically like #snd_seq_drop_input().
*/
int snd_seq_reset_pool_input(snd_seq_t *seq)
{