Accepting request 163761 from home:tiwai:branches:multimedia:libs

- Updated to version 1.0.27:
  including all previous fixes; all 00*-* patches dropped

OBS-URL: https://build.opensuse.org/request/show/163761
OBS-URL: https://build.opensuse.org/package/show/multimedia:libs/alsa?expand=0&rev=129
This commit is contained in:
Takashi Iwai 2013-04-12 14:23:52 +00:00 committed by Git OBS Bridge
parent 5ed110dffb
commit 251bda0afd
65 changed files with 11 additions and 10476 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,74 +0,0 @@
From 009193a34575fe439211b9a711e56322afc7460e Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Wed, 20 Mar 2013 20:37:50 +0100
Subject: [PATCH] pcm: fix and optimize snd_pcm_areas_copy function
The memcpy() function in snd_pcm_area_copy() should not be called
with the overlapped areas. Alex discovered - using own LD_PRELOAD checked
for memcpy() input - that the memcpy() is called with src == dst.
For some special plugin combos (rate+softvol+hw for example), the same
areas with same offsets can be asked to be copied (softvol). The collapse
check uses own areas created on heap, causing dst_area == src_area &&
dst_offset == src_offset check bypassed.
Two fixes are in this patch:
- use assert to check the memcpy() input for future triggers
- bypass the snd_pcm_area_copy() call for collapsed identical areas
Reported-by: Alexander Kruppa <akruppa@gmail.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/pcm/pcm.c | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index 5053a7b..05737d9 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -2711,6 +2711,8 @@ int snd_pcm_area_copy(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes_t
dst_area->step == (unsigned int) width) {
size_t bytes = samples * width / 8;
samples -= bytes * 8 / width;
+ assert(src < dst || src >= dst + bytes);
+ assert(dst < src || dst >= src + bytes);
memcpy(dst, src, bytes);
if (samples == 0)
return 0;
@@ -2845,17 +2847,21 @@ int snd_pcm_areas_copy(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_
break;
}
if (chns > 1 && chns * width == step) {
- /* Collapse the areas */
- snd_pcm_channel_area_t s, d;
- s.addr = src_start->addr;
- s.first = src_start->first;
- s.step = width;
- d.addr = dst_start->addr;
- d.first = dst_start->first;
- d.step = width;
- snd_pcm_area_copy(&d, dst_offset * chns,
- &s, src_offset * chns,
- frames * chns, format);
+ if (src_offset != dst_offset ||
+ src_start->addr != dst_start->addr ||
+ src_start->first != dst_start->first) {
+ /* Collapse the areas */
+ snd_pcm_channel_area_t s, d;
+ s.addr = src_start->addr;
+ s.first = src_start->first;
+ s.step = width;
+ d.addr = dst_start->addr;
+ d.first = dst_start->first;
+ d.step = width;
+ snd_pcm_area_copy(&d, dst_offset * chns,
+ &s, src_offset * chns,
+ frames * chns, format);
+ }
channels -= chns;
} else {
snd_pcm_area_copy(dst_start, dst_offset,
--
1.8.1.4

View File

@ -1,30 +0,0 @@
From 02d9f316a590102aecaaad7055862ffc42258d7a Mon Sep 17 00:00:00 2001
From: David Henningsson <david.henningsson@canonical.com>
Date: Mon, 25 Mar 2013 06:41:57 +0100
Subject: [PATCH] USB-audio: Add "HP Digital Stereo Headset" to SPDIF blacklist
Yet another headset without digital I/O.
Signed-off-by: David Henningsson <david.henningsson@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/conf/cards/USB-Audio.conf | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/conf/cards/USB-Audio.conf b/src/conf/cards/USB-Audio.conf
index 177a7af..71c2971 100644
--- a/src/conf/cards/USB-Audio.conf
+++ b/src/conf/cards/USB-Audio.conf
@@ -39,7 +39,8 @@ USB-Audio.pcm.iec958_device {
# The below don't have digital in/out, so prevent them from being opened.
"Blue Snowball" 999
- "Logitech Speaker Lapdesk N700" 999
+ "HP Digital Stereo Headset" 999
+ "Logitech Speaker Lapdesk N700" 999
"Logitech USB Headset" 999
"Logitech Wireless Headset" 999
"Plantronics GameCom 780" 999
--
1.8.1.4

View File

@ -1,27 +0,0 @@
From 730c833dd8b76cc280246be698980422cb1bce47 Mon Sep 17 00:00:00 2001
From: Daniel Svensson <dsvensson@gmail.com>
Date: Thu, 4 Apr 2013 23:47:19 +0200
Subject: [PATCH] pcm: fix typo, should be SND_PCM_STATE_PREPARED.
Signed-off-by: Daniel Svensson <dsvensson@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index 05737d9..0868dd5 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -162,7 +162,7 @@ The PCM device has accepted communication parameters and it is waiting
for #snd_pcm_prepare() call to prepare the hardware for
selected operation (playback or capture).
-\par SND_PCM_STATE_PREPARE
+\par SND_PCM_STATE_PREPARED
The PCM device is prepared for operation. Application can use
#snd_pcm_start() call, write or read data to start
the operation.
--
1.8.1.4

View File

@ -1,143 +0,0 @@
From e23fb2c4de29b24c28f0c609521faa28d948a05b Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 8 Apr 2013 13:28:03 +0200
Subject: [PATCH] control, pcm: implement snd_ctl_abort() and snd_pcm_abort()
functions
Upon an interrupt, it is necessary to abort the wait loops with the EINTR
error code. Introduce snd_*_abort() functions to handle this case.
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/control.h | 2 ++
include/pcm.h | 3 +++
src/control/control.c | 2 +-
src/control/control_local.h | 2 ++
src/control/hcontrol.c | 2 +-
src/pcm/pcm.c | 8 ++++++--
src/pcm/pcm_local.h | 2 ++
7 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/include/control.h b/include/control.h
index e840835..27fe2ac 100644
--- a/include/control.h
+++ b/include/control.h
@@ -234,6 +234,7 @@ int snd_ctl_open_lconf(snd_ctl_t **ctl, const char *name, int mode, snd_config_t
int snd_ctl_open_fallback(snd_ctl_t **ctl, snd_config_t *root, const char *name, const char *orig_name, int mode);
int snd_ctl_close(snd_ctl_t *ctl);
int snd_ctl_nonblock(snd_ctl_t *ctl, int nonblock);
+static inline int snd_ctl_abort(snd_ctl_t *ctl) { return snd_ctl_nonblock(ctl, 2); }
int snd_async_add_ctl_handler(snd_async_handler_t **handler, snd_ctl_t *ctl,
snd_async_callback_t callback, void *private_data);
snd_ctl_t *snd_async_handler_get_ctl(snd_async_handler_t *handler);
@@ -531,6 +532,7 @@ int snd_hctl_open(snd_hctl_t **hctl, const char *name, int mode);
int snd_hctl_open_ctl(snd_hctl_t **hctlp, snd_ctl_t *ctl);
int snd_hctl_close(snd_hctl_t *hctl);
int snd_hctl_nonblock(snd_hctl_t *hctl, int nonblock);
+static inline int snd_hctl_abort(snd_hctl_t *hctl) { return snd_hctl_nonblock(hctl, 2); }
int snd_hctl_poll_descriptors_count(snd_hctl_t *hctl);
int snd_hctl_poll_descriptors(snd_hctl_t *hctl, struct pollfd *pfds, unsigned int space);
int snd_hctl_poll_descriptors_revents(snd_hctl_t *ctl, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
diff --git a/include/pcm.h b/include/pcm.h
index 2235678..549d629 100644
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -314,6 +314,8 @@ typedef long snd_pcm_sframes_t;
#define SND_PCM_NONBLOCK 0x00000001
/** Async notification (flag for open mode) \hideinitializer */
#define SND_PCM_ASYNC 0x00000002
+/** In an abort state (internal, not allowed for open) */
+#define SND_PCM_ABORT 0x00008000
/** Disable automatic (but not forced!) rate resamplinig */
#define SND_PCM_NO_AUTO_RESAMPLE 0x00010000
/** Disable automatic (but not forced!) channel conversion */
@@ -437,6 +439,7 @@ int snd_pcm_poll_descriptors_count(snd_pcm_t *pcm);
int snd_pcm_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space);
int snd_pcm_poll_descriptors_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock);
+static inline int snd_pcm_abort(snd_pcm_t *pcm) { return snd_pcm_nonblock(pcm, 2); }
int snd_async_add_pcm_handler(snd_async_handler_t **handler, snd_pcm_t *pcm,
snd_async_callback_t callback, void *private_data);
snd_pcm_t *snd_async_handler_get_pcm(snd_async_handler_t *handler);
diff --git a/src/control/control.c b/src/control/control.c
index 66277ef..5687ce1 100644
--- a/src/control/control.c
+++ b/src/control/control.c
@@ -103,7 +103,7 @@ int snd_ctl_close(snd_ctl_t *ctl)
/**
* \brief set nonblock mode
* \param ctl CTL handle
- * \param nonblock 0 = block, 1 = nonblock mode
+ * \param nonblock 0 = block, 1 = nonblock mode, 2 = abort
* \return 0 on success otherwise a negative error code
*/
int snd_ctl_nonblock(snd_ctl_t *ctl, int nonblock)
diff --git a/src/control/control_local.h b/src/control/control_local.h
index 49150d8..9594ae5 100644
--- a/src/control/control_local.h
+++ b/src/control/control_local.h
@@ -98,3 +98,5 @@ int _snd_ctl_poll_descriptor(snd_ctl_t *ctl);
int snd_ctl_hw_open(snd_ctl_t **handle, const char *name, int card, int mode);
int snd_ctl_shm_open(snd_ctl_t **handlep, const char *name, const char *sockname, const char *sname, int mode);
int snd_ctl_async(snd_ctl_t *ctl, int sig, pid_t pid);
+
+#define CTLINABORT(x) ((x)->nonblock == 2)
diff --git a/src/control/hcontrol.c b/src/control/hcontrol.c
index ee1d907..7645c57 100644
--- a/src/control/hcontrol.c
+++ b/src/control/hcontrol.c
@@ -696,7 +696,7 @@ int snd_hctl_wait(snd_hctl_t *hctl, int timeout)
pollio = 0;
err_poll = poll(pfd, npfds, timeout);
if (err_poll < 0) {
- if (errno == EINTR)
+ if (errno == EINTR && !CTLINABORT(hctl->ctl))
continue;
return -errno;
}
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index 0868dd5..38febb9 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -716,7 +716,7 @@ int snd_pcm_close(snd_pcm_t *pcm)
/**
* \brief set nonblock mode
* \param pcm PCM handle
- * \param nonblock 0 = block, 1 = nonblock mode
+ * \param nonblock 0 = block, 1 = nonblock mode, 2 = abort
* \return 0 on success otherwise a negative error code
*/
int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock)
@@ -725,6 +725,10 @@ int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock)
assert(pcm);
if ((err = pcm->ops->nonblock(pcm->op_arg, nonblock)) < 0)
return err;
+ if (nonblock == 2) {
+ pcm->mode |= SND_PCM_ABORT;
+ return 0;
+ }
if (nonblock)
pcm->mode |= SND_PCM_NONBLOCK;
else {
@@ -2401,7 +2405,7 @@ int snd_pcm_wait_nocheck(snd_pcm_t *pcm, int timeout)
do {
err_poll = poll(pfd, npfds, timeout);
if (err_poll < 0) {
- if (errno == EINTR)
+ if (errno == EINTR && !PCMINABORT(pcm))
continue;
return -errno;
}
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
index 63b9036..e1c0baa 100644
--- a/src/pcm/pcm_local.h
+++ b/src/pcm/pcm_local.h
@@ -1006,3 +1006,5 @@ static inline void sw_set_period_event(snd_pcm_sw_params_t *params, int val)
{
params->reserved[sizeof(params->reserved) / sizeof(params->reserved[0]) - 1] = val;
}
+
+#define PCMINABORT(pcm) (((pcm)->mode & SND_PCM_ABORT) != 0)
--
1.8.2.1

View File

@ -1,567 +0,0 @@
From b6eb0f9bfddb836fcc366d81f07ba62e46c95ccf Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 8 Apr 2013 16:42:24 +0200
Subject: [PATCH] all places: doxygen cleanups
I see no errors with these changes using doxygen 1.8.1.1 .
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
doc/index.doxygen | 2 +-
include/control_external.h | 7 +++-
include/error.h | 1 +
include/mixer.h | 2 +-
include/pcm.h | 82 +++++++++++++++++++++++-----------------------
include/pcm_extplug.h | 5 +++
include/pcm_ioplug.h | 5 +++
include/seq_event.h | 10 ++++--
include/use-case.h | 81 +++++++++++++++++++++++----------------------
src/conf.c | 2 ++
src/control/control.c | 4 +--
src/control/ctlparse.c | 1 +
src/error.c | 7 ++++
src/mixer/mixer.c | 2 +-
src/ucm/main.c | 36 ++++++++++----------
15 files changed, 141 insertions(+), 106 deletions(-)
diff --git a/doc/index.doxygen b/doc/index.doxygen
index f76cc10..45aa68a 100644
--- a/doc/index.doxygen
+++ b/doc/index.doxygen
@@ -1,4 +1,4 @@
-/*! \page Index Preamble and License
+/*! \mainpage Index Preamble and License
\author Jaroslav Kysela <perex@perex.cz>
\author Abramo Bagnara <abramo@alsa-project.org>
diff --git a/include/control_external.h b/include/control_external.h
index e98f4d6..12958e7 100644
--- a/include/control_external.h
+++ b/include/control_external.h
@@ -60,6 +60,11 @@ typedef struct snd_ctl_ext snd_ctl_ext_t;
typedef struct snd_ctl_ext_callback snd_ctl_ext_callback_t;
/** Key to access a control pointer */
typedef unsigned long snd_ctl_ext_key_t;
+#ifdef DOC_HIDDEN
+/* redefine typedef's for stupid doxygen */
+typedef snd_ctl_ext snd_ctl_ext_t;
+typedef snd_ctl_ext_callback snd_ctl_ext_callback_t;
+#endif
/** Callback to handle TLV commands. */
typedef int (snd_ctl_ext_tlv_rw_t)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, int op_flag, unsigned int numid,
unsigned int *tlv, unsigned int tlv_size);
@@ -138,7 +143,7 @@ struct snd_ctl_ext {
} tlv;
};
-/** Callback table of ext */
+/** Callback table of ext. */
struct snd_ctl_ext_callback {
/**
* close the control handle; optional
diff --git a/include/error.h b/include/error.h
index 256cd5f..38ee070 100644
--- a/include/error.h
+++ b/include/error.h
@@ -74,6 +74,7 @@ extern int snd_lib_error_set_handler(snd_lib_error_handler_t handler);
}
#endif
+/** Local error handler function type */
typedef void (*snd_local_error_handler_t)(const char *file, int line,
const char *func, int err,
const char *fmt, va_list arg);
diff --git a/include/mixer.h b/include/mixer.h
index 58256a6..066d978 100644
--- a/include/mixer.h
+++ b/include/mixer.h
@@ -154,7 +154,7 @@ void *snd_mixer_class_get_private(const snd_mixer_class_t *class_);
snd_mixer_compare_t snd_mixer_class_get_compare(const snd_mixer_class_t *class_);
int snd_mixer_class_set_event(snd_mixer_class_t *class_, snd_mixer_event_t event);
int snd_mixer_class_set_private(snd_mixer_class_t *class_, void *private_data);
-int snd_mixer_class_set_private_free(snd_mixer_class_t *class_, void (*private_free)(snd_mixer_class_t *class_));
+int snd_mixer_class_set_private_free(snd_mixer_class_t *class_, void (*private_free)(snd_mixer_class_t *));
int snd_mixer_class_set_compare(snd_mixer_class_t *class_, snd_mixer_compare_t compare);
/**
diff --git a/include/pcm.h b/include/pcm.h
index 549d629..d94ba90 100644
--- a/include/pcm.h
+++ b/include/pcm.h
@@ -491,43 +491,43 @@ 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 */
- 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_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_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_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 */
+ 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_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_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,
};
@@ -541,14 +541,14 @@ enum snd_pcm_chmap_position {
/** the channel map header */
typedef struct snd_pcm_chmap {
- unsigned int channels; /** number of channels */
- unsigned int pos[0]; /** channel position array */
+ 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; /** channel map type */
- snd_pcm_chmap_t map; /** available channel map */
+ enum snd_pcm_chmap_type type; /**< channel map type */
+ snd_pcm_chmap_t map; /**< available channel map */
} snd_pcm_chmap_query_t;
diff --git a/include/pcm_extplug.h b/include/pcm_extplug.h
index 4eb10c7..884f322 100644
--- a/include/pcm_extplug.h
+++ b/include/pcm_extplug.h
@@ -49,6 +49,11 @@ enum {
typedef struct snd_pcm_extplug snd_pcm_extplug_t;
/** Callback table of extplug */
typedef struct snd_pcm_extplug_callback snd_pcm_extplug_callback_t;
+#ifdef DOC_HIDDEN
+/* redefine typedefs for stupid doxygen */
+typedef snd_pcm_extplug snd_pcm_extplug_t;
+typedef snd_pcm_extplug_callback snd_pcm_extplug_callback_t;
+#endif
/*
* Protocol version
diff --git a/include/pcm_ioplug.h b/include/pcm_ioplug.h
index 25202fd..e529e6a 100644
--- a/include/pcm_ioplug.h
+++ b/include/pcm_ioplug.h
@@ -54,6 +54,11 @@ enum {
typedef struct snd_pcm_ioplug snd_pcm_ioplug_t;
/** Callback table of ioplug */
typedef struct snd_pcm_ioplug_callback snd_pcm_ioplug_callback_t;
+#ifdef DOC_HIDDEN
+/* redefine typedefs for stupid doxygen */
+typedef snd_pcm_ioplug snd_pcm_ioplug_t;
+typedef snd_pcm_ioplug_callback snd_pcm_ioplug_callback_t;
+#endif
/*
* bit flags for additional conditions
diff --git a/include/seq_event.h b/include/seq_event.h
index 583f1d0..6bd0de3 100644
--- a/include/seq_event.h
+++ b/include/seq_event.h
@@ -254,10 +254,16 @@ typedef struct snd_seq_ev_raw32 {
} snd_seq_ev_raw32_t;
/** external stored data */
-typedef struct snd_seq_ev_ext {
+struct snd_seq_ev_ext {
unsigned int len; /**< length of data */
void *ptr; /**< pointer to data (note: can be 64-bit) */
-} __attribute__((packed)) snd_seq_ev_ext_t;
+} __attribute__((packed));
+/** external stored data */
+typedef struct snd_seq_ev_ext snd_seq_ev_ext_t;
+#ifdef DOC_HIDDEN
+/* redefine typedef for stupid doxygen */
+typedef snd_seq_ev_ext snd_seq_ev_ext_t;
+#endif
/** Result events */
typedef struct snd_seq_result {
diff --git a/include/use-case.h b/include/use-case.h
index c37c842..defd4ea 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -49,7 +49,8 @@ extern "C" {
* \{
*/
-/**
+/*! \page Usecase ALSA Use Case Interface
+ *
* ALSA Use Case Interface
*
* The use case manager works by configuring the sound card ALSA kcontrols to
@@ -96,15 +97,15 @@ extern "C" {
* case verb will configure the audio hardware for HiFi Music playback
* and capture.
*/
-#define SND_USE_CASE_VERB_INACTIVE "Inactive"
-#define SND_USE_CASE_VERB_HIFI "HiFi"
-#define SND_USE_CASE_VERB_HIFI_LOW_POWER "HiFi Low Power"
-#define SND_USE_CASE_VERB_VOICE "Voice"
-#define SND_USE_CASE_VERB_VOICE_LOW_POWER "Voice Low Power"
-#define SND_USE_CASE_VERB_VOICECALL "Voice Call"
-#define SND_USE_CASE_VERB_IP_VOICECALL "Voice Call IP"
-#define SND_USE_CASE_VERB_ANALOG_RADIO "FM Analog Radio"
-#define SND_USE_CASE_VERB_DIGITAL_RADIO "FM Digital Radio"
+#define SND_USE_CASE_VERB_INACTIVE "Inactive" /**< Inactive Verb */
+#define SND_USE_CASE_VERB_HIFI "HiFi" /**< HiFi Verb */
+#define SND_USE_CASE_VERB_HIFI_LOW_POWER "HiFi Low Power" /**< HiFi Low Power Verb */
+#define SND_USE_CASE_VERB_VOICE "Voice" /**< Voice Verb */
+#define SND_USE_CASE_VERB_VOICE_LOW_POWER "Voice Low Power" /**< Voice Low Power Verb */
+#define SND_USE_CASE_VERB_VOICECALL "Voice Call" /**< Voice Call Verb */
+#define SND_USE_CASE_VERB_IP_VOICECALL "Voice Call IP" /**< Voice Call IP Verb */
+#define SND_USE_CASE_VERB_ANALOG_RADIO "FM Analog Radio" /**< FM Analog Radio Verb */
+#define SND_USE_CASE_VERB_DIGITAL_RADIO "FM Digital Radio" /**< FM Digital Radio Verb */
/* add new verbs to end of list */
@@ -114,16 +115,16 @@ extern "C" {
* Physical system devices the render and capture audio. Devices can be OR'ed
* together to support audio on simultaneous devices.
*/
-#define SND_USE_CASE_DEV_NONE "None"
-#define SND_USE_CASE_DEV_SPEAKER "Speaker"
-#define SND_USE_CASE_DEV_LINE "Line"
-#define SND_USE_CASE_DEV_HEADPHONES "Headphones"
-#define SND_USE_CASE_DEV_HEADSET "Headset"
-#define SND_USE_CASE_DEV_HANDSET "Handset"
-#define SND_USE_CASE_DEV_BLUETOOTH "Bluetooth"
-#define SND_USE_CASE_DEV_EARPIECE "Earpiece"
-#define SND_USE_CASE_DEV_SPDIF "SPDIF"
-#define SND_USE_CASE_DEV_HDMI "HDMI"
+#define SND_USE_CASE_DEV_NONE "None" /**< None Device */
+#define SND_USE_CASE_DEV_SPEAKER "Speaker" /**< Speaker Device */
+#define SND_USE_CASE_DEV_LINE "Line" /**< Line Device */
+#define SND_USE_CASE_DEV_HEADPHONES "Headphones" /**< Headphones Device */
+#define SND_USE_CASE_DEV_HEADSET "Headset" /**< Headset Device */
+#define SND_USE_CASE_DEV_HANDSET "Handset" /**< Handset Device */
+#define SND_USE_CASE_DEV_BLUETOOTH "Bluetooth" /**< Bluetooth Device */
+#define SND_USE_CASE_DEV_EARPIECE "Earpiece" /**< Earpiece Device */
+#define SND_USE_CASE_DEV_SPDIF "SPDIF" /**< SPDIF Device */
+#define SND_USE_CASE_DEV_HDMI "HDMI" /**< HDMI Device */
/* add new devices to end of list */
@@ -145,12 +146,12 @@ extern "C" {
* 3. Call snd_use_case_get("PlaybackPCM") to get ALSA PCM sink name for
* ringtone pcm data.
*/
-#define SND_USE_CASE_MOD_CAPTURE_VOICE "Capture Voice"
-#define SND_USE_CASE_MOD_CAPTURE_MUSIC "Capture Music"
-#define SND_USE_CASE_MOD_PLAY_MUSIC "Play Music"
-#define SND_USE_CASE_MOD_PLAY_VOICE "Play Voice"
-#define SND_USE_CASE_MOD_PLAY_TONE "Play Tone"
-#define SND_USE_CASE_MOD_ECHO_REF "Echo Reference"
+#define SND_USE_CASE_MOD_CAPTURE_VOICE "Capture Voice" /**< Capture Voice Modifier */
+#define SND_USE_CASE_MOD_CAPTURE_MUSIC "Capture Music" /**< Capture Music Modifier */
+#define SND_USE_CASE_MOD_PLAY_MUSIC "Play Music" /**< Play Music Modifier */
+#define SND_USE_CASE_MOD_PLAY_VOICE "Play Voice" /**< Play Voice Modifier */
+#define SND_USE_CASE_MOD_PLAY_TONE "Play Tone" /**< Play Tone Modifier */
+#define SND_USE_CASE_MOD_ECHO_REF "Echo Reference" /**< Echo Reference Modifier */
/* add new modifiers to end of list */
@@ -162,9 +163,9 @@ extern "C" {
* audio driver in order to lower power consumption.
*
*/
-#define SND_USE_CASE_TQ_MUSIC "Music"
-#define SND_USE_CASE_TQ_VOICE "Voice"
-#define SND_USE_CASE_TQ_TONES "Tones"
+#define SND_USE_CASE_TQ_MUSIC "Music" /**< Music Tone Quality */
+#define SND_USE_CASE_TQ_VOICE "Voice" /**< Voice Tone Quality */
+#define SND_USE_CASE_TQ_TONES "Tones" /**< Tones Tone Quality */
/** use case container */
typedef struct snd_use_case_mgr snd_use_case_mgr_t;
@@ -197,16 +198,16 @@ int snd_use_case_free_list(const char *list[], int items);
* (in pair cardname+comment)
* _verbs - get verb list
* (in pair verb+comment)
- * _devices[/<verb>] - get list of supported devices
+ * _devices[/{verb}] - get list of supported devices
* (in pair device+comment)
- * _modifiers[/<verb>]- get list of supported modifiers
+ * _modifiers[/{verb}]- get list of supported modifiers
* (in pair modifier+comment)
- * TQ[/<verb>] - get list of TQ identifiers
+ * TQ[/{verb}] - get list of TQ identifiers
* _enadevs - get list of enabled devices
* _enamods - get list of enabled modifiers
*
- * _supporteddevs/<modifier>|<device>[/<verb>] - list of supported devices
- * _conflictingdevs/<modifier>|<device>[/<verb>] - list of conflicting devices
+ * _supporteddevs/{modifier}|{device}[/{verb}] - list of supported devices
+ * _conflictingdevs/{modifier}|{device}[/{verb}] - list of conflicting devices
* Note that at most one of the supported/conflicting devs lists has
* any entries, and when neither is present, all devices are supported.
*
@@ -230,8 +231,8 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
* NULL - return current card
* _verb - return current verb
*
- * [=]<NAME>[/[<modifier>|</device>][/<verb>]]
- * - value identifier <NAME>
+ * [=]{NAME}[/[{modifier}|{/device}][/{verb}]]
+ * - value identifier {NAME}
* - Search starts at given modifier or device if any,
* else at a verb
* - Search starts at given verb if any,
@@ -281,8 +282,8 @@ int snd_use_case_get(snd_use_case_mgr_t *uc_mgr,
* \return Zero if success, otherwise a negative error code
*
* Known identifiers:
- * _devstatus/<device> - return status for given device
- * _modstatus/<modifier> - return status for given modifier
+ * _devstatus/{device} - return status for given device
+ * _modstatus/{modifier} - return status for given modifier
*/
int snd_use_case_geti(snd_use_case_mgr_t *uc_mgr,
const char *identifier,
@@ -299,13 +300,13 @@ int snd_use_case_geti(snd_use_case_mgr_t *uc_mgr,
* _verb - set current verb = value
* _enadev - enable given device = value
* _disdev - disable given device = value
- * _swdev/<old_device> - new_device = value
+ * _swdev/{old_device} - new_device = value
* - disable old_device and then enable new_device
* - if old_device is not enabled just return
* - check transmit sequence firstly
* _enamod - enable given modifier = value
* _dismod - disable given modifier = value
- * _swmod/<old_modifier> - new_modifier = value
+ * _swmod/{old_modifier} - new_modifier = value
* - disable old_modifier and then enable new_modifier
* - if old_modifier is not enabled just return
* - check transmit sequence firstly
diff --git a/src/conf.c b/src/conf.c
index 4ba5863..bfed1c4 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -3505,11 +3505,13 @@ int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t
struct dirent **namelist;
int n;
+#ifndef DOC_HIDDEN
#ifdef _GNU_SOURCE
#define SORTFUNC versionsort
#else
#define SORTFUNC alphasort
#endif
+#endif
n = scandir(fi[idx].name, &namelist, config_filename_filter, SORTFUNC);
if (n > 0) {
int j;
diff --git a/src/control/control.c b/src/control/control.c
index 5687ce1..d66ed75 100644
--- a/src/control/control.c
+++ b/src/control/control.c
@@ -2323,8 +2323,8 @@ void snd_ctl_elem_value_copy(snd_ctl_elem_value_t *dst, const snd_ctl_elem_value
/**
* \brief compare one #snd_ctl_elem_value_t to another
- * \param dst pointer to destination
- * \param src pointer to source
+ * \param left pointer to first value
+ * \param right pointer to second value
* \return 0 on match, less than or greater than otherwise, see memcmp
*/
int snd_ctl_elem_value_compare(snd_ctl_elem_value_t *left, const snd_ctl_elem_value_t *right)
diff --git a/src/control/ctlparse.c b/src/control/ctlparse.c
index b0c4ef3..c442c44 100644
--- a/src/control/ctlparse.c
+++ b/src/control/ctlparse.c
@@ -297,6 +297,7 @@ static int get_ctl_enum_item_index(snd_ctl_t *handle,
/**
* \brief parse ASCII string as CTL element value
+ * \param handle CTL handle
* \param dst destination CTL element value
* \param info CTL element info structure
* \param value source ASCII string
diff --git a/src/error.c b/src/error.c
index 85cea5e..4566783 100644
--- a/src/error.c
+++ b/src/error.c
@@ -60,14 +60,21 @@ const char *snd_strerror(int errnum)
return snd_error_codes[errnum];
}
+#ifndef DOC_HIDDEN
#ifdef HAVE___THREAD
#define TLS_PFX __thread
#else
#define TLS_PFX /* NOP */
#endif
+#endif
static TLS_PFX snd_local_error_handler_t local_error = NULL;
+/**
+ * \brief Install local error handler
+ * \param func The local error handler function
+ * \retval Previous local error handler function
+ */
snd_local_error_handler_t snd_lib_error_set_local(snd_local_error_handler_t func)
{
snd_local_error_handler_t old = local_error;
diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c
index 8deceac..56e023d 100644
--- a/src/mixer/mixer.c
+++ b/src/mixer/mixer.c
@@ -1062,7 +1062,7 @@ int snd_mixer_class_set_private(snd_mixer_class_t *obj, void *private_data)
* \param private_free Mixer class private data free callback
* \return zero if success, otherwise a negative error code
*/
-int snd_mixer_class_set_private_free(snd_mixer_class_t *obj, void (*private_free)(snd_mixer_class_t *class))
+int snd_mixer_class_set_private_free(snd_mixer_class_t *obj, void (*private_free)(snd_mixer_class_t *))
{
assert(obj);
obj->private_free = private_free;
diff --git a/src/ucm/main.c b/src/ucm/main.c
index d8b8ada..d38b7fa 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -702,42 +702,42 @@ static int set_device(snd_use_case_mgr_t *uc_mgr,
* \param card_name name of card to open
* \return zero on success, otherwise a negative error code
*/
-int snd_use_case_mgr_open(snd_use_case_mgr_t **mgr,
+int snd_use_case_mgr_open(snd_use_case_mgr_t **uc_mgr,
const char *card_name)
{
- snd_use_case_mgr_t *uc_mgr;
+ snd_use_case_mgr_t *mgr;
int err;
/* create a new UCM */
- uc_mgr = calloc(1, sizeof(snd_use_case_mgr_t));
- if (uc_mgr == NULL)
+ mgr = calloc(1, sizeof(snd_use_case_mgr_t));
+ if (mgr == NULL)
return -ENOMEM;
- INIT_LIST_HEAD(&uc_mgr->verb_list);
- INIT_LIST_HEAD(&uc_mgr->default_list);
- INIT_LIST_HEAD(&uc_mgr->value_list);
- INIT_LIST_HEAD(&uc_mgr->active_modifiers);
- INIT_LIST_HEAD(&uc_mgr->active_devices);
- pthread_mutex_init(&uc_mgr->mutex, NULL);
-
- uc_mgr->card_name = strdup(card_name);
- if (uc_mgr->card_name == NULL) {
- free(uc_mgr);
+ INIT_LIST_HEAD(&mgr->verb_list);
+ INIT_LIST_HEAD(&mgr->default_list);
+ INIT_LIST_HEAD(&mgr->value_list);
+ INIT_LIST_HEAD(&mgr->active_modifiers);
+ INIT_LIST_HEAD(&mgr->active_devices);
+ pthread_mutex_init(&mgr->mutex, NULL);
+
+ mgr->card_name = strdup(card_name);
+ if (mgr->card_name == NULL) {
+ free(mgr);
return -ENOMEM;
}
/* get info on use_cases and verify against card */
- err = import_master_config(uc_mgr);
+ err = import_master_config(mgr);
if (err < 0) {
uc_error("error: failed to import %s use case configuration %d",
card_name, err);
goto err;
}
- *mgr = uc_mgr;
+ *uc_mgr = mgr;
return 0;
err:
- uc_mgr_free(uc_mgr);
+ uc_mgr_free(mgr);
return err;
}
@@ -973,10 +973,12 @@ static int get_conflicting_device_list(snd_use_case_mgr_t *uc_mgr,
return get_supcon_device_list(uc_mgr, list, name, DEVLIST_CONFLICTING);
}
+#ifndef DOC_HIDDEN
struct myvalue {
struct list_head list;
char *value;
};
+#endif
static int add_values(struct list_head *list,
const char *identifier,
--
1.8.2.1

View File

@ -1,117 +0,0 @@
From a6813c2d0e2fa4586122d23748033a8bab206b8b Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Tue, 9 Apr 2013 14:31:20 +0200
Subject: [PATCH] pcm: direct plugins: do more safe IPC semaphore handling
As reported dead-lock, do local lock counting and invoke abort() when
the lock counts do not match at close() time.
Reported-by: <mateen abdulmateen.shaikh@gmail.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/pcm/pcm_direct.h | 18 ++++++++++++++++--
src/pcm/pcm_dmix.c | 4 ++--
src/pcm/pcm_dshare.c | 9 +++++----
src/pcm/pcm_dsnoop.c | 9 +++++----
4 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
index 1c35dcb..70c2c6a 100644
--- a/src/pcm/pcm_direct.h
+++ b/src/pcm/pcm_direct.h
@@ -122,6 +122,7 @@ struct snd_pcm_direct {
mode_t ipc_perm; /* IPC socket permissions */
int ipc_gid; /* IPC socket gid */
int semid; /* IPC global semaphore identification */
+ int locked[DIRECT_IPC_SEMS]; /* local lock counter */
int shmid; /* IPC global shared memory identification */
snd_pcm_direct_share_t *shmptr; /* pointer to shared memory area */
snd_pcm_t *spcm; /* slave PCM handle */
@@ -257,13 +258,26 @@ static inline int snd_pcm_direct_semaphore_discard(snd_pcm_direct_t *dmix)
static inline int snd_pcm_direct_semaphore_down(snd_pcm_direct_t *dmix, int sem_num)
{
struct sembuf op[2] = { { sem_num, 0, 0 }, { sem_num, 1, SEM_UNDO } };
- return semop(dmix->semid, op, 2);
+ int err = semop(dmix->semid, op, 2);
+ if (err == 0) dmix->locked[sem_num]++;
+ return err;
}
static inline int snd_pcm_direct_semaphore_up(snd_pcm_direct_t *dmix, int sem_num)
{
struct sembuf op = { sem_num, -1, SEM_UNDO | IPC_NOWAIT };
- return semop(dmix->semid, &op, 1);
+ int err = semop(dmix->semid, &op, 1);
+ if (err == 0) dmix->locked[sem_num]--;
+ return err;
+}
+
+static inline int snd_pcm_direct_semaphore_final(snd_pcm_direct_t *dmix, int sem_num)
+{
+ if (dmix->locked[sem_num] != 1) {
+ assert(dmix->locked[sem_num] != 1);
+ abort();
+ }
+ return snd_pcm_direct_semaphore_up(dmix, sem_num);
}
int snd_pcm_direct_shm_create_or_connect(snd_pcm_direct_t *dmix);
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
index 16dba14..2bd5d39 100644
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -781,9 +781,9 @@ static int snd_pcm_dmix_close(snd_pcm_t *pcm)
shm_sum_discard(dmix);
if (snd_pcm_direct_shm_discard(dmix)) {
if (snd_pcm_direct_semaphore_discard(dmix))
- snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
+ snd_pcm_direct_semaphore_final(dmix, DIRECT_IPC_SEM_CLIENT);
} else
- snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
+ snd_pcm_direct_semaphore_final(dmix, DIRECT_IPC_SEM_CLIENT);
free(dmix->bindings);
pcm->private_data = NULL;
free(dmix);
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
index 1bdb670..5b32951 100644
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -470,10 +470,11 @@ static int snd_pcm_dshare_close(snd_pcm_t *pcm)
snd_pcm_direct_server_discard(dshare);
if (dshare->client)
snd_pcm_direct_client_discard(dshare);
- if (snd_pcm_direct_shm_discard(dshare))
- snd_pcm_direct_semaphore_discard(dshare);
- else
- snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT);
+ if (snd_pcm_direct_shm_discard(dshare)) {
+ if (snd_pcm_direct_semaphore_discard(dshare))
+ snd_pcm_direct_semaphore_final(dshare, DIRECT_IPC_SEM_CLIENT);
+ } else
+ snd_pcm_direct_semaphore_final(dshare, DIRECT_IPC_SEM_CLIENT);
free(dshare->bindings);
pcm->private_data = NULL;
free(dshare);
diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
index ea07e04..055e4f4 100644
--- a/src/pcm/pcm_dsnoop.c
+++ b/src/pcm/pcm_dsnoop.c
@@ -391,10 +391,11 @@ static int snd_pcm_dsnoop_close(snd_pcm_t *pcm)
snd_pcm_direct_server_discard(dsnoop);
if (dsnoop->client)
snd_pcm_direct_client_discard(dsnoop);
- if (snd_pcm_direct_shm_discard(dsnoop))
- snd_pcm_direct_semaphore_discard(dsnoop);
- else
- snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT);
+ if (snd_pcm_direct_shm_discard(dsnoop)) {
+ if (snd_pcm_direct_semaphore_discard(dsnoop))
+ snd_pcm_direct_semaphore_final(dsnoop, DIRECT_IPC_SEM_CLIENT);
+ } else
+ snd_pcm_direct_semaphore_final(dsnoop, DIRECT_IPC_SEM_CLIENT);
free(dsnoop->bindings);
pcm->private_data = NULL;
free(dsnoop);
--
1.8.2.1

View File

@ -1,56 +0,0 @@
From e79990ac5d09001c8c678feaed057e991ee8379e Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 9 Apr 2013 14:55:46 +0200
Subject: [PATCH] Clean up dlobj cache only when no user is present
Cleaning up the dlobj cache seems crashing some cases when the library
is used from another plugin like openal-soft. A simple workaround is
to do the cleanup only when really no user is left, i.e. after all
close calls.
Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=814250
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/dlmisc.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/src/dlmisc.c b/src/dlmisc.c
index ecbbe8d..585c7f6 100644
--- a/src/dlmisc.c
+++ b/src/dlmisc.c
@@ -295,17 +295,24 @@ void snd_dlobj_cache_cleanup(void)
struct list_head *p, *npos;
struct dlobj_cache *c;
+ /* clean up caches only when really no user is present */
snd_dlobj_lock();
+ list_for_each(p, &pcm_dlobj_list) {
+ c = list_entry(p, struct dlobj_cache, list);
+ if (c->refcnt)
+ goto unlock;
+ }
+
list_for_each_safe(p, npos, &pcm_dlobj_list) {
c = list_entry(p, struct dlobj_cache, list);
- if (c->refcnt == 0) {
- list_del(p);
- snd_dlclose(c->dlobj);
- free((void *)c->name); /* shut up gcc warning */
- free((void *)c->lib); /* shut up gcc warning */
- free(c);
- }
+ list_del(p);
+ snd_dlclose(c->dlobj);
+ free((void *)c->name); /* shut up gcc warning */
+ free((void *)c->lib); /* shut up gcc warning */
+ free(c);
}
+
+ unlock:
snd_dlobj_unlock();
}
#endif
--
1.8.2.1

View File

@ -1,27 +0,0 @@
From 91de1212d0da0e52c64f7392f35e3c129d6bbce5 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 9 Apr 2013 14:58:52 +0200
Subject: [PATCH] Optimize NULL check in snd_dlobj_cache_put()
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/dlmisc.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/dlmisc.c b/src/dlmisc.c
index 585c7f6..3788382 100644
--- a/src/dlmisc.c
+++ b/src/dlmisc.c
@@ -275,6 +275,9 @@ int snd_dlobj_cache_put(void *func)
struct dlobj_cache *c;
unsigned int refcnt;
+ if (!func)
+ return -ENOENT;
+
snd_dlobj_lock();
list_for_each(p, &pcm_dlobj_list) {
c = list_entry(p, struct dlobj_cache, list);
--
1.8.2.1

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,9 @@
-------------------------------------------------------------------
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 Tue Apr 9 15:04:10 CEST 2013 - tiwai@suse.de

127
alsa.spec
View File

@ -20,7 +20,7 @@ Name: alsa
BuildRequires: doxygen BuildRequires: doxygen
BuildRequires: libtool BuildRequires: libtool
BuildRequires: pkg-config BuildRequires: pkg-config
%define package_version 1.0.26 %define package_version 1.0.27
Requires: alsa-utils Requires: alsa-utils
Recommends: alsa-plugins alsa-oss Recommends: alsa-plugins alsa-oss
PreReq: %insserv_prereq %fillup_prereq PreReq: %insserv_prereq %fillup_prereq
@ -32,7 +32,7 @@ Obsoletes: alsa-64bit
Summary: Advanced Linux Sound Architecture Summary: Advanced Linux Sound Architecture
License: LGPL-2.1+ License: LGPL-2.1+
Group: System/Libraries Group: System/Libraries
Version: 1.0.26 Version: 1.0.27
Release: 0 Release: 0
Source: ftp://ftp.alsa-project.org/pub/lib/alsa-lib-%{package_version}.tar.bz2 Source: ftp://ftp.alsa-project.org/pub/lib/alsa-lib-%{package_version}.tar.bz2
Source2: baselibs.conf Source2: baselibs.conf
@ -53,68 +53,6 @@ Source34: alsa-init.sh
Source40: 50-alsa.conf Source40: 50-alsa.conf
Source41: install-snd-module Source41: install-snd-module
# Patch: alsa-lib-git-fixes.diff # 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
Patch55: 0055-pcm-fix-and-optimize-snd_pcm_areas_copy-function.patch
Patch56: 0056-USB-audio-Add-HP-Digital-Stereo-Headset-to-SPDIF-bla.patch
Patch57: 0057-pcm-fix-typo-should-be-SND_PCM_STATE_PREPARED.patch
Patch58: 0058-control-pcm-implement-snd_ctl_abort-and-snd_pcm_abor.patch
Patch59: 0059-all-places-doxygen-cleanups.patch
Patch60: 0060-pcm-direct-plugins-do-more-safe-IPC-semaphore-handli.patch
Patch61: 0061-Clean-up-dlobj-cache-only-when-no-user-is-present.patch
Patch62: 0062-Optimize-NULL-check-in-snd_dlobj_cache_put.patch
#
Patch99: alsa-lib-doxygen-avoid-crash-for-11.3.diff Patch99: alsa-lib-doxygen-avoid-crash-for-11.3.diff
Url: http://www.alsa-project.org/ Url: http://www.alsa-project.org/
BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRoot: %{_tmppath}/%{name}-%{version}-build
@ -165,67 +103,6 @@ Architecture.
%prep %prep
%setup -q -n alsa-lib-%{package_version} %setup -q -n alsa-lib-%{package_version}
# %patch -p1 # %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
%patch55 -p1
%patch56 -p1
%patch57 -p1
%patch58 -p1
%patch59 -p1
%patch60 -p1
%patch61 -p1
%patch62 -p1
%if %suse_version == 1130 %if %suse_version == 1130
%patch99 -p1 %patch99 -p1
%endif %endif