Accepting request 138457 from multimedia:libs
- backport from upstream tree: * lots of patches to support the new chmap API * fix segfault in rate plugin error path * add a couple of test programs * fix inifinte loop in htimestamp of dmix & co (forwarded request 138456 from tiwai) OBS-URL: https://build.opensuse.org/request/show/138457 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/alsa?expand=0&rev=126
This commit is contained in:
commit
28f46132ad
685
0001-Implement-the-channel-mapping-API.patch
Normal file
685
0001-Implement-the-channel-mapping-API.patch
Normal file
@ -0,0 +1,685 @@
|
|||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
150
0002-Implement-get_chmap-set_chmap-for-PCM-plug-route-and.patch
Normal file
150
0002-Implement-get_chmap-set_chmap-for-PCM-plug-route-and.patch
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
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,
|
179
0003-Implement-get_chmap-set_chmap-for-PCM-extplug-ioplug.patch
Normal file
179
0003-Implement-get_chmap-set_chmap-for-PCM-extplug-ioplug.patch
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
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 = {
|
288
0004-Add-test-chmap-program.patch
Normal file
288
0004-Add-test-chmap-program.patch
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
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(¶ms);
|
||||||
|
+ 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;
|
||||||
|
+}
|
188
0005-Cache-the-chmap-operation-errors.patch
Normal file
188
0005-Cache-the-chmap-operation-errors.patch
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
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;
|
56
0006-Define-channel-map-position-enum-in-pcm.h.patch
Normal file
56
0006-Define-channel-map-position-enum-in-pcm.h.patch
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
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);
|
110
0007-Follow-channel-position-definitions-to-mixer-channel.patch
Normal file
110
0007-Follow-channel-position-definitions-to-mixer-channel.patch
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
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)
|
88
0008-Add-SND_CHMAP_NA-and-bit-flag-definitions.patch
Normal file
88
0008-Add-SND_CHMAP_NA-and-bit-flag-definitions.patch
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
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");
|
||||||
|
}
|
587
0009-PCM-Introduce-snd_pcm_chmap_t-and-snd_pcm_chmap_quer.patch
Normal file
587
0009-PCM-Introduce-snd_pcm_chmap_t-and-snd_pcm_chmap_quer.patch
Normal file
@ -0,0 +1,587 @@
|
|||||||
|
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;
|
||||||
|
}
|
207
0010-PCM-Implement-snd_pcm_query_chmaps_from_hw.patch
Normal file
207
0010-PCM-Implement-snd_pcm_query_chmaps_from_hw.patch
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
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)
|
21
0011-Fix-duplicated-channel-entry-in-test-chmap.c.patch
Normal file
21
0011-Fix-duplicated-channel-entry-in-test-chmap.c.patch
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
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",
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
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 */
|
286
0013-PCM-Add-string-conversion-helper-functions-for-chmap.patch
Normal file
286
0013-PCM-Add-string-conversion-helper-functions-for-chmap.patch
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
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;
|
25
0014-PCM-Add-SND_CHMAP_API_VERSION-definition.patch
Normal file
25
0014-PCM-Add-SND_CHMAP_API_VERSION-definition.patch
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
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 */
|
65
0015-PCM-Add-snd_pcm_chmap_long_name.patch
Normal file
65
0015-PCM-Add-snd_pcm_chmap_long_name.patch
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
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;
|
198
0016-PCM-Add-query_chmaps-support-to-multi-plugin.patch
Normal file
198
0016-PCM-Add-query_chmaps-support-to-multi-plugin.patch
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
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,
|
||||||
|
};
|
249
0017-PCM-Add-chmap-options-to-hw-and-null-plugins.patch
Normal file
249
0017-PCM-Add-chmap-options-to-hw-and-null-plugins.patch
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
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);
|
85
0018-PCM-Add-the-missing-query_chmaps-for-route-plugin.patch
Normal file
85
0018-PCM-Add-the-missing-query_chmaps-for-route-plugin.patch
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
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;
|
104
0019-Add-chmap-override-definitions-for-Emu10k1-Audigy-an.patch
Normal file
104
0019-Add-chmap-override-definitions-for-Emu10k1-Audigy-an.patch
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
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
|
438
0020-PCM-Use-compounds-for-overriding-enhancing-chmaps.patch
Normal file
438
0020-PCM-Use-compounds-for-overriding-enhancing-chmaps.patch
Normal file
@ -0,0 +1,438 @@
|
|||||||
|
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;
|
@ -0,0 +1,51 @@
|
|||||||
|
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
|
21
0022-test-chmap-Fix-wrong-malloc-size.patch
Normal file
21
0022-test-chmap-Fix-wrong-malloc-size.patch
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
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;
|
116
0023-PCM-Define-MONO-and-other-channel-map-positions.patch
Normal file
116
0023-PCM-Define-MONO-and-other-channel-map-positions.patch
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
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)
|
@ -0,0 +1,67 @@
|
|||||||
|
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)
|
158
0025-PCM-A-few-doxygen-fixes-for-chmap-stuff.patch
Normal file
158
0025-PCM-A-few-doxygen-fixes-for-chmap-stuff.patch
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
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;
|
@ -0,0 +1,30 @@
|
|||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
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;
|
||||||
|
}
|
287
0028-test-add-audio_time.patch
Normal file
287
0028-test-add-audio_time.patch
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
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;
|
||||||
|
+}
|
@ -0,0 +1,49 @@
|
|||||||
|
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;
|
||||||
|
}
|
@ -1,3 +1,12 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Oct 17 10:05:36 CEST 2012 - tiwai@suse.de
|
||||||
|
|
||||||
|
- backport from upstream tree:
|
||||||
|
* lots of patches to support the new chmap API
|
||||||
|
* fix segfault in rate plugin error path
|
||||||
|
* add a couple of test programs
|
||||||
|
* fix inifinte loop in htimestamp of dmix & co
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Fri Sep 7 15:29:41 CEST 2012 - tiwai@suse.de
|
Fri Sep 7 15:29:41 CEST 2012 - tiwai@suse.de
|
||||||
|
|
||||||
|
59
alsa.spec
59
alsa.spec
@ -53,6 +53,36 @@ 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
|
||||||
|
#
|
||||||
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
|
||||||
@ -103,6 +133,35 @@ 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
|
||||||
%if %suse_version == 1130
|
%if %suse_version == 1130
|
||||||
%patch99 -p1
|
%patch99 -p1
|
||||||
%endif
|
%endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user