This commit is contained in:
parent
17d72ab7df
commit
7da6e94f1d
@ -18,6 +18,19 @@ index 9a71d95..ea6a8a0 100644
|
||||
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
|
||||
@ -36,6 +49,61 @@ index f73871f..bad0944 100644
|
||||
|
||||
if BUILD_PYTHON
|
||||
smixer_python_la_SOURCES = python.c
|
||||
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/mixer/simple_none.c b/src/mixer/simple_none.c
|
||||
index 0f4dd3a..4802200 100644
|
||||
--- a/src/mixer/simple_none.c
|
||||
@ -55,3 +123,535 @@ index 0f4dd3a..4802200 100644
|
||||
if (n * n != values)
|
||||
return 0;
|
||||
values = n;
|
||||
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
|
||||
index 74d1d1a..b44956f 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;
|
||||
diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c
|
||||
index 82823a0..6ddf14f 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/(8 * 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 bytes per sample (replaced with: 2)
|
||||
+ # %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;
|
||||
|
@ -1,3 +1,12 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Feb 3 15:54:47 CET 2009 - tiwai@suse.de
|
||||
|
||||
- Fix the automatic mmap-emul conversion in plug plugin
|
||||
- Fix off_t in kernel struct
|
||||
- Fix default PCM for GUS
|
||||
- New file plugin options
|
||||
- Fix handling of revents in snd_pcm_poll_descriptor_revents()
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Jan 22 13:59:24 CET 2009 - tiwai@suse.de
|
||||
|
||||
|
@ -34,7 +34,7 @@ Obsoletes: alsa-64bit
|
||||
#
|
||||
Summary: Advanced Linux Sound Architecture
|
||||
Version: 1.0.18
|
||||
Release: 13
|
||||
Release: 14
|
||||
Source: ftp://ftp.alsa-project.org/pub/lib/alsa-lib-%{package_version}.tar.bz2
|
||||
Source8: 40-alsa.rules
|
||||
Source11: alsasound
|
||||
@ -244,6 +244,12 @@ exit 0
|
||||
%{_datadir}/alsa
|
||||
|
||||
%changelog
|
||||
* Tue Feb 03 2009 tiwai@suse.de
|
||||
- Fix the automatic mmap-emul conversion in plug plugin
|
||||
- Fix off_t in kernel struct
|
||||
- Fix default PCM for GUS
|
||||
- New file plugin options
|
||||
- Fix handling of revents in snd_pcm_poll_descriptor_revents()
|
||||
* Thu Jan 22 2009 tiwai@suse.de
|
||||
- updated to version 1.0.19:
|
||||
* including previous patches
|
||||
|
Loading…
x
Reference in New Issue
Block a user