Accepting request 163766 from multimedia:libs

- Updated to version 1.0.27:
  including all previous fixes; all 00*-* patches dropped (forwarded request 163761 from tiwai)

OBS-URL: https://build.opensuse.org/request/show/163766
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/alsa?expand=0&rev=134
This commit is contained in:
Stephan Kulow 2013-04-14 08:11:02 +00:00 committed by Git OBS Bridge
commit 6514270a4b
58 changed files with 33 additions and 9421 deletions

View File

@ -1,685 +0,0 @@
From 3c4a22ea49a881cdbfe2d50eef94b17e38104734 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 25 Jul 2012 15:05:15 +0200
Subject: [PATCH 01/30] Implement the channel mapping API
Added new channel-mapping API functions.
Not all plugins are covered, especially the route, multi and external
plugins don't work yet.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/control.h | 7 +
include/pcm.h | 12 +++
include/sound/asound.h | 25 ++++++
src/pcm/pcm.c | 55 ++++++++++++++
src/pcm/pcm_adpcm.c | 3
src/pcm/pcm_alaw.c | 3
src/pcm/pcm_copy.c | 3
src/pcm/pcm_direct.c | 18 ++++
src/pcm/pcm_direct.h | 10 ++
src/pcm/pcm_dmix.c | 3
src/pcm/pcm_dshare.c | 2
src/pcm/pcm_dsnoop.c | 3
src/pcm/pcm_file.c | 3
src/pcm/pcm_generic.c | 18 ++++
src/pcm/pcm_generic.h | 11 ++
src/pcm/pcm_hooks.c | 3
src/pcm/pcm_hw.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++
src/pcm/pcm_iec958.c | 3
src/pcm/pcm_ladspa.c | 3
src/pcm/pcm_lfloat.c | 3
src/pcm/pcm_linear.c | 3
src/pcm/pcm_local.h | 3
src/pcm/pcm_meter.c | 3
src/pcm/pcm_mmap_emul.c | 3
src/pcm/pcm_mulaw.c | 2
src/pcm/pcm_rate.c | 3
src/pcm/pcm_softvol.c | 3
27 files changed, 386 insertions(+)
--- a/include/control.h
+++ b/include/control.h
@@ -182,6 +182,13 @@ typedef enum _snd_ctl_event_type {
/** Mute state */
#define SND_CTL_TLV_DB_GAIN_MUTE -9999999
+/** TLV type - fixed channel map positions */
+#define SND_CTL_TLVT_CHMAP_FIXED 0x00101
+/** TLV type - freely swappable channel map positions */
+#define SND_CTL_TLVT_CHMAP_VAR 0x00102
+/** TLV type - pair-wise swappable channel map positions */
+#define SND_CTL_TLVT_CHMAP_PAIRED 0x00103
+
/** CTL type */
typedef enum _snd_ctl_type {
/** Kernel level CTL */
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -474,6 +474,18 @@ int snd_pcm_wait(snd_pcm_t *pcm, int tim
int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
int snd_pcm_unlink(snd_pcm_t *pcm);
+enum {
+ SND_CHMAP_NONE = 0, /** unspecified channel position */
+ SND_CHMAP_FIXED, /** fixed channel position */
+ SND_CHMAP_VAR, /** freely swappable channel position */
+ SND_CHMAP_PAIRED, /** pair-wise swappable channel position */
+};
+
+int **snd_pcm_query_chmaps(snd_pcm_t *pcm);
+void snd_pcm_free_chmaps(int **maps);
+int *snd_pcm_get_chmap(snd_pcm_t *pcm);
+int snd_pcm_set_chmap(snd_pcm_t *pcm, const int *map);
+
//int snd_pcm_mixer_element(snd_pcm_t *pcm, snd_mixer_t *mixer, snd_mixer_elem_t **elem);
/*
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -477,6 +477,31 @@ enum {
SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
};
+/* channel positions */
+enum {
+ SNDRV_CHMAP_UNKNOWN = 0,
+ SNDRV_CHMAP_FL, /* front left */
+ SNDRV_CHMAP_FC, /* front center */
+ SNDRV_CHMAP_FR, /* front right */
+ SNDRV_CHMAP_FLC, /* front left center */
+ SNDRV_CHMAP_FRC, /* front right center */
+ SNDRV_CHMAP_RL, /* rear left */
+ SNDRV_CHMAP_RC, /* rear center */
+ SNDRV_CHMAP_RR, /* rear right */
+ SNDRV_CHMAP_RLC, /* rear left center */
+ SNDRV_CHMAP_RRC, /* rear right center */
+ SNDRV_CHMAP_SL, /* side left */
+ SNDRV_CHMAP_SR, /* side right */
+ SNDRV_CHMAP_LFE, /* LFE */
+ SNDRV_CHMAP_FLW, /* front left wide */
+ SNDRV_CHMAP_FRW, /* front right wide */
+ SNDRV_CHMAP_FLH, /* front left high */
+ SNDRV_CHMAP_FCH, /* front center high */
+ SNDRV_CHMAP_FRH, /* front right high */
+ SNDRV_CHMAP_TC, /* top center */
+ SNDRV_CHMAP_LAST = SNDRV_CHMAP_TC,
+};
+
enum {
SNDRV_PCM_IOCTL_PVERSION = _IOR('A', 0x00, int),
SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct sndrv_pcm_info),
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -7302,6 +7302,61 @@ OBSOLETE1(snd_pcm_sw_params_get_silence_
#endif /* DOC_HIDDEN */
+/**
+ * \!brief Query the available channel maps
+ * \param pcm PCM handle to query
+ * \return the NULL-terminated array of integer pointers, each of
+ * which contains the channel map. A channel map is represented by an
+ * integer array, beginning with the channel map type, followed by the
+ * number of channels, and the position of each channel.
+ */
+int **snd_pcm_query_chmaps(snd_pcm_t *pcm)
+{
+ if (!pcm->ops->query_chmaps)
+ return NULL;
+ return pcm->ops->query_chmaps(pcm);
+}
+
+/**
+ * \!brief Release the channel map array allocated via #snd_pcm_query_chmaps
+ * \param maps the array pointer to release
+ */
+void snd_pcm_free_chmaps(int **maps)
+{
+ int **p;
+ if (!maps)
+ return;
+ for (p = maps; *p; p++)
+ free(*p);
+ free(maps);
+}
+
+/**
+ * \!brief Get the current channel map
+ * \param pcm PCM instance
+ * \return the current channel map, or NULL if error
+ */
+int *snd_pcm_get_chmap(snd_pcm_t *pcm)
+{
+ if (!pcm->ops->get_chmap)
+ return NULL;
+ return pcm->ops->get_chmap(pcm);
+}
+
+/**
+ * \!brief Configure the current channel map
+ * \param pcm PCM instance
+ * \param map the channel map to write
+ * \return zero if succeeded, or a negative error code
+ */
+int snd_pcm_set_chmap(snd_pcm_t *pcm, const int *map)
+{
+ if (!pcm->ops->set_chmap)
+ return -ENXIO;
+ return pcm->ops->set_chmap(pcm, map);
+}
+
+
/*
* basic helpers
*/
--- a/src/pcm/pcm_adpcm.c
+++ b/src/pcm/pcm_adpcm.c
@@ -531,6 +531,9 @@ static const snd_pcm_ops_t snd_pcm_adpcm
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_generic_query_chmaps,
+ .get_chmap = snd_pcm_generic_get_chmap,
+ .set_chmap = snd_pcm_generic_set_chmap,
};
/**
--- a/src/pcm/pcm_alaw.c
+++ b/src/pcm/pcm_alaw.c
@@ -404,6 +404,9 @@ static const snd_pcm_ops_t snd_pcm_alaw_
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_generic_query_chmaps,
+ .get_chmap = snd_pcm_generic_get_chmap,
+ .set_chmap = snd_pcm_generic_set_chmap,
};
/**
--- a/src/pcm/pcm_copy.c
+++ b/src/pcm/pcm_copy.c
@@ -165,6 +165,9 @@ static const snd_pcm_ops_t snd_pcm_copy_
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_generic_query_chmaps,
+ .get_chmap = snd_pcm_generic_get_chmap,
+ .set_chmap = snd_pcm_generic_set_chmap,
};
/**
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -789,6 +789,24 @@ int snd_pcm_direct_munmap(snd_pcm_t *pcm
return 0;
}
+int **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm)
+{
+ snd_pcm_direct_t *dmix = pcm->private_data;
+ return snd_pcm_query_chmaps(dmix->spcm);
+}
+
+int *snd_pcm_direct_get_chmap(snd_pcm_t *pcm)
+{
+ snd_pcm_direct_t *dmix = pcm->private_data;
+ return snd_pcm_get_chmap(dmix->spcm);
+}
+
+int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const int *map)
+{
+ snd_pcm_direct_t *dmix = pcm->private_data;
+ return snd_pcm_set_chmap(dmix->spcm, map);
+}
+
int snd_pcm_direct_resume(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dmix = pcm->private_data;
--- a/src/pcm/pcm_direct.h
+++ b/src/pcm/pcm_direct.h
@@ -235,6 +235,12 @@ struct snd_pcm_direct {
snd1_pcm_direct_open_secondary_client
#define snd_pcm_direct_parse_open_conf \
snd1_pcm_direct_parse_open_conf
+#define snd_pcm_direct_query_chmaps \
+ snd1_pcm_direct_query_chmaps
+#define snd_pcm_direct_get_chmap \
+ snd1_pcm_direct_get_chmap
+#define snd_pcm_direct_set_chmap \
+ snd1_pcm_direct_set_chmap
int snd_pcm_direct_semaphore_create_or_connect(snd_pcm_direct_t *dmix);
@@ -290,6 +296,10 @@ void snd_pcm_direct_clear_timer_queue(sn
int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix);
int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name);
+int **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm);
+int *snd_pcm_direct_get_chmap(snd_pcm_t *pcm);
+int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const int *map);
+
int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -892,6 +892,9 @@ static const snd_pcm_ops_t snd_pcm_dmix_
.async = snd_pcm_direct_async,
.mmap = snd_pcm_direct_mmap,
.munmap = snd_pcm_direct_munmap,
+ .query_chmaps = snd_pcm_direct_query_chmaps,
+ .get_chmap = snd_pcm_direct_get_chmap,
+ .set_chmap = snd_pcm_direct_set_chmap,
};
static const snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -573,6 +573,8 @@ static const snd_pcm_ops_t snd_pcm_dshar
.async = snd_pcm_direct_async,
.mmap = snd_pcm_direct_mmap,
.munmap = snd_pcm_direct_munmap,
+ .get_chmap = snd_pcm_direct_get_chmap,
+ .set_chmap = snd_pcm_direct_set_chmap,
};
static const snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = {
--- a/src/pcm/pcm_dsnoop.c
+++ b/src/pcm/pcm_dsnoop.c
@@ -488,6 +488,9 @@ static const snd_pcm_ops_t snd_pcm_dsnoo
.async = snd_pcm_direct_async,
.mmap = snd_pcm_direct_mmap,
.munmap = snd_pcm_direct_munmap,
+ .query_chmaps = snd_pcm_direct_query_chmaps,
+ .get_chmap = snd_pcm_direct_get_chmap,
+ .set_chmap = snd_pcm_direct_set_chmap,
};
static const snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = {
--- a/src/pcm/pcm_file.c
+++ b/src/pcm/pcm_file.c
@@ -669,6 +669,9 @@ static const snd_pcm_ops_t snd_pcm_file_
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_generic_query_chmaps,
+ .get_chmap = snd_pcm_generic_get_chmap,
+ .set_chmap = snd_pcm_generic_set_chmap,
};
static const snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
--- a/src/pcm/pcm_generic.c
+++ b/src/pcm/pcm_generic.c
@@ -323,4 +323,22 @@ int snd_pcm_generic_munmap(snd_pcm_t *pc
return 0;
}
+int **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm)
+{
+ snd_pcm_generic_t *generic = pcm->private_data;
+ return snd_pcm_query_chmaps(generic->slave);
+}
+
+int *snd_pcm_generic_get_chmap(snd_pcm_t *pcm)
+{
+ snd_pcm_generic_t *generic = pcm->private_data;
+ return snd_pcm_get_chmap(generic->slave);
+}
+
+int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const int *map)
+{
+ snd_pcm_generic_t *generic = pcm->private_data;
+ return snd_pcm_set_chmap(generic->slave, map);
+}
+
#endif /* DOC_HIDDEN */
--- a/src/pcm/pcm_generic.h
+++ b/src/pcm/pcm_generic.h
@@ -103,6 +103,12 @@ typedef struct {
snd1_pcm_generic_mmap
#define snd_pcm_generic_munmap \
snd1_pcm_generic_munmap
+#define snd_pcm_generic_query_chmaps \
+ snd1_pcm_generic_query_chmaps
+#define snd_pcm_generic_get_chmap \
+ snd1_pcm_generic_get_chmap
+#define snd_pcm_generic_set_chmap \
+ snd1_pcm_generic_set_chmap
int snd_pcm_generic_close(snd_pcm_t *pcm);
int snd_pcm_generic_nonblock(snd_pcm_t *pcm, int nonblock);
@@ -149,3 +155,8 @@ int snd_pcm_generic_real_htimestamp(snd_
snd_htimestamp_t *tstamp);
int snd_pcm_generic_mmap(snd_pcm_t *pcm);
int snd_pcm_generic_munmap(snd_pcm_t *pcm);
+int **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm);
+int *snd_pcm_generic_get_chmap(snd_pcm_t *pcm);
+int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const int *map);
+
+
--- a/src/pcm/pcm_hooks.c
+++ b/src/pcm/pcm_hooks.c
@@ -165,6 +165,9 @@ static const snd_pcm_ops_t snd_pcm_hooks
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_generic_query_chmaps,
+ .get_chmap = snd_pcm_generic_get_chmap,
+ .set_chmap = snd_pcm_generic_set_chmap,
};
static const snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
--- a/src/pcm/pcm_hw.c
+++ b/src/pcm/pcm_hw.c
@@ -1004,6 +1004,181 @@ static int snd_pcm_hw_htimestamp(snd_pcm
return 0;
}
+static void fill_chmap_ctl_id(snd_pcm_t *pcm, snd_ctl_elem_id_t *id)
+{
+ snd_pcm_hw_t *hw = pcm->private_data;
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
+ if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
+ snd_ctl_elem_id_set_name(id, "Playback Channel Map");
+ else
+ snd_ctl_elem_id_set_name(id, "Capture Channel Map");
+ snd_ctl_elem_id_set_device(id, hw->device);
+ snd_ctl_elem_id_set_index(id, hw->subdevice);
+}
+
+static int is_chmap_type(int type)
+{
+ return (type >= SND_CTL_TLVT_CHMAP_FIXED &&
+ type <= SND_CTL_TLVT_CHMAP_PAIRED);
+}
+
+static int **snd_pcm_hw_query_chmaps(snd_pcm_t *pcm)
+{
+ snd_pcm_hw_t *hw = pcm->private_data;
+ snd_ctl_t *ctl;
+ snd_ctl_elem_id_t *id;
+ unsigned int tlv[256], *start;
+ int **map;
+ int i, ret, nums;
+
+ ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
+ if (ret < 0) {
+ SYSMSG("Cannot open the associated CTL\n");
+ return NULL;
+ }
+
+ snd_ctl_elem_id_alloca(&id);
+ fill_chmap_ctl_id(pcm, id);
+ ret = snd_ctl_elem_tlv_read(ctl, id, tlv, sizeof(tlv));
+ snd_ctl_close(ctl);
+ if (ret < 0) {
+ SYSMSG("Cannot read Channel Map TLV\n");
+ return NULL;
+ }
+
+#if 0
+ for (i = 0; i < 32; i++)
+ fprintf(stderr, "%02x: %08x\n", i, tlv[i]);
+#endif
+ if (tlv[0] != SND_CTL_TLVT_CONTAINER) {
+ if (!is_chmap_type(tlv[0])) {
+ SYSMSG("Invalid TLV type %d\n", tlv[0]);
+ return NULL;
+ }
+ start = tlv;
+ nums = 1;
+ } else {
+ unsigned int *p;
+ int size;
+ start = tlv + 2;
+ size = tlv[1];
+ nums = 0;
+ for (p = start; size > 0; ) {
+ if (!is_chmap_type(p[0])) {
+ SYSMSG("Invalid TLV type %d\n", p[0]);
+ return NULL;
+ }
+ nums++;
+ size -= p[1] + 8;
+ p += p[1] / 4 + 2;
+ }
+ }
+ map = calloc(nums + 1, sizeof(int *));
+ if (!map)
+ return NULL;
+ for (i = 0; i < nums; i++) {
+ map[i] = malloc(start[1] + 8);
+ if (!map[i])
+ goto nomem;
+ map[i][0] = start[0] - 0x100;
+ map[i][1] = start[1] / 4;
+ memcpy(map[i] + 2, start + 2, start[1]);
+ start += start[1] / 4 + 2;
+ }
+ return map;
+
+ nomem:
+ for (; i >= 0; i--)
+ free(map[i]);
+ free(map);
+ return NULL;
+}
+
+static int *snd_pcm_hw_get_chmap(snd_pcm_t *pcm)
+{
+ snd_pcm_hw_t *hw = pcm->private_data;
+ int *map;
+ snd_ctl_t *ctl;
+ snd_ctl_elem_id_t *id;
+ snd_ctl_elem_value_t *val;
+ unsigned int i;
+ int ret;
+
+ switch (FAST_PCM_STATE(hw)) {
+ case SNDRV_PCM_STATE_PREPARED:
+ case SNDRV_PCM_STATE_RUNNING:
+ case SNDRV_PCM_STATE_XRUN:
+ case SNDRV_PCM_STATE_DRAINING:
+ case SNDRV_PCM_STATE_PAUSED:
+ case SNDRV_PCM_STATE_SUSPENDED:
+ break;
+ default:
+ SYSMSG("Invalid PCM state for chmap_get: %s\n",
+ snd_pcm_state_name(FAST_PCM_STATE(hw)));
+ return NULL;
+ }
+ map = malloc(pcm->channels + 1);
+ if (!map)
+ return NULL;
+ *map = pcm->channels;
+ ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
+ if (ret < 0) {
+ free(map);
+ SYSMSG("Cannot open the associated CTL\n");
+ return NULL;
+ }
+ snd_ctl_elem_value_alloca(&val);
+ snd_ctl_elem_id_alloca(&id);
+ fill_chmap_ctl_id(pcm, id);
+ snd_ctl_elem_value_set_id(val, id);
+ ret = snd_ctl_elem_read(ctl, val);
+ if (ret < 0) {
+ snd_ctl_close(ctl);
+ free(map);
+ SYSMSG("Cannot read Channel Map ctl\n");
+ return NULL;
+ }
+ for (i = 0; i < pcm->channels; i++)
+ map[i + 1] = snd_ctl_elem_value_get_integer(val, i);
+ snd_ctl_close(ctl);
+ return map;
+}
+
+static int snd_pcm_hw_set_chmap(snd_pcm_t *pcm, const int *map)
+{
+ snd_pcm_hw_t *hw = pcm->private_data;
+ snd_ctl_t *ctl;
+ snd_ctl_elem_id_t *id;
+ snd_ctl_elem_value_t *val;
+ int i, ret;
+
+ if (*map < 0 || *map > 128) {
+ SYSMSG("Invalid number of channels %d\n", *map);
+ return -EINVAL;
+ }
+ if (FAST_PCM_STATE(hw) != SNDRV_PCM_STATE_PREPARED) {
+ SYSMSG("Invalid PCM state for chmap_set: %s\n",
+ snd_pcm_state_name(FAST_PCM_STATE(hw)));
+ return -EBADFD;
+ }
+ ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
+ if (ret < 0) {
+ SYSMSG("Cannot open the associated CTL\n");
+ return ret;
+ }
+ snd_ctl_elem_id_alloca(&id);
+ snd_ctl_elem_value_alloca(&val);
+ fill_chmap_ctl_id(pcm, id);
+ snd_ctl_elem_value_set_id(val, id);
+ for (i = 0; i < *map; i++)
+ snd_ctl_elem_value_set_integer(val, i, map[i + 1]);
+ ret = snd_ctl_elem_write(ctl, val);
+ snd_ctl_close(ctl);
+ if (ret < 0)
+ SYSMSG("Cannot write Channel Map ctl\n");
+ return ret;
+}
+
static void snd_pcm_hw_dump(snd_pcm_t *pcm, snd_output_t *out)
{
snd_pcm_hw_t *hw = pcm->private_data;
@@ -1037,6 +1212,9 @@ static const snd_pcm_ops_t snd_pcm_hw_op
.async = snd_pcm_hw_async,
.mmap = snd_pcm_hw_mmap,
.munmap = snd_pcm_hw_munmap,
+ .query_chmaps = snd_pcm_hw_query_chmaps,
+ .get_chmap = snd_pcm_hw_get_chmap,
+ .set_chmap = snd_pcm_hw_set_chmap,
};
static const snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
--- a/src/pcm/pcm_iec958.c
+++ b/src/pcm/pcm_iec958.c
@@ -429,6 +429,9 @@ static const snd_pcm_ops_t snd_pcm_iec95
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_generic_query_chmaps,
+ .get_chmap = snd_pcm_generic_get_chmap,
+ .set_chmap = snd_pcm_generic_set_chmap,
};
/**
--- a/src/pcm/pcm_ladspa.c
+++ b/src/pcm/pcm_ladspa.c
@@ -1084,6 +1084,9 @@ static const snd_pcm_ops_t snd_pcm_ladsp
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_generic_query_chmaps,
+ .get_chmap = snd_pcm_generic_get_chmap,
+ .set_chmap = snd_pcm_generic_set_chmap,
};
static int snd_pcm_ladspa_check_file(snd_pcm_ladspa_plugin_t * const plugin,
--- a/src/pcm/pcm_lfloat.c
+++ b/src/pcm/pcm_lfloat.c
@@ -363,6 +363,9 @@ static const snd_pcm_ops_t snd_pcm_lfloa
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_generic_query_chmaps,
+ .get_chmap = snd_pcm_generic_get_chmap,
+ .set_chmap = snd_pcm_generic_set_chmap,
};
/**
--- a/src/pcm/pcm_linear.c
+++ b/src/pcm/pcm_linear.c
@@ -435,6 +435,9 @@ static const snd_pcm_ops_t snd_pcm_linea
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_generic_query_chmaps,
+ .get_chmap = snd_pcm_generic_get_chmap,
+ .set_chmap = snd_pcm_generic_set_chmap,
};
--- a/src/pcm/pcm_local.h
+++ b/src/pcm/pcm_local.h
@@ -143,6 +143,9 @@ typedef struct {
void (*dump)(snd_pcm_t *pcm, snd_output_t *out);
int (*mmap)(snd_pcm_t *pcm);
int (*munmap)(snd_pcm_t *pcm);
+ int **(*query_chmaps)(snd_pcm_t *pcm);
+ int *(*get_chmap)(snd_pcm_t *pcm);
+ int (*set_chmap)(snd_pcm_t *pcm, const int *map);
} snd_pcm_ops_t;
typedef struct {
--- a/src/pcm/pcm_meter.c
+++ b/src/pcm/pcm_meter.c
@@ -514,6 +514,9 @@ static const snd_pcm_ops_t snd_pcm_meter
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_generic_query_chmaps,
+ .get_chmap = snd_pcm_generic_get_chmap,
+ .set_chmap = snd_pcm_generic_set_chmap,
};
static const snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
--- a/src/pcm/pcm_mmap_emul.c
+++ b/src/pcm/pcm_mmap_emul.c
@@ -368,6 +368,9 @@ static const snd_pcm_ops_t snd_pcm_mmap_
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_generic_query_chmaps,
+ .get_chmap = snd_pcm_generic_get_chmap,
+ .set_chmap = snd_pcm_generic_set_chmap,
};
static const snd_pcm_fast_ops_t snd_pcm_mmap_emul_fast_ops = {
--- a/src/pcm/pcm_mulaw.c
+++ b/src/pcm/pcm_mulaw.c
@@ -419,6 +419,8 @@ static const snd_pcm_ops_t snd_pcm_mulaw
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .get_chmap = snd_pcm_generic_get_chmap,
+ .set_chmap = snd_pcm_generic_set_chmap,
};
/**
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -1249,6 +1249,9 @@ static const snd_pcm_ops_t snd_pcm_rate_
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_generic_query_chmaps,
+ .get_chmap = snd_pcm_generic_get_chmap,
+ .set_chmap = snd_pcm_generic_set_chmap,
};
/**
--- a/src/pcm/pcm_softvol.c
+++ b/src/pcm/pcm_softvol.c
@@ -818,6 +818,9 @@ static const snd_pcm_ops_t snd_pcm_softv
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_generic_query_chmaps,
+ .get_chmap = snd_pcm_generic_get_chmap,
+ .set_chmap = snd_pcm_generic_set_chmap,
};
/**

View File

@ -1,150 +0,0 @@
From 3fb013065fee01ba7ac7c64fa48149f0e124fe26 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 25 Jul 2012 15:36:16 +0200
Subject: [PATCH 02/30] Implement get_chmap/set_chmap for PCM plug, route and
multi plugins
Still incomplete implementations. The query and set ops are missing
for route and multi plugins.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_multi.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/pcm/pcm_plug.c | 3 ++
src/pcm/pcm_route.c | 30 ++++++++++++++++++++++++++
3 files changed, 93 insertions(+)
--- a/src/pcm/pcm_multi.c
+++ b/src/pcm/pcm_multi.c
@@ -739,6 +739,63 @@ static int snd_pcm_multi_mmap(snd_pcm_t
return 0;
}
+static int *snd_pcm_multi_get_chmap(snd_pcm_t *pcm)
+{
+ snd_pcm_multi_t *multi = pcm->private_data;
+ int *map;
+ unsigned int i, idx;
+
+ map = malloc(pcm->channels + 4);
+ if (!map)
+ return NULL;
+ idx = 0;
+ for (i = 0; i < multi->slaves_count; ++i) {
+ int c, *slave_map;
+ slave_map = snd_pcm_get_chmap(multi->slaves[i].pcm);
+ if (!slave_map) {
+ free(map);
+ return NULL;
+ }
+ for (c = 0; c < *slave_map; c++) {
+ if (idx >= pcm->channels)
+ break;
+ map[idx++] = slave_map[c + 1];
+ }
+ free(slave_map);
+ }
+ return map;
+}
+
+static int snd_pcm_multi_set_chmap(snd_pcm_t *pcm, const int *map)
+{
+ snd_pcm_multi_t *multi = pcm->private_data;
+ unsigned int i, idx, chs;
+ int err;
+
+ chs = *map;
+ if (chs != pcm->channels)
+ return -EINVAL;
+ map++;
+ for (i = 0; i < multi->slaves_count; ++i) {
+ int *slave_map;
+ unsigned int slave_chs;
+ slave_chs = multi->slaves[i].channels_count;
+ if (idx + slave_chs > chs)
+ break;
+ slave_map = malloc(slave_chs * 4 + 4);
+ if (!slave_map)
+ return -ENOMEM;
+ *slave_map = slave_chs;
+ memcpy(slave_map, map + idx, slave_chs * 4);
+ err = snd_pcm_set_chmap(multi->slaves[i].pcm, slave_map);
+ free(slave_map);
+ if (err < 0)
+ return err;
+ idx += slave_chs;
+ }
+ return 0;
+}
+
static void snd_pcm_multi_dump(snd_pcm_t *pcm, snd_output_t *out)
{
snd_pcm_multi_t *multi = pcm->private_data;
@@ -775,6 +832,9 @@ static const snd_pcm_ops_t snd_pcm_multi
.async = snd_pcm_multi_async,
.mmap = snd_pcm_multi_mmap,
.munmap = snd_pcm_multi_munmap,
+ .query_chmaps = NULL, /* NYI */
+ .get_chmap = snd_pcm_multi_get_chmap,
+ .set_chmap = snd_pcm_multi_set_chmap,
};
static const snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
--- a/src/pcm/pcm_plug.c
+++ b/src/pcm/pcm_plug.c
@@ -1084,6 +1084,9 @@ static const snd_pcm_ops_t snd_pcm_plug_
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_generic_query_chmaps,
+ .get_chmap = snd_pcm_generic_get_chmap,
+ .set_chmap = snd_pcm_generic_set_chmap,
};
/**
--- a/src/pcm/pcm_route.c
+++ b/src/pcm/pcm_route.c
@@ -703,6 +703,33 @@ snd_pcm_route_read_areas(snd_pcm_t *pcm,
return size;
}
+static int *snd_pcm_route_get_chmap(snd_pcm_t *pcm)
+{
+ snd_pcm_route_t *route = pcm->private_data;
+ int *map, *slave_map;
+ unsigned int src, dst;
+
+ slave_map = snd_pcm_generic_get_chmap(pcm);
+ if (!slave_map)
+ return NULL;
+ map = calloc(4, route->schannels + 1);
+ if (!map) {
+ free(slave_map);
+ return NULL;
+ }
+ *map = route->schannels;
+ for (dst = 0; dst < route->params.ndsts; dst++) {
+ snd_pcm_route_ttable_dst_t *d = &route->params.dsts[dst];
+ for (src = 0; src < d->nsrcs; src++) {
+ int c = d->srcs[src].channel;
+ if (c < route->schannels && !map[c + 1])
+ map[c + 1] = slave_map[dst + 1];
+ }
+ }
+ free(slave_map);
+ return map;
+}
+
static void snd_pcm_route_dump(snd_pcm_t *pcm, snd_output_t *out)
{
snd_pcm_route_t *route = pcm->private_data;
@@ -760,6 +787,9 @@ static const snd_pcm_ops_t snd_pcm_route
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = NULL, /* NYI */
+ .get_chmap = snd_pcm_route_get_chmap,
+ .set_chmap = NULL, /* NYI */
};
static int route_load_ttable(snd_pcm_route_params_t *params, snd_pcm_stream_t stream,

View File

@ -1,179 +0,0 @@
From 662f79d4ec6b52bbaab28d5a9b60cc8bcdf042f9 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 25 Jul 2012 15:54:45 +0200
Subject: [PATCH 03/30] Implement get_chmap/set_chmap for PCM extplug/ioplug
plugins
Added the new ops for both external plugins, so the protocol numbers
are incremented.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/pcm_extplug.h | 14 +++++++++++++-
include/pcm_ioplug.h | 16 ++++++++++++++--
src/pcm/pcm_extplug.c | 33 +++++++++++++++++++++++++++++++++
src/pcm/pcm_ioplug.c | 33 +++++++++++++++++++++++++++++++++
4 files changed, 93 insertions(+), 3 deletions(-)
--- a/include/pcm_extplug.h
+++ b/include/pcm_extplug.h
@@ -55,7 +55,7 @@ typedef struct snd_pcm_extplug_callback
*/
#define SND_PCM_EXTPLUG_VERSION_MAJOR 1 /**< Protocol major version */
#define SND_PCM_EXTPLUG_VERSION_MINOR 0 /**< Protocol minor version */
-#define SND_PCM_EXTPLUG_VERSION_TINY 1 /**< Protocol tiny version */
+#define SND_PCM_EXTPLUG_VERSION_TINY 2 /**< Protocol tiny version */
/**
* Filter-plugin protocol version
*/
@@ -151,6 +151,18 @@ struct snd_pcm_extplug_callback {
* init; optional initialization called at prepare or reset
*/
int (*init)(snd_pcm_extplug_t *ext);
+ /**
+ * query the channel maps; optional; since v1.0.2
+ */
+ int **(*query_chmaps)(snd_pcm_extplug_t *ext);
+ /**
+ * get the channel map; optional; since v1.0.2
+ */
+ int *(*get_chmap)(snd_pcm_extplug_t *ext);
+ /**
+ * set the channel map; optional; since v1.0.2
+ */
+ int (*set_chmap)(snd_pcm_extplug_t *ext, const int *map);
};
--- a/include/pcm_ioplug.h
+++ b/include/pcm_ioplug.h
@@ -66,7 +66,7 @@ typedef struct snd_pcm_ioplug_callback s
*/
#define SND_PCM_IOPLUG_VERSION_MAJOR 1 /**< Protocol major version */
#define SND_PCM_IOPLUG_VERSION_MINOR 0 /**< Protocol minor version */
-#define SND_PCM_IOPLUG_VERSION_TINY 1 /**< Protocol tiny version */
+#define SND_PCM_IOPLUG_VERSION_TINY 2 /**< Protocol tiny version */
/**
* IO-plugin protocol version
*/
@@ -186,9 +186,21 @@ struct snd_pcm_ioplug_callback {
*/
void (*dump)(snd_pcm_ioplug_t *io, snd_output_t *out);
/**
- * get the delay for the running PCM; optional
+ * get the delay for the running PCM; optional; since v1.0.1
*/
int (*delay)(snd_pcm_ioplug_t *io, snd_pcm_sframes_t *delayp);
+ /**
+ * query the channel maps; optional; since v1.0.2
+ */
+ int **(*query_chmaps)(snd_pcm_ioplug_t *io);
+ /**
+ * get the channel map; optional; since v1.0.2
+ */
+ int *(*get_chmap)(snd_pcm_ioplug_t *io);
+ /**
+ * set the channel map; optional; since v1.0.2
+ */
+ int (*set_chmap)(snd_pcm_ioplug_t *io, const int *map);
};
--- a/src/pcm/pcm_extplug.c
+++ b/src/pcm/pcm_extplug.c
@@ -425,6 +425,36 @@ static int snd_pcm_extplug_close(snd_pcm
return 0;
}
+static int **snd_pcm_extplug_query_chmaps(snd_pcm_t *pcm)
+{
+ extplug_priv_t *ext = pcm->private_data;
+
+ if (ext->data->version >= 0x010002 &&
+ ext->data->callback->query_chmaps)
+ return ext->data->callback->query_chmaps(ext->data);
+ return snd_pcm_generic_query_chmaps(pcm);
+}
+
+static int *snd_pcm_extplug_get_chmap(snd_pcm_t *pcm)
+{
+ extplug_priv_t *ext = pcm->private_data;
+
+ if (ext->data->version >= 0x010002 &&
+ ext->data->callback->get_chmap)
+ return ext->data->callback->get_chmap(ext->data);
+ return snd_pcm_generic_get_chmap(pcm);
+}
+
+static int snd_pcm_extplug_set_chmap(snd_pcm_t *pcm, const int *map)
+{
+ extplug_priv_t *ext = pcm->private_data;
+
+ if (ext->data->version >= 0x010002 &&
+ ext->data->callback->set_chmap)
+ return ext->data->callback->set_chmap(ext->data, map);
+ return snd_pcm_generic_set_chmap(pcm, map);
+}
+
static const snd_pcm_ops_t snd_pcm_extplug_ops = {
.close = snd_pcm_extplug_close,
.info = snd_pcm_generic_info,
@@ -438,6 +468,9 @@ static const snd_pcm_ops_t snd_pcm_extpl
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_extplug_query_chmaps,
+ .get_chmap = snd_pcm_extplug_get_chmap,
+ .set_chmap = snd_pcm_extplug_set_chmap,
};
#endif /* !DOC_HIDDEN */
--- a/src/pcm/pcm_ioplug.c
+++ b/src/pcm/pcm_ioplug.c
@@ -710,6 +710,36 @@ static int snd_pcm_ioplug_munmap(snd_pcm
return 0;
}
+static int **snd_pcm_ioplug_query_chmaps(snd_pcm_t *pcm)
+{
+ ioplug_priv_t *io = pcm->private_data;
+
+ if (io->data->version >= 0x010002 &&
+ io->data->callback->query_chmaps)
+ return io->data->callback->query_chmaps(io->data);
+ return NULL;
+}
+
+static int *snd_pcm_ioplug_get_chmap(snd_pcm_t *pcm)
+{
+ ioplug_priv_t *io = pcm->private_data;
+
+ if (io->data->version >= 0x010002 &&
+ io->data->callback->get_chmap)
+ return io->data->callback->get_chmap(io->data);
+ return NULL;
+}
+
+static int snd_pcm_ioplug_set_chmap(snd_pcm_t *pcm, const int *map)
+{
+ ioplug_priv_t *io = pcm->private_data;
+
+ if (io->data->version >= 0x010002 &&
+ io->data->callback->set_chmap)
+ return io->data->callback->set_chmap(io->data, map);
+ return -ENXIO;
+}
+
static void snd_pcm_ioplug_dump(snd_pcm_t *pcm, snd_output_t *out)
{
ioplug_priv_t *io = pcm->private_data;
@@ -760,6 +790,9 @@ static const snd_pcm_ops_t snd_pcm_ioplu
.dump = snd_pcm_ioplug_dump,
.mmap = snd_pcm_ioplug_mmap,
.munmap = snd_pcm_ioplug_munmap,
+ .query_chmaps = snd_pcm_ioplug_query_chmaps,
+ .get_chmap = snd_pcm_ioplug_get_chmap,
+ .set_chmap = snd_pcm_ioplug_set_chmap,
};
static const snd_pcm_fast_ops_t snd_pcm_ioplug_fast_ops = {

View File

@ -1,288 +0,0 @@
From 3fc13d6f5b08edee49b106cd711d51bf3aef6ab7 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 30 Jul 2012 15:50:44 +0200
Subject: [PATCH 04/30] Add test/chmap program
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
test/Makefile.am | 3
test/chmap.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 256 insertions(+), 1 deletion(-)
create mode 100644 test/chmap.c
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -2,7 +2,7 @@ SUBDIRS=. lsb
check_PROGRAMS=control pcm pcm_min latency seq \
playmidi1 timer rawmidi midiloop \
- oldapi queue_timer namehint client_event_filter
+ oldapi queue_timer namehint client_event_filter chmap
control_LDADD=../src/libasound.la
pcm_LDADD=../src/libasound.la
@@ -18,6 +18,7 @@ queue_timer_LDADD=../src/libasound.la
namehint_LDADD=../src/libasound.la
client_event_filter_LDADD=../src/libasound.la
code_CFLAGS=-Wall -pipe -g -O2
+chmap_LDADD=../src/libasound.la
INCLUDES=-I$(top_srcdir)/include
AM_CFLAGS=-Wall -pipe -g
--- /dev/null
+++ b/test/chmap.c
@@ -0,0 +1,254 @@
+/*
+ * channel mapping API test program
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <getopt.h>
+#include "../include/asoundlib.h"
+
+static void usage(void)
+{
+ printf("usage: chmap [options] query\n"
+ " chmap [options] get\n"
+ " chmap [options] set CH0 CH1 CH2...\n"
+ "options:\n"
+ " -D device Specify PCM device to handle\n"
+ " -f format PCM format\n"
+ " -c channels Channels\n"
+ " -r rate Sample rate\n");
+}
+
+static const char * const chname[] = {
+ "Unknown",
+ "FL", "FC", "FR",
+ "FLC", "FRC", "RL", "RC", "RR",
+ "RLC", "RRC", "SL", "SR", "LFE",
+ "FLW", "FRW", "FLH",
+ "FCH", "FCH", "FRH",
+ "TC"
+};
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+
+static void print_channels(int channels, int *map)
+{
+ int i;
+ printf(" ");
+ for (i = 0; i < channels; i++) {
+ unsigned int c = *map++;
+ if (c >= ARRAY_SIZE(chname))
+ printf(" Ch%d", c);
+ else
+ printf(" %s", chname[c]);
+ }
+ printf("\n");
+}
+
+static int to_channel(const char *name)
+{
+ unsigned int i;
+
+ if (isdigit(*name))
+ return atoi(name);
+ for (i = 0; i < ARRAY_SIZE(chname); i++)
+ if (!strcmp(chname[i], name))
+ return i;
+ return 0;
+}
+
+static const char *chmap_type(int type)
+{
+ switch (type) {
+ case SND_CHMAP_NONE:
+ return "None";
+ case SND_CHMAP_FIXED:
+ return "Fixed";
+ case SND_CHMAP_VAR:
+ return "Variable";
+ case SND_CHMAP_PAIRED:
+ return "Paired";
+ default:
+ return "Unknown";
+ }
+}
+
+static int query_chmaps(snd_pcm_t *pcm)
+{
+ int **maps = snd_pcm_query_chmaps(pcm);
+ int **p, *v;
+
+ if (!maps) {
+ printf("Cannot query maps\n");
+ return 1;
+ }
+ for (p = maps; (v = *p) != NULL; p++) {
+ printf("Type = %s, Channels = %d\n", chmap_type(v[0]), v[1]);
+ print_channels(v[1], v + 2);
+ }
+ snd_pcm_free_chmaps(maps);
+ return 0;
+}
+
+static int setup_pcm(snd_pcm_t *pcm, int format, int channels, int rate)
+{
+ snd_pcm_hw_params_t *params;
+
+ snd_pcm_hw_params_alloca(&params);
+ if (snd_pcm_hw_params_any(pcm, params) < 0) {
+ printf("Cannot init hw_params\n");
+ return -1;
+ }
+ if (format != SND_PCM_FORMAT_UNKNOWN) {
+ if (snd_pcm_hw_params_set_format(pcm, params, format) < 0) {
+ printf("Cannot set format %s\n",
+ snd_pcm_format_name(format));
+ return -1;
+ }
+ }
+ if (channels > 0) {
+ if (snd_pcm_hw_params_set_channels(pcm, params, channels) < 0) {
+ printf("Cannot set channels %d\n", channels);
+ return -1;
+ }
+ }
+ if (rate > 0) {
+ if (snd_pcm_hw_params_set_rate_near(pcm, params, (unsigned int *)&rate, 0) < 0) {
+ printf("Cannot set rate %d\n", rate);
+ return -1;
+ }
+ }
+ if (snd_pcm_hw_params(pcm, params) < 0) {
+ printf("Cannot set hw_params\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int get_chmap(snd_pcm_t *pcm, int format, int channels, int rate)
+{
+ int *map;
+
+ if (setup_pcm(pcm, format, channels, rate))
+ return 1;
+ map = snd_pcm_get_chmap(pcm);
+ if (!map) {
+ printf("Cannot get chmap\n");
+ return 1;
+ }
+ printf("Channels = %d\n", *map);
+ print_channels(*map, map + 1);
+ free(map);
+ return 0;
+}
+
+static int set_chmap(snd_pcm_t *pcm, int format, int channels, int rate,
+ int nargs, char **arg)
+{
+ int i;
+ int *map;
+
+ if (channels && channels != nargs) {
+ printf("Inconsistent channels %d vs %d\n", channels, nargs);
+ return 1;
+ }
+ if (!channels) {
+ if (!nargs) {
+ printf("No channels are given\n");
+ return 1;
+ }
+ channels = nargs;
+ }
+ if (setup_pcm(pcm, format, channels, rate))
+ return 1;
+ map = malloc(sizeof(int) * channels + 1);
+ if (!map) {
+ printf("cannot malloc\n");
+ return 1;
+ }
+ *map = channels;
+ for (i = 0; i < channels; i++)
+ map[i + 1] = to_channel(arg[i]);
+ if (snd_pcm_set_chmap(pcm, map) < 0) {
+ printf("Cannot set chmap\n");
+ return 1;
+ }
+ free(map);
+
+ map = snd_pcm_get_chmap(pcm);
+ if (!map) {
+ printf("Cannot get chmap\n");
+ return 1;
+ }
+ printf("Get channels = %d\n", *map);
+ print_channels(*map, map + 1);
+ free(map);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ char *device = NULL;
+ int stream = SND_PCM_STREAM_PLAYBACK;
+ int format = SND_PCM_FORMAT_UNKNOWN;
+ int channels = 0;
+ int rate = 0;
+ snd_pcm_t *pcm;
+ int c;
+
+ while ((c = getopt(argc, argv, "D:s:f:c:r:")) != -1) {
+ switch (c) {
+ case 'D':
+ device = optarg;
+ break;
+ case 's':
+ if (*optarg == 'c' || *optarg == 'C')
+ stream = SND_PCM_STREAM_CAPTURE;
+ else
+ stream = SND_PCM_STREAM_PLAYBACK;
+ break;
+ case 'f':
+ format = snd_pcm_format_value(optarg);
+ break;
+ case 'c':
+ channels = atoi(optarg);
+ break;
+ case 'r':
+ rate = atoi(optarg);
+ break;
+ default:
+ usage();
+ return 1;
+ }
+ }
+
+ if (argc <= optind) {
+ usage();
+ return 1;
+ }
+
+ if (!device) {
+ printf("No device is specified\n");
+ return 1;
+ }
+
+ if (snd_pcm_open(&pcm, device, stream, SND_PCM_NONBLOCK) < 0) {
+ printf("Cannot open PCM stream %s for %s\n", device,
+ snd_pcm_stream_name(stream));
+ return 1;
+ }
+
+ switch (*argv[optind]) {
+ case 'q':
+ return query_chmaps(pcm);
+ case 'g':
+ return get_chmap(pcm, format, channels, rate);
+ case 's':
+ return set_chmap(pcm, format, channels, rate,
+ argc - optind - 1, argv + optind + 1);
+ }
+ usage();
+ return 1;
+}

View File

@ -1,188 +0,0 @@
From 34f6545520de73be55ee6c29a7ebd3c016fa9f06 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 30 Jul 2012 18:21:43 +0200
Subject: [PATCH 05/30] Cache the chmap operation errors
... not to retry the same error again.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_hw.c | 66 +++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 54 insertions(+), 12 deletions(-)
--- a/src/pcm/pcm_hw.c
+++ b/src/pcm/pcm_hw.c
@@ -105,6 +105,8 @@ typedef struct {
snd_pcm_format_t format;
int rate;
int channels;
+ /* for chmap */
+ unsigned int chmap_caps;
} snd_pcm_hw_t;
#define SNDRV_FILE_PCM_STREAM_PLAYBACK ALSA_DEVICE_DIRECTORY "pcmC%iD%ip"
@@ -1022,6 +1024,27 @@ static int is_chmap_type(int type)
type <= SND_CTL_TLVT_CHMAP_PAIRED);
}
+enum { CHMAP_CTL_QUERY, CHMAP_CTL_GET, CHMAP_CTL_SET };
+
+static int chmap_caps(snd_pcm_hw_t *hw, int type)
+{
+ if (hw->chmap_caps & (1 << type))
+ return 1;
+ if (hw->chmap_caps & (1 << (type + 8)))
+ return 0;
+ return 1;
+}
+
+static void chmap_caps_set_ok(snd_pcm_hw_t *hw, int type)
+{
+ hw->chmap_caps |= (1 << type);
+}
+
+static void chmap_caps_set_error(snd_pcm_hw_t *hw, int type)
+{
+ hw->chmap_caps |= (1 << (type + 8));
+}
+
static int **snd_pcm_hw_query_chmaps(snd_pcm_t *pcm)
{
snd_pcm_hw_t *hw = pcm->private_data;
@@ -1031,10 +1054,13 @@ static int **snd_pcm_hw_query_chmaps(snd
int **map;
int i, ret, nums;
+ if (!chmap_caps(hw, CHMAP_CTL_QUERY))
+ return NULL;
+
ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
if (ret < 0) {
SYSMSG("Cannot open the associated CTL\n");
- return NULL;
+ goto error;
}
snd_ctl_elem_id_alloca(&id);
@@ -1043,7 +1069,7 @@ static int **snd_pcm_hw_query_chmaps(snd
snd_ctl_close(ctl);
if (ret < 0) {
SYSMSG("Cannot read Channel Map TLV\n");
- return NULL;
+ goto error;
}
#if 0
@@ -1053,7 +1079,7 @@ static int **snd_pcm_hw_query_chmaps(snd
if (tlv[0] != SND_CTL_TLVT_CONTAINER) {
if (!is_chmap_type(tlv[0])) {
SYSMSG("Invalid TLV type %d\n", tlv[0]);
- return NULL;
+ goto error;
}
start = tlv;
nums = 1;
@@ -1066,7 +1092,7 @@ static int **snd_pcm_hw_query_chmaps(snd
for (p = start; size > 0; ) {
if (!is_chmap_type(p[0])) {
SYSMSG("Invalid TLV type %d\n", p[0]);
- return NULL;
+ goto error;
}
nums++;
size -= p[1] + 8;
@@ -1078,19 +1104,20 @@ static int **snd_pcm_hw_query_chmaps(snd
return NULL;
for (i = 0; i < nums; i++) {
map[i] = malloc(start[1] + 8);
- if (!map[i])
- goto nomem;
+ if (!map[i]) {
+ snd_pcm_free_chmaps(map);
+ return NULL;
+ }
map[i][0] = start[0] - 0x100;
map[i][1] = start[1] / 4;
memcpy(map[i] + 2, start + 2, start[1]);
start += start[1] / 4 + 2;
}
+ chmap_caps_set_ok(hw, CHMAP_CTL_QUERY);
return map;
- nomem:
- for (; i >= 0; i--)
- free(map[i]);
- free(map);
+ error:
+ chmap_caps_set_error(hw, CHMAP_CTL_QUERY);
return NULL;
}
@@ -1104,6 +1131,9 @@ static int *snd_pcm_hw_get_chmap(snd_pcm
unsigned int i;
int ret;
+ if (!chmap_caps(hw, CHMAP_CTL_GET))
+ return NULL;
+
switch (FAST_PCM_STATE(hw)) {
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_RUNNING:
@@ -1125,6 +1155,7 @@ static int *snd_pcm_hw_get_chmap(snd_pcm
if (ret < 0) {
free(map);
SYSMSG("Cannot open the associated CTL\n");
+ chmap_caps_set_error(hw, CHMAP_CTL_GET);
return NULL;
}
snd_ctl_elem_value_alloca(&val);
@@ -1132,15 +1163,16 @@ static int *snd_pcm_hw_get_chmap(snd_pcm
fill_chmap_ctl_id(pcm, id);
snd_ctl_elem_value_set_id(val, id);
ret = snd_ctl_elem_read(ctl, val);
+ snd_ctl_close(ctl);
if (ret < 0) {
- snd_ctl_close(ctl);
free(map);
SYSMSG("Cannot read Channel Map ctl\n");
+ chmap_caps_set_error(hw, CHMAP_CTL_GET);
return NULL;
}
for (i = 0; i < pcm->channels; i++)
map[i + 1] = snd_ctl_elem_value_get_integer(val, i);
- snd_ctl_close(ctl);
+ chmap_caps_set_ok(hw, CHMAP_CTL_GET);
return map;
}
@@ -1152,6 +1184,9 @@ static int snd_pcm_hw_set_chmap(snd_pcm_
snd_ctl_elem_value_t *val;
int i, ret;
+ if (!chmap_caps(hw, CHMAP_CTL_SET))
+ return -ENXIO;
+
if (*map < 0 || *map > 128) {
SYSMSG("Invalid number of channels %d\n", *map);
return -EINVAL;
@@ -1164,6 +1199,7 @@ static int snd_pcm_hw_set_chmap(snd_pcm_
ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
if (ret < 0) {
SYSMSG("Cannot open the associated CTL\n");
+ chmap_caps_set_error(hw, CHMAP_CTL_SET);
return ret;
}
snd_ctl_elem_id_alloca(&id);
@@ -1174,6 +1210,12 @@ static int snd_pcm_hw_set_chmap(snd_pcm_
snd_ctl_elem_value_set_integer(val, i, map[i + 1]);
ret = snd_ctl_elem_write(ctl, val);
snd_ctl_close(ctl);
+ if (ret >= 0)
+ chmap_caps_set_ok(hw, CHMAP_CTL_SET);
+ else if (ret == -ENOENT || ret == -EPERM || ret == -ENXIO) {
+ chmap_caps_set_error(hw, CHMAP_CTL_SET);
+ ret = -ENXIO;
+ }
if (ret < 0)
SYSMSG("Cannot write Channel Map ctl\n");
return ret;

View File

@ -1,56 +0,0 @@
From 915b26bfe8af876d467a37c336c6bf22d5e370fe Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 21 Aug 2012 12:16:39 +0200
Subject: [PATCH 06/30] Define channel map position enum in pcm.h
The original definition is in sound/asound.h, but we need to export to
alsa-lib users, too.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/pcm.h | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -474,13 +474,39 @@ int snd_pcm_wait(snd_pcm_t *pcm, int tim
int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
int snd_pcm_unlink(snd_pcm_t *pcm);
-enum {
+/** channel map list type */
+enum snd_pcm_chmap_type {
SND_CHMAP_NONE = 0, /** unspecified channel position */
SND_CHMAP_FIXED, /** fixed channel position */
SND_CHMAP_VAR, /** freely swappable channel position */
SND_CHMAP_PAIRED, /** pair-wise swappable channel position */
};
+/** channel positions */
+enum snd_pcm_chmap_position {
+ SND_CHMAP_UNKNOWN = 0, /** unspecified */
+ SND_CHMAP_FL, /** front left */
+ SND_CHMAP_FC, /** front center */
+ SND_CHMAP_FR, /** front right */
+ SND_CHMAP_FLC, /** front left center */
+ SND_CHMAP_FRC, /* front right center */
+ SND_CHMAP_RL, /** rear left */
+ SND_CHMAP_RC, /** rear center */
+ SND_CHMAP_RR, /** rear right */
+ SND_CHMAP_RLC, /** rear left center */
+ SND_CHMAP_RRC, /** rear right center */
+ SND_CHMAP_SL, /** side left */
+ SND_CHMAP_SR, /** side right */
+ SND_CHMAP_LFE, /** LFE */
+ SND_CHMAP_FLW, /** front left wide */
+ SND_CHMAP_FRW, /** front right wide */
+ SND_CHMAP_FLH, /** front left high */
+ SND_CHMAP_FCH, /** front center high */
+ SND_CHMAP_FRH, /** front right high */
+ SND_CHMAP_TC, /** top center */
+ SND_CHMAP_LAST = SND_CHMAP_TC, /** last entry */
+};
+
int **snd_pcm_query_chmaps(snd_pcm_t *pcm);
void snd_pcm_free_chmaps(int **maps);
int *snd_pcm_get_chmap(snd_pcm_t *pcm);

View File

@ -1,110 +0,0 @@
From 0f36270dd315b9baf3a93f5586776b91c0bcf589 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 21 Aug 2012 15:07:44 +0200
Subject: [PATCH 07/30] Follow channel position definitions to mixer channel
in mixer.h
mixer.h already contains some channel position definitions.
To be more consistent over all systems, better to follow the same
order for the new channel map, too. But since UNKNOWN channel must be
zero but the definition in mixer.h contains -1 as UNKNOWN, simply
shift the value with 1.
If the conversion is required between SND_CHMAP and SND_MIXER_SCHN,
just increment/decrement 1. Eventually I'll provide helper functions
for that...
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/pcm.h | 14 +++++++-------
include/sound/asound.h | 16 +++++++++-------
test/chmap.c | 11 ++++-------
3 files changed, 20 insertions(+), 21 deletions(-)
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -486,18 +486,18 @@ enum snd_pcm_chmap_type {
enum snd_pcm_chmap_position {
SND_CHMAP_UNKNOWN = 0, /** unspecified */
SND_CHMAP_FL, /** front left */
- SND_CHMAP_FC, /** front center */
SND_CHMAP_FR, /** front right */
- SND_CHMAP_FLC, /** front left center */
- SND_CHMAP_FRC, /* front right center */
SND_CHMAP_RL, /** rear left */
- SND_CHMAP_RC, /** rear center */
SND_CHMAP_RR, /** rear right */
- SND_CHMAP_RLC, /** rear left center */
- SND_CHMAP_RRC, /** rear right center */
+ SND_CHMAP_FC, /** front center */
+ SND_CHMAP_LFE, /** LFE */
SND_CHMAP_SL, /** side left */
SND_CHMAP_SR, /** side right */
- SND_CHMAP_LFE, /** LFE */
+ SND_CHMAP_RC, /** rear center */
+ SND_CHMAP_FLC, /** front left center */
+ SND_CHMAP_FRC, /** front right center */
+ SND_CHMAP_RLC, /** rear left center */
+ SND_CHMAP_RRC, /** rear right center */
SND_CHMAP_FLW, /** front left wide */
SND_CHMAP_FRW, /** front right wide */
SND_CHMAP_FLH, /** front left high */
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -479,20 +479,22 @@ enum {
/* channel positions */
enum {
+ /* this follows the alsa-lib mixer channel value + 1*/
SNDRV_CHMAP_UNKNOWN = 0,
SNDRV_CHMAP_FL, /* front left */
- SNDRV_CHMAP_FC, /* front center */
SNDRV_CHMAP_FR, /* front right */
- SNDRV_CHMAP_FLC, /* front left center */
- SNDRV_CHMAP_FRC, /* front right center */
SNDRV_CHMAP_RL, /* rear left */
- SNDRV_CHMAP_RC, /* rear center */
SNDRV_CHMAP_RR, /* rear right */
- SNDRV_CHMAP_RLC, /* rear left center */
- SNDRV_CHMAP_RRC, /* rear right center */
+ SNDRV_CHMAP_FC, /* front center */
+ SNDRV_CHMAP_LFE, /* LFE */
SNDRV_CHMAP_SL, /* side left */
SNDRV_CHMAP_SR, /* side right */
- SNDRV_CHMAP_LFE, /* LFE */
+ SNDRV_CHMAP_RC, /* rear center */
+ /* new definitions */
+ SNDRV_CHMAP_FLC, /* front left center */
+ SNDRV_CHMAP_FRC, /* front right center */
+ SNDRV_CHMAP_RLC, /* rear left center */
+ SNDRV_CHMAP_RRC, /* rear right center */
SNDRV_CHMAP_FLW, /* front left wide */
SNDRV_CHMAP_FRW, /* front right wide */
SNDRV_CHMAP_FLH, /* front left high */
--- a/test/chmap.c
+++ b/test/chmap.c
@@ -23,12 +23,9 @@ static void usage(void)
static const char * const chname[] = {
"Unknown",
- "FL", "FC", "FR",
- "FLC", "FRC", "RL", "RC", "RR",
- "RLC", "RRC", "SL", "SR", "LFE",
- "FLW", "FRW", "FLH",
- "FCH", "FCH", "FRH",
- "TC"
+ "FL", "FR", "RL", "RR", "FC", "LFE", "SL", "SR", "RC",
+ "FLC", "FRC", "RLC", "RRC", "FLW", "FRW", "FLH",
+ "FCH", "FCH", "FRH", "TC"
};
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
@@ -56,7 +53,7 @@ static int to_channel(const char *name)
for (i = 0; i < ARRAY_SIZE(chname); i++)
if (!strcmp(chname[i], name))
return i;
- return 0;
+ return SND_CHMAP_UNKNOWN;
}
static const char *chmap_type(int type)

View File

@ -1,88 +0,0 @@
From 48c2c90f19f07d02082d9fb84fb36ac1fcfa84e1 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 31 Aug 2012 13:53:22 -0700
Subject: [PATCH 08/30] Add SND_CHMAP_NA and bit flag definitions
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/pcm.h | 7 ++++++-
include/sound/asound.h | 9 +++++++--
test/chmap.c | 14 ++++++++++----
3 files changed, 23 insertions(+), 7 deletions(-)
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -504,9 +504,14 @@ enum snd_pcm_chmap_position {
SND_CHMAP_FCH, /** front center high */
SND_CHMAP_FRH, /** front right high */
SND_CHMAP_TC, /** top center */
- SND_CHMAP_LAST = SND_CHMAP_TC, /** last entry */
+ SND_CHMAP_NA, /** N/A, silent */
+ SND_CHMAP_LAST = SND_CHMAP_NA, /** last entry */
};
+#define SND_CHMAP_POSITION_MASK 0xffff /** bitmask for channel position */
+#define SND_CHMAP_PHASE_INVERSE (0x01 << 16) /* the channel is phase inverted */
+#define SND_CHMAP_DRIVER_SPEC (0x02 << 16) /* non-standard channel value */
+
int **snd_pcm_query_chmaps(snd_pcm_t *pcm);
void snd_pcm_free_chmaps(int **maps);
int *snd_pcm_get_chmap(snd_pcm_t *pcm);
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -479,7 +479,7 @@ enum {
/* channel positions */
enum {
- /* this follows the alsa-lib mixer channel value + 1*/
+ /* this follows the alsa-lib mixer channel value + 1 */
SNDRV_CHMAP_UNKNOWN = 0,
SNDRV_CHMAP_FL, /* front left */
SNDRV_CHMAP_FR, /* front right */
@@ -501,9 +501,14 @@ enum {
SNDRV_CHMAP_FCH, /* front center high */
SNDRV_CHMAP_FRH, /* front right high */
SNDRV_CHMAP_TC, /* top center */
- SNDRV_CHMAP_LAST = SNDRV_CHMAP_TC,
+ SNDRV_CHMAP_NA, /* N/A, silent */
+ SNDRV_CHMAP_LAST = SNDRV_CHMAP_NA,
};
+#define SNDRV_CHMAP_POSITION_MASK 0xffff
+#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16)
+#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16)
+
enum {
SNDRV_PCM_IOCTL_PVERSION = _IOR('A', 0x00, int),
SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct sndrv_pcm_info),
--- a/test/chmap.c
+++ b/test/chmap.c
@@ -25,7 +25,8 @@ static const char * const chname[] = {
"Unknown",
"FL", "FR", "RL", "RR", "FC", "LFE", "SL", "SR", "RC",
"FLC", "FRC", "RLC", "RRC", "FLW", "FRW", "FLH",
- "FCH", "FCH", "FRH", "TC"
+ "FCH", "FCH", "FRH", "TC",
+ "N/A",
};
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
@@ -36,10 +37,15 @@ static void print_channels(int channels,
printf(" ");
for (i = 0; i < channels; i++) {
unsigned int c = *map++;
- if (c >= ARRAY_SIZE(chname))
- printf(" Ch%d", c);
+ unsigned int pos = c & SND_CHMAP_POSITION_MASK;
+ if (c & SND_CHMAP_DRIVER_SPEC)
+ printf(" %d", p);
+ else if (p >= ARRAY_SIZE(chname))
+ printf(" Ch%d", p);
else
- printf(" %s", chname[c]);
+ printf(" %s", chname[p]);
+ if (c & SND_CHMAP_PHASE_INVERSE)
+ printf("[INV]");
}
printf("\n");
}

View File

@ -1,587 +0,0 @@
From 9c1a0ce72d71e4728d45dcd3986dd0ef0201dd67 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 4 Sep 2012 17:26:43 +0200
Subject: [PATCH 09/30] PCM: Introduce snd_pcm_chmap_t and
snd_pcm_chmap_query_t
Instead of passing ambiguous integer array, define snd_pcm_chmap_t and
snd_pcm_chmap_query_t so that user can understand more easily which
element is for what.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/pcm.h | 21 +++++++++++++++++----
include/pcm_extplug.h | 6 +++---
include/pcm_ioplug.h | 6 +++---
src/pcm/pcm.c | 10 +++++-----
src/pcm/pcm_direct.c | 6 +++---
src/pcm/pcm_direct.h | 6 +++---
src/pcm/pcm_extplug.c | 6 +++---
src/pcm/pcm_generic.c | 6 +++---
src/pcm/pcm_generic.h | 6 +++---
src/pcm/pcm_hw.c | 31 ++++++++++++++++---------------
src/pcm/pcm_ioplug.c | 6 +++---
src/pcm/pcm_local.h | 6 +++---
src/pcm/pcm_multi.c | 25 ++++++++++++++-----------
src/pcm/pcm_route.c | 10 +++++-----
test/chmap.c | 35 ++++++++++++++++++-----------------
15 files changed, 102 insertions(+), 84 deletions(-)
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -512,10 +512,23 @@ enum snd_pcm_chmap_position {
#define SND_CHMAP_PHASE_INVERSE (0x01 << 16) /* the channel is phase inverted */
#define SND_CHMAP_DRIVER_SPEC (0x02 << 16) /* non-standard channel value */
-int **snd_pcm_query_chmaps(snd_pcm_t *pcm);
-void snd_pcm_free_chmaps(int **maps);
-int *snd_pcm_get_chmap(snd_pcm_t *pcm);
-int snd_pcm_set_chmap(snd_pcm_t *pcm, const int *map);
+/** the channel map header */
+typedef struct snd_pcm_chmap {
+ unsigned int channels;
+ unsigned int pos[0];
+} snd_pcm_chmap_t;
+
+/** the header of array items returned from snd_pcm_query_chmaps() */
+typedef struct snd_pcm_chmap_query {
+ enum snd_pcm_chmap_type type;
+ snd_pcm_chmap_t map;
+} snd_pcm_chmap_query_t;
+
+
+snd_pcm_chmap_query_t **snd_pcm_query_chmaps(snd_pcm_t *pcm);
+void snd_pcm_free_chmaps(snd_pcm_chmap_query_t **maps);
+snd_pcm_chmap_t *snd_pcm_get_chmap(snd_pcm_t *pcm);
+int snd_pcm_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
//int snd_pcm_mixer_element(snd_pcm_t *pcm, snd_mixer_t *mixer, snd_mixer_elem_t **elem);
--- a/include/pcm_extplug.h
+++ b/include/pcm_extplug.h
@@ -154,15 +154,15 @@ struct snd_pcm_extplug_callback {
/**
* query the channel maps; optional; since v1.0.2
*/
- int **(*query_chmaps)(snd_pcm_extplug_t *ext);
+ snd_pcm_chmap_query_t **(*query_chmaps)(snd_pcm_extplug_t *ext);
/**
* get the channel map; optional; since v1.0.2
*/
- int *(*get_chmap)(snd_pcm_extplug_t *ext);
+ snd_pcm_chmap_t *(*get_chmap)(snd_pcm_extplug_t *ext);
/**
* set the channel map; optional; since v1.0.2
*/
- int (*set_chmap)(snd_pcm_extplug_t *ext, const int *map);
+ int (*set_chmap)(snd_pcm_extplug_t *ext, const snd_pcm_chmap_t *map);
};
--- a/include/pcm_ioplug.h
+++ b/include/pcm_ioplug.h
@@ -192,15 +192,15 @@ struct snd_pcm_ioplug_callback {
/**
* query the channel maps; optional; since v1.0.2
*/
- int **(*query_chmaps)(snd_pcm_ioplug_t *io);
+ snd_pcm_chmap_query_t **(*query_chmaps)(snd_pcm_ioplug_t *io);
/**
* get the channel map; optional; since v1.0.2
*/
- int *(*get_chmap)(snd_pcm_ioplug_t *io);
+ snd_pcm_chmap_t *(*get_chmap)(snd_pcm_ioplug_t *io);
/**
* set the channel map; optional; since v1.0.2
*/
- int (*set_chmap)(snd_pcm_ioplug_t *io, const int *map);
+ int (*set_chmap)(snd_pcm_ioplug_t *io, const snd_pcm_chmap_t *map);
};
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -7310,7 +7310,7 @@ OBSOLETE1(snd_pcm_sw_params_get_silence_
* integer array, beginning with the channel map type, followed by the
* number of channels, and the position of each channel.
*/
-int **snd_pcm_query_chmaps(snd_pcm_t *pcm)
+snd_pcm_chmap_query_t **snd_pcm_query_chmaps(snd_pcm_t *pcm)
{
if (!pcm->ops->query_chmaps)
return NULL;
@@ -7321,9 +7321,9 @@ int **snd_pcm_query_chmaps(snd_pcm_t *pc
* \!brief Release the channel map array allocated via #snd_pcm_query_chmaps
* \param maps the array pointer to release
*/
-void snd_pcm_free_chmaps(int **maps)
+void snd_pcm_free_chmaps(snd_pcm_chmap_query_t **maps)
{
- int **p;
+ snd_pcm_chmap_query_t **p = maps;
if (!maps)
return;
for (p = maps; *p; p++)
@@ -7336,7 +7336,7 @@ void snd_pcm_free_chmaps(int **maps)
* \param pcm PCM instance
* \return the current channel map, or NULL if error
*/
-int *snd_pcm_get_chmap(snd_pcm_t *pcm)
+snd_pcm_chmap_t *snd_pcm_get_chmap(snd_pcm_t *pcm)
{
if (!pcm->ops->get_chmap)
return NULL;
@@ -7349,7 +7349,7 @@ int *snd_pcm_get_chmap(snd_pcm_t *pcm)
* \param map the channel map to write
* \return zero if succeeded, or a negative error code
*/
-int snd_pcm_set_chmap(snd_pcm_t *pcm, const int *map)
+int snd_pcm_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
{
if (!pcm->ops->set_chmap)
return -ENXIO;
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -789,19 +789,19 @@ int snd_pcm_direct_munmap(snd_pcm_t *pcm
return 0;
}
-int **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm)
+snd_pcm_chmap_query_t **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dmix = pcm->private_data;
return snd_pcm_query_chmaps(dmix->spcm);
}
-int *snd_pcm_direct_get_chmap(snd_pcm_t *pcm)
+snd_pcm_chmap_t *snd_pcm_direct_get_chmap(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dmix = pcm->private_data;
return snd_pcm_get_chmap(dmix->spcm);
}
-int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const int *map)
+int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
{
snd_pcm_direct_t *dmix = pcm->private_data;
return snd_pcm_set_chmap(dmix->spcm, map);
--- a/src/pcm/pcm_direct.h
+++ b/src/pcm/pcm_direct.h
@@ -296,9 +296,9 @@ void snd_pcm_direct_clear_timer_queue(sn
int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix);
int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name);
-int **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm);
-int *snd_pcm_direct_get_chmap(snd_pcm_t *pcm);
-int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const int *map);
+snd_pcm_chmap_query_t **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm);
+snd_pcm_chmap_t *snd_pcm_direct_get_chmap(snd_pcm_t *pcm);
+int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);
--- a/src/pcm/pcm_extplug.c
+++ b/src/pcm/pcm_extplug.c
@@ -425,7 +425,7 @@ static int snd_pcm_extplug_close(snd_pcm
return 0;
}
-static int **snd_pcm_extplug_query_chmaps(snd_pcm_t *pcm)
+static snd_pcm_chmap_query_t **snd_pcm_extplug_query_chmaps(snd_pcm_t *pcm)
{
extplug_priv_t *ext = pcm->private_data;
@@ -435,7 +435,7 @@ static int **snd_pcm_extplug_query_chmap
return snd_pcm_generic_query_chmaps(pcm);
}
-static int *snd_pcm_extplug_get_chmap(snd_pcm_t *pcm)
+static snd_pcm_chmap_t *snd_pcm_extplug_get_chmap(snd_pcm_t *pcm)
{
extplug_priv_t *ext = pcm->private_data;
@@ -445,7 +445,7 @@ static int *snd_pcm_extplug_get_chmap(sn
return snd_pcm_generic_get_chmap(pcm);
}
-static int snd_pcm_extplug_set_chmap(snd_pcm_t *pcm, const int *map)
+static int snd_pcm_extplug_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
{
extplug_priv_t *ext = pcm->private_data;
--- a/src/pcm/pcm_generic.c
+++ b/src/pcm/pcm_generic.c
@@ -323,19 +323,19 @@ int snd_pcm_generic_munmap(snd_pcm_t *pc
return 0;
}
-int **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm)
+snd_pcm_chmap_query_t **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm)
{
snd_pcm_generic_t *generic = pcm->private_data;
return snd_pcm_query_chmaps(generic->slave);
}
-int *snd_pcm_generic_get_chmap(snd_pcm_t *pcm)
+snd_pcm_chmap_t *snd_pcm_generic_get_chmap(snd_pcm_t *pcm)
{
snd_pcm_generic_t *generic = pcm->private_data;
return snd_pcm_get_chmap(generic->slave);
}
-int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const int *map)
+int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
{
snd_pcm_generic_t *generic = pcm->private_data;
return snd_pcm_set_chmap(generic->slave, map);
--- a/src/pcm/pcm_generic.h
+++ b/src/pcm/pcm_generic.h
@@ -155,8 +155,8 @@ int snd_pcm_generic_real_htimestamp(snd_
snd_htimestamp_t *tstamp);
int snd_pcm_generic_mmap(snd_pcm_t *pcm);
int snd_pcm_generic_munmap(snd_pcm_t *pcm);
-int **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm);
-int *snd_pcm_generic_get_chmap(snd_pcm_t *pcm);
-int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const int *map);
+snd_pcm_chmap_query_t **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm);
+snd_pcm_chmap_t *snd_pcm_generic_get_chmap(snd_pcm_t *pcm);
+int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
--- a/src/pcm/pcm_hw.c
+++ b/src/pcm/pcm_hw.c
@@ -1045,13 +1045,13 @@ static void chmap_caps_set_error(snd_pcm
hw->chmap_caps |= (1 << (type + 8));
}
-static int **snd_pcm_hw_query_chmaps(snd_pcm_t *pcm)
+static snd_pcm_chmap_query_t **snd_pcm_hw_query_chmaps(snd_pcm_t *pcm)
{
snd_pcm_hw_t *hw = pcm->private_data;
snd_ctl_t *ctl;
snd_ctl_elem_id_t *id;
unsigned int tlv[256], *start;
- int **map;
+ snd_pcm_chmap_query_t **map;
int i, ret, nums;
if (!chmap_caps(hw, CHMAP_CTL_QUERY))
@@ -1108,9 +1108,9 @@ static int **snd_pcm_hw_query_chmaps(snd
snd_pcm_free_chmaps(map);
return NULL;
}
- map[i][0] = start[0] - 0x100;
- map[i][1] = start[1] / 4;
- memcpy(map[i] + 2, start + 2, start[1]);
+ map[i]->type = start[0] - 0x100;
+ map[i]->map.channels = start[1] / 4;
+ memcpy(map[i]->map.pos, start + 2, start[1]);
start += start[1] / 4 + 2;
}
chmap_caps_set_ok(hw, CHMAP_CTL_QUERY);
@@ -1121,10 +1121,10 @@ static int **snd_pcm_hw_query_chmaps(snd
return NULL;
}
-static int *snd_pcm_hw_get_chmap(snd_pcm_t *pcm)
+static snd_pcm_chmap_t *snd_pcm_hw_get_chmap(snd_pcm_t *pcm)
{
snd_pcm_hw_t *hw = pcm->private_data;
- int *map;
+ snd_pcm_chmap_t *map;
snd_ctl_t *ctl;
snd_ctl_elem_id_t *id;
snd_ctl_elem_value_t *val;
@@ -1150,7 +1150,7 @@ static int *snd_pcm_hw_get_chmap(snd_pcm
map = malloc(pcm->channels + 1);
if (!map)
return NULL;
- *map = pcm->channels;
+ map->channels = pcm->channels;
ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
if (ret < 0) {
free(map);
@@ -1171,24 +1171,25 @@ static int *snd_pcm_hw_get_chmap(snd_pcm
return NULL;
}
for (i = 0; i < pcm->channels; i++)
- map[i + 1] = snd_ctl_elem_value_get_integer(val, i);
+ map->pos[i] = snd_ctl_elem_value_get_integer(val, i);
chmap_caps_set_ok(hw, CHMAP_CTL_GET);
return map;
}
-static int snd_pcm_hw_set_chmap(snd_pcm_t *pcm, const int *map)
+static int snd_pcm_hw_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
{
snd_pcm_hw_t *hw = pcm->private_data;
snd_ctl_t *ctl;
snd_ctl_elem_id_t *id;
snd_ctl_elem_value_t *val;
- int i, ret;
+ unsigned int i;
+ int ret;
if (!chmap_caps(hw, CHMAP_CTL_SET))
return -ENXIO;
- if (*map < 0 || *map > 128) {
- SYSMSG("Invalid number of channels %d\n", *map);
+ if (map->channels > 128) {
+ SYSMSG("Invalid number of channels %d\n", map->channels);
return -EINVAL;
}
if (FAST_PCM_STATE(hw) != SNDRV_PCM_STATE_PREPARED) {
@@ -1206,8 +1207,8 @@ static int snd_pcm_hw_set_chmap(snd_pcm_
snd_ctl_elem_value_alloca(&val);
fill_chmap_ctl_id(pcm, id);
snd_ctl_elem_value_set_id(val, id);
- for (i = 0; i < *map; i++)
- snd_ctl_elem_value_set_integer(val, i, map[i + 1]);
+ for (i = 0; i < map->channels; i++)
+ snd_ctl_elem_value_set_integer(val, i, map->pos[i]);
ret = snd_ctl_elem_write(ctl, val);
snd_ctl_close(ctl);
if (ret >= 0)
--- a/src/pcm/pcm_ioplug.c
+++ b/src/pcm/pcm_ioplug.c
@@ -710,7 +710,7 @@ static int snd_pcm_ioplug_munmap(snd_pcm
return 0;
}
-static int **snd_pcm_ioplug_query_chmaps(snd_pcm_t *pcm)
+static snd_pcm_chmap_query_t **snd_pcm_ioplug_query_chmaps(snd_pcm_t *pcm)
{
ioplug_priv_t *io = pcm->private_data;
@@ -720,7 +720,7 @@ static int **snd_pcm_ioplug_query_chmaps
return NULL;
}
-static int *snd_pcm_ioplug_get_chmap(snd_pcm_t *pcm)
+static snd_pcm_chmap_t *snd_pcm_ioplug_get_chmap(snd_pcm_t *pcm)
{
ioplug_priv_t *io = pcm->private_data;
@@ -730,7 +730,7 @@ static int *snd_pcm_ioplug_get_chmap(snd
return NULL;
}
-static int snd_pcm_ioplug_set_chmap(snd_pcm_t *pcm, const int *map)
+static int snd_pcm_ioplug_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
{
ioplug_priv_t *io = pcm->private_data;
--- a/src/pcm/pcm_local.h
+++ b/src/pcm/pcm_local.h
@@ -143,9 +143,9 @@ typedef struct {
void (*dump)(snd_pcm_t *pcm, snd_output_t *out);
int (*mmap)(snd_pcm_t *pcm);
int (*munmap)(snd_pcm_t *pcm);
- int **(*query_chmaps)(snd_pcm_t *pcm);
- int *(*get_chmap)(snd_pcm_t *pcm);
- int (*set_chmap)(snd_pcm_t *pcm, const int *map);
+ snd_pcm_chmap_query_t **(*query_chmaps)(snd_pcm_t *pcm);
+ snd_pcm_chmap_t *(*get_chmap)(snd_pcm_t *pcm);
+ int (*set_chmap)(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
} snd_pcm_ops_t;
typedef struct {
--- a/src/pcm/pcm_multi.c
+++ b/src/pcm/pcm_multi.c
@@ -739,10 +739,10 @@ static int snd_pcm_multi_mmap(snd_pcm_t
return 0;
}
-static int *snd_pcm_multi_get_chmap(snd_pcm_t *pcm)
+static snd_pcm_chmap_t *snd_pcm_multi_get_chmap(snd_pcm_t *pcm)
{
snd_pcm_multi_t *multi = pcm->private_data;
- int *map;
+ snd_pcm_chmap_t *map;
unsigned int i, idx;
map = malloc(pcm->channels + 4);
@@ -750,34 +750,37 @@ static int *snd_pcm_multi_get_chmap(snd_
return NULL;
idx = 0;
for (i = 0; i < multi->slaves_count; ++i) {
- int c, *slave_map;
+ unsigned int c;
+ snd_pcm_chmap_t *slave_map;
slave_map = snd_pcm_get_chmap(multi->slaves[i].pcm);
if (!slave_map) {
free(map);
return NULL;
}
- for (c = 0; c < *slave_map; c++) {
+ for (c = 0; c < slave_map->channels; c++) {
if (idx >= pcm->channels)
break;
- map[idx++] = slave_map[c + 1];
+ map->pos[idx++] = slave_map->pos[c];
}
free(slave_map);
}
return map;
}
-static int snd_pcm_multi_set_chmap(snd_pcm_t *pcm, const int *map)
+static int snd_pcm_multi_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
{
snd_pcm_multi_t *multi = pcm->private_data;
+ const unsigned int *pos;
unsigned int i, idx, chs;
int err;
- chs = *map;
+ chs = map->channels;
if (chs != pcm->channels)
return -EINVAL;
- map++;
+ pos = map->pos;
+ idx = 0;
for (i = 0; i < multi->slaves_count; ++i) {
- int *slave_map;
+ snd_pcm_chmap_t *slave_map;
unsigned int slave_chs;
slave_chs = multi->slaves[i].channels_count;
if (idx + slave_chs > chs)
@@ -785,8 +788,8 @@ static int snd_pcm_multi_set_chmap(snd_p
slave_map = malloc(slave_chs * 4 + 4);
if (!slave_map)
return -ENOMEM;
- *slave_map = slave_chs;
- memcpy(slave_map, map + idx, slave_chs * 4);
+ slave_map->channels = slave_chs;
+ memcpy(slave_map->pos, pos + idx, slave_chs * 4);
err = snd_pcm_set_chmap(multi->slaves[i].pcm, slave_map);
free(slave_map);
if (err < 0)
--- a/src/pcm/pcm_route.c
+++ b/src/pcm/pcm_route.c
@@ -703,10 +703,10 @@ snd_pcm_route_read_areas(snd_pcm_t *pcm,
return size;
}
-static int *snd_pcm_route_get_chmap(snd_pcm_t *pcm)
+static snd_pcm_chmap_t *snd_pcm_route_get_chmap(snd_pcm_t *pcm)
{
snd_pcm_route_t *route = pcm->private_data;
- int *map, *slave_map;
+ snd_pcm_chmap_t *map, *slave_map;
unsigned int src, dst;
slave_map = snd_pcm_generic_get_chmap(pcm);
@@ -717,13 +717,13 @@ static int *snd_pcm_route_get_chmap(snd_
free(slave_map);
return NULL;
}
- *map = route->schannels;
+ map->channels = route->schannels;
for (dst = 0; dst < route->params.ndsts; dst++) {
snd_pcm_route_ttable_dst_t *d = &route->params.dsts[dst];
for (src = 0; src < d->nsrcs; src++) {
int c = d->srcs[src].channel;
- if (c < route->schannels && !map[c + 1])
- map[c + 1] = slave_map[dst + 1];
+ if (c < route->schannels && !map->pos[c])
+ map->pos[c] = slave_map->pos[dst];
}
}
free(slave_map);
--- a/test/chmap.c
+++ b/test/chmap.c
@@ -31,13 +31,14 @@ static const char * const chname[] = {
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
-static void print_channels(int channels, int *map)
+static void print_channels(const snd_pcm_chmap_t *map)
{
- int i;
+ unsigned int i;
+
printf(" ");
- for (i = 0; i < channels; i++) {
- unsigned int c = *map++;
- unsigned int pos = c & SND_CHMAP_POSITION_MASK;
+ for (i = 0; i < map->channels; i++) {
+ unsigned int c = map->pos[i];
+ unsigned int p = c & SND_CHMAP_POSITION_MASK;
if (c & SND_CHMAP_DRIVER_SPEC)
printf(" %d", p);
else if (p >= ARRAY_SIZE(chname))
@@ -80,16 +81,16 @@ static const char *chmap_type(int type)
static int query_chmaps(snd_pcm_t *pcm)
{
- int **maps = snd_pcm_query_chmaps(pcm);
- int **p, *v;
+ snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps(pcm);
+ snd_pcm_chmap_query_t **p, *v;
if (!maps) {
printf("Cannot query maps\n");
return 1;
}
for (p = maps; (v = *p) != NULL; p++) {
- printf("Type = %s, Channels = %d\n", chmap_type(v[0]), v[1]);
- print_channels(v[1], v + 2);
+ printf("Type = %s, Channels = %d\n", chmap_type(v->type), v->map.channels);
+ print_channels(&v->map);
}
snd_pcm_free_chmaps(maps);
return 0;
@@ -132,7 +133,7 @@ static int setup_pcm(snd_pcm_t *pcm, int
static int get_chmap(snd_pcm_t *pcm, int format, int channels, int rate)
{
- int *map;
+ snd_pcm_chmap_t *map;
if (setup_pcm(pcm, format, channels, rate))
return 1;
@@ -141,8 +142,8 @@ static int get_chmap(snd_pcm_t *pcm, int
printf("Cannot get chmap\n");
return 1;
}
- printf("Channels = %d\n", *map);
- print_channels(*map, map + 1);
+ printf("Channels = %d\n", map->channels);
+ print_channels(map);
free(map);
return 0;
}
@@ -151,7 +152,7 @@ static int set_chmap(snd_pcm_t *pcm, int
int nargs, char **arg)
{
int i;
- int *map;
+ snd_pcm_chmap_t *map;
if (channels && channels != nargs) {
printf("Inconsistent channels %d vs %d\n", channels, nargs);
@@ -171,9 +172,9 @@ static int set_chmap(snd_pcm_t *pcm, int
printf("cannot malloc\n");
return 1;
}
- *map = channels;
+ map->channels = channels;
for (i = 0; i < channels; i++)
- map[i + 1] = to_channel(arg[i]);
+ map->pos[i] = to_channel(arg[i]);
if (snd_pcm_set_chmap(pcm, map) < 0) {
printf("Cannot set chmap\n");
return 1;
@@ -185,8 +186,8 @@ static int set_chmap(snd_pcm_t *pcm, int
printf("Cannot get chmap\n");
return 1;
}
- printf("Get channels = %d\n", *map);
- print_channels(*map, map + 1);
+ printf("Get channels = %d\n", map->channels);
+ print_channels(map);
free(map);
return 0;
}

View File

@ -1,207 +0,0 @@
From 01dc0e6825b5620510faaefaef40ff8cfb692b6e Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 7 Sep 2012 14:15:04 +0200
Subject: [PATCH 10/30] PCM: Implement snd_pcm_query_chmaps_from_hw()
This is a function similar like snd_pcm_query_chmaps() but performs
the query without a PCM handle. The card, device and substream
numbers are passed as well as stream direction.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/pcm.h | 3 +
src/pcm/pcm_hw.c | 117 +++++++++++++++++++++++++++++++++++--------------------
2 files changed, 79 insertions(+), 41 deletions(-)
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -526,6 +526,9 @@ typedef struct snd_pcm_chmap_query {
snd_pcm_chmap_query_t **snd_pcm_query_chmaps(snd_pcm_t *pcm);
+snd_pcm_chmap_query_t **snd_pcm_query_chmaps_from_hw(int card, int dev,
+ int subdev,
+ snd_pcm_stream_t stream);
void snd_pcm_free_chmaps(snd_pcm_chmap_query_t **maps);
snd_pcm_chmap_t *snd_pcm_get_chmap(snd_pcm_t *pcm);
int snd_pcm_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
--- a/src/pcm/pcm_hw.c
+++ b/src/pcm/pcm_hw.c
@@ -1006,80 +1006,82 @@ static int snd_pcm_hw_htimestamp(snd_pcm
return 0;
}
-static void fill_chmap_ctl_id(snd_pcm_t *pcm, snd_ctl_elem_id_t *id)
+static void __fill_chmap_ctl_id(snd_ctl_elem_id_t *id, int dev, int subdev,
+ int stream)
{
- snd_pcm_hw_t *hw = pcm->private_data;
snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
- if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
+ if (stream == SND_PCM_STREAM_PLAYBACK)
snd_ctl_elem_id_set_name(id, "Playback Channel Map");
else
snd_ctl_elem_id_set_name(id, "Capture Channel Map");
- snd_ctl_elem_id_set_device(id, hw->device);
- snd_ctl_elem_id_set_index(id, hw->subdevice);
-}
-
-static int is_chmap_type(int type)
-{
- return (type >= SND_CTL_TLVT_CHMAP_FIXED &&
- type <= SND_CTL_TLVT_CHMAP_PAIRED);
-}
-
-enum { CHMAP_CTL_QUERY, CHMAP_CTL_GET, CHMAP_CTL_SET };
-
-static int chmap_caps(snd_pcm_hw_t *hw, int type)
-{
- if (hw->chmap_caps & (1 << type))
- return 1;
- if (hw->chmap_caps & (1 << (type + 8)))
- return 0;
- return 1;
+ snd_ctl_elem_id_set_device(id, dev);
+ snd_ctl_elem_id_set_index(id, subdev);
}
-static void chmap_caps_set_ok(snd_pcm_hw_t *hw, int type)
+static void fill_chmap_ctl_id(snd_pcm_t *pcm, snd_ctl_elem_id_t *id)
{
- hw->chmap_caps |= (1 << type);
+ snd_pcm_hw_t *hw = pcm->private_data;
+ return __fill_chmap_ctl_id(id, hw->device, hw->subdevice, pcm->stream);
}
-static void chmap_caps_set_error(snd_pcm_hw_t *hw, int type)
+static int is_chmap_type(int type)
{
- hw->chmap_caps |= (1 << (type + 8));
+ return (type >= SND_CTL_TLVT_CHMAP_FIXED &&
+ type <= SND_CTL_TLVT_CHMAP_PAIRED);
}
-static snd_pcm_chmap_query_t **snd_pcm_hw_query_chmaps(snd_pcm_t *pcm)
+/**
+ * \!brief Query the available channel maps
+ * \param card the card number
+ * \param dev the PCM device number
+ * \param subdev the PCM substream index
+ * \param stream the direction of PCM stream
+ * \return the NULL-terminated array of integer pointers, or NULL at error.
+ *
+ * This function works like snd_pcm_query_chmaps() but it takes the card,
+ * device, substream and stream numbers instead of the already opened
+ * snd_pcm_t instance, so that you can query available channel maps of
+ * a PCM before actually opening it.
+ *
+ * As the parameters stand, the query is performed only to the hw PCM
+ * devices, not the abstracted PCM object in alsa-lib.
+ */
+snd_pcm_chmap_query_t **
+snd_pcm_query_chmaps_from_hw(int card, int dev, int subdev,
+ snd_pcm_stream_t stream)
{
- snd_pcm_hw_t *hw = pcm->private_data;
snd_ctl_t *ctl;
snd_ctl_elem_id_t *id;
unsigned int tlv[256], *start;
snd_pcm_chmap_query_t **map;
int i, ret, nums;
- if (!chmap_caps(hw, CHMAP_CTL_QUERY))
- return NULL;
-
- ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
+ ret = snd_ctl_hw_open(&ctl, NULL, card, 0);
if (ret < 0) {
SYSMSG("Cannot open the associated CTL\n");
- goto error;
+ return NULL;
}
snd_ctl_elem_id_alloca(&id);
- fill_chmap_ctl_id(pcm, id);
+ __fill_chmap_ctl_id(id, dev, subdev, stream);
ret = snd_ctl_elem_tlv_read(ctl, id, tlv, sizeof(tlv));
snd_ctl_close(ctl);
if (ret < 0) {
SYSMSG("Cannot read Channel Map TLV\n");
- goto error;
+ return NULL;
}
#if 0
for (i = 0; i < 32; i++)
fprintf(stderr, "%02x: %08x\n", i, tlv[i]);
#endif
+ /* FIXME: the parser below assumes that the TLV only contains
+ * chmap-related blocks
+ */
if (tlv[0] != SND_CTL_TLVT_CONTAINER) {
if (!is_chmap_type(tlv[0])) {
SYSMSG("Invalid TLV type %d\n", tlv[0]);
- goto error;
+ return NULL;
}
start = tlv;
nums = 1;
@@ -1092,7 +1094,7 @@ static snd_pcm_chmap_query_t **snd_pcm_h
for (p = start; size > 0; ) {
if (!is_chmap_type(p[0])) {
SYSMSG("Invalid TLV type %d\n", p[0]);
- goto error;
+ return NULL;
}
nums++;
size -= p[1] + 8;
@@ -1113,12 +1115,45 @@ static snd_pcm_chmap_query_t **snd_pcm_h
memcpy(map[i]->map.pos, start + 2, start[1]);
start += start[1] / 4 + 2;
}
- chmap_caps_set_ok(hw, CHMAP_CTL_QUERY);
return map;
+}
+
+enum { CHMAP_CTL_QUERY, CHMAP_CTL_GET, CHMAP_CTL_SET };
+
+static int chmap_caps(snd_pcm_hw_t *hw, int type)
+{
+ if (hw->chmap_caps & (1 << type))
+ return 1;
+ if (hw->chmap_caps & (1 << (type + 8)))
+ return 0;
+ return 1;
+}
+
+static void chmap_caps_set_ok(snd_pcm_hw_t *hw, int type)
+{
+ hw->chmap_caps |= (1 << type);
+}
- error:
- chmap_caps_set_error(hw, CHMAP_CTL_QUERY);
- return NULL;
+static void chmap_caps_set_error(snd_pcm_hw_t *hw, int type)
+{
+ hw->chmap_caps |= (1 << (type + 8));
+}
+
+static snd_pcm_chmap_query_t **snd_pcm_hw_query_chmaps(snd_pcm_t *pcm)
+{
+ snd_pcm_hw_t *hw = pcm->private_data;
+ snd_pcm_chmap_query_t **map;
+
+ if (!chmap_caps(hw, CHMAP_CTL_QUERY))
+ return NULL;
+
+ map = snd_pcm_query_chmaps_from_hw(hw->card, hw->device,
+ hw->subdevice, pcm->stream);
+ if (map)
+ chmap_caps_set_ok(hw, CHMAP_CTL_QUERY);
+ else
+ chmap_caps_set_error(hw, CHMAP_CTL_QUERY);
+ return map;
}
static snd_pcm_chmap_t *snd_pcm_hw_get_chmap(snd_pcm_t *pcm)

View File

@ -1,21 +0,0 @@
From ec96740d9919b5e0c050a4b91aebee4b1dbb8298 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 7 Sep 2012 14:31:39 +0200
Subject: [PATCH 11/30] Fix duplicated channel entry in test/chmap.c
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
test/chmap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/test/chmap.c
+++ b/test/chmap.c
@@ -25,7 +25,7 @@ static const char * const chname[] = {
"Unknown",
"FL", "FR", "RL", "RR", "FC", "LFE", "SL", "SR", "RC",
"FLC", "FRC", "RLC", "RRC", "FLW", "FRW", "FLH",
- "FCH", "FCH", "FRH", "TC",
+ "FCH", "FRH", "TC",
"N/A",
};

View File

@ -1,32 +0,0 @@
From 6950a1030c4f878b51104268e3cd13401d56bf60 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 10 Sep 2012 16:59:36 +0200
Subject: [PATCH 12/30] PCM: Fix prefix for snd_pcm_chmap_type enum members
Add _TYPE prefix to distinguish from the channel position.
Also add SND_CHMAP_TYPE_LAST entry pointing the last one like other
enums.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/pcm.h | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -476,10 +476,11 @@ int snd_pcm_unlink(snd_pcm_t *pcm);
/** channel map list type */
enum snd_pcm_chmap_type {
- SND_CHMAP_NONE = 0, /** unspecified channel position */
- SND_CHMAP_FIXED, /** fixed channel position */
- SND_CHMAP_VAR, /** freely swappable channel position */
- SND_CHMAP_PAIRED, /** pair-wise swappable channel position */
+ SND_CHMAP_TYPE_NONE = 0,/** unspecified channel position */
+ SND_CHMAP_TYPE_FIXED, /** fixed channel position */
+ SND_CHMAP_TYPE_VAR, /** freely swappable channel position */
+ SND_CHMAP_TYPE_PAIRED, /** pair-wise swappable channel position */
+ SND_CHMAP_TYPE_LAST = SND_CHMAP_TYPE_PAIRED, /** last entry */
};
/** channel positions */

View File

@ -1,286 +0,0 @@
From b4c64e815a051e711798be1d772f123d19c1ff6e Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 10 Sep 2012 18:07:36 +0200
Subject: [PATCH 13/30] PCM: Add string conversion helper functions for chmap
Added a few helper functions between chmap and string.
snd_pcm_chmap_type_name() -- a string of the given chmap type
snd_pcm_chmap_name() -- a string of the given channel position
snd_pcm_chmap_print() -- print channel map on the given buffer
snd_pcm_chmap_from_string() -- get a channel position from string
snd_pcm_parse_string() -- parse the whole channel map from string
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/pcm.h | 6 ++
src/pcm/pcm.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
test/chmap.c | 69 ++++------------------------
3 files changed, 160 insertions(+), 57 deletions(-)
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -534,6 +534,12 @@ void snd_pcm_free_chmaps(snd_pcm_chmap_q
snd_pcm_chmap_t *snd_pcm_get_chmap(snd_pcm_t *pcm);
int snd_pcm_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
+const char *snd_pcm_chmap_type_name(enum snd_pcm_chmap_type val);
+const char *snd_pcm_chmap_name(enum snd_pcm_chmap_position val);
+int snd_pcm_chmap_print(const snd_pcm_chmap_t *map, size_t maxlen, char *buf);
+unsigned int snd_pcm_chmap_from_string(const char *str);
+snd_pcm_chmap_t *snd_pcm_chmap_parse_string(const char *str);
+
//int snd_pcm_mixer_element(snd_pcm_t *pcm, snd_mixer_t *mixer, snd_mixer_elem_t **elem);
/*
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -633,6 +633,7 @@ playback devices.
#include <malloc.h>
#include <stdarg.h>
#include <signal.h>
+#include <ctype.h>
#include <sys/poll.h>
#include <sys/shm.h>
#include <sys/mman.h>
@@ -7356,6 +7357,147 @@ int snd_pcm_set_chmap(snd_pcm_t *pcm, co
return pcm->ops->set_chmap(pcm, map);
}
+/*
+ */
+#define _NAME(n) [SND_CHMAP_TYPE_##n] = #n
+static const char *chmap_type_names[SND_CHMAP_TYPE_LAST + 1] = {
+ _NAME(NONE), _NAME(FIXED), _NAME(VAR), _NAME(PAIRED),
+};
+#undef _NAME
+
+const char *snd_pcm_chmap_type_name(enum snd_pcm_chmap_type val)
+{
+ if (val <= SND_CHMAP_TYPE_LAST)
+ return chmap_type_names[val];
+ else
+ return NULL;
+}
+
+#define _NAME(n) [SND_CHMAP_##n] = #n
+static const char *chmap_names[SND_CHMAP_LAST + 1] = {
+ _NAME(UNKNOWN),
+ _NAME(FL), _NAME(FR),
+ _NAME(RL), _NAME(RR),
+ _NAME(FC), _NAME(LFE),
+ _NAME(SL), _NAME(SR),
+ _NAME(RC), _NAME(FLC), _NAME(FRC), _NAME(RLC), _NAME(RRC),
+ _NAME(FLW), _NAME(FRW),
+ _NAME(FLH), _NAME(FCH), _NAME(FRH), _NAME(TC),
+ _NAME(NA),
+};
+#undef _NAME
+
+const char *snd_pcm_chmap_name(enum snd_pcm_chmap_position val)
+{
+ if (val <= SND_CHMAP_LAST)
+ return chmap_names[val];
+ else
+ return NULL;
+}
+
+int snd_pcm_chmap_print(const snd_pcm_chmap_t *map, size_t maxlen, char *buf)
+{
+ unsigned int i, len = 0;
+
+ for (i = 0; i < map->channels; i++) {
+ unsigned int p = map->pos[i] & SND_CHMAP_POSITION_MASK;
+ if (i > 0) {
+ len += snprintf(buf + len, maxlen - len, " ");
+ if (len >= maxlen)
+ return -ENOMEM;
+ }
+ if (map->pos[i] & SND_CHMAP_DRIVER_SPEC)
+ len += snprintf(buf + len, maxlen, "%d", p);
+ else {
+ const char *name = chmap_names[p];
+ if (name)
+ len += snprintf(buf + len, maxlen - len,
+ "%s", name);
+ else
+ len += snprintf(buf + len, maxlen - len,
+ "Ch%d", p);
+ }
+ if (len >= maxlen)
+ return -ENOMEM;
+ if (map->pos[i] & SND_CHMAP_PHASE_INVERSE) {
+ len += snprintf(buf + len, maxlen - len, "[INV]");
+ if (len >= maxlen)
+ return -ENOMEM;
+ }
+ }
+ return len;
+}
+
+static int str_to_chmap(const char *str, int len)
+{
+ int val;
+
+ if (isdigit(*str)) {
+ val = atoi(str);
+ if (val < 0)
+ return -1;
+ return val | SND_CHMAP_DRIVER_SPEC;
+ } else if (str[0] == 'C' && str[1] == 'h') {
+ val = atoi(str + 2);
+ if (val < 0)
+ return -1;
+ return val;
+ } else {
+ for (val = 0; val <= SND_CHMAP_LAST; val++) {
+ if (!strncmp(str, chmap_names[val], len))
+ return val;
+ }
+ return -1;
+ }
+}
+
+unsigned int snd_pcm_chmap_from_string(const char *str)
+{
+ return str_to_chmap(str, strlen(str));
+}
+
+snd_pcm_chmap_t *snd_pcm_chmap_parse_string(const char *str)
+{
+ int i, ch = 0;
+ int tmp_map[64];
+ snd_pcm_chmap_t *map;
+
+ for (;;) {
+ const char *p;
+ int len, val;
+
+ if (ch >= (int)(sizeof(tmp_map) / sizeof(tmp_map[0])))
+ return NULL;
+ for (p = str; *p && isalnum(*p); p++)
+ ;
+ len = p - str;
+ if (!len)
+ return NULL;
+ val = str_to_chmap(str, len);
+ if (val < 0)
+ return NULL;
+ str += len;
+ if (*str == '[') {
+ if (!strncmp(str, "[INV]", 5)) {
+ val |= SND_CHMAP_PHASE_INVERSE;
+ str += 5;
+ }
+ }
+ tmp_map[ch] = val;
+ ch++;
+ for (; *str && !isalnum(*str); str++)
+ ;
+ if (!*str)
+ break;
+ }
+ map = malloc(sizeof(*map) + ch * sizeof(int));
+ if (!map)
+ return NULL;
+ map->channels = ch;
+ for (i = 0; i < ch; i++)
+ map->pos[i] = tmp_map[i];
+ return map;
+}
/*
* basic helpers
--- a/test/chmap.c
+++ b/test/chmap.c
@@ -21,62 +21,11 @@ static void usage(void)
" -r rate Sample rate\n");
}
-static const char * const chname[] = {
- "Unknown",
- "FL", "FR", "RL", "RR", "FC", "LFE", "SL", "SR", "RC",
- "FLC", "FRC", "RLC", "RRC", "FLW", "FRW", "FLH",
- "FCH", "FRH", "TC",
- "N/A",
-};
-
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
-
static void print_channels(const snd_pcm_chmap_t *map)
{
- unsigned int i;
-
- printf(" ");
- for (i = 0; i < map->channels; i++) {
- unsigned int c = map->pos[i];
- unsigned int p = c & SND_CHMAP_POSITION_MASK;
- if (c & SND_CHMAP_DRIVER_SPEC)
- printf(" %d", p);
- else if (p >= ARRAY_SIZE(chname))
- printf(" Ch%d", p);
- else
- printf(" %s", chname[p]);
- if (c & SND_CHMAP_PHASE_INVERSE)
- printf("[INV]");
- }
- printf("\n");
-}
-
-static int to_channel(const char *name)
-{
- unsigned int i;
-
- if (isdigit(*name))
- return atoi(name);
- for (i = 0; i < ARRAY_SIZE(chname); i++)
- if (!strcmp(chname[i], name))
- return i;
- return SND_CHMAP_UNKNOWN;
-}
-
-static const char *chmap_type(int type)
-{
- switch (type) {
- case SND_CHMAP_NONE:
- return "None";
- case SND_CHMAP_FIXED:
- return "Fixed";
- case SND_CHMAP_VAR:
- return "Variable";
- case SND_CHMAP_PAIRED:
- return "Paired";
- default:
- return "Unknown";
- }
+ char tmp[128];
+ if (snd_pcm_chmap_print(map, sizeof(tmp), tmp) > 0)
+ printf(" %s\n", tmp);
}
static int query_chmaps(snd_pcm_t *pcm)
@@ -89,7 +38,9 @@ static int query_chmaps(snd_pcm_t *pcm)
return 1;
}
for (p = maps; (v = *p) != NULL; p++) {
- printf("Type = %s, Channels = %d\n", chmap_type(v->type), v->map.channels);
+ printf("Type = %s, Channels = %d\n",
+ snd_pcm_chmap_type_name(v->type),
+ v->map.channels);
print_channels(&v->map);
}
snd_pcm_free_chmaps(maps);
@@ -173,8 +124,12 @@ static int set_chmap(snd_pcm_t *pcm, int
return 1;
}
map->channels = channels;
- for (i = 0; i < channels; i++)
- map->pos[i] = to_channel(arg[i]);
+ for (i = 0; i < channels; i++) {
+ int val = snd_pcm_chmap_from_string(arg[i]);
+ if (val < 0)
+ val = SND_CHMAP_UNKNOWN;
+ map->pos[i] = val;
+ }
if (snd_pcm_set_chmap(pcm, map) < 0) {
printf("Cannot set chmap\n");
return 1;

View File

@ -1,25 +0,0 @@
From fe81684745e5c121e2d110bf6955e3f2858d2c7c Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 11 Sep 2012 11:33:31 +0200
Subject: [PATCH 14/30] PCM: Add SND_CHMAP_API_VERSION definition
Just to make it easier for apps to support chmap conditionally via
simple ifdefs.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/pcm.h | 3 +++
1 file changed, 3 insertions(+)
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -474,6 +474,9 @@ int snd_pcm_wait(snd_pcm_t *pcm, int tim
int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
int snd_pcm_unlink(snd_pcm_t *pcm);
+/** channel mapping API version number */
+#define SND_CHMAP_API_VERSION ((1 << 16) | (0 << 8) | 0)
+
/** channel map list type */
enum snd_pcm_chmap_type {
SND_CHMAP_TYPE_NONE = 0,/** unspecified channel position */

View File

@ -1,65 +0,0 @@
From 25f3259b48e921886bda58075936de3d53b84bc1 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 11 Sep 2012 12:48:46 +0200
Subject: [PATCH 15/30] PCM: Add snd_pcm_chmap_long_name()
Just return a more verbose name than snd_pcm_chmap_name(), but
including white spaces.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/pcm.h | 1 +
src/pcm/pcm.c | 32 ++++++++++++++++++++++++++++++++
2 files changed, 33 insertions(+)
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -539,6 +539,7 @@ int snd_pcm_set_chmap(snd_pcm_t *pcm, co
const char *snd_pcm_chmap_type_name(enum snd_pcm_chmap_type val);
const char *snd_pcm_chmap_name(enum snd_pcm_chmap_position val);
+const char *snd_pcm_chmap_long_name(enum snd_pcm_chmap_position val);
int snd_pcm_chmap_print(const snd_pcm_chmap_t *map, size_t maxlen, char *buf);
unsigned int snd_pcm_chmap_from_string(const char *str);
snd_pcm_chmap_t *snd_pcm_chmap_parse_string(const char *str);
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -7395,6 +7395,38 @@ const char *snd_pcm_chmap_name(enum snd_
return NULL;
}
+static const char *chmap_long_names[SND_CHMAP_LAST + 1] = {
+ [SND_CHMAP_UNKNOWN] = "Unknown",
+ [SND_CHMAP_FL] = "Front Left",
+ [SND_CHMAP_FR] = "Front Right",
+ [SND_CHMAP_RL] = "Rear Left",
+ [SND_CHMAP_RR] = "Rear Right",
+ [SND_CHMAP_FC] = "Front Center",
+ [SND_CHMAP_LFE] = "LFE",
+ [SND_CHMAP_SL] = "Side Left",
+ [SND_CHMAP_SR] = "Side Right",
+ [SND_CHMAP_RC] = "Rear Center",
+ [SND_CHMAP_FLC] = "Front Left Center",
+ [SND_CHMAP_FRC] = "Front Right Center",
+ [SND_CHMAP_RLC] = "Rear Left Center",
+ [SND_CHMAP_RRC] = "Rear Right Center",
+ [SND_CHMAP_FLW] = "Front Left Wide",
+ [SND_CHMAP_FRW] = "Front Right Wide",
+ [SND_CHMAP_FLH] = "Front Left High",
+ [SND_CHMAP_FCH] = "Front Center High",
+ [SND_CHMAP_FRH] = "Front Right High",
+ [SND_CHMAP_TC] = "Top Center",
+ [SND_CHMAP_NA] = "Unused",
+};
+
+const char *snd_pcm_chmap_long_name(enum snd_pcm_chmap_position val)
+{
+ if (val <= SND_CHMAP_LAST)
+ return chmap_long_names[val];
+ else
+ return NULL;
+}
+
int snd_pcm_chmap_print(const snd_pcm_chmap_t *map, size_t maxlen, char *buf)
{
unsigned int i, len = 0;

View File

@ -1,198 +0,0 @@
From 81135aac49c8a3b547181d44f78ffe2594db5dbe Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 12 Sep 2012 12:56:14 +0200
Subject: [PATCH 16/30] PCM: Add query_chmaps support to multi plugin
Also fix some bugs in get_chmap().
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_multi.c | 152 +++++++++++++++++++++++++++++++++++++---------------
1 file changed, 111 insertions(+), 41 deletions(-)
--- a/src/pcm/pcm_multi.c
+++ b/src/pcm/pcm_multi.c
@@ -739,64 +739,134 @@ static int snd_pcm_multi_mmap(snd_pcm_t
return 0;
}
+static snd_pcm_chmap_query_t **snd_pcm_multi_query_chmaps(snd_pcm_t *pcm)
+{
+ snd_pcm_multi_t *multi = pcm->private_data;
+ snd_pcm_chmap_query_t **slave_maps[multi->slaves_count];
+ snd_pcm_chmap_query_t **maps;
+ unsigned int i;
+ int err = -ENOMEM;
+
+ memset(slave_maps, 0, sizeof(slave_maps));
+ maps = calloc(2, sizeof(*maps));
+ if (!maps)
+ return NULL;
+ maps[0] = calloc(multi->channels_count + 2, sizeof(int *));
+ if (!maps[0])
+ goto error;
+ maps[0]->type = SND_CHMAP_TYPE_FIXED;
+ maps[0]->map.channels = multi->channels_count;
+
+ for (i = 0; i < multi->slaves_count; i++) {
+ slave_maps[i] = snd_pcm_query_chmaps(multi->slaves[i].pcm);
+ if (!slave_maps[i])
+ goto error;
+ }
+
+ for (i = 0; i < multi->channels_count; i++) {
+ snd_pcm_multi_channel_t *bind = &multi->channels[i];
+ unsigned int slave_channels =
+ multi->slaves[bind->slave_idx].channels_count;
+ snd_pcm_chmap_query_t **p;
+
+ for (p = slave_maps[bind->slave_idx]; *p; p++) {
+ if ((*p)->map.channels == slave_channels) {
+ maps[0]->map.pos[i] =
+ (*p)->map.pos[bind->slave_channel];
+ break;
+ }
+ }
+ }
+ err = 0;
+
+ error:
+ for (i = 0; i < multi->slaves_count; i++) {
+ if (slave_maps[i])
+ snd_pcm_free_chmaps(slave_maps[i]);
+ }
+
+ if (err) {
+ snd_pcm_free_chmaps(maps);
+ return NULL;
+ }
+
+ return maps;
+}
+
static snd_pcm_chmap_t *snd_pcm_multi_get_chmap(snd_pcm_t *pcm)
{
snd_pcm_multi_t *multi = pcm->private_data;
snd_pcm_chmap_t *map;
- unsigned int i, idx;
+ snd_pcm_chmap_t *slave_maps[multi->slaves_count];
+ unsigned int i;
+ int err = -ENOMEM;
- map = malloc(pcm->channels + 4);
+ memset(slave_maps, 0, sizeof(slave_maps));
+ map = calloc(multi->channels_count + 1, sizeof(int));
if (!map)
return NULL;
- idx = 0;
- for (i = 0; i < multi->slaves_count; ++i) {
- unsigned int c;
- snd_pcm_chmap_t *slave_map;
- slave_map = snd_pcm_get_chmap(multi->slaves[i].pcm);
- if (!slave_map) {
- free(map);
- return NULL;
- }
- for (c = 0; c < slave_map->channels; c++) {
- if (idx >= pcm->channels)
- break;
- map->pos[idx++] = slave_map->pos[c];
- }
- free(slave_map);
+
+ for (i = 0; i < multi->slaves_count; i++) {
+ slave_maps[i] = snd_pcm_get_chmap(multi->slaves[i].pcm);
+ if (!slave_maps[i])
+ goto error;
}
+
+ map->channels = multi->channels_count;
+ for (i = 0; i < multi->channels_count; i++) {
+ snd_pcm_multi_channel_t *bind = &multi->channels[i];
+ map->pos[i] = slave_maps[bind->slave_idx]->pos[bind->slave_channel];
+ }
+ err = 0;
+
+ error:
+ for (i = 0; i < multi->slaves_count; i++)
+ free(slave_maps[i]);
+
+ if (err) {
+ free(map);
+ return NULL;
+ }
+
return map;
}
static int snd_pcm_multi_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
{
snd_pcm_multi_t *multi = pcm->private_data;
- const unsigned int *pos;
- unsigned int i, idx, chs;
- int err;
+ snd_pcm_chmap_t *slave_maps[multi->slaves_count];
+ unsigned int i;
+ int err = 0;
- chs = map->channels;
- if (chs != pcm->channels)
+ if (map->channels != multi->channels_count)
return -EINVAL;
- pos = map->pos;
- idx = 0;
- for (i = 0; i < multi->slaves_count; ++i) {
- snd_pcm_chmap_t *slave_map;
- unsigned int slave_chs;
- slave_chs = multi->slaves[i].channels_count;
- if (idx + slave_chs > chs)
- break;
- slave_map = malloc(slave_chs * 4 + 4);
- if (!slave_map)
- return -ENOMEM;
- slave_map->channels = slave_chs;
- memcpy(slave_map->pos, pos + idx, slave_chs * 4);
- err = snd_pcm_set_chmap(multi->slaves[i].pcm, slave_map);
- free(slave_map);
+
+ for (i = 0; i < multi->slaves_count; i++) {
+ slave_maps[i] = calloc(multi->slaves[i].channels_count + 1,
+ sizeof(int));
+ if (!slave_maps[i]) {
+ err = -ENOMEM;
+ goto error;
+ }
+ }
+
+ for (i = 0; i < multi->channels_count; i++) {
+ snd_pcm_multi_channel_t *bind = &multi->channels[i];
+ slave_maps[bind->slave_idx]->pos[bind->slave_channel] =
+ map->pos[i];
+ }
+
+ for (i = 0; i < multi->slaves_count; i++) {
+ err = snd_pcm_set_chmap(multi->slaves[i].pcm, slave_maps[i]);
if (err < 0)
- return err;
- idx += slave_chs;
+ goto error;
}
- return 0;
+
+ error:
+ for (i = 0; i < multi->slaves_count; i++)
+ free(slave_maps[i]);
+
+ return err;
}
static void snd_pcm_multi_dump(snd_pcm_t *pcm, snd_output_t *out)
@@ -835,7 +905,7 @@ static const snd_pcm_ops_t snd_pcm_multi
.async = snd_pcm_multi_async,
.mmap = snd_pcm_multi_mmap,
.munmap = snd_pcm_multi_munmap,
- .query_chmaps = NULL, /* NYI */
+ .query_chmaps = snd_pcm_multi_query_chmaps,
.get_chmap = snd_pcm_multi_get_chmap,
.set_chmap = snd_pcm_multi_set_chmap,
};

View File

@ -1,249 +0,0 @@
From e1975d20f5d52b370b5e78f5eb5f80a33f55a656 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 12 Sep 2012 14:47:17 +0200
Subject: [PATCH 17/30] PCM: Add chmap options to hw and null plugins
Add a config definition "chmap" to override (or enhance) the channel
maps. So far, only a single channel map can be provided, and the
channel count consistency isn't strictly tested at all.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm.c | 29 +++++++++++++++++++++++++++++
src/pcm/pcm_hw.c | 28 ++++++++++++++++++++++++++++
src/pcm/pcm_local.h | 5 +++++
src/pcm/pcm_null.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 111 insertions(+), 1 deletion(-)
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -7531,6 +7531,35 @@ snd_pcm_chmap_t *snd_pcm_chmap_parse_str
return map;
}
+snd_pcm_chmap_query_t **
+_snd_pcm_make_single_query_chmaps(snd_pcm_chmap_t *src)
+{
+ snd_pcm_chmap_query_t **maps;
+
+ maps = calloc(2, sizeof(*maps));
+ if (!maps)
+ return NULL;
+ *maps = malloc((src->channels + 2) * sizeof(int));
+ if (!*maps) {
+ free(maps);
+ return NULL;
+ }
+ (*maps)->type = SND_CHMAP_TYPE_FIXED;
+ memcpy(&(*maps)->map, src, (src->channels + 1) * sizeof(int));
+ return maps;
+}
+
+snd_pcm_chmap_t *_snd_pcm_copy_chmap(snd_pcm_chmap_t *src)
+{
+ snd_pcm_chmap_t *map;
+
+ map = malloc((src->channels + 1) * sizeof(int));
+ if (!map)
+ return NULL;
+ memcpy(map, src, (src->channels + 1) * sizeof(int));
+ return map;
+}
+
/*
* basic helpers
*/
--- a/src/pcm/pcm_hw.c
+++ b/src/pcm/pcm_hw.c
@@ -107,6 +107,7 @@ typedef struct {
int channels;
/* for chmap */
unsigned int chmap_caps;
+ snd_pcm_chmap_t *chmap_override;
} snd_pcm_hw_t;
#define SNDRV_FILE_PCM_STREAM_PLAYBACK ALSA_DEVICE_DIRECTORY "pcmC%iD%ip"
@@ -1144,6 +1145,9 @@ static snd_pcm_chmap_query_t **snd_pcm_h
snd_pcm_hw_t *hw = pcm->private_data;
snd_pcm_chmap_query_t **map;
+ if (hw->chmap_override)
+ return _snd_pcm_make_single_query_chmaps(hw->chmap_override);
+
if (!chmap_caps(hw, CHMAP_CTL_QUERY))
return NULL;
@@ -1166,6 +1170,9 @@ static snd_pcm_chmap_t *snd_pcm_hw_get_c
unsigned int i;
int ret;
+ if (hw->chmap_override)
+ return _snd_pcm_copy_chmap(hw->chmap_override);
+
if (!chmap_caps(hw, CHMAP_CTL_GET))
return NULL;
@@ -1220,6 +1227,9 @@ static int snd_pcm_hw_set_chmap(snd_pcm_
unsigned int i;
int ret;
+ if (hw->chmap_override)
+ return -ENXIO;
+
if (!chmap_caps(hw, CHMAP_CTL_SET))
return -ENXIO;
@@ -1593,6 +1603,7 @@ pcm.name {
[format STR] # Restrict only to the given format
[channels INT] # Restrict only to the given channels
[rate INT] # Restrict only to the given rate
+ [chmap MAP] # Override channel map
}
\endcode
@@ -1629,6 +1640,7 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, c
snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
snd_config_t *n;
int nonblock = 1; /* non-block per default */
+ snd_pcm_chmap_t *chmap = NULL;
snd_pcm_hw_t *hw;
/* look for defaults.pcm.nonblock definition */
@@ -1719,6 +1731,20 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, c
channels = val;
continue;
}
+ if (strcmp(id, "chmap") == 0) {
+ err = snd_config_get_string(n, &str);
+ if (err < 0) {
+ SNDERR("Invalid type for %s", id);
+ return -EINVAL;
+ }
+ free(chmap);
+ chmap = snd_pcm_chmap_parse_string(str);
+ if (!chmap) {
+ SNDERR("Invalid channel map for %s", id);
+ return -EINVAL;
+ }
+ continue;
+ }
SNDERR("Unknown field %s", id);
return -EINVAL;
}
@@ -1750,6 +1776,8 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, c
hw->channels = channels;
if (rate > 0)
hw->rate = rate;
+ if (chmap)
+ hw->chmap_override = chmap;
return 0;
}
--- a/src/pcm/pcm_local.h
+++ b/src/pcm/pcm_local.h
@@ -973,3 +973,8 @@ static inline void gettimestamp(snd_htim
}
#endif
}
+
+snd_pcm_chmap_query_t **
+_snd_pcm_make_single_query_chmaps(snd_pcm_chmap_t *src);
+snd_pcm_chmap_t *_snd_pcm_copy_chmap(snd_pcm_chmap_t *src);
+
--- a/src/pcm/pcm_null.c
+++ b/src/pcm/pcm_null.c
@@ -44,6 +44,7 @@ typedef struct {
snd_pcm_uframes_t appl_ptr;
snd_pcm_uframes_t hw_ptr;
int poll_fd;
+ snd_pcm_chmap_t *chmap;
} snd_pcm_null_t;
#endif
@@ -268,6 +269,24 @@ static int snd_pcm_null_sw_params(snd_pc
return 0;
}
+static snd_pcm_chmap_query_t **snd_pcm_null_query_chmaps(snd_pcm_t *pcm)
+{
+ snd_pcm_null_t *null = pcm->private_data;
+
+ if (null->chmap)
+ return _snd_pcm_make_single_query_chmaps(null->chmap);
+ return NULL;
+}
+
+static snd_pcm_chmap_t *snd_pcm_null_get_chmap(snd_pcm_t *pcm)
+{
+ snd_pcm_null_t *null = pcm->private_data;
+
+ if (null->chmap)
+ return _snd_pcm_copy_chmap(null->chmap);
+ return NULL;
+}
+
static void snd_pcm_null_dump(snd_pcm_t *pcm, snd_output_t *out)
{
snd_output_printf(out, "Null PCM\n");
@@ -290,6 +309,9 @@ static const snd_pcm_ops_t snd_pcm_null_
.async = snd_pcm_null_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
+ .query_chmaps = snd_pcm_null_query_chmaps,
+ .get_chmap = snd_pcm_null_get_chmap,
+ .set_chmap = NULL,
};
static const snd_pcm_fast_ops_t snd_pcm_null_fast_ops = {
@@ -385,6 +407,7 @@ and /dev/full (capture, must be readable
\code
pcm.name {
type null # Null PCM
+ [chmap MAP]
}
\endcode
@@ -415,6 +438,10 @@ int _snd_pcm_null_open(snd_pcm_t **pcmp,
snd_pcm_stream_t stream, int mode)
{
snd_config_iterator_t i, next;
+ snd_pcm_null_t *null;
+ snd_pcm_chmap_t *chmap = NULL;
+ int err;
+
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id;
@@ -422,10 +449,31 @@ int _snd_pcm_null_open(snd_pcm_t **pcmp,
continue;
if (snd_pcm_conf_generic_id(id))
continue;
+ if (strcmp(id, "chmap") == 0) {
+ const char *str;
+ err = snd_config_get_string(n, &str);
+ if (err < 0) {
+ SNDERR("Invalid type for %s", id);
+ return -EINVAL;
+ }
+ free(chmap);
+ chmap = snd_pcm_chmap_parse_string(str);
+ if (!chmap) {
+ SNDERR("Invalid channel map for %s", id);
+ return -EINVAL;
+ }
+ continue;
+ }
SNDERR("Unknown field %s", id);
return -EINVAL;
}
- return snd_pcm_null_open(pcmp, name, stream, mode);
+ err = snd_pcm_null_open(pcmp, name, stream, mode);
+ if (err < 0)
+ return err;
+
+ null = (*pcmp)->private_data;
+ null->chmap = chmap;
+ return 0;
}
#ifndef DOC_HIDDEN
SND_DLSYM_BUILD_VERSION(_snd_pcm_null_open, SND_PCM_DLSYM_VERSION);

View File

@ -1,85 +0,0 @@
From a102028a5a747ecdf1d6fcd16aef0994477a951b Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 12 Sep 2012 15:09:57 +0200
Subject: [PATCH 18/30] PCM: Add the missing query_chmaps for route plugin
Also fix the channel count in get_chmap for route plugin.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_route.c | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
--- a/src/pcm/pcm_route.c
+++ b/src/pcm/pcm_route.c
@@ -67,6 +67,7 @@ typedef struct {
int use_getput;
unsigned int src_size;
snd_pcm_format_t dst_sfmt;
+ unsigned int nsrcs;
unsigned int ndsts;
snd_pcm_route_ttable_dst_t *dsts;
} snd_pcm_route_params_t;
@@ -707,22 +708,23 @@ static snd_pcm_chmap_t *snd_pcm_route_ge
{
snd_pcm_route_t *route = pcm->private_data;
snd_pcm_chmap_t *map, *slave_map;
- unsigned int src, dst;
+ unsigned int src, dst, nsrcs;
slave_map = snd_pcm_generic_get_chmap(pcm);
if (!slave_map)
return NULL;
- map = calloc(4, route->schannels + 1);
+ nsrcs = route->params.nsrcs;
+ map = calloc(4, nsrcs + 1);
if (!map) {
free(slave_map);
return NULL;
}
- map->channels = route->schannels;
+ map->channels = nsrcs;
for (dst = 0; dst < route->params.ndsts; dst++) {
snd_pcm_route_ttable_dst_t *d = &route->params.dsts[dst];
for (src = 0; src < d->nsrcs; src++) {
int c = d->srcs[src].channel;
- if (c < route->schannels && !map->pos[c])
+ if (c < nsrcs && !map->pos[c])
map->pos[c] = slave_map->pos[dst];
}
}
@@ -730,6 +732,17 @@ static snd_pcm_chmap_t *snd_pcm_route_ge
return map;
}
+static snd_pcm_chmap_query_t **snd_pcm_route_query_chmaps(snd_pcm_t *pcm)
+{
+ snd_pcm_chmap_query_t **maps;
+ snd_pcm_chmap_t *map = snd_pcm_route_get_chmap(pcm);
+ if (!map)
+ return NULL;
+ maps = _snd_pcm_make_single_query_chmaps(map);
+ free(map);
+ return maps;
+}
+
static void snd_pcm_route_dump(snd_pcm_t *pcm, snd_output_t *out)
{
snd_pcm_route_t *route = pcm->private_data;
@@ -787,7 +800,7 @@ static const snd_pcm_ops_t snd_pcm_route
.async = snd_pcm_generic_async,
.mmap = snd_pcm_generic_mmap,
.munmap = snd_pcm_generic_munmap,
- .query_chmaps = NULL, /* NYI */
+ .query_chmaps = snd_pcm_route_query_chmaps,
.get_chmap = snd_pcm_route_get_chmap,
.set_chmap = NULL, /* NYI */
};
@@ -812,6 +825,7 @@ static int route_load_ttable(snd_pcm_rou
dmul = tt_ssize;
}
params->ndsts = dused;
+ params->nsrcs = sused;
dptr = calloc(dused, sizeof(*params->dsts));
if (!dptr)
return -ENOMEM;

View File

@ -1,104 +0,0 @@
From 5ba11d69dafbd4502469fd957b4580169779664c Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 12 Sep 2012 15:15:32 +0200
Subject: [PATCH 19/30] Add chmap override definitions for Emu10k1, Audigy and
Audigy2 cards
These cards won't provide the channel maps from the driver itself
because of the dynamic routing. For simplicity, define chmaps in the
configurations, so that chmap querying of individual stereo streams
and combined multi streams works properly.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/conf/cards/Audigy.conf | 3 +++
src/conf/cards/Audigy2.conf | 4 ++++
src/conf/cards/EMU10K1.conf | 3 +++
3 files changed, 10 insertions(+)
--- a/src/conf/cards/Audigy.conf
+++ b/src/conf/cards/Audigy.conf
@@ -13,6 +13,7 @@ Audigy.pcm.front.0 {
slave.pcm {
type hw
card $CARD
+ chmap "FL,FR"
}
hooks.0 {
type ctl_elems
@@ -65,6 +66,7 @@ Audigy.pcm.rear.0 {
slave.pcm {
type hw
card $CARD
+ chmap "RL,RR"
}
hooks.0 {
type ctl_elems
@@ -100,6 +102,7 @@ Audigy.pcm.center_lfe.0 {
slave.pcm {
type hw
card $CARD
+ chmap "FC,LFE"
}
hooks.0 {
type ctl_elems
--- a/src/conf/cards/Audigy2.conf
+++ b/src/conf/cards/Audigy2.conf
@@ -13,6 +13,7 @@ Audigy2.pcm.front.0 {
slave.pcm {
type hw
card $CARD
+ chmap "FL,FR"
}
hooks.0 {
type ctl_elems
@@ -65,6 +66,7 @@ Audigy2.pcm.rear.0 {
slave.pcm {
type hw
card $CARD
+ chmap "RL,RR"
}
hooks.0 {
type ctl_elems
@@ -100,6 +102,7 @@ Audigy2.pcm.center_lfe.0 {
slave.pcm {
type hw
card $CARD
+ chmap "FC,LFE"
}
hooks.0 {
type ctl_elems
@@ -151,6 +154,7 @@ Audigy2.pcm.side.0 {
slave.pcm {
type hw
card $CARD
+ chmap "SL,SR"
}
hooks.0 {
type ctl_elems
--- a/src/conf/cards/EMU10K1.conf
+++ b/src/conf/cards/EMU10K1.conf
@@ -15,6 +15,7 @@ EMU10K1.pcm.front.0 {
slave.pcm {
type hw
card $CARD
+ chmap "FL,FR"
}
hooks.0 {
type ctl_elems
@@ -73,6 +74,7 @@ EMU10K1.pcm.rear.0 {
slave.pcm {
type hw
card $CARD
+ chmap "RL,RR"
}
hooks.0 {
type ctl_elems
@@ -111,6 +113,7 @@ EMU10K1.pcm.center_lfe.0 {
slave.pcm {
type hw
card $CARD
+ chmap "FC,LFE"
}
hooks.0 {
type ctl_elems

View File

@ -1,438 +0,0 @@
From ec7acfc408856cfe71a122e3b5387463d7b3d919 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 12 Sep 2012 17:13:22 +0200
Subject: [PATCH 20/30] PCM: Use compounds for overriding / enhancing chmaps
Instead of a single channel map, multiple channel maps can be provided
in a form of compound (array) to hw and null plugins. In null
get_chmap, the channel map corresponding to the current channels is
copied from the given channel maps.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/conf/cards/Audigy.conf | 6 +-
src/conf/cards/Audigy2.conf | 8 +--
src/conf/cards/EMU10K1.conf | 6 +-
src/pcm/pcm.c | 109 +++++++++++++++++++++++++++++++++++++++++---
src/pcm/pcm_hw.c | 25 ++++------
src/pcm/pcm_local.h | 10 +++-
src/pcm/pcm_null.c | 25 ++++------
7 files changed, 144 insertions(+), 45 deletions(-)
--- a/src/conf/cards/Audigy.conf
+++ b/src/conf/cards/Audigy.conf
@@ -13,7 +13,7 @@ Audigy.pcm.front.0 {
slave.pcm {
type hw
card $CARD
- chmap "FL,FR"
+ chmap [ "UNKNOWN" "FL,FR" ]
}
hooks.0 {
type ctl_elems
@@ -66,7 +66,7 @@ Audigy.pcm.rear.0 {
slave.pcm {
type hw
card $CARD
- chmap "RL,RR"
+ chmap [ "UNKNOWN" "RL,RR" ]
}
hooks.0 {
type ctl_elems
@@ -102,7 +102,7 @@ Audigy.pcm.center_lfe.0 {
slave.pcm {
type hw
card $CARD
- chmap "FC,LFE"
+ chmap [ "UNKNOWN" "FC,LFE" ]
}
hooks.0 {
type ctl_elems
--- a/src/conf/cards/Audigy2.conf
+++ b/src/conf/cards/Audigy2.conf
@@ -13,7 +13,7 @@ Audigy2.pcm.front.0 {
slave.pcm {
type hw
card $CARD
- chmap "FL,FR"
+ chmap [ "UNKNOWN" "FL,FR" ]
}
hooks.0 {
type ctl_elems
@@ -66,7 +66,7 @@ Audigy2.pcm.rear.0 {
slave.pcm {
type hw
card $CARD
- chmap "RL,RR"
+ chmap [ "UNKNOWN" "RL,RR" ]
}
hooks.0 {
type ctl_elems
@@ -102,7 +102,7 @@ Audigy2.pcm.center_lfe.0 {
slave.pcm {
type hw
card $CARD
- chmap "FC,LFE"
+ chmap [ "UNKNOWN" "FC,LFE" ]
}
hooks.0 {
type ctl_elems
@@ -154,7 +154,7 @@ Audigy2.pcm.side.0 {
slave.pcm {
type hw
card $CARD
- chmap "SL,SR"
+ chmap [ "UNKNOWN" "SL,SR" ]
}
hooks.0 {
type ctl_elems
--- a/src/conf/cards/EMU10K1.conf
+++ b/src/conf/cards/EMU10K1.conf
@@ -15,7 +15,7 @@ EMU10K1.pcm.front.0 {
slave.pcm {
type hw
card $CARD
- chmap "FL,FR"
+ chmap [ "UNKNOWN" "FL,FR" ]
}
hooks.0 {
type ctl_elems
@@ -74,7 +74,7 @@ EMU10K1.pcm.rear.0 {
slave.pcm {
type hw
card $CARD
- chmap "RL,RR"
+ chmap [ "UNKNOWN" "RL,RR" ]
}
hooks.0 {
type ctl_elems
@@ -113,7 +113,7 @@ EMU10K1.pcm.center_lfe.0 {
slave.pcm {
type hw
card $CARD
- chmap "FC,LFE"
+ chmap [ "UNKNOWN" "FC,LFE" ]
}
hooks.0 {
type ctl_elems
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -7531,25 +7531,37 @@ snd_pcm_chmap_t *snd_pcm_chmap_parse_str
return map;
}
+/* copy a single channel map with the fixed type to chmap_query pointer */
+static int _copy_to_fixed_query_map(snd_pcm_chmap_query_t **dst,
+ const snd_pcm_chmap_t *src)
+{
+ *dst = malloc((src->channels + 2) * sizeof(int));
+ if (!*dst)
+ return -ENOMEM;
+ (*dst)->type = SND_CHMAP_TYPE_FIXED;
+ memcpy(&(*dst)->map, src, (src->channels + 1) * sizeof(int));
+ return 0;
+}
+
+#ifndef DOC_HIDDEN
+/* make a chmap_query array from a single channel map */
snd_pcm_chmap_query_t **
-_snd_pcm_make_single_query_chmaps(snd_pcm_chmap_t *src)
+_snd_pcm_make_single_query_chmaps(const snd_pcm_chmap_t *src)
{
snd_pcm_chmap_query_t **maps;
maps = calloc(2, sizeof(*maps));
if (!maps)
return NULL;
- *maps = malloc((src->channels + 2) * sizeof(int));
- if (!*maps) {
+ if (_copy_to_fixed_query_map(maps, src)) {
free(maps);
return NULL;
}
- (*maps)->type = SND_CHMAP_TYPE_FIXED;
- memcpy(&(*maps)->map, src, (src->channels + 1) * sizeof(int));
return maps;
}
-snd_pcm_chmap_t *_snd_pcm_copy_chmap(snd_pcm_chmap_t *src)
+/* make a copy of chmap */
+snd_pcm_chmap_t *_snd_pcm_copy_chmap(const snd_pcm_chmap_t *src)
{
snd_pcm_chmap_t *map;
@@ -7560,6 +7572,91 @@ snd_pcm_chmap_t *_snd_pcm_copy_chmap(snd
return map;
}
+/* make a copy of channel maps */
+snd_pcm_chmap_query_t **
+_snd_pcm_copy_chmap_query(snd_pcm_chmap_query_t * const *src)
+{
+ snd_pcm_chmap_query_t * const *p;
+ snd_pcm_chmap_query_t **maps;
+ int i, nums;
+
+ for (nums = 0, p = src; *p; p++)
+ nums++;
+
+ maps = calloc(nums + 1, sizeof(*maps));
+ if (!maps)
+ return NULL;
+ for (i = 0; i < nums; i++) {
+ maps[i] = malloc((src[i]->map.channels + 2) * sizeof(int));
+ if (!maps[i]) {
+ snd_pcm_free_chmaps(maps);
+ return NULL;
+ }
+ memcpy(maps[i], src[i], (src[i]->map.channels + 2) * sizeof(int));
+ }
+ return maps;
+}
+
+/* select the channel map with the current PCM channels and make a copy */
+snd_pcm_chmap_t *
+_snd_pcm_choose_fixed_chmap(snd_pcm_t *pcm, snd_pcm_chmap_query_t * const *maps)
+{
+ snd_pcm_chmap_query_t * const *p;
+
+ for (p = maps; *p; p++) {
+ if ((*p)->map.channels == pcm->channels)
+ return _snd_pcm_copy_chmap(&(*p)->map);
+ }
+ return NULL;
+}
+
+/* make chmap_query array from the config tree;
+ * conf must be a compound (array)
+ */
+snd_pcm_chmap_query_t **
+_snd_pcm_parse_config_chmaps(snd_config_t *conf)
+{
+ snd_pcm_chmap_t *chmap;
+ snd_pcm_chmap_query_t **maps;
+ snd_config_iterator_t i, next;
+ const char *str;
+ int nums, err;
+
+ if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND)
+ return NULL;
+
+ nums = 0;
+ snd_config_for_each(i, next, conf) {
+ nums++;
+ }
+
+ maps = calloc(nums + 1, sizeof(*maps));
+ if (!maps)
+ return NULL;
+
+ nums = 0;
+ snd_config_for_each(i, next, conf) {
+ snd_config_t *n = snd_config_iterator_entry(i);
+ err = snd_config_get_string(n, &str);
+ if (err < 0)
+ goto error;
+ chmap = snd_pcm_chmap_parse_string(str);
+ if (!chmap)
+ goto error;
+ if (_copy_to_fixed_query_map(maps + nums, chmap)) {
+ free(chmap);
+ goto error;
+ }
+ nums++;
+ }
+ return maps;
+
+ error:
+ snd_pcm_free_chmaps(maps);
+ return NULL;
+}
+#endif /* DOC_HIDDEN */
+
/*
* basic helpers
*/
--- a/src/pcm/pcm_hw.c
+++ b/src/pcm/pcm_hw.c
@@ -107,7 +107,7 @@ typedef struct {
int channels;
/* for chmap */
unsigned int chmap_caps;
- snd_pcm_chmap_t *chmap_override;
+ snd_pcm_chmap_query_t **chmap_override;
} snd_pcm_hw_t;
#define SNDRV_FILE_PCM_STREAM_PLAYBACK ALSA_DEVICE_DIRECTORY "pcmC%iD%ip"
@@ -1146,7 +1146,7 @@ static snd_pcm_chmap_query_t **snd_pcm_h
snd_pcm_chmap_query_t **map;
if (hw->chmap_override)
- return _snd_pcm_make_single_query_chmaps(hw->chmap_override);
+ return _snd_pcm_copy_chmap_query(hw->chmap_override);
if (!chmap_caps(hw, CHMAP_CTL_QUERY))
return NULL;
@@ -1171,7 +1171,7 @@ static snd_pcm_chmap_t *snd_pcm_hw_get_c
int ret;
if (hw->chmap_override)
- return _snd_pcm_copy_chmap(hw->chmap_override);
+ return _snd_pcm_choose_fixed_chmap(pcm, hw->chmap_override);
if (!chmap_caps(hw, CHMAP_CTL_GET))
return NULL;
@@ -1603,7 +1603,7 @@ pcm.name {
[format STR] # Restrict only to the given format
[channels INT] # Restrict only to the given channels
[rate INT] # Restrict only to the given rate
- [chmap MAP] # Override channel map
+ [chmap MAP] # Override channel maps; MAP is a string array
}
\endcode
@@ -1640,7 +1640,7 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, c
snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
snd_config_t *n;
int nonblock = 1; /* non-block per default */
- snd_pcm_chmap_t *chmap = NULL;
+ snd_pcm_chmap_query_t **chmap = NULL;
snd_pcm_hw_t *hw;
/* look for defaults.pcm.nonblock definition */
@@ -1732,13 +1732,8 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, c
continue;
}
if (strcmp(id, "chmap") == 0) {
- err = snd_config_get_string(n, &str);
- if (err < 0) {
- SNDERR("Invalid type for %s", id);
- return -EINVAL;
- }
- free(chmap);
- chmap = snd_pcm_chmap_parse_string(str);
+ snd_pcm_free_chmaps(chmap);
+ chmap = _snd_pcm_parse_config_chmaps(n);
if (!chmap) {
SNDERR("Invalid channel map for %s", id);
return -EINVAL;
@@ -1746,17 +1741,21 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, c
continue;
}
SNDERR("Unknown field %s", id);
+ snd_pcm_free_chmaps(chmap);
return -EINVAL;
}
if (card < 0) {
SNDERR("card is not defined");
+ snd_pcm_free_chmaps(chmap);
return -EINVAL;
}
err = snd_pcm_hw_open(pcmp, name, card, device, subdevice, stream,
mode | (nonblock ? SND_PCM_NONBLOCK : 0),
0, sync_ptr_ioctl);
- if (err < 0)
+ if (err < 0) {
+ snd_pcm_free_chmaps(chmap);
return err;
+ }
if (nonblock && ! (mode & SND_PCM_NONBLOCK)) {
/* revert to blocking mode for read/write access */
snd_pcm_hw_nonblock(*pcmp, 0);
--- a/src/pcm/pcm_local.h
+++ b/src/pcm/pcm_local.h
@@ -975,6 +975,12 @@ static inline void gettimestamp(snd_htim
}
snd_pcm_chmap_query_t **
-_snd_pcm_make_single_query_chmaps(snd_pcm_chmap_t *src);
-snd_pcm_chmap_t *_snd_pcm_copy_chmap(snd_pcm_chmap_t *src);
+_snd_pcm_make_single_query_chmaps(const snd_pcm_chmap_t *src);
+snd_pcm_chmap_t *_snd_pcm_copy_chmap(const snd_pcm_chmap_t *src);
+snd_pcm_chmap_query_t **
+_snd_pcm_copy_chmap_query(snd_pcm_chmap_query_t * const *src);
+snd_pcm_chmap_query_t **
+_snd_pcm_parse_config_chmaps(snd_config_t *conf);
+snd_pcm_chmap_t *
+_snd_pcm_choose_fixed_chmap(snd_pcm_t *pcm, snd_pcm_chmap_query_t * const *maps);
--- a/src/pcm/pcm_null.c
+++ b/src/pcm/pcm_null.c
@@ -44,7 +44,7 @@ typedef struct {
snd_pcm_uframes_t appl_ptr;
snd_pcm_uframes_t hw_ptr;
int poll_fd;
- snd_pcm_chmap_t *chmap;
+ snd_pcm_chmap_query_t **chmap;
} snd_pcm_null_t;
#endif
@@ -274,7 +274,7 @@ static snd_pcm_chmap_query_t **snd_pcm_n
snd_pcm_null_t *null = pcm->private_data;
if (null->chmap)
- return _snd_pcm_make_single_query_chmaps(null->chmap);
+ return _snd_pcm_copy_chmap_query(null->chmap);
return NULL;
}
@@ -283,7 +283,7 @@ static snd_pcm_chmap_t *snd_pcm_null_get
snd_pcm_null_t *null = pcm->private_data;
if (null->chmap)
- return _snd_pcm_copy_chmap(null->chmap);
+ return _snd_pcm_choose_fixed_chmap(pcm, null->chmap);
return NULL;
}
@@ -407,7 +407,7 @@ and /dev/full (capture, must be readable
\code
pcm.name {
type null # Null PCM
- [chmap MAP]
+ [chmap MAP] # Provide channel maps; MAP is a string array
}
\endcode
@@ -439,7 +439,7 @@ int _snd_pcm_null_open(snd_pcm_t **pcmp,
{
snd_config_iterator_t i, next;
snd_pcm_null_t *null;
- snd_pcm_chmap_t *chmap = NULL;
+ snd_pcm_chmap_query_t **chmap = NULL;
int err;
snd_config_for_each(i, next, conf) {
@@ -450,14 +450,8 @@ int _snd_pcm_null_open(snd_pcm_t **pcmp,
if (snd_pcm_conf_generic_id(id))
continue;
if (strcmp(id, "chmap") == 0) {
- const char *str;
- err = snd_config_get_string(n, &str);
- if (err < 0) {
- SNDERR("Invalid type for %s", id);
- return -EINVAL;
- }
- free(chmap);
- chmap = snd_pcm_chmap_parse_string(str);
+ snd_pcm_free_chmaps(chmap);
+ chmap = _snd_pcm_parse_config_chmaps(n);
if (!chmap) {
SNDERR("Invalid channel map for %s", id);
return -EINVAL;
@@ -465,11 +459,14 @@ int _snd_pcm_null_open(snd_pcm_t **pcmp,
continue;
}
SNDERR("Unknown field %s", id);
+ snd_pcm_free_chmaps(chmap);
return -EINVAL;
}
err = snd_pcm_null_open(pcmp, name, stream, mode);
- if (err < 0)
+ if (err < 0) {
+ snd_pcm_free_chmaps(chmap);
return err;
+ }
null = (*pcmp)->private_data;
null->chmap = chmap;

View File

@ -1,51 +0,0 @@
From 2c61a4173ff2c3d57eb77b3f66e0d0e517c799d6 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 12 Sep 2012 17:34:49 +0200
Subject: [PATCH 21/30] conf: Add chmap definitions to TRIDENT and SI7018
configurations
Manually add the channel map definitions as the channel front/rear is
determined dynamically.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/conf/cards/SI7018.conf | 2 ++
src/conf/cards/TRID4DWAVENX.conf | 2 ++
2 files changed, 4 insertions(+)
--- a/src/conf/cards/SI7018.conf
+++ b/src/conf/cards/SI7018.conf
@@ -13,6 +13,7 @@ SI7018.pcm.front.0 {
}
type hw
card $CARD
+ chmap [ "UNKNOWN" "FL,FR" ]
}
<confdir:pcm/rear.conf>
@@ -26,6 +27,7 @@ SI7018.pcm.rear.0 {
slave.pcm {
type hw
card $CARD
+ chmap [ "UNKNOWN" "RL,RR" ]
}
hooks.0 {
type ctl_elems
--- a/src/conf/cards/TRID4DWAVENX.conf
+++ b/src/conf/cards/TRID4DWAVENX.conf
@@ -11,6 +11,7 @@ TRID4DWAVENX.pcm.front.0 {
}
type hw
card $CARD
+ chmap [ "UNKNOWN" "FL,FR" ]
}
<confdir:pcm/rear.conf>
@@ -24,6 +25,7 @@ TRID4DWAVENX.pcm.rear.0 {
slave.pcm {
type hw
card $CARD
+ chmap [ "UNKNOWN" "RL,RR" ]
}
hooks.0 {
type ctl_elems

View File

@ -1,21 +0,0 @@
From 58c45b30309a1dd255c8b9e5cb34398658867b81 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 13 Sep 2012 08:06:26 +0200
Subject: [PATCH 22/30] test/chmap: Fix wrong malloc size
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
test/chmap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/test/chmap.c
+++ b/test/chmap.c
@@ -118,7 +118,7 @@ static int set_chmap(snd_pcm_t *pcm, int
}
if (setup_pcm(pcm, format, channels, rate))
return 1;
- map = malloc(sizeof(int) * channels + 1);
+ map = malloc(sizeof(int) * (channels + 1));
if (!map) {
printf("cannot malloc\n");
return 1;

View File

@ -1,116 +0,0 @@
From f7300682dc0fe9faec94461af6fdcf098047a0d1 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 12 Sep 2012 18:43:59 +0200
Subject: [PATCH 23/30] PCM: Define MONO and other channel map positions
Follow the new definitions in the kernel side. MONO and others have
been added, and the order of position table was changed again.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/pcm.h | 11 +++++++++--
include/sound/asound.h | 13 ++++++++++---
src/pcm/pcm.c | 14 +++++++++++---
3 files changed, 30 insertions(+), 8 deletions(-)
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -489,6 +489,8 @@ enum snd_pcm_chmap_type {
/** channel positions */
enum snd_pcm_chmap_position {
SND_CHMAP_UNKNOWN = 0, /** unspecified */
+ SND_CHMAP_NA, /** N/A, silent */
+ SND_CHMAP_MONO, /** mono stream */
SND_CHMAP_FL, /** front left */
SND_CHMAP_FR, /** front right */
SND_CHMAP_RL, /** rear left */
@@ -508,8 +510,13 @@ enum snd_pcm_chmap_position {
SND_CHMAP_FCH, /** front center high */
SND_CHMAP_FRH, /** front right high */
SND_CHMAP_TC, /** top center */
- SND_CHMAP_NA, /** N/A, silent */
- SND_CHMAP_LAST = SND_CHMAP_NA, /** last entry */
+ SND_CHMAP_TFL, /** top front left */
+ SND_CHMAP_TFR, /** top front right */
+ SND_CHMAP_TFC, /** top front center */
+ SND_CHMAP_TRL, /** top rear left */
+ SND_CHMAP_TRR, /** top rear right */
+ SND_CHMAP_TRC, /** top rear center */
+ SND_CHMAP_LAST = SND_CHMAP_TRC, /** last entry */
};
#define SND_CHMAP_POSITION_MASK 0xffff /** bitmask for channel position */
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -479,8 +479,10 @@ enum {
/* channel positions */
enum {
- /* this follows the alsa-lib mixer channel value + 1 */
SNDRV_CHMAP_UNKNOWN = 0,
+ SNDRV_CHMAP_NA, /* N/A, silent */
+ SNDRV_CHMAP_MONO, /* mono stream */
+ /* this follows the alsa-lib mixer channel value + 3 */
SNDRV_CHMAP_FL, /* front left */
SNDRV_CHMAP_FR, /* front right */
SNDRV_CHMAP_RL, /* rear left */
@@ -501,8 +503,13 @@ enum {
SNDRV_CHMAP_FCH, /* front center high */
SNDRV_CHMAP_FRH, /* front right high */
SNDRV_CHMAP_TC, /* top center */
- SNDRV_CHMAP_NA, /* N/A, silent */
- SNDRV_CHMAP_LAST = SNDRV_CHMAP_NA,
+ SNDRV_CHMAP_TFL, /* top front left */
+ SNDRV_CHMAP_TFR, /* top front right */
+ SNDRV_CHMAP_TFC, /* top front center */
+ SNDRV_CHMAP_TRL, /* top rear left */
+ SNDRV_CHMAP_TRR, /* top rear right */
+ SNDRV_CHMAP_TRC, /* top rear center */
+ SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
};
#define SNDRV_CHMAP_POSITION_MASK 0xffff
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -7375,7 +7375,7 @@ const char *snd_pcm_chmap_type_name(enum
#define _NAME(n) [SND_CHMAP_##n] = #n
static const char *chmap_names[SND_CHMAP_LAST + 1] = {
- _NAME(UNKNOWN),
+ _NAME(UNKNOWN), _NAME(NA), _NAME(MONO),
_NAME(FL), _NAME(FR),
_NAME(RL), _NAME(RR),
_NAME(FC), _NAME(LFE),
@@ -7383,7 +7383,8 @@ static const char *chmap_names[SND_CHMAP
_NAME(RC), _NAME(FLC), _NAME(FRC), _NAME(RLC), _NAME(RRC),
_NAME(FLW), _NAME(FRW),
_NAME(FLH), _NAME(FCH), _NAME(FRH), _NAME(TC),
- _NAME(NA),
+ _NAME(TFL), _NAME(TFR), _NAME(TFC),
+ _NAME(TRL), _NAME(TRR), _NAME(TRC),
};
#undef _NAME
@@ -7397,6 +7398,8 @@ const char *snd_pcm_chmap_name(enum snd_
static const char *chmap_long_names[SND_CHMAP_LAST + 1] = {
[SND_CHMAP_UNKNOWN] = "Unknown",
+ [SND_CHMAP_NA] = "Unused",
+ [SND_CHMAP_MONO] = "Mono",
[SND_CHMAP_FL] = "Front Left",
[SND_CHMAP_FR] = "Front Right",
[SND_CHMAP_RL] = "Rear Left",
@@ -7416,7 +7419,12 @@ static const char *chmap_long_names[SND_
[SND_CHMAP_FCH] = "Front Center High",
[SND_CHMAP_FRH] = "Front Right High",
[SND_CHMAP_TC] = "Top Center",
- [SND_CHMAP_NA] = "Unused",
+ [SND_CHMAP_TFL] = "Top Front Left",
+ [SND_CHMAP_TFR] = "Top Front Right",
+ [SND_CHMAP_TFC] = "Top Front Center",
+ [SND_CHMAP_TRL] = "Top Rear Left",
+ [SND_CHMAP_TRR] = "Top Rear Right",
+ [SND_CHMAP_TRC] = "Top Rear Center",
};
const char *snd_pcm_chmap_long_name(enum snd_pcm_chmap_position val)

View File

@ -1,67 +0,0 @@
From c6db60e32758e8f4bb6f066a5c6fc7758a0f4c49 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 12 Sep 2012 18:44:42 +0200
Subject: [PATCH 24/30] PCM: Fix the conversion from string to chmap position
Use strncasecmp() to allow lower cases, and also evaluate the inverted
phase suffix, too.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm.c | 37 +++++++++++++++++++++++++++----------
1 file changed, 27 insertions(+), 10 deletions(-)
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -7471,24 +7471,41 @@ int snd_pcm_chmap_print(const snd_pcm_ch
static int str_to_chmap(const char *str, int len)
{
int val;
+ unsigned long v;
+ char *p;
if (isdigit(*str)) {
- val = atoi(str);
- if (val < 0)
+ v = strtoul(str, &p, 0);
+ if (v == ULONG_MAX)
return -1;
- return val | SND_CHMAP_DRIVER_SPEC;
- } else if (str[0] == 'C' && str[1] == 'h') {
- val = atoi(str + 2);
- if (val < 0)
+ val = v;
+ val |= SND_CHMAP_DRIVER_SPEC;
+ str = p;
+ } else if (!strncasecmp(str, "ch", 2)) {
+ v = strtoul(str + 2, &p, 0);
+ if (v == ULONG_MAX)
return -1;
- return val;
+ val = v;
+ str = p;
} else {
for (val = 0; val <= SND_CHMAP_LAST; val++) {
- if (!strncmp(str, chmap_names[val], len))
- return val;
+ int slen;
+ assert(chmap_names[val]);
+ slen = strlen(chmap_names[val]);
+ if (slen > len)
+ continue;
+ if (!strncasecmp(str, chmap_names[val], slen) &&
+ !isalpha(str[slen])) {
+ str += slen;
+ break;
+ }
}
- return -1;
+ if (val > SND_CHMAP_LAST)
+ return -1;
}
+ if (str && !strncasecmp(str, "[INV]", 5))
+ val |= SND_CHMAP_PHASE_INVERSE;
+ return val;
}
unsigned int snd_pcm_chmap_from_string(const char *str)

View File

@ -1,158 +0,0 @@
From 63f6f4a6103e55d242440488999e648beb5e4e4d Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 13 Sep 2012 08:38:59 +0200
Subject: [PATCH 25/30] PCM: A few doxygen fixes for chmap stuff
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/pcm.h | 18 +++++++++++-------
src/pcm/pcm.c | 43 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+), 7 deletions(-)
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -519,20 +519,24 @@ enum snd_pcm_chmap_position {
SND_CHMAP_LAST = SND_CHMAP_TRC, /** last entry */
};
-#define SND_CHMAP_POSITION_MASK 0xffff /** bitmask for channel position */
-#define SND_CHMAP_PHASE_INVERSE (0x01 << 16) /* the channel is phase inverted */
-#define SND_CHMAP_DRIVER_SPEC (0x02 << 16) /* non-standard channel value */
+/** bitmask for channel position */
+#define SND_CHMAP_POSITION_MASK 0xffff
+
+/** bit flag indicating the channel is phase inverted */
+#define SND_CHMAP_PHASE_INVERSE (0x01 << 16)
+/** bit flag indicating the non-standard channel value */
+#define SND_CHMAP_DRIVER_SPEC (0x02 << 16)
/** the channel map header */
typedef struct snd_pcm_chmap {
- unsigned int channels;
- unsigned int pos[0];
+ unsigned int channels; /** number of channels */
+ unsigned int pos[0]; /** channel position array */
} snd_pcm_chmap_t;
/** the header of array items returned from snd_pcm_query_chmaps() */
typedef struct snd_pcm_chmap_query {
- enum snd_pcm_chmap_type type;
- snd_pcm_chmap_t map;
+ enum snd_pcm_chmap_type type; /** channel map type */
+ snd_pcm_chmap_t map; /** available channel map */
} snd_pcm_chmap_query_t;
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -7310,6 +7310,9 @@ OBSOLETE1(snd_pcm_sw_params_get_silence_
* which contains the channel map. A channel map is represented by an
* integer array, beginning with the channel map type, followed by the
* number of channels, and the position of each channel.
+ *
+ * Note: the caller is requested to release the returned value via
+ * snd_pcm_free_chmaps().
*/
snd_pcm_chmap_query_t **snd_pcm_query_chmaps(snd_pcm_t *pcm)
{
@@ -7336,6 +7339,8 @@ void snd_pcm_free_chmaps(snd_pcm_chmap_q
* \!brief Get the current channel map
* \param pcm PCM instance
* \return the current channel map, or NULL if error
+ *
+ * Note: the caller is requested to release the returned value via free()
*/
snd_pcm_chmap_t *snd_pcm_get_chmap(snd_pcm_t *pcm)
{
@@ -7359,12 +7364,19 @@ int snd_pcm_set_chmap(snd_pcm_t *pcm, co
/*
*/
+#ifndef DOC_HIDDEN
#define _NAME(n) [SND_CHMAP_TYPE_##n] = #n
static const char *chmap_type_names[SND_CHMAP_TYPE_LAST + 1] = {
_NAME(NONE), _NAME(FIXED), _NAME(VAR), _NAME(PAIRED),
};
#undef _NAME
+#endif
+/**
+ * \!brief Get a name string for a channel map type as query results
+ * \param val Channel position
+ * \return The string corresponding to the given type, or NULL
+ */
const char *snd_pcm_chmap_type_name(enum snd_pcm_chmap_type val)
{
if (val <= SND_CHMAP_TYPE_LAST)
@@ -7373,6 +7385,7 @@ const char *snd_pcm_chmap_type_name(enum
return NULL;
}
+#ifndef DOC_HIDDEN
#define _NAME(n) [SND_CHMAP_##n] = #n
static const char *chmap_names[SND_CHMAP_LAST + 1] = {
_NAME(UNKNOWN), _NAME(NA), _NAME(MONO),
@@ -7387,7 +7400,13 @@ static const char *chmap_names[SND_CHMAP
_NAME(TRL), _NAME(TRR), _NAME(TRC),
};
#undef _NAME
+#endif
+/**
+ * \!brief Get a name string for a standard channel map position
+ * \param val Channel position
+ * \return The string corresponding to the given position, or NULL
+ */
const char *snd_pcm_chmap_name(enum snd_pcm_chmap_position val)
{
if (val <= SND_CHMAP_LAST)
@@ -7427,6 +7446,11 @@ static const char *chmap_long_names[SND_
[SND_CHMAP_TRC] = "Top Rear Center",
};
+/**
+ * \!brief Get a longer name string for a standard channel map position
+ * \param val Channel position
+ * \return The string corresponding to the given position, or NULL
+ */
const char *snd_pcm_chmap_long_name(enum snd_pcm_chmap_position val)
{
if (val <= SND_CHMAP_LAST)
@@ -7435,6 +7459,13 @@ const char *snd_pcm_chmap_long_name(enum
return NULL;
}
+/**
+ * \!brief Print the channels in chmap on the buffer
+ * \param map The channel map to print
+ * \param maxlen The maximal length to write (including NUL letter)
+ * \param buf The buffer to write
+ * \return The actual string length or a negative error code
+ */
int snd_pcm_chmap_print(const snd_pcm_chmap_t *map, size_t maxlen, char *buf)
{
unsigned int i, len = 0;
@@ -7508,11 +7539,23 @@ static int str_to_chmap(const char *str,
return val;
}
+/**
+ * \!brief Convert from string to channel position
+ * \param str The string to parse
+ * \return The channel position value or -1 as an error
+ */
unsigned int snd_pcm_chmap_from_string(const char *str)
{
return str_to_chmap(str, strlen(str));
}
+/**
+ * \!brief Convert from string to channel map
+ * \param str The string to parse
+ * \return The channel map
+ *
+ * Note: the caller is requested to release the returned value via free()
+ */
snd_pcm_chmap_t *snd_pcm_chmap_parse_string(const char *str)
{
int i, ch = 0;

View File

@ -1,30 +0,0 @@
From 5a2daef19225478df7e3c1f8c6c9cb847e574b44 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 20 Sep 2012 13:43:12 +0200
Subject: [PATCH 26/30] PCM: Fill SND_CHMAP_NA to silent channels in route
plugin
Instead of SND_CHMAP_UNKNOWN, fill SND_CHMAP_NA to the silent channels.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_route.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/src/pcm/pcm_route.c
+++ b/src/pcm/pcm_route.c
@@ -720,11 +720,13 @@ static snd_pcm_chmap_t *snd_pcm_route_ge
return NULL;
}
map->channels = nsrcs;
+ for (src = 0; src < nsrcs; src++)
+ map->pos[src] = SND_CHMAP_NA;
for (dst = 0; dst < route->params.ndsts; dst++) {
snd_pcm_route_ttable_dst_t *d = &route->params.dsts[dst];
for (src = 0; src < d->nsrcs; src++) {
int c = d->srcs[src].channel;
- if (c < nsrcs && !map->pos[c])
+ if (c < nsrcs && map->pos[c] == SND_CHMAP_NA)
map->pos[c] = slave_map->pos[dst];
}
}

View File

@ -1,43 +0,0 @@
From 5a6ce315201f9e2abee51f4f890c1f5c6592c998 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 21 Sep 2012 17:59:42 +0200
Subject: [PATCH 27/30] PCM: Fix infinite loop in htimestamp of dmix, dsnoop
and dshare plugins
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_dmix.c | 1 +
src/pcm/pcm_dshare.c | 1 +
src/pcm/pcm_dsnoop.c | 1 +
3 files changed, 3 insertions(+)
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -853,6 +853,7 @@ static int snd_pcm_dmix_htimestamp(snd_p
break;
*avail = avail1;
*tstamp = snd_pcm_hw_fast_tstamp(dmix->spcm);
+ ok = 1;
}
return 0;
}
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -543,6 +543,7 @@ static int snd_pcm_dshare_htimestamp(snd
break;
*avail = avail1;
*tstamp = snd_pcm_hw_fast_tstamp(dshare->spcm);
+ ok = 1;
}
return 0;
}
--- a/src/pcm/pcm_dsnoop.c
+++ b/src/pcm/pcm_dsnoop.c
@@ -458,6 +458,7 @@ static int snd_pcm_dsnoop_htimestamp(snd
break;
*avail = avail1;
*tstamp = snd_pcm_hw_fast_tstamp(dsnoop->spcm);
+ ok = 1;
}
return 0;
}

View File

@ -1,287 +0,0 @@
From 6429a450a315e00d9e00af46eb42784a4cc5dce1 Mon Sep 17 00:00:00 2001
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Date: Fri, 21 Sep 2012 20:05:18 -0500
Subject: [PATCH 28/30] test: add audio_time
Simple test to create playback and capture streams, and
check elapsed time vs. sample counts reported by driver.
This should be helpful for driver developers and anyone
interested in system/audio time drift.
tested only on HDAudio
[added Makefile.am change by tiwai]
TODO:
- make period configurable
- better output messages
- support for wall clock when it's in the mainline
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
test/Makefile.am | 4
test/audio_time.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 240 insertions(+), 1 deletion(-)
create mode 100644 test/audio_time.c
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -2,7 +2,8 @@ SUBDIRS=. lsb
check_PROGRAMS=control pcm pcm_min latency seq \
playmidi1 timer rawmidi midiloop \
- oldapi queue_timer namehint client_event_filter chmap
+ oldapi queue_timer namehint client_event_filter \
+ chmap audio_time
control_LDADD=../src/libasound.la
pcm_LDADD=../src/libasound.la
@@ -19,6 +20,7 @@ namehint_LDADD=../src/libasound.la
client_event_filter_LDADD=../src/libasound.la
code_CFLAGS=-Wall -pipe -g -O2
chmap_LDADD=../src/libasound.la
+audio_time_LDADD=../src/libasound.la
INCLUDES=-I$(top_srcdir)/include
AM_CFLAGS=-Wall -pipe -g
--- /dev/null
+++ b/test/audio_time.c
@@ -0,0 +1,237 @@
+/*
+ * This program only tracks the difference between system time
+ * and audio time, as reported in snd_pcm_status(). It should be
+ * helpful to verify the information reported by drivers.
+ */
+
+#include "../include/asoundlib.h"
+#include <math.h>
+
+static char *device = "hw:0,0";
+
+snd_output_t *output = NULL;
+
+long long timestamp2ns(snd_htimestamp_t t)
+{
+ long long nsec;
+
+ nsec = t.tv_sec * 1000000000;
+ nsec += t.tv_nsec;
+
+ return nsec;
+}
+
+long long timediff(snd_htimestamp_t t1, snd_htimestamp_t t2)
+{
+ long long nsec1, nsec2;
+
+ nsec1 = timestamp2ns(t1);
+ nsec2 = timestamp2ns(t2);
+
+ return nsec1 - nsec2;
+}
+
+void gettimestamp(snd_pcm_t *handle, snd_htimestamp_t *timestamp,
+ snd_htimestamp_t *trigger_timestamp,
+ snd_pcm_uframes_t *avail, snd_pcm_sframes_t *delay)
+{
+ int err;
+ snd_pcm_status_t *status;
+
+ snd_pcm_status_alloca(&status);
+ if ((err = snd_pcm_status(handle, status)) < 0) {
+ printf("Stream status error: %s\n", snd_strerror(err));
+ exit(0);
+ }
+ snd_pcm_status_get_trigger_htstamp(status, trigger_timestamp);
+ snd_pcm_status_get_htstamp(status, timestamp);
+ *avail = snd_pcm_status_get_avail(status);
+ *delay = snd_pcm_status_get_delay(status);
+}
+
+#define PERIOD 6000
+#define PCM_LINK /* sync start for playback and capture */
+#define TRACK_CAPTURE /* dump capture timing info */
+#define TRACK_PLAYBACK /* dump playback timing info */
+#define PLAYBACK_BUFFERS 4
+
+
+int main(void)
+{
+ int err;
+ unsigned int i;
+ snd_pcm_t *handle_p = NULL;
+ snd_pcm_t *handle_c = NULL;
+ snd_pcm_sframes_t frames;
+ snd_htimestamp_t tstamp_c, tstamp_p;
+ snd_htimestamp_t trigger_tstamp_c, trigger_tstamp_p;
+ unsigned char buffer_p[PERIOD*4*4];
+ unsigned char buffer_c[PERIOD*4*4];
+
+ snd_pcm_sw_params_t *swparams_p;
+ snd_pcm_sw_params_t *swparams_c;
+
+ snd_pcm_uframes_t curr_count_c;
+ snd_pcm_uframes_t frame_count_c = 0;
+ snd_pcm_uframes_t curr_count_p;
+ snd_pcm_uframes_t frame_count_p = 0;
+
+ snd_pcm_sframes_t delay_p, delay_c;
+ snd_pcm_uframes_t avail_p, avail_c;
+
+ if ((err = snd_pcm_open(&handle_p, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
+ printf("Playback open error: %s\n", snd_strerror(err));
+ goto _exit;
+ }
+ if ((err = snd_pcm_set_params(handle_p,
+ SND_PCM_FORMAT_S16,
+ SND_PCM_ACCESS_RW_INTERLEAVED,
+ 2,
+ 48000,
+ 0,
+ 500000)) < 0) { /* 0.5sec */
+ printf("Playback open error: %s\n", snd_strerror(err));
+ goto _exit;
+ }
+
+ snd_pcm_sw_params_alloca(&swparams_p);
+ /* get the current swparams */
+ err = snd_pcm_sw_params_current(handle_p, swparams_p);
+ if (err < 0) {
+ printf("Unable to determine current swparams_p: %s\n", snd_strerror(err));
+ goto _exit;
+ }
+
+ /* enable tstamp */
+ err = snd_pcm_sw_params_set_tstamp_mode(handle_p, swparams_p, SND_PCM_TSTAMP_ENABLE);
+ if (err < 0) {
+ printf("Unable to set tstamp mode : %s\n", snd_strerror(err));
+ goto _exit;
+ }
+
+ /* write the sw parameters */
+ err = snd_pcm_sw_params(handle_p, swparams_p);
+ if (err < 0) {
+ printf("Unable to set swparams_p : %s\n", snd_strerror(err));
+ goto _exit;
+ }
+
+ if ((err = snd_pcm_open(&handle_c, device, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) {
+ printf("Capture open error: %s\n", snd_strerror(err));
+ goto _exit;
+ }
+ if ((err = snd_pcm_set_params(handle_c,
+ SND_PCM_FORMAT_S16,
+ SND_PCM_ACCESS_RW_INTERLEAVED,
+ 2,
+ 48000,
+ 0,
+ 500000)) < 0) { /* 0.5sec */
+ printf("Capture open error: %s\n", snd_strerror(err));
+ goto _exit;
+ }
+
+ snd_pcm_sw_params_alloca(&swparams_c);
+ /* get the current swparams */
+ err = snd_pcm_sw_params_current(handle_c, swparams_c);
+ if (err < 0) {
+ printf("Unable to determine current swparams_c: %s\n", snd_strerror(err));
+ goto _exit;
+ }
+
+ /* enable tstamp */
+ err = snd_pcm_sw_params_set_tstamp_mode(handle_c, swparams_c, SND_PCM_TSTAMP_ENABLE);
+ if (err < 0) {
+ printf("Unable to set tstamp mode : %s\n", snd_strerror(err));
+ goto _exit;
+ }
+
+ /* write the sw parameters */
+ err = snd_pcm_sw_params(handle_c, swparams_c);
+ if (err < 0) {
+ printf("Unable to set swparams_c : %s\n", snd_strerror(err));
+ goto _exit;
+ }
+
+#ifdef PCM_LINK
+ if ((err = snd_pcm_link(handle_c, handle_p)) < 0) {
+ printf("Streams link error: %s\n", snd_strerror(err));
+ exit(0);
+ }
+#endif
+
+ i = PLAYBACK_BUFFERS;
+ while (i--) {
+ frames = snd_pcm_writei(handle_p, buffer_p, PERIOD);
+ if (frames < 0) {
+ printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
+ goto _exit;
+ }
+ frame_count_p += frames;
+ }
+
+ if (PLAYBACK_BUFFERS != 4)
+ snd_pcm_start(handle_p);
+
+#ifndef PCM_LINK
+ /* need to start capture explicitly */
+ snd_pcm_start(handle_c);
+#endif
+
+ while (1) {
+
+ frames = snd_pcm_wait(handle_c, -1);
+ if (frames < 0) {
+ printf("snd_pcm_wait failed: %s\n", snd_strerror(frames));
+ goto _exit;
+ }
+
+ frames = snd_pcm_readi(handle_c, buffer_c, PERIOD);
+ if (frames < 0) {
+ printf("snd_pcm_readi failed: %s\n", snd_strerror(frames));
+ goto _exit;
+ }
+ frame_count_c += frames;
+
+ frames = snd_pcm_writei(handle_p, buffer_p, PERIOD);
+ if (frames < 0) {
+ printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
+ goto _exit;
+ }
+
+ frame_count_p += frames;
+
+#if defined(TRACK_PLAYBACK)
+ gettimestamp(handle_p, &tstamp_p, &trigger_tstamp_p, &avail_p, &delay_p);
+
+ curr_count_p = frame_count_p - delay_p; /* written minus queued */
+
+ printf("playback: systime: %lli nsec, sample time %lli nsec \tsystime delta %lli \n",
+ timediff(tstamp_p,trigger_tstamp_p),
+ (long long)round(((float)curr_count_p * 1000000000.0 / 48000.0)),
+ timediff(tstamp_p, trigger_tstamp_p) - (long long)round((double)curr_count_p * 1000000000.0 / 48000.0)
+ );
+#endif
+
+#if defined(TRACK_CAPTURE)
+ gettimestamp(handle_c, &tstamp_c, &trigger_tstamp_c, &avail_c, &delay_c);
+
+ curr_count_c = frame_count_c + delay_c; /* read plus queued */
+
+ printf("\t capture: systime: %lli nsec, sample time %lli nsec \tsystime delta %lli \n",
+ timediff(tstamp_c,trigger_tstamp_c),
+ (long long)round(((float)curr_count_c * 1000000000.0 / 48000.0)),
+ timediff(tstamp_c, trigger_tstamp_c) - (long long)round((double)curr_count_c * 1000000000.0 / 48000.0)
+ );
+#endif
+
+ }
+
+_exit:
+ if (handle_p)
+ snd_pcm_close(handle_p);
+ if (handle_c)
+ snd_pcm_close(handle_c);
+
+ return 0;
+}

View File

@ -1,49 +0,0 @@
From 4bdb09126a32feb4394eaeb1d400d87e7c968770 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 10 Oct 2012 10:22:54 +0200
Subject: [PATCH 30/30] PCM: Fix the invalid snd_pcm_close() calls in rate
plugin
It happens in the error path, should call snd_pcm_free() instead.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_rate.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -1394,13 +1394,13 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp,
}
} else {
SNDERR("Invalid type for rate converter");
- snd_pcm_close(pcm);
+ snd_pcm_free(pcm);
free(rate);
return -EINVAL;
}
if (err < 0) {
SNDERR("Cannot find rate converter");
- snd_pcm_close(pcm);
+ snd_pcm_free(pcm);
free(rate);
return -ENOENT;
}
@@ -1409,7 +1409,7 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp,
open_func = SND_PCM_RATE_PLUGIN_ENTRY(linear);
err = open_func(SND_PCM_RATE_PLUGIN_VERSION, &rate->obj, &rate->ops);
if (err < 0) {
- snd_pcm_close(pcm);
+ snd_pcm_free(pcm);
free(rate);
return err;
}
@@ -1418,7 +1418,7 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp,
if (! rate->ops.init || ! (rate->ops.convert || rate->ops.convert_s16) ||
! rate->ops.input_frames || ! rate->ops.output_frames) {
SNDERR("Inproper rate plugin %s initialization", type);
- snd_pcm_close(pcm);
+ snd_pcm_free(pcm);
free(rate);
return err;
}

View File

@ -1,272 +0,0 @@
From cf40ea169aad366b222283f431addafea6327149 Mon Sep 17 00:00:00 2001
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Date: Tue, 12 Jun 2012 14:36:40 -0500
Subject: [PATCH 31/35] pcm: support for audio timestamps
add new snd_pcm_status_get_audio_htstamp() routine to
query the audio timestamps provided by the kernel.
This change provides applications with better ways
to track elapsed time. Before this patch, applications
would subtract queued samples (delay) from written samples,
resulting in a 1-2 sample error.
Also add snd_pcm_hw_params_supports_audio_wallclock_ts()
to query what the hardware supports.
TODO: check protocol compatibility?
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/pcm.h | 2 ++
include/sound/asound.h | 7 ++++--
src/pcm/pcm.c | 31 +++++++++++++++++++++++
test/audio_time.c | 68 ++++++++++++++++++++++++++++++++++++++++++--------
4 files changed, 96 insertions(+), 12 deletions(-)
diff --git a/include/pcm.h b/include/pcm.h
index 290593b..1ce91e7 100644
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -631,6 +631,7 @@ int snd_pcm_hw_params_is_half_duplex(const snd_pcm_hw_params_t *params);
int snd_pcm_hw_params_is_joint_duplex(const snd_pcm_hw_params_t *params);
int snd_pcm_hw_params_can_sync_start(const snd_pcm_hw_params_t *params);
int snd_pcm_hw_params_can_disable_period_wakeup(const snd_pcm_hw_params_t *params);
+int snd_pcm_hw_params_supports_audio_wallclock_ts(const snd_pcm_hw_params_t *params);
int snd_pcm_hw_params_get_rate_numden(const snd_pcm_hw_params_t *params,
unsigned int *rate_num,
unsigned int *rate_den);
@@ -939,6 +940,7 @@ void snd_pcm_status_get_trigger_tstamp(const snd_pcm_status_t *obj, snd_timestam
void snd_pcm_status_get_trigger_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr);
void snd_pcm_status_get_tstamp(const snd_pcm_status_t *obj, snd_timestamp_t *ptr);
void snd_pcm_status_get_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr);
+void snd_pcm_status_get_audio_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr);
snd_pcm_sframes_t snd_pcm_status_get_delay(const snd_pcm_status_t *obj);
snd_pcm_uframes_t snd_pcm_status_get_avail(const snd_pcm_status_t *obj);
snd_pcm_uframes_t snd_pcm_status_get_avail_max(const snd_pcm_status_t *obj);
diff --git a/include/sound/asound.h b/include/sound/asound.h
index e24d144..16d03e8 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -160,7 +160,7 @@ enum {
* *
*****************************************************************************/
-#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10)
+#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 11)
typedef unsigned long sndrv_pcm_uframes_t;
typedef long sndrv_pcm_sframes_t;
@@ -285,6 +285,7 @@ enum sndrv_pcm_subformat {
#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */
#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */
#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */
+#define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* has audio wall clock for audio/system time sync */
enum sndrv_pcm_state {
SNDRV_PCM_STATE_OPEN = 0, /* stream is open */
@@ -426,7 +427,8 @@ struct sndrv_pcm_status {
sndrv_pcm_uframes_t avail_max; /* max frames available on hw since last status */
sndrv_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */
int suspended_state; /* suspended stream state */
- unsigned char reserved[60]; /* must be filled with zero */
+ struct timespec audio_tstamp; /* from sample counter or wall clock */
+ unsigned char reserved[60-sizeof(struct timespec)]; /* must be filled with zero */
};
struct sndrv_pcm_mmap_status {
@@ -435,6 +437,7 @@ struct sndrv_pcm_mmap_status {
sndrv_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */
struct timespec tstamp; /* Timestamp */
int suspended_state; /* RO: suspended stream state */
+ struct timespec audio_tstamp; /* from sample counter or wall clock */
};
struct sndrv_pcm_mmap_control {
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index 65c7646..5880057 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -3124,6 +3124,26 @@ int snd_pcm_hw_params_can_disable_period_wakeup(const snd_pcm_hw_params_t *param
}
/**
+ * \brief Check if hardware supports audio wallclock timestamps
+ * \param params Configuration space
+ * \retval 0 Hardware doesn't support audio wallclock timestamps
+ * \retval 1 Hardware supports audio wallclock timestamps
+ *
+ * This function should only be called when the configuration space
+ * contains a single configuration. Call #snd_pcm_hw_params to choose
+ * a single configuration from the configuration space.
+ */
+int snd_pcm_hw_params_supports_audio_wallclock_ts(const snd_pcm_hw_params_t *params)
+{
+ assert(params);
+ if (CHECK_SANITY(params->info == ~0U)) {
+ SNDMSG("invalid PCM info field");
+ return 0; /* FIXME: should be a negative error? */
+ }
+ return !!(params->info & SNDRV_PCM_INFO_HAS_WALL_CLOCK);
+}
+
+/**
* \brief Get rate exact info from a configuration space
* \param params Configuration space
* \param rate_num Pointer to returned rate numerator
@@ -6214,6 +6234,17 @@ void snd_pcm_status_get_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *p
use_default_symbol_version(__snd_pcm_status_get_htstamp, snd_pcm_status_get_htstamp, ALSA_0.9.0rc8);
/**
+ * \brief Get "now" hi-res audio timestamp from a PCM status container
+ * \param obj pointer to #snd_pcm_status_t
+ * \param ptr Pointer to returned timestamp
+ */
+void snd_pcm_status_get_audio_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr)
+{
+ assert(obj && ptr);
+ *ptr = obj->audio_tstamp;
+}
+
+/**
* \brief Get delay from a PCM status container (see #snd_pcm_delay)
* \return Delay in frames
*
diff --git a/test/audio_time.c b/test/audio_time.c
index a910783..03817c7 100644
--- a/test/audio_time.c
+++ b/test/audio_time.c
@@ -33,6 +33,7 @@ long long timediff(snd_htimestamp_t t1, snd_htimestamp_t t2)
void gettimestamp(snd_pcm_t *handle, snd_htimestamp_t *timestamp,
snd_htimestamp_t *trigger_timestamp,
+ snd_htimestamp_t *audio_timestamp,
snd_pcm_uframes_t *avail, snd_pcm_sframes_t *delay)
{
int err;
@@ -45,6 +46,7 @@ void gettimestamp(snd_pcm_t *handle, snd_htimestamp_t *timestamp,
}
snd_pcm_status_get_trigger_htstamp(status, trigger_timestamp);
snd_pcm_status_get_htstamp(status, timestamp);
+ snd_pcm_status_get_audio_htstamp(status, audio_timestamp);
*avail = snd_pcm_status_get_avail(status);
*delay = snd_pcm_status_get_delay(status);
}
@@ -53,6 +55,7 @@ void gettimestamp(snd_pcm_t *handle, snd_htimestamp_t *timestamp,
#define PCM_LINK /* sync start for playback and capture */
#define TRACK_CAPTURE /* dump capture timing info */
#define TRACK_PLAYBACK /* dump playback timing info */
+#define TRACK_SAMPLE_COUNTS /* show difference between sample counters and audiotimestamps returned by driver */
#define PLAYBACK_BUFFERS 4
@@ -65,9 +68,13 @@ int main(void)
snd_pcm_sframes_t frames;
snd_htimestamp_t tstamp_c, tstamp_p;
snd_htimestamp_t trigger_tstamp_c, trigger_tstamp_p;
+ snd_htimestamp_t audio_tstamp_c, audio_tstamp_p;
unsigned char buffer_p[PERIOD*4*4];
unsigned char buffer_c[PERIOD*4*4];
+ snd_pcm_hw_params_t *hwparams_p;
+ snd_pcm_hw_params_t *hwparams_c;
+
snd_pcm_sw_params_t *swparams_p;
snd_pcm_sw_params_t *swparams_c;
@@ -94,6 +101,18 @@ int main(void)
goto _exit;
}
+ snd_pcm_hw_params_alloca(&hwparams_p);
+ /* get the current hwparams */
+ err = snd_pcm_hw_params_current(handle_p, hwparams_p);
+ if (err < 0) {
+ printf("Unable to determine current hwparams_p: %s\n", snd_strerror(err));
+ goto _exit;
+ }
+ if (snd_pcm_hw_params_supports_audio_wallclock_ts(hwparams_p))
+ printf("Playback relies on audio wallclock timestamps\n");
+ else
+ printf("Playback relies on audio sample counter timestamps\n");
+
snd_pcm_sw_params_alloca(&swparams_p);
/* get the current swparams */
err = snd_pcm_sw_params_current(handle_p, swparams_p);
@@ -131,6 +150,18 @@ int main(void)
goto _exit;
}
+ snd_pcm_hw_params_alloca(&hwparams_c);
+ /* get the current hwparams */
+ err = snd_pcm_hw_params_current(handle_c, hwparams_c);
+ if (err < 0) {
+ printf("Unable to determine current hwparams_c: %s\n", snd_strerror(err));
+ goto _exit;
+ }
+ if (snd_pcm_hw_params_supports_audio_wallclock_ts(hwparams_c))
+ printf("Capture relies on audio wallclock timestamps\n");
+ else
+ printf("Capture relies on audio sample counter timestamps\n");
+
snd_pcm_sw_params_alloca(&swparams_c);
/* get the current swparams */
err = snd_pcm_sw_params_current(handle_c, swparams_c);
@@ -202,26 +233,43 @@ int main(void)
frame_count_p += frames;
#if defined(TRACK_PLAYBACK)
- gettimestamp(handle_p, &tstamp_p, &trigger_tstamp_p, &avail_p, &delay_p);
+ gettimestamp(handle_p, &tstamp_p, &trigger_tstamp_p, &audio_tstamp_p, &avail_p, &delay_p);
+#if defined(TRACK_SAMPLE_COUNTS)
curr_count_p = frame_count_p - delay_p; /* written minus queued */
- printf("playback: systime: %lli nsec, sample time %lli nsec \tsystime delta %lli \n",
- timediff(tstamp_p,trigger_tstamp_p),
- (long long)round(((float)curr_count_p * 1000000000.0 / 48000.0)),
- timediff(tstamp_p, trigger_tstamp_p) - (long long)round((double)curr_count_p * 1000000000.0 / 48000.0)
+ printf("playback: curr_count %lli driver count %lli, delta %lli\n",
+ (long long)curr_count_p * 1000000000LL / 48000 ,
+ timestamp2ns(audio_tstamp_p),
+ (long long)curr_count_p * 1000000000LL / 48000 - timestamp2ns(audio_tstamp_p)
+ );
+#endif
+
+ printf("playback: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli\n",
+ timediff(tstamp_p, trigger_tstamp_p),
+ timestamp2ns(audio_tstamp_p),
+ timediff(tstamp_p, trigger_tstamp_p) - timestamp2ns(audio_tstamp_p)
);
#endif
#if defined(TRACK_CAPTURE)
- gettimestamp(handle_c, &tstamp_c, &trigger_tstamp_c, &avail_c, &delay_c);
+ gettimestamp(handle_c, &tstamp_c, &trigger_tstamp_c, &audio_tstamp_c, &avail_c, &delay_c);
+#if defined(TRACK_SAMPLE_COUNTS)
curr_count_c = frame_count_c + delay_c; /* read plus queued */
- printf("\t capture: systime: %lli nsec, sample time %lli nsec \tsystime delta %lli \n",
- timediff(tstamp_c,trigger_tstamp_c),
- (long long)round(((float)curr_count_c * 1000000000.0 / 48000.0)),
- timediff(tstamp_c, trigger_tstamp_c) - (long long)round((double)curr_count_c * 1000000000.0 / 48000.0)
+
+ printf("capture: curr_count %lli driver count %lli, delta %lli\n",
+ (long long)curr_count_c * 1000000000LL / 48000 ,
+ timestamp2ns(audio_tstamp_c),
+ (long long)curr_count_c * 1000000000LL / 48000 - timestamp2ns(audio_tstamp_c)
+ );
+#endif
+
+ printf("\t capture: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli\n",
+ timediff(tstamp_c, trigger_tstamp_c),
+ timestamp2ns(audio_tstamp_c),
+ timediff(tstamp_c, trigger_tstamp_c) - timestamp2ns(audio_tstamp_c)
);
#endif
--
1.8.0

View File

@ -1,39 +0,0 @@
From 2b49df0c554cb9c7fc717dcf82d1b8f5310eef62 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Sun, 28 Oct 2012 12:30:29 +0100
Subject: [PATCH 32/35] pcm: fix 64-bit SNDRV_PCM_IOCTL_STATUS ABI breakage
Commit cf40ea169aad (pcm: support for audio timestamps) added the new
audio_tstamp field to struct sndrv_pcm_status. However, struct timespec
requires 64-bit alignment, so the 64-bit compiler would insert
32 bits of padding before this field, which broke SNDRV_PCM_IOCTL_STATUS
with error messages like this:
kernel: unknown ioctl = 0x80984120
To solve this, insert the padding explicitly so that it can be taken
into account when calculating the ABI structure size.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
---
include/sound/asound.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/sound/asound.h b/include/sound/asound.h
index 16d03e8..8fdad91 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -427,8 +427,9 @@ struct sndrv_pcm_status {
sndrv_pcm_uframes_t avail_max; /* max frames available on hw since last status */
sndrv_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */
int suspended_state; /* suspended stream state */
+ u_int32_t reserved_alignment; /* must be filled with zero */
struct timespec audio_tstamp; /* from sample counter or wall clock */
- unsigned char reserved[60-sizeof(struct timespec)]; /* must be filled with zero */
+ unsigned char reserved[56-sizeof(struct timespec)]; /* must be filled with zero */
};
struct sndrv_pcm_mmap_status {
--
1.8.0

View File

@ -1,34 +0,0 @@
From edcd677bf2065c560ef578940bab8f0aacddf0e6 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Tue, 30 Oct 2012 11:43:07 +0100
Subject: [PATCH 33/35] PCM: Fix memory leak for pcm empty and asym plugins
The init-only plugins do not have own pcm handle, so free the references
to open function immediately after open.
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/pcm/pcm.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index 5880057..359d295 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -2171,7 +2171,12 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
if (open_func) {
err = open_func(pcmp, name, pcm_root, pcm_conf, stream, mode);
if (err >= 0) {
- (*pcmp)->open_func = open_func;
+ if ((*pcmp)->open_func) {
+ /* only init plugin (like empty, asym) */
+ snd_dlobj_cache_put(open_func);
+ } else {
+ (*pcmp)->open_func = open_func;
+ }
err = 0;
} else {
snd_dlobj_cache_put(open_func);
--
1.8.0

View File

@ -1,179 +0,0 @@
From 49dde08641f8c6b480c0d410d4fdb2160752dd9a Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Tue, 30 Oct 2012 13:07:48 +0100
Subject: [PATCH 34/35] Reduce compilation warnings
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/alisp/alisp.c | 2 +-
src/mixer/simple_none.c | 2 --
src/pcm/pcm_generic.c | 2 +-
src/pcm/pcm_ioplug.c | 2 +-
src/pcm/pcm_ladspa.c | 8 +-------
src/pcm/pcm_mmap_emul.c | 2 --
src/pcm/pcm_route.c | 2 +-
src/pcm/pcm_share.c | 5 +----
src/seq/seqmid.c | 2 +-
9 files changed, 7 insertions(+), 20 deletions(-)
diff --git a/src/alisp/alisp.c b/src/alisp/alisp.c
index 7575f55..5dd5b06 100644
--- a/src/alisp/alisp.c
+++ b/src/alisp/alisp.c
@@ -3256,7 +3256,7 @@ int alsa_lisp(struct alisp_cfg *cfg, struct alisp_instance **_instance)
else
alsa_lisp_free(instance);
- return 0;
+ return retval;
}
void alsa_lisp_free(struct alisp_instance *instance)
diff --git a/src/mixer/simple_none.c b/src/mixer/simple_none.c
index b11e9e8..1c2774a 100644
--- a/src/mixer/simple_none.c
+++ b/src/mixer/simple_none.c
@@ -672,7 +672,6 @@ static int simple_update(snd_mixer_elem_t *melem)
unsigned int caps, pchannels, cchannels;
long pmin, pmax, cmin, cmax;
selem_ctl_t *ctl;
- const char *name;
caps = 0;
pchannels = 0;
@@ -683,7 +682,6 @@ static int simple_update(snd_mixer_elem_t *melem)
cmax = LONG_MIN;
assert(snd_mixer_elem_get_type(melem) == SND_MIXER_ELEM_SIMPLE);
simple = snd_mixer_elem_get_private(melem);
- name = snd_mixer_selem_get_name(melem);
ctl = &simple->ctls[CTL_SINGLE];
if (ctl->elem) {
pchannels = cchannels = ctl->values;
diff --git a/src/pcm/pcm_generic.c b/src/pcm/pcm_generic.c
index 0436439..d56e5d3 100644
--- a/src/pcm/pcm_generic.c
+++ b/src/pcm/pcm_generic.c
@@ -41,7 +41,7 @@ int snd_pcm_generic_close(snd_pcm_t *pcm)
if (generic->close_slave)
err = snd_pcm_close(generic->slave);
free(generic);
- return 0;
+ return err;
}
int snd_pcm_generic_nonblock(snd_pcm_t *pcm, int nonblock)
diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c
index 9c6275a..a90c844 100644
--- a/src/pcm/pcm_ioplug.c
+++ b/src/pcm/pcm_ioplug.c
@@ -625,7 +625,7 @@ static snd_pcm_sframes_t snd_pcm_ioplug_avail_update(snd_pcm_t *pcm)
snd_pcm_uframes_t avail;
snd_pcm_ioplug_hw_ptr_update(pcm);
- if (io->data->state == SNDRV_PCM_STATE_XRUN)
+ if (io->data->state == SND_PCM_STATE_XRUN)
return -EPIPE;
if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
diff --git a/src/pcm/pcm_ladspa.c b/src/pcm/pcm_ladspa.c
index 31e2875..0a9c52e 100644
--- a/src/pcm/pcm_ladspa.c
+++ b/src/pcm/pcm_ladspa.c
@@ -612,8 +612,7 @@ static int snd_pcm_ladspa_allocate_instances(snd_pcm_t *pcm, snd_pcm_ladspa_t *l
{
struct list_head *list, *pos;
unsigned int depth, idx, count;
- unsigned int in_channel, out_channel;
- unsigned int in_channels, out_channels;
+ unsigned int in_channels;
unsigned int in_ports, out_ports;
snd_pcm_ladspa_instance_t *instance = NULL;
int err;
@@ -622,11 +621,8 @@ static int snd_pcm_ladspa_allocate_instances(snd_pcm_t *pcm, snd_pcm_ladspa_t *l
in_channels = ladspa->channels > 0 ? ladspa->channels :
(pcm->stream == SND_PCM_STREAM_PLAYBACK ? pcm->channels : ladspa->plug.gen.slave->channels);
depth = 0;
- out_channels = 0;
list_for_each(pos, list) {
snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
- if (pos->next == list) /* last entry */
- out_channels = pcm->stream == SND_PCM_STREAM_PLAYBACK ? ladspa->plug.gen.slave->channels : pcm->channels;
in_ports = snd_pcm_ladspa_count_ports(plugin, LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO);
out_ports = snd_pcm_ladspa_count_ports(plugin, LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO);
count = 1;
@@ -636,8 +632,6 @@ static int snd_pcm_ladspa_allocate_instances(snd_pcm_t *pcm, snd_pcm_ladspa_t *l
else
plugin->policy = SND_PCM_LADSPA_POLICY_NONE;
}
- in_channel = 0;
- out_channel = 0;
for (idx = 0; idx < count; idx++) {
instance = (snd_pcm_ladspa_instance_t *)calloc(1, sizeof(snd_pcm_ladspa_instance_t));
if (instance == NULL)
diff --git a/src/pcm/pcm_mmap_emul.c b/src/pcm/pcm_mmap_emul.c
index 236fe69..811cb1c 100644
--- a/src/pcm/pcm_mmap_emul.c
+++ b/src/pcm/pcm_mmap_emul.c
@@ -332,9 +332,7 @@ static snd_pcm_sframes_t snd_pcm_mmap_emul_avail_update(snd_pcm_t *pcm)
{
mmap_emul_t *map = pcm->private_data;
snd_pcm_t *slave = map->gen.slave;
- snd_pcm_sframes_t avail;
- avail = snd_pcm_avail_update(slave);
if (!map->mmap_emul || pcm->stream == SND_PCM_STREAM_PLAYBACK)
map->hw_ptr = *slave->hw.ptr;
else
diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c
index a3d1695..2beedf6 100644
--- a/src/pcm/pcm_route.c
+++ b/src/pcm/pcm_route.c
@@ -725,7 +725,7 @@ static snd_pcm_chmap_t *snd_pcm_route_get_chmap(snd_pcm_t *pcm)
for (dst = 0; dst < route->params.ndsts; dst++) {
snd_pcm_route_ttable_dst_t *d = &route->params.dsts[dst];
for (src = 0; src < d->nsrcs; src++) {
- int c = d->srcs[src].channel;
+ unsigned int c = d->srcs[src].channel;
if (c < nsrcs && map->pos[c] == SND_CHMAP_NA)
map->pos[c] = slave_map->pos[dst];
}
diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c
index 56a8685..936e2f9 100644
--- a/src/pcm/pcm_share.c
+++ b/src/pcm/pcm_share.c
@@ -136,18 +136,15 @@ static snd_pcm_uframes_t snd_pcm_share_slave_avail(snd_pcm_share_slave_t *slave)
static snd_pcm_uframes_t _snd_pcm_share_slave_forward(snd_pcm_share_slave_t *slave)
{
struct list_head *i;
- snd_pcm_uframes_t buffer_size, boundary;
- snd_pcm_uframes_t slave_appl_ptr;
+ snd_pcm_uframes_t buffer_size;
snd_pcm_sframes_t frames, safety_frames;
snd_pcm_sframes_t min_frames, max_frames;
snd_pcm_uframes_t avail, slave_avail;
snd_pcm_uframes_t slave_hw_avail;
slave_avail = snd_pcm_share_slave_avail(slave);
- boundary = slave->pcm->boundary;
buffer_size = slave->pcm->buffer_size;
min_frames = slave_avail;
max_frames = 0;
- slave_appl_ptr = *slave->pcm->appl.ptr;
list_for_each(i, &slave->clients) {
snd_pcm_share_t *share = list_entry(i, snd_pcm_share_t, list);
snd_pcm_t *pcm = share->pcm;
diff --git a/src/seq/seqmid.c b/src/seq/seqmid.c
index 2ff7e8d..7d8bf1a 100644
--- a/src/seq/seqmid.c
+++ b/src/seq/seqmid.c
@@ -423,7 +423,7 @@ int snd_seq_parse_address(snd_seq_t *seq, snd_seq_addr_t *addr, const char *arg)
return -EINVAL;
cinfo.client = -1;
while (snd_seq_query_next_client(seq, &cinfo) >= 0) {
- if ((strlen(cinfo.name) == len) &&
+ if ((strlen(cinfo.name) == (size_t)len) &&
! strncmp(arg, cinfo.name, len)) {
addr->client = cinfo.client;
return 0;
--
1.8.0

View File

@ -1,222 +0,0 @@
From 3fd4ab9be0db7c7430ebd258f2717a976381715d Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 13 Nov 2012 16:16:26 +0100
Subject: [PATCH 35/35] PCM: Avoid busy loop in snd_pcm_write_areas() with
rate plugin
snd_pcm_write_areas() tries to wait until avail >= avail_min condition
is satisfied. This doesn't work always well when a rate plugin is in
the play.
When a partial data with a smaller size than a period is written, the
rate plugin doesn't transfer the data immediately to the slave PCM,
but kept in an internal buffer and it changes only the hwptr of the
plugin. Thus, the condition "avail < avail_min" is triggered for a
wait check although the underlying slave PCM has enough room. This
results in a call of snd_pcm_wait() which returns immediately after
poll() call, and the snd_pcm_write_areas() loop continues. As a
consequence, it falls into a CPU hog.
This patch fixes that busy loop by introducing a new fast_ops to check
the availability for wait of avail_min. Then a plugin can ask the
slave PCM whether the wait is required (or possible).
A few plugins like multi plugin need a special handling. Otherwise a
generic plugin function can be used.
Reported-by: Trent Piepho <tpiepho@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm.c | 8 ++++----
src/pcm/pcm_generic.c | 6 ++++++
src/pcm/pcm_generic.h | 4 +++-
src/pcm/pcm_hooks.c | 1 +
src/pcm/pcm_local.h | 11 +++++++++++
src/pcm/pcm_meter.c | 1 +
src/pcm/pcm_mmap_emul.c | 1 +
src/pcm/pcm_multi.c | 8 ++++++++
src/pcm/pcm_plugin.c | 1 +
src/pcm/pcm_rate.c | 1 +
10 files changed, 37 insertions(+), 5 deletions(-)
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index 359d295..f8b68ed 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -2357,7 +2357,7 @@ int snd_pcm_open_named_slave(snd_pcm_t **pcmp, const char *name,
*/
int snd_pcm_wait(snd_pcm_t *pcm, int timeout)
{
- if (snd_pcm_mmap_avail(pcm) >= pcm->avail_min) {
+ if (!snd_pcm_may_wait_for_avail_min(pcm, snd_pcm_mmap_avail(pcm))) {
/* check more precisely */
switch (snd_pcm_state(pcm)) {
case SND_PCM_STATE_XRUN:
@@ -6776,14 +6776,14 @@ snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area
goto _end;
}
if ((state == SND_PCM_STATE_RUNNING &&
- (snd_pcm_uframes_t)avail < pcm->avail_min &&
- size > (snd_pcm_uframes_t)avail)) {
+ size > (snd_pcm_uframes_t)avail &&
+ snd_pcm_may_wait_for_avail_min(pcm, avail))) {
if (pcm->mode & SND_PCM_NONBLOCK) {
err = -EAGAIN;
goto _end;
}
- err = snd_pcm_wait(pcm, -1);
+ err = snd_pcm_wait_nocheck(pcm, -1);
if (err < 0)
break;
goto _again;
diff --git a/src/pcm/pcm_generic.c b/src/pcm/pcm_generic.c
index d56e5d3..5fc4888 100644
--- a/src/pcm/pcm_generic.c
+++ b/src/pcm/pcm_generic.c
@@ -341,4 +341,10 @@ int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
return snd_pcm_set_chmap(generic->slave, map);
}
+int snd_pcm_generic_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail ATTRIBUTE_UNUSED)
+{
+ snd_pcm_generic_t *generic = pcm->private_data;
+ return snd_pcm_may_wait_for_avail_min(generic->slave, snd_pcm_mmap_avail(generic->slave));
+}
+
#endif /* DOC_HIDDEN */
diff --git a/src/pcm/pcm_generic.h b/src/pcm/pcm_generic.h
index 916c6ec..d189077 100644
--- a/src/pcm/pcm_generic.h
+++ b/src/pcm/pcm_generic.h
@@ -109,6 +109,8 @@ typedef struct {
snd1_pcm_generic_get_chmap
#define snd_pcm_generic_set_chmap \
snd1_pcm_generic_set_chmap
+#define snd_pcm_generic_may_wait_for_avail_min \
+ snd1_pcm_generic_may_wait_for_avail_min
int snd_pcm_generic_close(snd_pcm_t *pcm);
int snd_pcm_generic_nonblock(snd_pcm_t *pcm, int nonblock);
@@ -158,5 +160,5 @@ int snd_pcm_generic_munmap(snd_pcm_t *pcm);
snd_pcm_chmap_query_t **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm);
snd_pcm_chmap_t *snd_pcm_generic_get_chmap(snd_pcm_t *pcm);
int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
-
+int snd_pcm_generic_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail);
diff --git a/src/pcm/pcm_hooks.c b/src/pcm/pcm_hooks.c
index 0feb4a3..f837282 100644
--- a/src/pcm/pcm_hooks.c
+++ b/src/pcm/pcm_hooks.c
@@ -199,6 +199,7 @@ static const snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
.poll_descriptors = snd_pcm_generic_poll_descriptors,
.poll_revents = snd_pcm_generic_poll_revents,
+ .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
};
/**
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
index e7798fd..8cf7c3d 100644
--- a/src/pcm/pcm_local.h
+++ b/src/pcm/pcm_local.h
@@ -177,6 +177,7 @@ typedef struct {
int (*poll_descriptors_count)(snd_pcm_t *pcm);
int (*poll_descriptors)(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space);
int (*poll_revents)(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
+ int (*may_wait_for_avail_min)(snd_pcm_t *pcm, snd_pcm_uframes_t avail);
} snd_pcm_fast_ops_t;
struct _snd_pcm {
@@ -984,3 +985,13 @@ _snd_pcm_parse_config_chmaps(snd_config_t *conf);
snd_pcm_chmap_t *
_snd_pcm_choose_fixed_chmap(snd_pcm_t *pcm, snd_pcm_chmap_query_t * const *maps);
+/* return true if the PCM stream may wait to get avail_min space */
+static inline int snd_pcm_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail)
+{
+ if (avail >= pcm->avail_min)
+ return 0;
+ if (pcm->fast_ops->may_wait_for_avail_min)
+ return pcm->fast_ops->may_wait_for_avail_min(pcm, avail);
+ return 1;
+}
+
diff --git a/src/pcm/pcm_meter.c b/src/pcm/pcm_meter.c
index 42a125e..e60b92d 100644
--- a/src/pcm/pcm_meter.c
+++ b/src/pcm/pcm_meter.c
@@ -545,6 +545,7 @@ static const snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
.poll_descriptors = snd_pcm_generic_poll_descriptors,
.poll_revents = snd_pcm_generic_poll_revents,
+ .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
};
/**
diff --git a/src/pcm/pcm_mmap_emul.c b/src/pcm/pcm_mmap_emul.c
index 811cb1c..67d2e05 100644
--- a/src/pcm/pcm_mmap_emul.c
+++ b/src/pcm/pcm_mmap_emul.c
@@ -400,6 +400,7 @@ static const snd_pcm_fast_ops_t snd_pcm_mmap_emul_fast_ops = {
.poll_descriptors = snd_pcm_generic_poll_descriptors,
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
.poll_revents = snd_pcm_generic_poll_revents,
+ .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
};
#ifndef DOC_HIDDEN
diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c
index ffb1b53..2db82c0 100644
--- a/src/pcm/pcm_multi.c
+++ b/src/pcm/pcm_multi.c
@@ -739,6 +739,13 @@ static int snd_pcm_multi_mmap(snd_pcm_t *pcm)
return 0;
}
+static int snd_pcm_multi_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail)
+{
+ snd_pcm_multi_t *multi = pcm->private_data;
+ snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm;
+ return snd_pcm_may_wait_for_avail_min(slave, snd_pcm_mmap_avail(slave));
+}
+
static snd_pcm_chmap_query_t **snd_pcm_multi_query_chmaps(snd_pcm_t *pcm)
{
snd_pcm_multi_t *multi = pcm->private_data;
@@ -937,6 +944,7 @@ static const snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
.poll_descriptors_count = snd_pcm_multi_poll_descriptors_count,
.poll_descriptors = snd_pcm_multi_poll_descriptors,
.poll_revents = snd_pcm_multi_poll_revents,
+ .may_wait_for_avail_min = snd_pcm_multi_may_wait_for_avail_min,
};
/**
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index d88e117..96218a8 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -570,6 +570,7 @@ const snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
.poll_descriptors = snd_pcm_generic_poll_descriptors,
.poll_revents = snd_pcm_generic_poll_revents,
+ .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
};
#endif
diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
index 4ba8521..54a3e67 100644
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -1234,6 +1234,7 @@ static const snd_pcm_fast_ops_t snd_pcm_rate_fast_ops = {
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
.poll_descriptors = snd_pcm_generic_poll_descriptors,
.poll_revents = snd_pcm_rate_poll_revents,
+ .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
};
static const snd_pcm_ops_t snd_pcm_rate_ops = {
--
1.8.0

File diff suppressed because it is too large Load Diff

View File

@ -1,102 +0,0 @@
From 67d692af480ed0656fb0fe7fdc6451374447dc7c Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 26 Nov 2012 18:10:26 +0100
Subject: [PATCH 37/38] PCM: Add more chmap definitions for UAC2
The new PCM chmap positions have been added in (to be) 3.8-rc1 kernel,
and now updated alsa-lib, too.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/pcm.h | 13 +++++++++++--
include/sound/asound.h | 12 +++++++++++-
src/pcm/pcm.c | 12 ++++++++++++
3 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/include/pcm.h b/include/pcm.h
index 1ce91e7..2235678 100644
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -475,7 +475,7 @@ int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
int snd_pcm_unlink(snd_pcm_t *pcm);
/** channel mapping API version number */
-#define SND_CHMAP_API_VERSION ((1 << 16) | (0 << 8) | 0)
+#define SND_CHMAP_API_VERSION ((1 << 16) | (0 << 8) | 1)
/** channel map list type */
enum snd_pcm_chmap_type {
@@ -516,7 +516,16 @@ enum snd_pcm_chmap_position {
SND_CHMAP_TRL, /** top rear left */
SND_CHMAP_TRR, /** top rear right */
SND_CHMAP_TRC, /** top rear center */
- SND_CHMAP_LAST = SND_CHMAP_TRC, /** last entry */
+ SND_CHMAP_TFLC, /* top front left center */
+ SND_CHMAP_TFRC, /* top front right center */
+ SND_CHMAP_TSL, /* top side left */
+ SND_CHMAP_TSR, /* top side right */
+ SND_CHMAP_LLFE, /* left LFE */
+ SND_CHMAP_RLFE, /* right LFE */
+ SND_CHMAP_BC, /* bottom center */
+ SND_CHMAP_BLC, /* bottom left center */
+ SND_CHMAP_BRC, /* bottom right center */
+ SND_CHMAP_LAST = SND_CHMAP_BRC,
};
/** bitmask for channel position */
diff --git a/include/sound/asound.h b/include/sound/asound.h
index 515b8fc..1774a5c 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -492,7 +492,17 @@ enum {
SNDRV_CHMAP_TRL, /* top rear left */
SNDRV_CHMAP_TRR, /* top rear right */
SNDRV_CHMAP_TRC, /* top rear center */
- SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
+ /* new definitions for UAC2 */
+ SNDRV_CHMAP_TFLC, /* top front left center */
+ SNDRV_CHMAP_TFRC, /* top front right center */
+ SNDRV_CHMAP_TSL, /* top side left */
+ SNDRV_CHMAP_TSR, /* top side right */
+ SNDRV_CHMAP_LLFE, /* left LFE */
+ SNDRV_CHMAP_RLFE, /* right LFE */
+ SNDRV_CHMAP_BC, /* bottom center */
+ SNDRV_CHMAP_BLC, /* bottom left center */
+ SNDRV_CHMAP_BRC, /* bottom right center */
+ SNDRV_CHMAP_LAST = SNDRV_CHMAP_BRC,
};
#define SNDRV_CHMAP_POSITION_MASK 0xffff
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index e16b07f..d616705 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -7434,6 +7434,9 @@ static const char *chmap_names[SND_CHMAP_LAST + 1] = {
_NAME(FLH), _NAME(FCH), _NAME(FRH), _NAME(TC),
_NAME(TFL), _NAME(TFR), _NAME(TFC),
_NAME(TRL), _NAME(TRR), _NAME(TRC),
+ _NAME(TFLC), _NAME(TFRC), _NAME(TSL), _NAME(TSR),
+ _NAME(LLFE), _NAME(RLFE),
+ _NAME(BC), _NAME(BLC), _NAME(BRC),
};
#undef _NAME
#endif
@@ -7480,6 +7483,15 @@ static const char *chmap_long_names[SND_CHMAP_LAST + 1] = {
[SND_CHMAP_TRL] = "Top Rear Left",
[SND_CHMAP_TRR] = "Top Rear Right",
[SND_CHMAP_TRC] = "Top Rear Center",
+ [SND_CHMAP_TFLC] = "Top Front Left Center",
+ [SND_CHMAP_TFRC] = "Top Front Right Center",
+ [SND_CHMAP_TSL] = "Top Side Left",
+ [SND_CHMAP_TSR] = "Top Side Right",
+ [SND_CHMAP_LLFE] = "Left LFE",
+ [SND_CHMAP_RLFE] = "Right LFE",
+ [SND_CHMAP_BC] = "Bottom Center",
+ [SND_CHMAP_BLC] = "Bottom Left Center",
+ [SND_CHMAP_BRC] = "Bottom Right Center",
};
/**
--
1.8.0.1

View File

@ -1,27 +0,0 @@
From f47816d6b78003b5161ffb67b3b5c1b62b8a2a00 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 26 Nov 2012 18:13:01 +0100
Subject: [PATCH 38/38] PCM: shut up a compile "unused parameter" compile
warning in pcm_multi.c
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_multi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c
index 2db82c0..f58852c 100644
--- a/src/pcm/pcm_multi.c
+++ b/src/pcm/pcm_multi.c
@@ -739,7 +739,7 @@ static int snd_pcm_multi_mmap(snd_pcm_t *pcm)
return 0;
}
-static int snd_pcm_multi_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail)
+static int snd_pcm_multi_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail ATTRIBUTE_UNUSED)
{
snd_pcm_multi_t *multi = pcm->private_data;
snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm;
--
1.8.0.1

View File

@ -1,25 +0,0 @@
From 22d6b6e643d81467bcd2b0d8934c6b84bed51787 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 30 Nov 2012 14:33:54 +0100
Subject: [PATCH] Add workaround for conflicting snd_seq_event_t definitions
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/local.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/local.h b/include/local.h
index b0a9368..268970a 100644
--- a/include/local.h
+++ b/include/local.h
@@ -144,6 +144,7 @@
#define snd_seq_tick_time_t sndrv_seq_tick_time_t
#define snd_seq_real_time sndrv_seq_real_time
#define snd_seq_timestamp sndrv_seq_timestamp
+#define snd_seq_event_type_t sndrv_seq_event_type_t
#define snd_seq_event sndrv_seq_event
#define snd_seq_connect sndrv_seq_connect
#define snd_seq_ev_note sndrv_seq_ev_note
--
1.8.0.1

View File

@ -1,139 +0,0 @@
From 03c26d0edeeefb7550ba8cca91167343677022ab Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 4 Dec 2012 12:17:00 +0100
Subject: [PATCH] PCM: Fix conflict of _snd_pcm_hw_params definitions
Fix the call of _snd_pcm_hw_params() to _snd_pcm_hw_params_internal().
The build passed wrongly because of _snd_pcm_hw_params define.
Having the same function name as the struct name is is simply
confusing...
Also, to be sure, _snd_pcm_hw_params is undef'ed in pcm_local.h, too.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm.c | 2 +-
src/pcm/pcm_file.c | 2 +-
src/pcm/pcm_generic.c | 2 +-
src/pcm/pcm_local.h | 1 +
src/pcm/pcm_meter.c | 2 +-
src/pcm/pcm_mmap_emul.c | 4 ++--
src/pcm/pcm_plug.c | 2 +-
src/pcm/pcm_share.c | 2 +-
8 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index d616705..5053a7b 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -828,7 +828,7 @@ int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
{
int err;
assert(pcm && params);
- err = _snd_pcm_hw_params(pcm, params);
+ err = _snd_pcm_hw_params_internal(pcm, params);
if (err < 0)
return err;
err = snd_pcm_prepare(pcm);
diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c
index c8214b4..5950401 100644
--- a/src/pcm/pcm_file.c
+++ b/src/pcm/pcm_file.c
@@ -602,7 +602,7 @@ static int snd_pcm_file_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
snd_pcm_file_t *file = pcm->private_data;
unsigned int channel;
snd_pcm_t *slave = file->gen.slave;
- int err = _snd_pcm_hw_params(slave, params);
+ int err = _snd_pcm_hw_params_internal(slave, params);
if (err < 0)
return err;
file->buffer_bytes = snd_pcm_frames_to_bytes(slave, slave->buffer_size);
diff --git a/src/pcm/pcm_generic.c b/src/pcm/pcm_generic.c
index 5fc4888..f068ee2 100644
--- a/src/pcm/pcm_generic.c
+++ b/src/pcm/pcm_generic.c
@@ -101,7 +101,7 @@ int snd_pcm_generic_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
int snd_pcm_generic_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
{
snd_pcm_generic_t *generic = pcm->private_data;
- return _snd_pcm_hw_params(generic->slave, params);
+ return _snd_pcm_hw_params_internal(generic->slave, params);
}
int snd_pcm_generic_prepare(snd_pcm_t *pcm)
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
index c616e56..63b9036 100644
--- a/src/pcm/pcm_local.h
+++ b/src/pcm/pcm_local.h
@@ -579,6 +579,7 @@ static inline int muldiv_near(int a, int b, int c)
int snd_pcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
int _snd_pcm_hw_params_internal(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
+#undef _snd_pcm_hw_params
int snd_pcm_hw_refine_soft(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
int snd_pcm_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
int (*cprepare)(snd_pcm_t *pcm,
diff --git a/src/pcm/pcm_meter.c b/src/pcm/pcm_meter.c
index e60b92d..573b6fe 100644
--- a/src/pcm/pcm_meter.c
+++ b/src/pcm/pcm_meter.c
@@ -419,7 +419,7 @@ static int snd_pcm_meter_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *pa
static int snd_pcm_meter_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
{
snd_pcm_meter_t *meter = pcm->private_data;
- return _snd_pcm_hw_params(meter->gen.slave, params);
+ return _snd_pcm_hw_params_internal(meter->gen.slave, params);
}
static int snd_pcm_meter_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
diff --git a/src/pcm/pcm_mmap_emul.c b/src/pcm/pcm_mmap_emul.c
index 67d2e05..63789bc 100644
--- a/src/pcm/pcm_mmap_emul.c
+++ b/src/pcm/pcm_mmap_emul.c
@@ -160,7 +160,7 @@ static int snd_pcm_mmap_emul_hw_params(snd_pcm_t *pcm,
snd_pcm_access_mask_t *pmask;
int err;
- err = _snd_pcm_hw_params(map->gen.slave, params);
+ err = _snd_pcm_hw_params_internal(map->gen.slave, params);
if (err >= 0) {
map->mmap_emul = 0;
return err;
@@ -186,7 +186,7 @@ static int snd_pcm_mmap_emul_hw_params(snd_pcm_t *pcm,
default:
goto _err;
}
- err = _snd_pcm_hw_params(map->gen.slave, params);
+ err = _snd_pcm_hw_params_internal(map->gen.slave, params);
if (err < 0)
goto _err;
diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c
index 0bd8850..fa84eaa 100644
--- a/src/pcm/pcm_plug.c
+++ b/src/pcm/pcm_plug.c
@@ -1040,7 +1040,7 @@ static int snd_pcm_plug_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
return err;
}
slave = plug->gen.slave;
- err = _snd_pcm_hw_params(slave, params);
+ err = _snd_pcm_hw_params_internal(slave, params);
if (err < 0) {
snd_pcm_plug_clear(pcm);
return err;
diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c
index 936e2f9..118ab26 100644
--- a/src/pcm/pcm_share.c
+++ b/src/pcm/pcm_share.c
@@ -595,7 +595,7 @@ static int snd_pcm_share_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *pa
static int snd_pcm_share_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
{
snd_pcm_share_t *share = pcm->private_data;
- return _snd_pcm_hw_params(share->slave->pcm, params);
+ return _snd_pcm_hw_params_internal(share->slave->pcm, params);
}
static int snd_pcm_share_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
--
1.8.0.1

View File

@ -1,180 +0,0 @@
From 8d14698931d6c319c42c4bc39886e92d13d19f1e Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 7 Dec 2012 09:27:11 +0100
Subject: [PATCH 41/43] configure: Quite AM_CONDITIONAL() arguments
Otherwise it won't be processed properly with the recent automake.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
configure.in | 91 ++++++++++++++++++++++++++++++------------------------------
1 file changed, 46 insertions(+), 45 deletions(-)
diff --git a/configure.in b/configure.in
index 383f5de..e397dad 100644
--- a/configure.in
+++ b/configure.in
@@ -15,7 +15,7 @@ AC_CANONICAL_HOST
AM_INIT_AUTOMAKE(alsa-lib, 1.0.26)
eval LIBTOOL_VERSION_INFO="2:0:0"
dnl *************************************************
-AM_CONDITIONAL(INSTALL_M4, test -n "${ACLOCAL}")
+AM_CONDITIONAL([INSTALL_M4], [test -n "${ACLOCAL}"])
# Test for new silent rules and enable only if they are available
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
@@ -63,7 +63,7 @@ AC_HEADER_TIME
dnl Checks for library functions.
AC_PROG_GCC_TRADITIONAL
AC_CHECK_FUNC([hsearch_r], [HAVE_HSEARCH_R=yes])
-AM_CONDITIONAL(ALSA_HSEARCH_R, [test "x$HAVE_HSEARCH_R" != xyes])
+AM_CONDITIONAL([ALSA_HSEARCH_R], [test "x$HAVE_HSEARCH_R" != xyes])
AC_CHECK_FUNCS([uselocale])
SAVE_LIBRARY_VERSION
@@ -161,7 +161,7 @@ if test "$versioned" = "yes"; then
else
AC_MSG_RESULT(no)
fi
-AM_CONDITIONAL(VERSIONED_SYMBOLS, test x$versioned = xyes)
+AM_CONDITIONAL([VERSIONED_SYMBOLS], [test x$versioned = xyes])
dnl Check for symbolic-functions
AC_MSG_CHECKING(for symbolic-functions)
@@ -179,7 +179,7 @@ if test "$symfuncs" = "yes"; then
else
AC_MSG_RESULT(no)
fi
-AM_CONDITIONAL(SYMBOLIC_FUNCTIONS, test x"$symfuncs" = xyes)
+AM_CONDITIONAL([SYMBOLIC_FUNCTIONS], [test x"$symfuncs" = xyes])
dnl See if toolchain has a custom prefix for symbols ...
AC_MSG_CHECKING(for custom symbol prefixes)
@@ -254,6 +254,7 @@ AC_MSG_CHECKING(for libdl)
AC_ARG_WITH(libdl,
AS_HELP_STRING([--with-libdl], [Use libdl for plugins (default = yes)]),
[ have_libdl="$withval" ], [ have_libdl="yes" ])
+HAVE_LIBDL=
if test "$have_libdl" = "yes"; then
AC_CHECK_LIB([dl], [dlsym], [HAVE_LIBDL="yes"])
if test "$HAVE_LIBDL" = "yes" ; then
@@ -263,7 +264,7 @@ if test "$have_libdl" = "yes"; then
else
AC_MSG_RESULT(no)
fi
-AM_CONDITIONAL(BUILD_MODULES, test "$HAVE_LIBDL"="yes")
+AM_CONDITIONAL([BUILD_MODULES], [test "$HAVE_LIBDL" = "yes"])
dnl Check for pthread
AC_MSG_CHECKING(for pthread)
@@ -409,7 +410,7 @@ 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"])
-AM_CONDITIONAL(KEEP_OLD_SYMBOLS, test x$keep_old_symbols = xyes)
+AM_CONDITIONAL([KEEP_OLD_SYMBOLS], [test x$keep_old_symbols = xyes])
AC_ARG_ENABLE(python,
AS_HELP_STRING([--disable-python], [disable the python components]),
@@ -438,14 +439,14 @@ fi
AC_SUBST(PYTHON_LIBS)
AC_SUBST(PYTHON_INCLUDES)
-AM_CONDITIONAL(BUILD_MIXER, test x$build_mixer = xyes)
-AM_CONDITIONAL(BUILD_PCM, test x$build_pcm = xyes)
-AM_CONDITIONAL(BUILD_RAWMIDI, test x$build_rawmidi = xyes)
-AM_CONDITIONAL(BUILD_HWDEP, test x$build_hwdep = xyes)
-AM_CONDITIONAL(BUILD_SEQ, test x$build_seq = xyes)
-AM_CONDITIONAL(BUILD_UCM, test x$build_ucm = xyes)
-AM_CONDITIONAL(BUILD_ALISP, test x$build_alisp = xyes)
-AM_CONDITIONAL(BUILD_PYTHON, test x$build_python = xyes)
+AM_CONDITIONAL([BUILD_MIXER], [test x$build_mixer = xyes])
+AM_CONDITIONAL([BUILD_PCM], [test x$build_pcm = xyes])
+AM_CONDITIONAL([BUILD_RAWMIDI], [test x$build_rawmidi = xyes])
+AM_CONDITIONAL([BUILD_HWDEP], [test x$build_hwdep = xyes])
+AM_CONDITIONAL([BUILD_SEQ], [test x$build_seq = xyes])
+AM_CONDITIONAL([BUILD_UCM], [test x$build_ucm = xyes])
+AM_CONDITIONAL([BUILD_ALISP], [test x$build_alisp = xyes])
+AM_CONDITIONAL([BUILD_PYTHON], [test x$build_python = xyes])
if test "$build_mixer" = "yes"; then
AC_DEFINE([BUILD_MIXER], "1", [Build mixer component])
@@ -520,34 +521,34 @@ if test "$softfloat" = "yes"; then
build_pcm_ladspa="no"
fi
-AM_CONDITIONAL(BUILD_PCM_PLUGIN, test x$build_pcm_plugin = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_COPY, test x$build_pcm_copy = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_LINEAR, test x$build_pcm_linear = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_ROUTE, test x$build_pcm_route = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_MULAW, test x$build_pcm_mulaw = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_ALAW, test x$build_pcm_alaw = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_ADPCM, test x$build_pcm_adpcm = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_RATE, test x$build_pcm_rate = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_PLUG, test x$build_pcm_plug = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_MULTI, test x$build_pcm_multi = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_SHM, test x$build_pcm_shm = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_FILE, test x$build_pcm_file = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_NULL, test x$build_pcm_null = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_EMPTY, test x$build_pcm_empty = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_SHARE, test x$build_pcm_share = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_METER, test x$build_pcm_meter = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_HOOKS, test x$build_pcm_hooks = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_LFLOAT, test x$build_pcm_lfloat = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_LADSPA, test x$build_pcm_ladspa = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_DMIX, test x$build_pcm_dmix = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_DSHARE, test x$build_pcm_dshare = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_DSNOOP, test x$build_pcm_dsnoop = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_ASYM, test x$build_pcm_asym = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_IEC958, test x$build_pcm_iec958 = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_SOFTVOL, test x$build_pcm_softvol = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_EXTPLUG, test x$build_pcm_extplug = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_IOPLUG, test x$build_pcm_ioplug = xyes)
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_MMAP_EMUL, test x$build_pcm_mmap_emul = xyes)
+AM_CONDITIONAL([BUILD_PCM_PLUGIN], [test x$build_pcm_plugin = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_COPY], [test x$build_pcm_copy = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_LINEAR], [test x$build_pcm_linear = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_ROUTE], [test x$build_pcm_route = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_MULAW], [test x$build_pcm_mulaw = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_ALAW], [test x$build_pcm_alaw = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_ADPCM], [test x$build_pcm_adpcm = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_RATE], [test x$build_pcm_rate = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_PLUG], [test x$build_pcm_plug = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_MULTI], [test x$build_pcm_multi = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_SHM], [test x$build_pcm_shm = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_FILE], [test x$build_pcm_file = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_NULL], [test x$build_pcm_null = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_EMPTY], [test x$build_pcm_empty = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_SHARE], [test x$build_pcm_share = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_METER], [test x$build_pcm_meter = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_HOOKS], [test x$build_pcm_hooks = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_LFLOAT], [test x$build_pcm_lfloat = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_LADSPA], [test x$build_pcm_ladspa = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_DMIX], [test x$build_pcm_dmix = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_DSHARE], [test x$build_pcm_dshare = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_DSNOOP], [test x$build_pcm_dsnoop = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_ASYM], [test x$build_pcm_asym = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_IEC958], [test x$build_pcm_iec958 = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_SOFTVOL], [test x$build_pcm_softvol = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_EXTPLUG], [test x$build_pcm_extplug = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_IOPLUG], [test x$build_pcm_ioplug = xyes])
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_MMAP_EMUL], [test x$build_pcm_mmap_emul = xyes])
dnl Defines for plug plugin
if test "$build_pcm_rate" = "yes"; then
@@ -606,9 +607,9 @@ for p in $ctl_plugins; do
done
done
-AM_CONDITIONAL(BUILD_CTL_PLUGIN, test x$build_ctl_plugin = xyes)
-AM_CONDITIONAL(BUILD_CTL_PLUGIN_SHM, test x$build_ctl_shm = xyes)
-AM_CONDITIONAL(BUILD_CTL_PLUGIN_EXT, test x$build_ctl_ext = xyes)
+AM_CONDITIONAL([BUILD_CTL_PLUGIN], [test x$build_ctl_plugin = xyes])
+AM_CONDITIONAL([BUILD_CTL_PLUGIN_SHM], [test x$build_ctl_shm = xyes])
+AM_CONDITIONAL([BUILD_CTL_PLUGIN_EXT], [test x$build_ctl_ext = xyes])
dnl Create ctl plugin symbol list for static library
rm -f "$srcdir"/src/control/ctl_symbols_list.c
--
1.8.0.1

View File

@ -1,53 +0,0 @@
From 1b428e7719fdec1b5e3206b8e55a86c4891d1849 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 7 Dec 2012 09:28:06 +0100
Subject: [PATCH 42/43] mixer: Don't build simple_abst when no libdl is
available
Check BUILD_MODULES conditional not to compile simple_abst.c.
Also return -ENXIO to caller statically in that case.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/mixer/Makefile.am | 6 +++++-
src/mixer/mixer_simple.h | 10 ++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/src/mixer/Makefile.am b/src/mixer/Makefile.am
index bb466ed..c0749a4 100644
--- a/src/mixer/Makefile.am
+++ b/src/mixer/Makefile.am
@@ -1,6 +1,10 @@
EXTRA_LTLIBRARIES=libmixer.la
-libmixer_la_SOURCES = bag.c mixer.c simple.c simple_none.c simple_abst.c
+libmixer_la_SOURCES = bag.c mixer.c simple.c simple_none.c
+
+if BUILD_MODULES
+libmixer_la_SOURCES += simple_abst.c
+endif
noinst_HEADERS = mixer_local.h mixer_simple.h
diff --git a/src/mixer/mixer_simple.h b/src/mixer/mixer_simple.h
index e88b007..116eebd 100644
--- a/src/mixer/mixer_simple.h
+++ b/src/mixer/mixer_simple.h
@@ -28,4 +28,14 @@
snd1_mixer_simple_basic_register
int snd_mixer_simple_none_register(snd_mixer_t *mixer, struct snd_mixer_selem_regopt *options, snd_mixer_class_t **classp);
+
+#ifdef HAVE_LIBDL
int snd_mixer_simple_basic_register(snd_mixer_t *mixer, struct snd_mixer_selem_regopt *options, snd_mixer_class_t **classp);
+#else
+static inline int snd_mixer_simple_basic_register(snd_mixer_t *mixer,
+ struct snd_mixer_selem_regopt *options,
+ snd_mixer_class_t **classp)
+{
+ return -ENXIO;
+}
+#endif
--
1.8.0.1

View File

@ -1,55 +0,0 @@
From 72bbf96e1fa0be63892343b331fac42414fdc8da Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 13 Dec 2012 09:55:44 +0100
Subject: [PATCH 43/43] Fix endian check in local.h
SNDRV_LITTLE_ENDIAN and SNDRV_BIG_ENDIAN checks have been removed from
sound/asound.h during UAPI header move, and this resulted in a wrong
detected endian.
Move together with the similar check for SND_*_ENDIAN at the earlier
place in local.h.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/local.h | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/include/local.h b/include/local.h
index 268970a..53cb647 100644
--- a/include/local.h
+++ b/include/local.h
@@ -44,6 +44,16 @@
#define RTLD_NOW 0
#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define SND_LITTLE_ENDIAN
+#define SNDRV_LITTLE_ENDIAN
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define SND_BIG_ENDIAN
+#define SNDRV_BIG_ENDIAN
+#else
+#error "Unsupported endian..."
+#endif
+
#define _snd_config_iterator list_head
#define _snd_interval snd_interval
#define _snd_pcm_info snd_pcm_info
@@ -168,13 +178,6 @@
#include "seq_midi_event.h"
#include "list.h"
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define SND_LITTLE_ENDIAN
-#endif
-#if __BYTE_ORDER == __BIG_ENDIAN
-#define SND_BIG_ENDIAN
-#endif
-
struct _snd_async_handler {
enum {
SND_ASYNC_HANDLER_GENERIC,
--
1.8.0.1

View File

@ -1,36 +0,0 @@
From b11911dddf2fd58e24c808da26105cb1e1bce722 Mon Sep 17 00:00:00 2001
From: Olivier Blin <dev@blino.org>
Date: Sat, 15 Dec 2012 01:58:59 +0100
Subject: [PATCH 44/50] configure: do not detect incorrect cross-compiler
On Ubuntu 11.04, configuring with --build=x86_64-unknown-linux-gnu
--host=x86_64-linux-gnu finds a wrong cross-compiler:
checking for cross-compiler... x86_64-x86_64-pc-linux-gnu-gcc
This happens because of a dash vs underscore inconsistency in configure.in:
host=x86_64-pc-linux-gnu
host_cpu=x86_64
host_os=linux-gnu
which ${host_cpu}-${host_os}-gcc >/dev/null 2>&1 && echo ${host_cpu}-${host-os}-gcc
This bug has been introduced in the initial --with-host support from
2002, commit eb267ade29c9a49c07b1c33dc9bf7a6790217400
This configure command is about "cross-compiling for i586", where the
system compiler is used, which just -m32 additional options.
The --build value comes from config.guess.
---
configure.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/configure.in
+++ b/configure.in
@@ -31,7 +31,7 @@ then
which ${program_prefix}gcc >/dev/null 2>&1 && CC=${program_prefix}gcc
which ${host_cpu}-${host_os}-gcc >/dev/null 2>&1 \
- && CC=${host_cpu}-${host-os}-gcc
+ && CC=${host_cpu}-${host_os}-gcc
which ${host_cpu}-${host_vendor}-${host_os}-gcc >/dev/null 2>&1 \
&& CC=${host_cpu}-${host_vendor}-${host_os}-gcc

View File

@ -1,24 +0,0 @@
From 1629e2fbf3dc211eceb37f980e11e5babe1cefe4 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen <tanuk@iki.fi>
Date: Sat, 26 Jan 2013 14:20:20 +0200
Subject: [PATCH 45/50] ucm: Set uc_mgr->ctl to NULL after closing it.
Fixes a double-free bug.
Signed-off-by: Tanu Kaskinen <tanuk@iki.fi>
Acked-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/ucm/main.c | 1 +
1 file changed, 1 insertion(+)
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -145,6 +145,7 @@ static int open_ctl(snd_use_case_mgr_t *
free(uc_mgr->ctl_dev);
uc_mgr->ctl_dev = NULL;
snd_ctl_close(uc_mgr->ctl);
+ uc_mgr->ctl = NULL;
}
err = snd_ctl_open(ctl, ctl_dev, 0);

View File

@ -1,41 +0,0 @@
From 2cfc8b9b44a8e493c41b3d63d5a00b306a18a5ed Mon Sep 17 00:00:00 2001
From: Jerome Forissier <jerome@taodyne.com>
Date: Wed, 30 Jan 2013 16:22:17 +0100
Subject: [PATCH 46/50] snd_pcm_direct_parse_open_conf(): use thread-safe
getgrnam_r()
Fixes a thread safety issue with snd_pcm_open().
Signed-off-by: Jerome Forissier <jerome@taodyne.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_direct.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -1629,13 +1629,20 @@ int snd_pcm_direct_parse_open_conf(snd_c
continue;
}
if (isdigit(*group) == 0) {
- struct group *grp = getgrnam(group);
- if (grp == NULL) {
+ long clen = sysconf(_SC_GETGR_R_SIZE_MAX);
+ size_t len = (clen == -1) ? 1024 : (size_t)clen;
+ struct group grp, *pgrp;
+ char *buffer = (char *)malloc(len);
+ if (buffer == NULL)
+ return -ENOMEM;
+ int st = getgrnam_r(group, &grp, buffer, len, &pgrp);
+ if (st != 0) {
SNDERR("The field ipc_gid must be a valid group (create group %s)", group);
- free(group);
+ free(buffer);
return -EINVAL;
}
- rec->ipc_gid = grp->gr_gid;
+ rec->ipc_gid = pgrp->gr_gid;
+ free(buffer);
} else {
rec->ipc_gid = strtol(group, &endp, 10);
}

View File

@ -1,98 +0,0 @@
From 44c1a623dd1fc9e831616b663bebc54ca98df994 Mon Sep 17 00:00:00 2001
From: Jerome Forissier <jerome@taodyne.com>
Date: Thu, 31 Jan 2013 15:47:23 +0100
Subject: [PATCH 47/50] Add snd_lib_error_set_local() to install a thread-local
error handler.
This is required so we can make other functions reentrant (such as
snd_device_name_hint()).
The default error handling function snd_lib_error_default() now checks
if a local handler exists, and if so, calls it. Otherwise, the previous
behavior is unchanged.
Signed-off-by: Jerome Forissier <jerome@taodyne.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
configure.in | 10 ++++++++++
include/error.h | 6 ++++++
src/error.c | 24 +++++++++++++++++++++++-
3 files changed, 39 insertions(+), 1 deletion(-)
--- a/configure.in
+++ b/configure.in
@@ -281,6 +281,16 @@ else
AC_MSG_RESULT(no)
fi
+dnl Check for __thread
+AC_MSG_CHECKING([for __thread])
+AC_LINK_IFELSE([AC_LANG_PROGRAM([#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 1) || (__GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ < 2))
+#error gcc has this bug: http://gcc.gnu.org/ml/gcc-bugs/2006-09/msg02275.html
+#endif], [static __thread int p = 0])],
+[AC_DEFINE(HAVE___THREAD, 1,
+Define to 1 if compiler supports __thread)
+AC_MSG_RESULT([yes])],
+[AC_MSG_RESULT([no])])
+
dnl Check for librt
AC_MSG_CHECKING(for librt)
AC_ARG_WITH(librt,
--- a/include/error.h
+++ b/include/error.h
@@ -74,5 +74,11 @@ extern int snd_lib_error_set_handler(snd
}
#endif
+typedef void (*snd_local_error_handler_t)(const char *file, int line,
+ const char *func, int err,
+ const char *fmt, va_list arg);
+
+snd_local_error_handler_t snd_lib_error_set_local(snd_local_error_handler_t func);
+
#endif /* __ALSA_ERROR_H */
--- a/src/error.c
+++ b/src/error.c
@@ -60,6 +60,21 @@ const char *snd_strerror(int errnum)
return snd_error_codes[errnum];
}
+#ifdef HAVE___THREAD
+#define TLS_PFX __thread
+#else
+#define TLS_PFX /* NOP */
+#endif
+
+static TLS_PFX snd_local_error_handler_t local_error = NULL;
+
+snd_local_error_handler_t snd_lib_error_set_local(snd_local_error_handler_t func)
+{
+ snd_local_error_handler_t old = local_error;
+ local_error = func;
+ return old;
+}
+
/**
* \brief The default error handler function.
* \param file The filename where the error was hit.
@@ -69,12 +84,19 @@ const char *snd_strerror(int errnum)
* \param fmt The message (including the format characters).
* \param ... Optional arguments.
*
- * Prints the error message including location to \c stderr.
+ * If a local error function has been installed for the current thread by
+ * \ref snd_lib_error_set_local, it is called. Otherwise, prints the error
+ * message including location to \c stderr.
*/
static void snd_lib_error_default(const char *file, int line, const char *function, int err, const char *fmt, ...)
{
va_list arg;
va_start(arg, fmt);
+ if (local_error) {
+ local_error(file, line, function, err, fmt, arg);
+ va_end(arg);
+ return;
+ }
fprintf(stderr, "ALSA lib %s:%i:(%s) ", file, line, function);
vfprintf(stderr, fmt, arg);
if (err)

View File

@ -1,61 +0,0 @@
From 25dbb102810b31c02358904d70d53c960fb0a10e Mon Sep 17 00:00:00 2001
From: Jerome Forissier <jerome@taodyne.com>
Date: Thu, 31 Jan 2013 15:47:24 +0100
Subject: [PATCH 48/50] snd_device_name_hint(): do not change the global error
handler.
This is the first step towards making this function reentrant.
Signed-off-by: Jerome Forissier <jerome@taodyne.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/control/namehint.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
--- a/src/control/namehint.c
+++ b/src/control/namehint.c
@@ -80,7 +80,8 @@ static void zero_handler(const char *fil
int line ATTRIBUTE_UNUSED,
const char *function ATTRIBUTE_UNUSED,
int err ATTRIBUTE_UNUSED,
- const char *fmt ATTRIBUTE_UNUSED, ...)
+ const char *fmt ATTRIBUTE_UNUSED,
+ va_list arg ATTRIBUTE_UNUSED)
{
}
@@ -212,7 +213,7 @@ static int try_config(struct hint_list *
const char *base,
const char *name)
{
- snd_lib_error_handler_t eh;
+ snd_local_error_handler_t eh;
snd_config_t *res = NULL, *cfg, *cfg1, *n;
snd_config_iterator_t i, next;
char *buf, *buf1 = NULL, *buf2;
@@ -239,10 +240,9 @@ static int try_config(struct hint_list *
sprintf(buf, "%s:CARD=%s", name, snd_ctl_card_info_get_id(list->info));
else
strcpy(buf, name);
- eh = snd_lib_error;
- snd_lib_error_set_handler(&zero_handler);
+ eh = snd_lib_error_set_local(&zero_handler);
err = snd_config_search_definition(snd_config, base, buf, &res);
- snd_lib_error_set_handler(eh);
+ snd_lib_error_set_local(eh);
if (err < 0)
goto __skip_add;
cleanup_res = 1;
@@ -337,10 +337,9 @@ static int try_config(struct hint_list *
goto __ok;
/* find, if all parameters have a default, */
/* otherwise filter this definition */
- eh = snd_lib_error;
- snd_lib_error_set_handler(&zero_handler);
+ eh = snd_lib_error_set_local(&zero_handler);
err = snd_config_search_alias_hooks(snd_config, base, buf, &res);
- snd_lib_error_set_handler(eh);
+ snd_lib_error_set_local(eh);
if (err < 0)
goto __cleanup;
if (snd_config_search(res, "@args", &cfg) >= 0) {

View File

@ -1,197 +0,0 @@
From f49b2dc522a2564315c76d075203b15a39941e8a Mon Sep 17 00:00:00 2001
From: Jerome Forissier <jerome@taodyne.com>
Date: Thu, 31 Jan 2013 15:47:25 +0100
Subject: [PATCH 49/50] snd_device_name_hint(): do not use global snd_config.
This commit and its parent make the function reentrant.
Signed-off-by: Jerome Forissier <jerome@taodyne.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/control/namehint.c | 52 ++++++++++++++++++++++++++++---------------------
1 file changed, 30 insertions(+), 22 deletions(-)
--- a/src/control/namehint.c
+++ b/src/control/namehint.c
@@ -209,7 +209,8 @@ static char *get_dev_name(struct hint_li
#define BUF_SIZE 128
#endif
-static int try_config(struct hint_list *list,
+static int try_config(snd_config_t *config,
+ struct hint_list *list,
const char *base,
const char *name)
{
@@ -229,7 +230,7 @@ static int try_config(struct hint_list *
return -ENOMEM;
sprintf(buf, "%s.%s", base, name);
/* look for redirection */
- if (snd_config_search(snd_config, buf, &cfg) >= 0 &&
+ if (snd_config_search(config, buf, &cfg) >= 0 &&
snd_config_get_string(cfg, &str) >= 0 &&
((strncmp(base, str, strlen(base)) == 0 &&
str[strlen(base)] == '.') || strchr(str, '.') == NULL))
@@ -241,7 +242,7 @@ static int try_config(struct hint_list *
else
strcpy(buf, name);
eh = snd_lib_error_set_local(&zero_handler);
- err = snd_config_search_definition(snd_config, base, buf, &res);
+ err = snd_config_search_definition(config, base, buf, &res);
snd_lib_error_set_local(eh);
if (err < 0)
goto __skip_add;
@@ -338,7 +339,7 @@ static int try_config(struct hint_list *
/* find, if all parameters have a default, */
/* otherwise filter this definition */
eh = snd_lib_error_set_local(&zero_handler);
- err = snd_config_search_alias_hooks(snd_config, base, buf, &res);
+ err = snd_config_search_alias_hooks(config, base, buf, &res);
snd_lib_error_set_local(eh);
if (err < 0)
goto __cleanup;
@@ -405,7 +406,7 @@ static const next_devices_t next_devices
};
#endif
-static int add_card(struct hint_list *list, int card)
+static int add_card(snd_config_t *config, struct hint_list *list, int card)
{
int err, ok;
snd_config_t *conf, *n;
@@ -417,7 +418,7 @@ static int add_card(struct hint_list *li
snd_ctl_card_info_alloca(&info);
list->info = info;
- err = snd_config_search(snd_config, list->siface, &conf);
+ err = snd_config_search(config, list->siface, &conf);
if (err < 0)
return err;
sprintf(ctl_name, "hw:%i", card);
@@ -448,7 +449,7 @@ static int add_card(struct hint_list *li
ok = 0;
for (device = 0; err >= 0 && device <= max_device; device++) {
list->device = device;
- err = try_config(list, list->siface, str);
+ err = try_config(config, list, list->siface, str);
if (err < 0)
break;
ok++;
@@ -463,7 +464,7 @@ static int add_card(struct hint_list *li
if (err < 0) {
list->card = card;
list->device = -1;
- err = try_config(list, list->siface, str);
+ err = try_config(config, list, list->siface, str);
}
if (err == -ENOMEM)
goto __error;
@@ -492,14 +493,14 @@ static int get_card_name(struct hint_lis
return 0;
}
-static int add_software_devices(struct hint_list *list)
+static int add_software_devices(snd_config_t *config, struct hint_list *list)
{
int err;
snd_config_t *conf, *n;
snd_config_iterator_t i, next;
const char *str;
- err = snd_config_search(snd_config, list->siface, &conf);
+ err = snd_config_search(config, list->siface, &conf);
if (err < 0)
return err;
snd_config_for_each(i, next, conf) {
@@ -508,7 +509,7 @@ static int add_software_devices(struct h
continue;
list->card = -1;
list->device = -1;
- err = try_config(list, list->siface, str);
+ err = try_config(config, list, list->siface, str);
if (err == -ENOMEM)
return -ENOMEM;
}
@@ -546,13 +547,14 @@ int snd_device_name_hint(int card, const
struct hint_list list;
char ehints[24];
const char *str;
- snd_config_t *conf;
+ snd_config_t *conf, *local_config = NULL;
+ snd_config_update_t *local_config_update = NULL;
snd_config_iterator_t i, next;
int err;
if (hints == NULL)
return -EINVAL;
- err = snd_config_update();
+ err = snd_config_update_r(&local_config, &local_config_update, NULL);
if (err < 0)
return err;
list.list = NULL;
@@ -572,18 +574,21 @@ int snd_device_name_hint(int card, const
list.iface = SND_CTL_ELEM_IFACE_HWDEP;
else if (strcmp(iface, "ctl") == 0)
list.iface = SND_CTL_ELEM_IFACE_MIXER;
- else
- return -EINVAL;
+ else {
+ err = -EINVAL;
+ goto __error;
+ }
+
list.show_all = 0;
list.cardname = NULL;
- if (snd_config_search(snd_config, "defaults.namehint.showall", &conf) >= 0)
+ if (snd_config_search(local_config, "defaults.namehint.showall", &conf) >= 0)
list.show_all = snd_config_get_bool(conf) > 0;
if (card >= 0) {
err = get_card_name(&list, card);
if (err >= 0)
- err = add_card(&list, card);
+ err = add_card(local_config, &list, card);
} else {
- add_software_devices(&list);
+ add_software_devices(local_config, &list);
err = snd_card_next(&card);
if (err < 0)
goto __error;
@@ -591,7 +596,7 @@ int snd_device_name_hint(int card, const
err = get_card_name(&list, card);
if (err < 0)
goto __error;
- err = add_card(&list, card);
+ err = add_card(local_config, &list, card);
if (err < 0)
goto __error;
err = snd_card_next(&card);
@@ -600,7 +605,7 @@ int snd_device_name_hint(int card, const
}
}
sprintf(ehints, "namehint.%s", list.siface);
- err = snd_config_search(snd_config, ehints, &conf);
+ err = snd_config_search(local_config, ehints, &conf);
if (err >= 0) {
snd_config_for_each(i, next, conf) {
if (snd_config_get_string(snd_config_iterator_entry(i),
@@ -617,7 +622,6 @@ int snd_device_name_hint(int card, const
snd_device_name_free_hint((void **)list.list);
if (list.cardname)
free(list.cardname);
- return err;
} else {
err = hint_list_add(&list, NULL, NULL);
if (err < 0)
@@ -626,7 +630,11 @@ int snd_device_name_hint(int card, const
if (list.cardname)
free(list.cardname);
}
- return 0;
+ if (local_config)
+ snd_config_delete(local_config);
+ if (local_config_update)
+ snd_config_update_free(local_config_update);
+ return err;
}
/**

View File

@ -1,27 +0,0 @@
From 7f2b2c8c1650a1883b48abfcdb455138943854f9 Mon Sep 17 00:00:00 2001
From: Allan Wirth <allan@allanwirth.com>
Date: Thu, 31 Jan 2013 13:55:33 -0500
Subject: [PATCH 50/50] conf: Fix a memory access violation resulting from
improper error propogation
Fixes an issue where a variable is used undeclared, which can cause seg
faults on some systems if the configuration file is not formatted
properly.
Signed-off-by: Allan Wirth <allan@allanwirth.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/conf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/src/conf.c
+++ b/src/conf.c
@@ -3530,7 +3530,7 @@ int snd_config_hook_load(snd_config_t *r
if (err < 0)
goto _err;
}
- } else if (config_file_open(root, fi[idx].name) < 0)
+ } else if ((err = config_file_open(root, fi[idx].name)) < 0)
goto _err;
}
*dst = NULL;

View File

@ -1,35 +0,0 @@
From 3e7dc283ed2d3ed2341f0657811c588f4dbcba6d Mon Sep 17 00:00:00 2001
From: David Henningsson <david.henningsson@canonical.com>
Date: Tue, 12 Feb 2013 10:06:11 +0100
Subject: [PATCH 51/54] Add sys/types.h to include list
This is needed by snd_pcm_format_silence* functions which
return u_int*_t. It was discovered while trying to compile ALSA
programs with eglibc 2.17.
Credits to Richard Shaw, Gary Buhrmaster, Matthieu Baerts and
Adam Conrad for this fix.
BugLink: https://bugs.launchpad.net/bugs/1109298
BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=885306
Signed-off-by: David Henningsson <david.henningsson@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/asoundlib-head.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/asoundlib-head.h b/include/asoundlib-head.h
index 20c8a68..6edbab0 100644
--- a/include/asoundlib-head.h
+++ b/include/asoundlib-head.h
@@ -31,6 +31,7 @@
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/types.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
--
1.8.1.4

View File

@ -1,88 +0,0 @@
From 8c6da54073b2c966d9a4e137ba4d521eac92816f Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 12 Oct 2012 12:22:53 +0200
Subject: [PATCH 52/54] control: Simplify using snd_config_get_bool()
snd_config_get_bool() was improved to parse also ASCII strings now,
so we don't have to open-code the boolean parser in
src/control/setup.c any longer.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/control/setup.c | 37 ++++++-------------------------------
1 file changed, 6 insertions(+), 31 deletions(-)
diff --git a/src/control/setup.c b/src/control/setup.c
index eecda45..bd3599d 100644
--- a/src/control/setup.c
+++ b/src/control/setup.c
@@ -400,7 +400,6 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da
{
snd_config_t *conf;
snd_config_iterator_t i, next;
- char *tmp;
int iface = SND_CTL_ELEM_IFACE_MIXER;
const char *name = NULL;
long index = 0;
@@ -464,33 +463,17 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da
continue;
}
if (strcmp(id, "lock") == 0) {
- if ((err = snd_config_get_ascii(n, &tmp)) < 0) {
- SNDERR("field %s has an invalid type", id);
- goto _err;
- }
- err = snd_config_get_bool_ascii(tmp);
- if (err < 0) {
- SNDERR("field %s is not a boolean", id);
- free(tmp);
+ err = snd_config_get_bool(n);
+ if (err < 0)
goto _err;
- }
lock = err;
- free(tmp);
continue;
}
if (strcmp(id, "preserve") == 0) {
- if ((err = snd_config_get_ascii(n, &tmp)) < 0) {
- SNDERR("field %s has an invalid type", id);
- goto _err;
- }
- err = snd_config_get_bool_ascii(tmp);
- if (err < 0) {
- SNDERR("field %s is not a boolean", id);
- free(tmp);
+ err = snd_config_get_bool(n);
+ if (err < 0)
goto _err;
- }
preserve = err;
- free(tmp);
continue;
}
if (strcmp(id, "value") == 0) {
@@ -502,18 +485,10 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da
continue;
}
if (strcmp(id, "optional") == 0) {
- if ((err = snd_config_get_ascii(n, &tmp)) < 0) {
- SNDERR("field %s has an invalid type", id);
- goto _err;
- }
- err = snd_config_get_bool_ascii(tmp);
- if (err < 0) {
- SNDERR("field %s is not a boolean", id);
- free(tmp);
+ err = snd_config_get_bool(n);
+ if (err < 0)
goto _err;
- }
optional = err;
- free(tmp);
continue;
}
SNDERR("Unknown field %s", id);
--
1.8.1.4

View File

@ -1,124 +0,0 @@
From f5f45589f81c46d4ca4cbbe089441a0f7ac5e197 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 11 Feb 2013 12:28:45 +0100
Subject: [PATCH 53/54] Add workaround for conflicting IEC958 controls for
HD-audio
When both an SPDIF and an HDMI output are present on HD-audio, both
try to access IEC958 controls with index=0 although one of them must
be wrong. For avoiding this conflict, the recent kernel code (3.9 and
3.8 stable) moves the IEC958 controls of an SPDIF with index=16 once
when the conflict happens.
In this patch, the corresponding support is added in alsa-lib side.
The new "skip_rest" boolean flag is added to the hooked element
definition which indicates that the rest of element array will be
ignored once when this element is present and evaluated. With this
new flag, the HD-audio config takes index=16 primarily, then take
index=0 as fallback.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/conf/cards/HDA-Intel.conf | 16 ++++++++++++++++
src/control/setup.c | 19 ++++++++++++++++---
2 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/src/conf/cards/HDA-Intel.conf b/src/conf/cards/HDA-Intel.conf
index d4f2667..3957c12 100644
--- a/src/conf/cards/HDA-Intel.conf
+++ b/src/conf/cards/HDA-Intel.conf
@@ -113,6 +113,22 @@ HDA-Intel.pcm.iec958.0 {
hook_args [
{
name "IEC958 Playback Default"
+ index 16
+ optional true
+ lock true
+ preserve true
+ value [ $AES0 $AES1 $AES2 $AES3 ]
+ }
+ {
+ name "IEC958 Playback Switch"
+ index 16
+ optional true
+ value true
+ # if this element is present, skip the rest
+ skip_rest true
+ }
+ {
+ name "IEC958 Playback Default"
lock true
preserve true
value [ $AES0 $AES1 $AES2 $AES3 ]
diff --git a/src/control/setup.c b/src/control/setup.c
index bd3599d..f23bf2c 100644
--- a/src/control/setup.c
+++ b/src/control/setup.c
@@ -396,7 +396,7 @@ static int snd_config_get_ctl_elem_value(snd_config_t *conf,
return 0;
}
-static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_data)
+static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_data, int *quit)
{
snd_config_t *conf;
snd_config_iterator_t i, next;
@@ -408,6 +408,7 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da
int lock = 0;
int preserve = 0;
int optional = 0;
+ int skip_rest = 0;
snd_config_t *value = NULL, *mask = NULL;
snd_sctl_elem_t *elem = NULL;
int err;
@@ -491,6 +492,13 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da
optional = err;
continue;
}
+ if (strcmp(id, "skip_rest") == 0) {
+ err = snd_config_get_bool(n);
+ if (err < 0)
+ goto _err;
+ skip_rest = err;
+ continue;
+ }
SNDERR("Unknown field %s", id);
return -EINVAL;
}
@@ -539,6 +547,9 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da
if (! optional)
SNDERR("Cannot obtain info for CTL elem (%s,'%s',%li,%li,%li): %s", snd_ctl_elem_iface_name(iface), name, index, device, subdevice, snd_strerror(err));
goto _err;
+ } else {
+ if (skip_rest)
+ *quit = 1;
}
snd_ctl_elem_value_set_id(elem->val, elem->id);
snd_ctl_elem_value_set_id(elem->old, elem->id);
@@ -594,7 +605,7 @@ int snd_sctl_build(snd_sctl_t **sctl, snd_ctl_t *handle, snd_config_t *conf, snd
{
snd_sctl_t *h;
snd_config_iterator_t i, next;
- int err;
+ int err, quit = 0;
assert(sctl);
assert(handle);
@@ -614,11 +625,13 @@ int snd_sctl_build(snd_sctl_t **sctl, snd_ctl_t *handle, snd_config_t *conf, snd
INIT_LIST_HEAD(&h->elems);
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
- err = add_elem(h, n, private_data);
+ err = add_elem(h, n, private_data, &quit);
if (err < 0) {
free_elems(h);
return err;
}
+ if (quit)
+ break;
}
*sctl = h;
return 0;
--
1.8.1.4

View File

@ -1,28 +0,0 @@
From 28493d9d693b1387ed38a849b2d256b34baba2b4 Mon Sep 17 00:00:00 2001
From: Sander Jansen <s.jansen@gmail.com>
Date: Mon, 25 Feb 2013 10:41:40 -0600
Subject: [PATCH 54/54] snd_mixer_poll_descriptors_revents should loop over
pollfd
Signed-off-by: Sander Jansen <s.jansen@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/mixer/mixer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c
index 85d843f..8deceac 100644
--- a/src/mixer/mixer.c
+++ b/src/mixer/mixer.c
@@ -743,7 +743,7 @@ int snd_mixer_poll_descriptors_revents(snd_mixer_t *mixer, struct pollfd *pfds,
if (nfds == 0)
return -EINVAL;
res = 0;
- for (idx = 0; idx < nfds; idx++)
+ for (idx = 0; idx < nfds; idx++, pfds++)
res |= pfds->revents & (POLLIN|POLLERR|POLLNVAL);
*revents = res;
return 0;
--
1.8.1.4

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8c9f8161603cc3db640619650401292c3e110da63429ab6938aac763319f6e7d
size 883076

3
alsa-lib-1.0.27.tar.bz2 Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:947caa14cf53c614d0a206fe9f5964de6ee9617f9007e8fceffd6b3cfd89bc5d
size 898132

View File

@ -1,3 +1,29 @@
-------------------------------------------------------------------
Fri Apr 12 15:26:38 CEST 2013 - tiwai@suse.de
- Updated to version 1.0.27:
including all previous fixes; all 00*-* patches dropped
-------------------------------------------------------------------
Tue Apr 9 15:04:10 CEST 2013 - tiwai@suse.de
- Backport upstream fixes:
0058-control-pcm-implement-snd_ctl_abort-and-snd_pcm_abor.patch
0059-all-places-doxygen-cleanups.patch
0060-pcm-direct-plugins-do-more-safe-IPC-semaphore-handli.patch
- Fix segfault with openal-soft (bnc#814250):
0061-Clean-up-dlobj-cache-only-when-no-user-is-present.patch
0062-Optimize-NULL-check-in-snd_dlobj_cache_put.patch
-------------------------------------------------------------------
Fri Apr 5 12:42:57 CEST 2013 - tiwai@suse.de
- Backport upstream fix patches:
0055-pcm-fix-and-optimize-snd_pcm_areas_copy-function.patch
0056-USB-audio-Add-HP-Digital-Stereo-Headset-to-SPDIF-bla.patch
0057-pcm-fix-typo-should-be-SND_PCM_STATE_PREPARED.patch
- Fix typos in comments in joystick script (bnc#805765)
-------------------------------------------------------------------
Mon Mar 11 11:08:30 CET 2013 - tiwai@suse.de

111
alsa.spec
View File

@ -20,7 +20,7 @@ Name: alsa
BuildRequires: doxygen
BuildRequires: libtool
BuildRequires: pkg-config
%define package_version 1.0.26
%define package_version 1.0.27
Requires: alsa-utils
Recommends: alsa-plugins alsa-oss
PreReq: %insserv_prereq %fillup_prereq
@ -32,7 +32,7 @@ Obsoletes: alsa-64bit
Summary: Advanced Linux Sound Architecture
License: LGPL-2.1+
Group: System/Libraries
Version: 1.0.26
Version: 1.0.27
Release: 0
Source: ftp://ftp.alsa-project.org/pub/lib/alsa-lib-%{package_version}.tar.bz2
Source2: baselibs.conf
@ -53,60 +53,6 @@ Source34: alsa-init.sh
Source40: 50-alsa.conf
Source41: install-snd-module
# Patch: alsa-lib-git-fixes.diff
Patch1: 0001-Implement-the-channel-mapping-API.patch
Patch2: 0002-Implement-get_chmap-set_chmap-for-PCM-plug-route-and.patch
Patch3: 0003-Implement-get_chmap-set_chmap-for-PCM-extplug-ioplug.patch
Patch4: 0004-Add-test-chmap-program.patch
Patch5: 0005-Cache-the-chmap-operation-errors.patch
Patch6: 0006-Define-channel-map-position-enum-in-pcm.h.patch
Patch7: 0007-Follow-channel-position-definitions-to-mixer-channel.patch
Patch8: 0008-Add-SND_CHMAP_NA-and-bit-flag-definitions.patch
Patch9: 0009-PCM-Introduce-snd_pcm_chmap_t-and-snd_pcm_chmap_quer.patch
Patch10: 0010-PCM-Implement-snd_pcm_query_chmaps_from_hw.patch
Patch11: 0011-Fix-duplicated-channel-entry-in-test-chmap.c.patch
Patch12: 0012-PCM-Fix-prefix-for-snd_pcm_chmap_type-enum-members.patch
Patch13: 0013-PCM-Add-string-conversion-helper-functions-for-chmap.patch
Patch14: 0014-PCM-Add-SND_CHMAP_API_VERSION-definition.patch
Patch15: 0015-PCM-Add-snd_pcm_chmap_long_name.patch
Patch16: 0016-PCM-Add-query_chmaps-support-to-multi-plugin.patch
Patch17: 0017-PCM-Add-chmap-options-to-hw-and-null-plugins.patch
Patch18: 0018-PCM-Add-the-missing-query_chmaps-for-route-plugin.patch
Patch19: 0019-Add-chmap-override-definitions-for-Emu10k1-Audigy-an.patch
Patch20: 0020-PCM-Use-compounds-for-overriding-enhancing-chmaps.patch
Patch21: 0021-conf-Add-chmap-definitions-to-TRIDENT-and-SI7018-con.patch
Patch22: 0022-test-chmap-Fix-wrong-malloc-size.patch
Patch23: 0023-PCM-Define-MONO-and-other-channel-map-positions.patch
Patch24: 0024-PCM-Fix-the-conversion-from-string-to-chmap-position.patch
Patch25: 0025-PCM-A-few-doxygen-fixes-for-chmap-stuff.patch
Patch26: 0026-PCM-Fill-SND_CHMAP_NA-to-silent-channels-in-route-pl.patch
Patch27: 0027-PCM-Fix-infinite-loop-in-htimestamp-of-dmix-dsnoop-a.patch
Patch28: 0028-test-add-audio_time.patch
Patch30: 0030-PCM-Fix-the-invalid-snd_pcm_close-calls-in-rate-plug.patch
Patch31: 0031-pcm-support-for-audio-timestamps.patch
Patch32: 0032-pcm-fix-64-bit-SNDRV_PCM_IOCTL_STATUS-ABI-breakage.patch
Patch33: 0033-PCM-Fix-memory-leak-for-pcm-empty-and-asym-plugins.patch
Patch34: 0034-Reduce-compilation-warnings.patch
Patch35: 0035-PCM-Avoid-busy-loop-in-snd_pcm_write_areas-with-rate.patch
Patch36: 0036-Merge-kernel-uapi-sound-asound.h-and-asequencer.h.patch
Patch37: 0037-PCM-Add-more-chmap-definitions-for-UAC2.patch
Patch38: 0038-PCM-shut-up-a-compile-unused-parameter-compile-warni.patch
Patch39: 0039-Add-workaround-for-conflicting-snd_seq_event_t-defin.patch
Patch40: 0040-PCM-Fix-conflict-of-_snd_pcm_hw_params-definitions.patch
Patch41: 0041-configure-Quite-AM_CONDITIONAL-arguments.patch
Patch42: 0042-mixer-Don-t-build-simple_abst-when-no-libdl-is-avail.patch
Patch43: 0043-Fix-endian-check-in-local.h.patch
Patch44: 0044-configure-do-not-detect-incorrect-cross-compiler.patch
Patch45: 0045-ucm-Set-uc_mgr-ctl-to-NULL-after-closing-it.patch
Patch46: 0046-snd_pcm_direct_parse_open_conf-use-thread-safe-getgr.patch
Patch47: 0047-Add-snd_lib_error_set_local-to-install-a-thread-loca.patch
Patch48: 0048-snd_device_name_hint-do-not-change-the-global-error-.patch
Patch49: 0049-snd_device_name_hint-do-not-use-global-snd_config.patch
Patch50: 0050-conf-Fix-a-memory-access-violation-resulting-from-im.patch
Patch51: 0051-Add-sys-types.h-to-include-list.patch
Patch52: 0052-control-Simplify-using-snd_config_get_bool.patch
Patch53: 0053-Add-workaround-for-conflicting-IEC958-controls-for-H.patch
Patch54: 0054-snd_mixer_poll_descriptors_revents-should-loop-over-.patch
#
Patch99: alsa-lib-doxygen-avoid-crash-for-11.3.diff
Url: http://www.alsa-project.org/
BuildRoot: %{_tmppath}/%{name}-%{version}-build
@ -157,59 +103,6 @@ Architecture.
%prep
%setup -q -n alsa-lib-%{package_version}
# %patch -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%patch26 -p1
%patch27 -p1
%patch28 -p1
%patch30 -p1
%patch31 -p1
%patch32 -p1
%patch33 -p1
%patch34 -p1
%patch35 -p1
%patch36 -p1
%patch37 -p1
%patch38 -p1
%patch39 -p1
%patch40 -p1
%patch41 -p1
%patch42 -p1
%patch43 -p1
%patch44 -p1
%patch45 -p1
%patch46 -p1
%patch47 -p1
%patch48 -p1
%patch49 -p1
%patch50 -p1
%patch51 -p1
%patch52 -p1
%patch53 -p1
%patch54 -p1
%if %suse_version == 1130
%patch99 -p1
%endif

View File

@ -40,7 +40,7 @@ function start () {
if [ -n "$jsmod" -a "$jsmod" != off ]; then
/sbin/modprobe $jsmod >/dev/null 2>&1
fi
# load joystick moulde
# load joystick module
eval jsdev=\$JOYSTICK_MODULE_$js
eval jsdev_opts=\$JOYSTICK_MODULE_OPTION_$js
if [ -n "$jsdev" -a "$jsdev" != off ]; then
@ -56,7 +56,7 @@ function stop () {
if [ -n "$jsmod" -a "$jsmod" != off ]; then
/sbin/modprobe -r $jsmod
fi
# remove joystick moulde
# remove joystick module
eval jsdev=\$JOYSTICK_MODULE_$js
if [ -n "$jsdev" -a "$jsdev" != off ]; then
/sbin/modprobe -r $jsdev