Accepting request 163766 from multimedia:libs
- Updated to version 1.0.27: including all previous fixes; all 00*-* patches dropped (forwarded request 163761 from tiwai) OBS-URL: https://build.opensuse.org/request/show/163766 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/alsa?expand=0&rev=134
This commit is contained in:
commit
6514270a4b
@ -1,685 +0,0 @@
|
|||||||
From 3c4a22ea49a881cdbfe2d50eef94b17e38104734 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Wed, 25 Jul 2012 15:05:15 +0200
|
|
||||||
Subject: [PATCH 01/30] Implement the channel mapping API
|
|
||||||
|
|
||||||
Added new channel-mapping API functions.
|
|
||||||
Not all plugins are covered, especially the route, multi and external
|
|
||||||
plugins don't work yet.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/control.h | 7 +
|
|
||||||
include/pcm.h | 12 +++
|
|
||||||
include/sound/asound.h | 25 ++++++
|
|
||||||
src/pcm/pcm.c | 55 ++++++++++++++
|
|
||||||
src/pcm/pcm_adpcm.c | 3
|
|
||||||
src/pcm/pcm_alaw.c | 3
|
|
||||||
src/pcm/pcm_copy.c | 3
|
|
||||||
src/pcm/pcm_direct.c | 18 ++++
|
|
||||||
src/pcm/pcm_direct.h | 10 ++
|
|
||||||
src/pcm/pcm_dmix.c | 3
|
|
||||||
src/pcm/pcm_dshare.c | 2
|
|
||||||
src/pcm/pcm_dsnoop.c | 3
|
|
||||||
src/pcm/pcm_file.c | 3
|
|
||||||
src/pcm/pcm_generic.c | 18 ++++
|
|
||||||
src/pcm/pcm_generic.h | 11 ++
|
|
||||||
src/pcm/pcm_hooks.c | 3
|
|
||||||
src/pcm/pcm_hw.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
src/pcm/pcm_iec958.c | 3
|
|
||||||
src/pcm/pcm_ladspa.c | 3
|
|
||||||
src/pcm/pcm_lfloat.c | 3
|
|
||||||
src/pcm/pcm_linear.c | 3
|
|
||||||
src/pcm/pcm_local.h | 3
|
|
||||||
src/pcm/pcm_meter.c | 3
|
|
||||||
src/pcm/pcm_mmap_emul.c | 3
|
|
||||||
src/pcm/pcm_mulaw.c | 2
|
|
||||||
src/pcm/pcm_rate.c | 3
|
|
||||||
src/pcm/pcm_softvol.c | 3
|
|
||||||
27 files changed, 386 insertions(+)
|
|
||||||
|
|
||||||
--- a/include/control.h
|
|
||||||
+++ b/include/control.h
|
|
||||||
@@ -182,6 +182,13 @@ typedef enum _snd_ctl_event_type {
|
|
||||||
/** Mute state */
|
|
||||||
#define SND_CTL_TLV_DB_GAIN_MUTE -9999999
|
|
||||||
|
|
||||||
+/** TLV type - fixed channel map positions */
|
|
||||||
+#define SND_CTL_TLVT_CHMAP_FIXED 0x00101
|
|
||||||
+/** TLV type - freely swappable channel map positions */
|
|
||||||
+#define SND_CTL_TLVT_CHMAP_VAR 0x00102
|
|
||||||
+/** TLV type - pair-wise swappable channel map positions */
|
|
||||||
+#define SND_CTL_TLVT_CHMAP_PAIRED 0x00103
|
|
||||||
+
|
|
||||||
/** CTL type */
|
|
||||||
typedef enum _snd_ctl_type {
|
|
||||||
/** Kernel level CTL */
|
|
||||||
--- a/include/pcm.h
|
|
||||||
+++ b/include/pcm.h
|
|
||||||
@@ -474,6 +474,18 @@ int snd_pcm_wait(snd_pcm_t *pcm, int tim
|
|
||||||
int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
|
|
||||||
int snd_pcm_unlink(snd_pcm_t *pcm);
|
|
||||||
|
|
||||||
+enum {
|
|
||||||
+ SND_CHMAP_NONE = 0, /** unspecified channel position */
|
|
||||||
+ SND_CHMAP_FIXED, /** fixed channel position */
|
|
||||||
+ SND_CHMAP_VAR, /** freely swappable channel position */
|
|
||||||
+ SND_CHMAP_PAIRED, /** pair-wise swappable channel position */
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+int **snd_pcm_query_chmaps(snd_pcm_t *pcm);
|
|
||||||
+void snd_pcm_free_chmaps(int **maps);
|
|
||||||
+int *snd_pcm_get_chmap(snd_pcm_t *pcm);
|
|
||||||
+int snd_pcm_set_chmap(snd_pcm_t *pcm, const int *map);
|
|
||||||
+
|
|
||||||
//int snd_pcm_mixer_element(snd_pcm_t *pcm, snd_mixer_t *mixer, snd_mixer_elem_t **elem);
|
|
||||||
|
|
||||||
/*
|
|
||||||
--- a/include/sound/asound.h
|
|
||||||
+++ b/include/sound/asound.h
|
|
||||||
@@ -477,6 +477,31 @@ enum {
|
|
||||||
SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
|
|
||||||
};
|
|
||||||
|
|
||||||
+/* channel positions */
|
|
||||||
+enum {
|
|
||||||
+ SNDRV_CHMAP_UNKNOWN = 0,
|
|
||||||
+ SNDRV_CHMAP_FL, /* front left */
|
|
||||||
+ SNDRV_CHMAP_FC, /* front center */
|
|
||||||
+ SNDRV_CHMAP_FR, /* front right */
|
|
||||||
+ SNDRV_CHMAP_FLC, /* front left center */
|
|
||||||
+ SNDRV_CHMAP_FRC, /* front right center */
|
|
||||||
+ SNDRV_CHMAP_RL, /* rear left */
|
|
||||||
+ SNDRV_CHMAP_RC, /* rear center */
|
|
||||||
+ SNDRV_CHMAP_RR, /* rear right */
|
|
||||||
+ SNDRV_CHMAP_RLC, /* rear left center */
|
|
||||||
+ SNDRV_CHMAP_RRC, /* rear right center */
|
|
||||||
+ SNDRV_CHMAP_SL, /* side left */
|
|
||||||
+ SNDRV_CHMAP_SR, /* side right */
|
|
||||||
+ SNDRV_CHMAP_LFE, /* LFE */
|
|
||||||
+ SNDRV_CHMAP_FLW, /* front left wide */
|
|
||||||
+ SNDRV_CHMAP_FRW, /* front right wide */
|
|
||||||
+ SNDRV_CHMAP_FLH, /* front left high */
|
|
||||||
+ SNDRV_CHMAP_FCH, /* front center high */
|
|
||||||
+ SNDRV_CHMAP_FRH, /* front right high */
|
|
||||||
+ SNDRV_CHMAP_TC, /* top center */
|
|
||||||
+ SNDRV_CHMAP_LAST = SNDRV_CHMAP_TC,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
enum {
|
|
||||||
SNDRV_PCM_IOCTL_PVERSION = _IOR('A', 0x00, int),
|
|
||||||
SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct sndrv_pcm_info),
|
|
||||||
--- a/src/pcm/pcm.c
|
|
||||||
+++ b/src/pcm/pcm.c
|
|
||||||
@@ -7302,6 +7302,61 @@ OBSOLETE1(snd_pcm_sw_params_get_silence_
|
|
||||||
|
|
||||||
#endif /* DOC_HIDDEN */
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * \!brief Query the available channel maps
|
|
||||||
+ * \param pcm PCM handle to query
|
|
||||||
+ * \return the NULL-terminated array of integer pointers, each of
|
|
||||||
+ * which contains the channel map. A channel map is represented by an
|
|
||||||
+ * integer array, beginning with the channel map type, followed by the
|
|
||||||
+ * number of channels, and the position of each channel.
|
|
||||||
+ */
|
|
||||||
+int **snd_pcm_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ if (!pcm->ops->query_chmaps)
|
|
||||||
+ return NULL;
|
|
||||||
+ return pcm->ops->query_chmaps(pcm);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * \!brief Release the channel map array allocated via #snd_pcm_query_chmaps
|
|
||||||
+ * \param maps the array pointer to release
|
|
||||||
+ */
|
|
||||||
+void snd_pcm_free_chmaps(int **maps)
|
|
||||||
+{
|
|
||||||
+ int **p;
|
|
||||||
+ if (!maps)
|
|
||||||
+ return;
|
|
||||||
+ for (p = maps; *p; p++)
|
|
||||||
+ free(*p);
|
|
||||||
+ free(maps);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * \!brief Get the current channel map
|
|
||||||
+ * \param pcm PCM instance
|
|
||||||
+ * \return the current channel map, or NULL if error
|
|
||||||
+ */
|
|
||||||
+int *snd_pcm_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ if (!pcm->ops->get_chmap)
|
|
||||||
+ return NULL;
|
|
||||||
+ return pcm->ops->get_chmap(pcm);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * \!brief Configure the current channel map
|
|
||||||
+ * \param pcm PCM instance
|
|
||||||
+ * \param map the channel map to write
|
|
||||||
+ * \return zero if succeeded, or a negative error code
|
|
||||||
+ */
|
|
||||||
+int snd_pcm_set_chmap(snd_pcm_t *pcm, const int *map)
|
|
||||||
+{
|
|
||||||
+ if (!pcm->ops->set_chmap)
|
|
||||||
+ return -ENXIO;
|
|
||||||
+ return pcm->ops->set_chmap(pcm, map);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* basic helpers
|
|
||||||
*/
|
|
||||||
--- a/src/pcm/pcm_adpcm.c
|
|
||||||
+++ b/src/pcm/pcm_adpcm.c
|
|
||||||
@@ -531,6 +531,9 @@ static const snd_pcm_ops_t snd_pcm_adpcm
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_generic_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_generic_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_generic_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
--- a/src/pcm/pcm_alaw.c
|
|
||||||
+++ b/src/pcm/pcm_alaw.c
|
|
||||||
@@ -404,6 +404,9 @@ static const snd_pcm_ops_t snd_pcm_alaw_
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_generic_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_generic_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_generic_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
--- a/src/pcm/pcm_copy.c
|
|
||||||
+++ b/src/pcm/pcm_copy.c
|
|
||||||
@@ -165,6 +165,9 @@ static const snd_pcm_ops_t snd_pcm_copy_
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_generic_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_generic_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_generic_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
--- a/src/pcm/pcm_direct.c
|
|
||||||
+++ b/src/pcm/pcm_direct.c
|
|
||||||
@@ -789,6 +789,24 @@ int snd_pcm_direct_munmap(snd_pcm_t *pcm
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+int **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_direct_t *dmix = pcm->private_data;
|
|
||||||
+ return snd_pcm_query_chmaps(dmix->spcm);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int *snd_pcm_direct_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_direct_t *dmix = pcm->private_data;
|
|
||||||
+ return snd_pcm_get_chmap(dmix->spcm);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const int *map)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_direct_t *dmix = pcm->private_data;
|
|
||||||
+ return snd_pcm_set_chmap(dmix->spcm, map);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int snd_pcm_direct_resume(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
snd_pcm_direct_t *dmix = pcm->private_data;
|
|
||||||
--- a/src/pcm/pcm_direct.h
|
|
||||||
+++ b/src/pcm/pcm_direct.h
|
|
||||||
@@ -235,6 +235,12 @@ struct snd_pcm_direct {
|
|
||||||
snd1_pcm_direct_open_secondary_client
|
|
||||||
#define snd_pcm_direct_parse_open_conf \
|
|
||||||
snd1_pcm_direct_parse_open_conf
|
|
||||||
+#define snd_pcm_direct_query_chmaps \
|
|
||||||
+ snd1_pcm_direct_query_chmaps
|
|
||||||
+#define snd_pcm_direct_get_chmap \
|
|
||||||
+ snd1_pcm_direct_get_chmap
|
|
||||||
+#define snd_pcm_direct_set_chmap \
|
|
||||||
+ snd1_pcm_direct_set_chmap
|
|
||||||
|
|
||||||
int snd_pcm_direct_semaphore_create_or_connect(snd_pcm_direct_t *dmix);
|
|
||||||
|
|
||||||
@@ -290,6 +296,10 @@ void snd_pcm_direct_clear_timer_queue(sn
|
|
||||||
int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix);
|
|
||||||
int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name);
|
|
||||||
|
|
||||||
+int **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm);
|
|
||||||
+int *snd_pcm_direct_get_chmap(snd_pcm_t *pcm);
|
|
||||||
+int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const int *map);
|
|
||||||
+
|
|
||||||
int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
|
|
||||||
struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm_dmix.c
|
|
||||||
+++ b/src/pcm/pcm_dmix.c
|
|
||||||
@@ -892,6 +892,9 @@ static const snd_pcm_ops_t snd_pcm_dmix_
|
|
||||||
.async = snd_pcm_direct_async,
|
|
||||||
.mmap = snd_pcm_direct_mmap,
|
|
||||||
.munmap = snd_pcm_direct_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_direct_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_direct_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_direct_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
|
|
||||||
--- a/src/pcm/pcm_dshare.c
|
|
||||||
+++ b/src/pcm/pcm_dshare.c
|
|
||||||
@@ -573,6 +573,8 @@ static const snd_pcm_ops_t snd_pcm_dshar
|
|
||||||
.async = snd_pcm_direct_async,
|
|
||||||
.mmap = snd_pcm_direct_mmap,
|
|
||||||
.munmap = snd_pcm_direct_munmap,
|
|
||||||
+ .get_chmap = snd_pcm_direct_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_direct_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = {
|
|
||||||
--- a/src/pcm/pcm_dsnoop.c
|
|
||||||
+++ b/src/pcm/pcm_dsnoop.c
|
|
||||||
@@ -488,6 +488,9 @@ static const snd_pcm_ops_t snd_pcm_dsnoo
|
|
||||||
.async = snd_pcm_direct_async,
|
|
||||||
.mmap = snd_pcm_direct_mmap,
|
|
||||||
.munmap = snd_pcm_direct_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_direct_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_direct_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_direct_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = {
|
|
||||||
--- a/src/pcm/pcm_file.c
|
|
||||||
+++ b/src/pcm/pcm_file.c
|
|
||||||
@@ -669,6 +669,9 @@ static const snd_pcm_ops_t snd_pcm_file_
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_generic_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_generic_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_generic_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
|
|
||||||
--- a/src/pcm/pcm_generic.c
|
|
||||||
+++ b/src/pcm/pcm_generic.c
|
|
||||||
@@ -323,4 +323,22 @@ int snd_pcm_generic_munmap(snd_pcm_t *pc
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+int **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_generic_t *generic = pcm->private_data;
|
|
||||||
+ return snd_pcm_query_chmaps(generic->slave);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int *snd_pcm_generic_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_generic_t *generic = pcm->private_data;
|
|
||||||
+ return snd_pcm_get_chmap(generic->slave);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const int *map)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_generic_t *generic = pcm->private_data;
|
|
||||||
+ return snd_pcm_set_chmap(generic->slave, map);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
#endif /* DOC_HIDDEN */
|
|
||||||
--- a/src/pcm/pcm_generic.h
|
|
||||||
+++ b/src/pcm/pcm_generic.h
|
|
||||||
@@ -103,6 +103,12 @@ typedef struct {
|
|
||||||
snd1_pcm_generic_mmap
|
|
||||||
#define snd_pcm_generic_munmap \
|
|
||||||
snd1_pcm_generic_munmap
|
|
||||||
+#define snd_pcm_generic_query_chmaps \
|
|
||||||
+ snd1_pcm_generic_query_chmaps
|
|
||||||
+#define snd_pcm_generic_get_chmap \
|
|
||||||
+ snd1_pcm_generic_get_chmap
|
|
||||||
+#define snd_pcm_generic_set_chmap \
|
|
||||||
+ snd1_pcm_generic_set_chmap
|
|
||||||
|
|
||||||
int snd_pcm_generic_close(snd_pcm_t *pcm);
|
|
||||||
int snd_pcm_generic_nonblock(snd_pcm_t *pcm, int nonblock);
|
|
||||||
@@ -149,3 +155,8 @@ int snd_pcm_generic_real_htimestamp(snd_
|
|
||||||
snd_htimestamp_t *tstamp);
|
|
||||||
int snd_pcm_generic_mmap(snd_pcm_t *pcm);
|
|
||||||
int snd_pcm_generic_munmap(snd_pcm_t *pcm);
|
|
||||||
+int **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm);
|
|
||||||
+int *snd_pcm_generic_get_chmap(snd_pcm_t *pcm);
|
|
||||||
+int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const int *map);
|
|
||||||
+
|
|
||||||
+
|
|
||||||
--- a/src/pcm/pcm_hooks.c
|
|
||||||
+++ b/src/pcm/pcm_hooks.c
|
|
||||||
@@ -165,6 +165,9 @@ static const snd_pcm_ops_t snd_pcm_hooks
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_generic_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_generic_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_generic_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
|
|
||||||
--- a/src/pcm/pcm_hw.c
|
|
||||||
+++ b/src/pcm/pcm_hw.c
|
|
||||||
@@ -1004,6 +1004,181 @@ static int snd_pcm_hw_htimestamp(snd_pcm
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void fill_chmap_ctl_id(snd_pcm_t *pcm, snd_ctl_elem_id_t *id)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_hw_t *hw = pcm->private_data;
|
|
||||||
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
|
|
||||||
+ if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
|
|
||||||
+ snd_ctl_elem_id_set_name(id, "Playback Channel Map");
|
|
||||||
+ else
|
|
||||||
+ snd_ctl_elem_id_set_name(id, "Capture Channel Map");
|
|
||||||
+ snd_ctl_elem_id_set_device(id, hw->device);
|
|
||||||
+ snd_ctl_elem_id_set_index(id, hw->subdevice);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int is_chmap_type(int type)
|
|
||||||
+{
|
|
||||||
+ return (type >= SND_CTL_TLVT_CHMAP_FIXED &&
|
|
||||||
+ type <= SND_CTL_TLVT_CHMAP_PAIRED);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int **snd_pcm_hw_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_hw_t *hw = pcm->private_data;
|
|
||||||
+ snd_ctl_t *ctl;
|
|
||||||
+ snd_ctl_elem_id_t *id;
|
|
||||||
+ unsigned int tlv[256], *start;
|
|
||||||
+ int **map;
|
|
||||||
+ int i, ret, nums;
|
|
||||||
+
|
|
||||||
+ ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ SYSMSG("Cannot open the associated CTL\n");
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ snd_ctl_elem_id_alloca(&id);
|
|
||||||
+ fill_chmap_ctl_id(pcm, id);
|
|
||||||
+ ret = snd_ctl_elem_tlv_read(ctl, id, tlv, sizeof(tlv));
|
|
||||||
+ snd_ctl_close(ctl);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ SYSMSG("Cannot read Channel Map TLV\n");
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+#if 0
|
|
||||||
+ for (i = 0; i < 32; i++)
|
|
||||||
+ fprintf(stderr, "%02x: %08x\n", i, tlv[i]);
|
|
||||||
+#endif
|
|
||||||
+ if (tlv[0] != SND_CTL_TLVT_CONTAINER) {
|
|
||||||
+ if (!is_chmap_type(tlv[0])) {
|
|
||||||
+ SYSMSG("Invalid TLV type %d\n", tlv[0]);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+ start = tlv;
|
|
||||||
+ nums = 1;
|
|
||||||
+ } else {
|
|
||||||
+ unsigned int *p;
|
|
||||||
+ int size;
|
|
||||||
+ start = tlv + 2;
|
|
||||||
+ size = tlv[1];
|
|
||||||
+ nums = 0;
|
|
||||||
+ for (p = start; size > 0; ) {
|
|
||||||
+ if (!is_chmap_type(p[0])) {
|
|
||||||
+ SYSMSG("Invalid TLV type %d\n", p[0]);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+ nums++;
|
|
||||||
+ size -= p[1] + 8;
|
|
||||||
+ p += p[1] / 4 + 2;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ map = calloc(nums + 1, sizeof(int *));
|
|
||||||
+ if (!map)
|
|
||||||
+ return NULL;
|
|
||||||
+ for (i = 0; i < nums; i++) {
|
|
||||||
+ map[i] = malloc(start[1] + 8);
|
|
||||||
+ if (!map[i])
|
|
||||||
+ goto nomem;
|
|
||||||
+ map[i][0] = start[0] - 0x100;
|
|
||||||
+ map[i][1] = start[1] / 4;
|
|
||||||
+ memcpy(map[i] + 2, start + 2, start[1]);
|
|
||||||
+ start += start[1] / 4 + 2;
|
|
||||||
+ }
|
|
||||||
+ return map;
|
|
||||||
+
|
|
||||||
+ nomem:
|
|
||||||
+ for (; i >= 0; i--)
|
|
||||||
+ free(map[i]);
|
|
||||||
+ free(map);
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int *snd_pcm_hw_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_hw_t *hw = pcm->private_data;
|
|
||||||
+ int *map;
|
|
||||||
+ snd_ctl_t *ctl;
|
|
||||||
+ snd_ctl_elem_id_t *id;
|
|
||||||
+ snd_ctl_elem_value_t *val;
|
|
||||||
+ unsigned int i;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ switch (FAST_PCM_STATE(hw)) {
|
|
||||||
+ case SNDRV_PCM_STATE_PREPARED:
|
|
||||||
+ case SNDRV_PCM_STATE_RUNNING:
|
|
||||||
+ case SNDRV_PCM_STATE_XRUN:
|
|
||||||
+ case SNDRV_PCM_STATE_DRAINING:
|
|
||||||
+ case SNDRV_PCM_STATE_PAUSED:
|
|
||||||
+ case SNDRV_PCM_STATE_SUSPENDED:
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ SYSMSG("Invalid PCM state for chmap_get: %s\n",
|
|
||||||
+ snd_pcm_state_name(FAST_PCM_STATE(hw)));
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+ map = malloc(pcm->channels + 1);
|
|
||||||
+ if (!map)
|
|
||||||
+ return NULL;
|
|
||||||
+ *map = pcm->channels;
|
|
||||||
+ ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ free(map);
|
|
||||||
+ SYSMSG("Cannot open the associated CTL\n");
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+ snd_ctl_elem_value_alloca(&val);
|
|
||||||
+ snd_ctl_elem_id_alloca(&id);
|
|
||||||
+ fill_chmap_ctl_id(pcm, id);
|
|
||||||
+ snd_ctl_elem_value_set_id(val, id);
|
|
||||||
+ ret = snd_ctl_elem_read(ctl, val);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ snd_ctl_close(ctl);
|
|
||||||
+ free(map);
|
|
||||||
+ SYSMSG("Cannot read Channel Map ctl\n");
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+ for (i = 0; i < pcm->channels; i++)
|
|
||||||
+ map[i + 1] = snd_ctl_elem_value_get_integer(val, i);
|
|
||||||
+ snd_ctl_close(ctl);
|
|
||||||
+ return map;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int snd_pcm_hw_set_chmap(snd_pcm_t *pcm, const int *map)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_hw_t *hw = pcm->private_data;
|
|
||||||
+ snd_ctl_t *ctl;
|
|
||||||
+ snd_ctl_elem_id_t *id;
|
|
||||||
+ snd_ctl_elem_value_t *val;
|
|
||||||
+ int i, ret;
|
|
||||||
+
|
|
||||||
+ if (*map < 0 || *map > 128) {
|
|
||||||
+ SYSMSG("Invalid number of channels %d\n", *map);
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ }
|
|
||||||
+ if (FAST_PCM_STATE(hw) != SNDRV_PCM_STATE_PREPARED) {
|
|
||||||
+ SYSMSG("Invalid PCM state for chmap_set: %s\n",
|
|
||||||
+ snd_pcm_state_name(FAST_PCM_STATE(hw)));
|
|
||||||
+ return -EBADFD;
|
|
||||||
+ }
|
|
||||||
+ ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ SYSMSG("Cannot open the associated CTL\n");
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+ snd_ctl_elem_id_alloca(&id);
|
|
||||||
+ snd_ctl_elem_value_alloca(&val);
|
|
||||||
+ fill_chmap_ctl_id(pcm, id);
|
|
||||||
+ snd_ctl_elem_value_set_id(val, id);
|
|
||||||
+ for (i = 0; i < *map; i++)
|
|
||||||
+ snd_ctl_elem_value_set_integer(val, i, map[i + 1]);
|
|
||||||
+ ret = snd_ctl_elem_write(ctl, val);
|
|
||||||
+ snd_ctl_close(ctl);
|
|
||||||
+ if (ret < 0)
|
|
||||||
+ SYSMSG("Cannot write Channel Map ctl\n");
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void snd_pcm_hw_dump(snd_pcm_t *pcm, snd_output_t *out)
|
|
||||||
{
|
|
||||||
snd_pcm_hw_t *hw = pcm->private_data;
|
|
||||||
@@ -1037,6 +1212,9 @@ static const snd_pcm_ops_t snd_pcm_hw_op
|
|
||||||
.async = snd_pcm_hw_async,
|
|
||||||
.mmap = snd_pcm_hw_mmap,
|
|
||||||
.munmap = snd_pcm_hw_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_hw_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_hw_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_hw_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
|
|
||||||
--- a/src/pcm/pcm_iec958.c
|
|
||||||
+++ b/src/pcm/pcm_iec958.c
|
|
||||||
@@ -429,6 +429,9 @@ static const snd_pcm_ops_t snd_pcm_iec95
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_generic_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_generic_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_generic_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
--- a/src/pcm/pcm_ladspa.c
|
|
||||||
+++ b/src/pcm/pcm_ladspa.c
|
|
||||||
@@ -1084,6 +1084,9 @@ static const snd_pcm_ops_t snd_pcm_ladsp
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_generic_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_generic_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_generic_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int snd_pcm_ladspa_check_file(snd_pcm_ladspa_plugin_t * const plugin,
|
|
||||||
--- a/src/pcm/pcm_lfloat.c
|
|
||||||
+++ b/src/pcm/pcm_lfloat.c
|
|
||||||
@@ -363,6 +363,9 @@ static const snd_pcm_ops_t snd_pcm_lfloa
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_generic_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_generic_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_generic_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
--- a/src/pcm/pcm_linear.c
|
|
||||||
+++ b/src/pcm/pcm_linear.c
|
|
||||||
@@ -435,6 +435,9 @@ static const snd_pcm_ops_t snd_pcm_linea
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_generic_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_generic_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_generic_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm_local.h
|
|
||||||
+++ b/src/pcm/pcm_local.h
|
|
||||||
@@ -143,6 +143,9 @@ typedef struct {
|
|
||||||
void (*dump)(snd_pcm_t *pcm, snd_output_t *out);
|
|
||||||
int (*mmap)(snd_pcm_t *pcm);
|
|
||||||
int (*munmap)(snd_pcm_t *pcm);
|
|
||||||
+ int **(*query_chmaps)(snd_pcm_t *pcm);
|
|
||||||
+ int *(*get_chmap)(snd_pcm_t *pcm);
|
|
||||||
+ int (*set_chmap)(snd_pcm_t *pcm, const int *map);
|
|
||||||
} snd_pcm_ops_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
--- a/src/pcm/pcm_meter.c
|
|
||||||
+++ b/src/pcm/pcm_meter.c
|
|
||||||
@@ -514,6 +514,9 @@ static const snd_pcm_ops_t snd_pcm_meter
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_generic_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_generic_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_generic_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
|
|
||||||
--- a/src/pcm/pcm_mmap_emul.c
|
|
||||||
+++ b/src/pcm/pcm_mmap_emul.c
|
|
||||||
@@ -368,6 +368,9 @@ static const snd_pcm_ops_t snd_pcm_mmap_
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_generic_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_generic_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_generic_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const snd_pcm_fast_ops_t snd_pcm_mmap_emul_fast_ops = {
|
|
||||||
--- a/src/pcm/pcm_mulaw.c
|
|
||||||
+++ b/src/pcm/pcm_mulaw.c
|
|
||||||
@@ -419,6 +419,8 @@ static const snd_pcm_ops_t snd_pcm_mulaw
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .get_chmap = snd_pcm_generic_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_generic_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
--- a/src/pcm/pcm_rate.c
|
|
||||||
+++ b/src/pcm/pcm_rate.c
|
|
||||||
@@ -1249,6 +1249,9 @@ static const snd_pcm_ops_t snd_pcm_rate_
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_generic_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_generic_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_generic_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
--- a/src/pcm/pcm_softvol.c
|
|
||||||
+++ b/src/pcm/pcm_softvol.c
|
|
||||||
@@ -818,6 +818,9 @@ static const snd_pcm_ops_t snd_pcm_softv
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_generic_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_generic_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_generic_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
@ -1,150 +0,0 @@
|
|||||||
From 3fb013065fee01ba7ac7c64fa48149f0e124fe26 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Wed, 25 Jul 2012 15:36:16 +0200
|
|
||||||
Subject: [PATCH 02/30] Implement get_chmap/set_chmap for PCM plug, route and
|
|
||||||
multi plugins
|
|
||||||
|
|
||||||
Still incomplete implementations. The query and set ops are missing
|
|
||||||
for route and multi plugins.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/pcm/pcm_multi.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
src/pcm/pcm_plug.c | 3 ++
|
|
||||||
src/pcm/pcm_route.c | 30 ++++++++++++++++++++++++++
|
|
||||||
3 files changed, 93 insertions(+)
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm_multi.c
|
|
||||||
+++ b/src/pcm/pcm_multi.c
|
|
||||||
@@ -739,6 +739,63 @@ static int snd_pcm_multi_mmap(snd_pcm_t
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int *snd_pcm_multi_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_multi_t *multi = pcm->private_data;
|
|
||||||
+ int *map;
|
|
||||||
+ unsigned int i, idx;
|
|
||||||
+
|
|
||||||
+ map = malloc(pcm->channels + 4);
|
|
||||||
+ if (!map)
|
|
||||||
+ return NULL;
|
|
||||||
+ idx = 0;
|
|
||||||
+ for (i = 0; i < multi->slaves_count; ++i) {
|
|
||||||
+ int c, *slave_map;
|
|
||||||
+ slave_map = snd_pcm_get_chmap(multi->slaves[i].pcm);
|
|
||||||
+ if (!slave_map) {
|
|
||||||
+ free(map);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+ for (c = 0; c < *slave_map; c++) {
|
|
||||||
+ if (idx >= pcm->channels)
|
|
||||||
+ break;
|
|
||||||
+ map[idx++] = slave_map[c + 1];
|
|
||||||
+ }
|
|
||||||
+ free(slave_map);
|
|
||||||
+ }
|
|
||||||
+ return map;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int snd_pcm_multi_set_chmap(snd_pcm_t *pcm, const int *map)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_multi_t *multi = pcm->private_data;
|
|
||||||
+ unsigned int i, idx, chs;
|
|
||||||
+ int err;
|
|
||||||
+
|
|
||||||
+ chs = *map;
|
|
||||||
+ if (chs != pcm->channels)
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ map++;
|
|
||||||
+ for (i = 0; i < multi->slaves_count; ++i) {
|
|
||||||
+ int *slave_map;
|
|
||||||
+ unsigned int slave_chs;
|
|
||||||
+ slave_chs = multi->slaves[i].channels_count;
|
|
||||||
+ if (idx + slave_chs > chs)
|
|
||||||
+ break;
|
|
||||||
+ slave_map = malloc(slave_chs * 4 + 4);
|
|
||||||
+ if (!slave_map)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+ *slave_map = slave_chs;
|
|
||||||
+ memcpy(slave_map, map + idx, slave_chs * 4);
|
|
||||||
+ err = snd_pcm_set_chmap(multi->slaves[i].pcm, slave_map);
|
|
||||||
+ free(slave_map);
|
|
||||||
+ if (err < 0)
|
|
||||||
+ return err;
|
|
||||||
+ idx += slave_chs;
|
|
||||||
+ }
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void snd_pcm_multi_dump(snd_pcm_t *pcm, snd_output_t *out)
|
|
||||||
{
|
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
|
||||||
@@ -775,6 +832,9 @@ static const snd_pcm_ops_t snd_pcm_multi
|
|
||||||
.async = snd_pcm_multi_async,
|
|
||||||
.mmap = snd_pcm_multi_mmap,
|
|
||||||
.munmap = snd_pcm_multi_munmap,
|
|
||||||
+ .query_chmaps = NULL, /* NYI */
|
|
||||||
+ .get_chmap = snd_pcm_multi_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_multi_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
|
|
||||||
--- a/src/pcm/pcm_plug.c
|
|
||||||
+++ b/src/pcm/pcm_plug.c
|
|
||||||
@@ -1084,6 +1084,9 @@ static const snd_pcm_ops_t snd_pcm_plug_
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_generic_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_generic_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_generic_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
--- a/src/pcm/pcm_route.c
|
|
||||||
+++ b/src/pcm/pcm_route.c
|
|
||||||
@@ -703,6 +703,33 @@ snd_pcm_route_read_areas(snd_pcm_t *pcm,
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int *snd_pcm_route_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_route_t *route = pcm->private_data;
|
|
||||||
+ int *map, *slave_map;
|
|
||||||
+ unsigned int src, dst;
|
|
||||||
+
|
|
||||||
+ slave_map = snd_pcm_generic_get_chmap(pcm);
|
|
||||||
+ if (!slave_map)
|
|
||||||
+ return NULL;
|
|
||||||
+ map = calloc(4, route->schannels + 1);
|
|
||||||
+ if (!map) {
|
|
||||||
+ free(slave_map);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+ *map = route->schannels;
|
|
||||||
+ for (dst = 0; dst < route->params.ndsts; dst++) {
|
|
||||||
+ snd_pcm_route_ttable_dst_t *d = &route->params.dsts[dst];
|
|
||||||
+ for (src = 0; src < d->nsrcs; src++) {
|
|
||||||
+ int c = d->srcs[src].channel;
|
|
||||||
+ if (c < route->schannels && !map[c + 1])
|
|
||||||
+ map[c + 1] = slave_map[dst + 1];
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ free(slave_map);
|
|
||||||
+ return map;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void snd_pcm_route_dump(snd_pcm_t *pcm, snd_output_t *out)
|
|
||||||
{
|
|
||||||
snd_pcm_route_t *route = pcm->private_data;
|
|
||||||
@@ -760,6 +787,9 @@ static const snd_pcm_ops_t snd_pcm_route
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = NULL, /* NYI */
|
|
||||||
+ .get_chmap = snd_pcm_route_get_chmap,
|
|
||||||
+ .set_chmap = NULL, /* NYI */
|
|
||||||
};
|
|
||||||
|
|
||||||
static int route_load_ttable(snd_pcm_route_params_t *params, snd_pcm_stream_t stream,
|
|
@ -1,179 +0,0 @@
|
|||||||
From 662f79d4ec6b52bbaab28d5a9b60cc8bcdf042f9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Wed, 25 Jul 2012 15:54:45 +0200
|
|
||||||
Subject: [PATCH 03/30] Implement get_chmap/set_chmap for PCM extplug/ioplug
|
|
||||||
plugins
|
|
||||||
|
|
||||||
Added the new ops for both external plugins, so the protocol numbers
|
|
||||||
are incremented.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/pcm_extplug.h | 14 +++++++++++++-
|
|
||||||
include/pcm_ioplug.h | 16 ++++++++++++++--
|
|
||||||
src/pcm/pcm_extplug.c | 33 +++++++++++++++++++++++++++++++++
|
|
||||||
src/pcm/pcm_ioplug.c | 33 +++++++++++++++++++++++++++++++++
|
|
||||||
4 files changed, 93 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
--- a/include/pcm_extplug.h
|
|
||||||
+++ b/include/pcm_extplug.h
|
|
||||||
@@ -55,7 +55,7 @@ typedef struct snd_pcm_extplug_callback
|
|
||||||
*/
|
|
||||||
#define SND_PCM_EXTPLUG_VERSION_MAJOR 1 /**< Protocol major version */
|
|
||||||
#define SND_PCM_EXTPLUG_VERSION_MINOR 0 /**< Protocol minor version */
|
|
||||||
-#define SND_PCM_EXTPLUG_VERSION_TINY 1 /**< Protocol tiny version */
|
|
||||||
+#define SND_PCM_EXTPLUG_VERSION_TINY 2 /**< Protocol tiny version */
|
|
||||||
/**
|
|
||||||
* Filter-plugin protocol version
|
|
||||||
*/
|
|
||||||
@@ -151,6 +151,18 @@ struct snd_pcm_extplug_callback {
|
|
||||||
* init; optional initialization called at prepare or reset
|
|
||||||
*/
|
|
||||||
int (*init)(snd_pcm_extplug_t *ext);
|
|
||||||
+ /**
|
|
||||||
+ * query the channel maps; optional; since v1.0.2
|
|
||||||
+ */
|
|
||||||
+ int **(*query_chmaps)(snd_pcm_extplug_t *ext);
|
|
||||||
+ /**
|
|
||||||
+ * get the channel map; optional; since v1.0.2
|
|
||||||
+ */
|
|
||||||
+ int *(*get_chmap)(snd_pcm_extplug_t *ext);
|
|
||||||
+ /**
|
|
||||||
+ * set the channel map; optional; since v1.0.2
|
|
||||||
+ */
|
|
||||||
+ int (*set_chmap)(snd_pcm_extplug_t *ext, const int *map);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
--- a/include/pcm_ioplug.h
|
|
||||||
+++ b/include/pcm_ioplug.h
|
|
||||||
@@ -66,7 +66,7 @@ typedef struct snd_pcm_ioplug_callback s
|
|
||||||
*/
|
|
||||||
#define SND_PCM_IOPLUG_VERSION_MAJOR 1 /**< Protocol major version */
|
|
||||||
#define SND_PCM_IOPLUG_VERSION_MINOR 0 /**< Protocol minor version */
|
|
||||||
-#define SND_PCM_IOPLUG_VERSION_TINY 1 /**< Protocol tiny version */
|
|
||||||
+#define SND_PCM_IOPLUG_VERSION_TINY 2 /**< Protocol tiny version */
|
|
||||||
/**
|
|
||||||
* IO-plugin protocol version
|
|
||||||
*/
|
|
||||||
@@ -186,9 +186,21 @@ struct snd_pcm_ioplug_callback {
|
|
||||||
*/
|
|
||||||
void (*dump)(snd_pcm_ioplug_t *io, snd_output_t *out);
|
|
||||||
/**
|
|
||||||
- * get the delay for the running PCM; optional
|
|
||||||
+ * get the delay for the running PCM; optional; since v1.0.1
|
|
||||||
*/
|
|
||||||
int (*delay)(snd_pcm_ioplug_t *io, snd_pcm_sframes_t *delayp);
|
|
||||||
+ /**
|
|
||||||
+ * query the channel maps; optional; since v1.0.2
|
|
||||||
+ */
|
|
||||||
+ int **(*query_chmaps)(snd_pcm_ioplug_t *io);
|
|
||||||
+ /**
|
|
||||||
+ * get the channel map; optional; since v1.0.2
|
|
||||||
+ */
|
|
||||||
+ int *(*get_chmap)(snd_pcm_ioplug_t *io);
|
|
||||||
+ /**
|
|
||||||
+ * set the channel map; optional; since v1.0.2
|
|
||||||
+ */
|
|
||||||
+ int (*set_chmap)(snd_pcm_ioplug_t *io, const int *map);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm_extplug.c
|
|
||||||
+++ b/src/pcm/pcm_extplug.c
|
|
||||||
@@ -425,6 +425,36 @@ static int snd_pcm_extplug_close(snd_pcm
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int **snd_pcm_extplug_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ extplug_priv_t *ext = pcm->private_data;
|
|
||||||
+
|
|
||||||
+ if (ext->data->version >= 0x010002 &&
|
|
||||||
+ ext->data->callback->query_chmaps)
|
|
||||||
+ return ext->data->callback->query_chmaps(ext->data);
|
|
||||||
+ return snd_pcm_generic_query_chmaps(pcm);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int *snd_pcm_extplug_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ extplug_priv_t *ext = pcm->private_data;
|
|
||||||
+
|
|
||||||
+ if (ext->data->version >= 0x010002 &&
|
|
||||||
+ ext->data->callback->get_chmap)
|
|
||||||
+ return ext->data->callback->get_chmap(ext->data);
|
|
||||||
+ return snd_pcm_generic_get_chmap(pcm);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int snd_pcm_extplug_set_chmap(snd_pcm_t *pcm, const int *map)
|
|
||||||
+{
|
|
||||||
+ extplug_priv_t *ext = pcm->private_data;
|
|
||||||
+
|
|
||||||
+ if (ext->data->version >= 0x010002 &&
|
|
||||||
+ ext->data->callback->set_chmap)
|
|
||||||
+ return ext->data->callback->set_chmap(ext->data, map);
|
|
||||||
+ return snd_pcm_generic_set_chmap(pcm, map);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static const snd_pcm_ops_t snd_pcm_extplug_ops = {
|
|
||||||
.close = snd_pcm_extplug_close,
|
|
||||||
.info = snd_pcm_generic_info,
|
|
||||||
@@ -438,6 +468,9 @@ static const snd_pcm_ops_t snd_pcm_extpl
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_extplug_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_extplug_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_extplug_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* !DOC_HIDDEN */
|
|
||||||
--- a/src/pcm/pcm_ioplug.c
|
|
||||||
+++ b/src/pcm/pcm_ioplug.c
|
|
||||||
@@ -710,6 +710,36 @@ static int snd_pcm_ioplug_munmap(snd_pcm
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int **snd_pcm_ioplug_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ ioplug_priv_t *io = pcm->private_data;
|
|
||||||
+
|
|
||||||
+ if (io->data->version >= 0x010002 &&
|
|
||||||
+ io->data->callback->query_chmaps)
|
|
||||||
+ return io->data->callback->query_chmaps(io->data);
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int *snd_pcm_ioplug_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ ioplug_priv_t *io = pcm->private_data;
|
|
||||||
+
|
|
||||||
+ if (io->data->version >= 0x010002 &&
|
|
||||||
+ io->data->callback->get_chmap)
|
|
||||||
+ return io->data->callback->get_chmap(io->data);
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int snd_pcm_ioplug_set_chmap(snd_pcm_t *pcm, const int *map)
|
|
||||||
+{
|
|
||||||
+ ioplug_priv_t *io = pcm->private_data;
|
|
||||||
+
|
|
||||||
+ if (io->data->version >= 0x010002 &&
|
|
||||||
+ io->data->callback->set_chmap)
|
|
||||||
+ return io->data->callback->set_chmap(io->data, map);
|
|
||||||
+ return -ENXIO;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void snd_pcm_ioplug_dump(snd_pcm_t *pcm, snd_output_t *out)
|
|
||||||
{
|
|
||||||
ioplug_priv_t *io = pcm->private_data;
|
|
||||||
@@ -760,6 +790,9 @@ static const snd_pcm_ops_t snd_pcm_ioplu
|
|
||||||
.dump = snd_pcm_ioplug_dump,
|
|
||||||
.mmap = snd_pcm_ioplug_mmap,
|
|
||||||
.munmap = snd_pcm_ioplug_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_ioplug_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_ioplug_get_chmap,
|
|
||||||
+ .set_chmap = snd_pcm_ioplug_set_chmap,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const snd_pcm_fast_ops_t snd_pcm_ioplug_fast_ops = {
|
|
@ -1,288 +0,0 @@
|
|||||||
From 3fc13d6f5b08edee49b106cd711d51bf3aef6ab7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Mon, 30 Jul 2012 15:50:44 +0200
|
|
||||||
Subject: [PATCH 04/30] Add test/chmap program
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
test/Makefile.am | 3
|
|
||||||
test/chmap.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
2 files changed, 256 insertions(+), 1 deletion(-)
|
|
||||||
create mode 100644 test/chmap.c
|
|
||||||
|
|
||||||
--- a/test/Makefile.am
|
|
||||||
+++ b/test/Makefile.am
|
|
||||||
@@ -2,7 +2,7 @@ SUBDIRS=. lsb
|
|
||||||
|
|
||||||
check_PROGRAMS=control pcm pcm_min latency seq \
|
|
||||||
playmidi1 timer rawmidi midiloop \
|
|
||||||
- oldapi queue_timer namehint client_event_filter
|
|
||||||
+ oldapi queue_timer namehint client_event_filter chmap
|
|
||||||
|
|
||||||
control_LDADD=../src/libasound.la
|
|
||||||
pcm_LDADD=../src/libasound.la
|
|
||||||
@@ -18,6 +18,7 @@ queue_timer_LDADD=../src/libasound.la
|
|
||||||
namehint_LDADD=../src/libasound.la
|
|
||||||
client_event_filter_LDADD=../src/libasound.la
|
|
||||||
code_CFLAGS=-Wall -pipe -g -O2
|
|
||||||
+chmap_LDADD=../src/libasound.la
|
|
||||||
|
|
||||||
INCLUDES=-I$(top_srcdir)/include
|
|
||||||
AM_CFLAGS=-Wall -pipe -g
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/test/chmap.c
|
|
||||||
@@ -0,0 +1,254 @@
|
|
||||||
+/*
|
|
||||||
+ * channel mapping API test program
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <ctype.h>
|
|
||||||
+#include <getopt.h>
|
|
||||||
+#include "../include/asoundlib.h"
|
|
||||||
+
|
|
||||||
+static void usage(void)
|
|
||||||
+{
|
|
||||||
+ printf("usage: chmap [options] query\n"
|
|
||||||
+ " chmap [options] get\n"
|
|
||||||
+ " chmap [options] set CH0 CH1 CH2...\n"
|
|
||||||
+ "options:\n"
|
|
||||||
+ " -D device Specify PCM device to handle\n"
|
|
||||||
+ " -f format PCM format\n"
|
|
||||||
+ " -c channels Channels\n"
|
|
||||||
+ " -r rate Sample rate\n");
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static const char * const chname[] = {
|
|
||||||
+ "Unknown",
|
|
||||||
+ "FL", "FC", "FR",
|
|
||||||
+ "FLC", "FRC", "RL", "RC", "RR",
|
|
||||||
+ "RLC", "RRC", "SL", "SR", "LFE",
|
|
||||||
+ "FLW", "FRW", "FLH",
|
|
||||||
+ "FCH", "FCH", "FRH",
|
|
||||||
+ "TC"
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
|
||||||
+
|
|
||||||
+static void print_channels(int channels, int *map)
|
|
||||||
+{
|
|
||||||
+ int i;
|
|
||||||
+ printf(" ");
|
|
||||||
+ for (i = 0; i < channels; i++) {
|
|
||||||
+ unsigned int c = *map++;
|
|
||||||
+ if (c >= ARRAY_SIZE(chname))
|
|
||||||
+ printf(" Ch%d", c);
|
|
||||||
+ else
|
|
||||||
+ printf(" %s", chname[c]);
|
|
||||||
+ }
|
|
||||||
+ printf("\n");
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int to_channel(const char *name)
|
|
||||||
+{
|
|
||||||
+ unsigned int i;
|
|
||||||
+
|
|
||||||
+ if (isdigit(*name))
|
|
||||||
+ return atoi(name);
|
|
||||||
+ for (i = 0; i < ARRAY_SIZE(chname); i++)
|
|
||||||
+ if (!strcmp(chname[i], name))
|
|
||||||
+ return i;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static const char *chmap_type(int type)
|
|
||||||
+{
|
|
||||||
+ switch (type) {
|
|
||||||
+ case SND_CHMAP_NONE:
|
|
||||||
+ return "None";
|
|
||||||
+ case SND_CHMAP_FIXED:
|
|
||||||
+ return "Fixed";
|
|
||||||
+ case SND_CHMAP_VAR:
|
|
||||||
+ return "Variable";
|
|
||||||
+ case SND_CHMAP_PAIRED:
|
|
||||||
+ return "Paired";
|
|
||||||
+ default:
|
|
||||||
+ return "Unknown";
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ int **maps = snd_pcm_query_chmaps(pcm);
|
|
||||||
+ int **p, *v;
|
|
||||||
+
|
|
||||||
+ if (!maps) {
|
|
||||||
+ printf("Cannot query maps\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ for (p = maps; (v = *p) != NULL; p++) {
|
|
||||||
+ printf("Type = %s, Channels = %d\n", chmap_type(v[0]), v[1]);
|
|
||||||
+ print_channels(v[1], v + 2);
|
|
||||||
+ }
|
|
||||||
+ snd_pcm_free_chmaps(maps);
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int setup_pcm(snd_pcm_t *pcm, int format, int channels, int rate)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_hw_params_t *params;
|
|
||||||
+
|
|
||||||
+ snd_pcm_hw_params_alloca(¶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;
|
|
||||||
+}
|
|
@ -1,188 +0,0 @@
|
|||||||
From 34f6545520de73be55ee6c29a7ebd3c016fa9f06 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Mon, 30 Jul 2012 18:21:43 +0200
|
|
||||||
Subject: [PATCH 05/30] Cache the chmap operation errors
|
|
||||||
|
|
||||||
... not to retry the same error again.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/pcm/pcm_hw.c | 66 +++++++++++++++++++++++++++++++++++++++++++++----------
|
|
||||||
1 file changed, 54 insertions(+), 12 deletions(-)
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm_hw.c
|
|
||||||
+++ b/src/pcm/pcm_hw.c
|
|
||||||
@@ -105,6 +105,8 @@ typedef struct {
|
|
||||||
snd_pcm_format_t format;
|
|
||||||
int rate;
|
|
||||||
int channels;
|
|
||||||
+ /* for chmap */
|
|
||||||
+ unsigned int chmap_caps;
|
|
||||||
} snd_pcm_hw_t;
|
|
||||||
|
|
||||||
#define SNDRV_FILE_PCM_STREAM_PLAYBACK ALSA_DEVICE_DIRECTORY "pcmC%iD%ip"
|
|
||||||
@@ -1022,6 +1024,27 @@ static int is_chmap_type(int type)
|
|
||||||
type <= SND_CTL_TLVT_CHMAP_PAIRED);
|
|
||||||
}
|
|
||||||
|
|
||||||
+enum { CHMAP_CTL_QUERY, CHMAP_CTL_GET, CHMAP_CTL_SET };
|
|
||||||
+
|
|
||||||
+static int chmap_caps(snd_pcm_hw_t *hw, int type)
|
|
||||||
+{
|
|
||||||
+ if (hw->chmap_caps & (1 << type))
|
|
||||||
+ return 1;
|
|
||||||
+ if (hw->chmap_caps & (1 << (type + 8)))
|
|
||||||
+ return 0;
|
|
||||||
+ return 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void chmap_caps_set_ok(snd_pcm_hw_t *hw, int type)
|
|
||||||
+{
|
|
||||||
+ hw->chmap_caps |= (1 << type);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void chmap_caps_set_error(snd_pcm_hw_t *hw, int type)
|
|
||||||
+{
|
|
||||||
+ hw->chmap_caps |= (1 << (type + 8));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int **snd_pcm_hw_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
snd_pcm_hw_t *hw = pcm->private_data;
|
|
||||||
@@ -1031,10 +1054,13 @@ static int **snd_pcm_hw_query_chmaps(snd
|
|
||||||
int **map;
|
|
||||||
int i, ret, nums;
|
|
||||||
|
|
||||||
+ if (!chmap_caps(hw, CHMAP_CTL_QUERY))
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
|
|
||||||
if (ret < 0) {
|
|
||||||
SYSMSG("Cannot open the associated CTL\n");
|
|
||||||
- return NULL;
|
|
||||||
+ goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
snd_ctl_elem_id_alloca(&id);
|
|
||||||
@@ -1043,7 +1069,7 @@ static int **snd_pcm_hw_query_chmaps(snd
|
|
||||||
snd_ctl_close(ctl);
|
|
||||||
if (ret < 0) {
|
|
||||||
SYSMSG("Cannot read Channel Map TLV\n");
|
|
||||||
- return NULL;
|
|
||||||
+ goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
@@ -1053,7 +1079,7 @@ static int **snd_pcm_hw_query_chmaps(snd
|
|
||||||
if (tlv[0] != SND_CTL_TLVT_CONTAINER) {
|
|
||||||
if (!is_chmap_type(tlv[0])) {
|
|
||||||
SYSMSG("Invalid TLV type %d\n", tlv[0]);
|
|
||||||
- return NULL;
|
|
||||||
+ goto error;
|
|
||||||
}
|
|
||||||
start = tlv;
|
|
||||||
nums = 1;
|
|
||||||
@@ -1066,7 +1092,7 @@ static int **snd_pcm_hw_query_chmaps(snd
|
|
||||||
for (p = start; size > 0; ) {
|
|
||||||
if (!is_chmap_type(p[0])) {
|
|
||||||
SYSMSG("Invalid TLV type %d\n", p[0]);
|
|
||||||
- return NULL;
|
|
||||||
+ goto error;
|
|
||||||
}
|
|
||||||
nums++;
|
|
||||||
size -= p[1] + 8;
|
|
||||||
@@ -1078,19 +1104,20 @@ static int **snd_pcm_hw_query_chmaps(snd
|
|
||||||
return NULL;
|
|
||||||
for (i = 0; i < nums; i++) {
|
|
||||||
map[i] = malloc(start[1] + 8);
|
|
||||||
- if (!map[i])
|
|
||||||
- goto nomem;
|
|
||||||
+ if (!map[i]) {
|
|
||||||
+ snd_pcm_free_chmaps(map);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
map[i][0] = start[0] - 0x100;
|
|
||||||
map[i][1] = start[1] / 4;
|
|
||||||
memcpy(map[i] + 2, start + 2, start[1]);
|
|
||||||
start += start[1] / 4 + 2;
|
|
||||||
}
|
|
||||||
+ chmap_caps_set_ok(hw, CHMAP_CTL_QUERY);
|
|
||||||
return map;
|
|
||||||
|
|
||||||
- nomem:
|
|
||||||
- for (; i >= 0; i--)
|
|
||||||
- free(map[i]);
|
|
||||||
- free(map);
|
|
||||||
+ error:
|
|
||||||
+ chmap_caps_set_error(hw, CHMAP_CTL_QUERY);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1104,6 +1131,9 @@ static int *snd_pcm_hw_get_chmap(snd_pcm
|
|
||||||
unsigned int i;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
+ if (!chmap_caps(hw, CHMAP_CTL_GET))
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
switch (FAST_PCM_STATE(hw)) {
|
|
||||||
case SNDRV_PCM_STATE_PREPARED:
|
|
||||||
case SNDRV_PCM_STATE_RUNNING:
|
|
||||||
@@ -1125,6 +1155,7 @@ static int *snd_pcm_hw_get_chmap(snd_pcm
|
|
||||||
if (ret < 0) {
|
|
||||||
free(map);
|
|
||||||
SYSMSG("Cannot open the associated CTL\n");
|
|
||||||
+ chmap_caps_set_error(hw, CHMAP_CTL_GET);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
snd_ctl_elem_value_alloca(&val);
|
|
||||||
@@ -1132,15 +1163,16 @@ static int *snd_pcm_hw_get_chmap(snd_pcm
|
|
||||||
fill_chmap_ctl_id(pcm, id);
|
|
||||||
snd_ctl_elem_value_set_id(val, id);
|
|
||||||
ret = snd_ctl_elem_read(ctl, val);
|
|
||||||
+ snd_ctl_close(ctl);
|
|
||||||
if (ret < 0) {
|
|
||||||
- snd_ctl_close(ctl);
|
|
||||||
free(map);
|
|
||||||
SYSMSG("Cannot read Channel Map ctl\n");
|
|
||||||
+ chmap_caps_set_error(hw, CHMAP_CTL_GET);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
for (i = 0; i < pcm->channels; i++)
|
|
||||||
map[i + 1] = snd_ctl_elem_value_get_integer(val, i);
|
|
||||||
- snd_ctl_close(ctl);
|
|
||||||
+ chmap_caps_set_ok(hw, CHMAP_CTL_GET);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1152,6 +1184,9 @@ static int snd_pcm_hw_set_chmap(snd_pcm_
|
|
||||||
snd_ctl_elem_value_t *val;
|
|
||||||
int i, ret;
|
|
||||||
|
|
||||||
+ if (!chmap_caps(hw, CHMAP_CTL_SET))
|
|
||||||
+ return -ENXIO;
|
|
||||||
+
|
|
||||||
if (*map < 0 || *map > 128) {
|
|
||||||
SYSMSG("Invalid number of channels %d\n", *map);
|
|
||||||
return -EINVAL;
|
|
||||||
@@ -1164,6 +1199,7 @@ static int snd_pcm_hw_set_chmap(snd_pcm_
|
|
||||||
ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
|
|
||||||
if (ret < 0) {
|
|
||||||
SYSMSG("Cannot open the associated CTL\n");
|
|
||||||
+ chmap_caps_set_error(hw, CHMAP_CTL_SET);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
snd_ctl_elem_id_alloca(&id);
|
|
||||||
@@ -1174,6 +1210,12 @@ static int snd_pcm_hw_set_chmap(snd_pcm_
|
|
||||||
snd_ctl_elem_value_set_integer(val, i, map[i + 1]);
|
|
||||||
ret = snd_ctl_elem_write(ctl, val);
|
|
||||||
snd_ctl_close(ctl);
|
|
||||||
+ if (ret >= 0)
|
|
||||||
+ chmap_caps_set_ok(hw, CHMAP_CTL_SET);
|
|
||||||
+ else if (ret == -ENOENT || ret == -EPERM || ret == -ENXIO) {
|
|
||||||
+ chmap_caps_set_error(hw, CHMAP_CTL_SET);
|
|
||||||
+ ret = -ENXIO;
|
|
||||||
+ }
|
|
||||||
if (ret < 0)
|
|
||||||
SYSMSG("Cannot write Channel Map ctl\n");
|
|
||||||
return ret;
|
|
@ -1,56 +0,0 @@
|
|||||||
From 915b26bfe8af876d467a37c336c6bf22d5e370fe Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Tue, 21 Aug 2012 12:16:39 +0200
|
|
||||||
Subject: [PATCH 06/30] Define channel map position enum in pcm.h
|
|
||||||
|
|
||||||
The original definition is in sound/asound.h, but we need to export to
|
|
||||||
alsa-lib users, too.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/pcm.h | 28 +++++++++++++++++++++++++++-
|
|
||||||
1 file changed, 27 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/include/pcm.h
|
|
||||||
+++ b/include/pcm.h
|
|
||||||
@@ -474,13 +474,39 @@ int snd_pcm_wait(snd_pcm_t *pcm, int tim
|
|
||||||
int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
|
|
||||||
int snd_pcm_unlink(snd_pcm_t *pcm);
|
|
||||||
|
|
||||||
-enum {
|
|
||||||
+/** channel map list type */
|
|
||||||
+enum snd_pcm_chmap_type {
|
|
||||||
SND_CHMAP_NONE = 0, /** unspecified channel position */
|
|
||||||
SND_CHMAP_FIXED, /** fixed channel position */
|
|
||||||
SND_CHMAP_VAR, /** freely swappable channel position */
|
|
||||||
SND_CHMAP_PAIRED, /** pair-wise swappable channel position */
|
|
||||||
};
|
|
||||||
|
|
||||||
+/** channel positions */
|
|
||||||
+enum snd_pcm_chmap_position {
|
|
||||||
+ SND_CHMAP_UNKNOWN = 0, /** unspecified */
|
|
||||||
+ SND_CHMAP_FL, /** front left */
|
|
||||||
+ SND_CHMAP_FC, /** front center */
|
|
||||||
+ SND_CHMAP_FR, /** front right */
|
|
||||||
+ SND_CHMAP_FLC, /** front left center */
|
|
||||||
+ SND_CHMAP_FRC, /* front right center */
|
|
||||||
+ SND_CHMAP_RL, /** rear left */
|
|
||||||
+ SND_CHMAP_RC, /** rear center */
|
|
||||||
+ SND_CHMAP_RR, /** rear right */
|
|
||||||
+ SND_CHMAP_RLC, /** rear left center */
|
|
||||||
+ SND_CHMAP_RRC, /** rear right center */
|
|
||||||
+ SND_CHMAP_SL, /** side left */
|
|
||||||
+ SND_CHMAP_SR, /** side right */
|
|
||||||
+ SND_CHMAP_LFE, /** LFE */
|
|
||||||
+ SND_CHMAP_FLW, /** front left wide */
|
|
||||||
+ SND_CHMAP_FRW, /** front right wide */
|
|
||||||
+ SND_CHMAP_FLH, /** front left high */
|
|
||||||
+ SND_CHMAP_FCH, /** front center high */
|
|
||||||
+ SND_CHMAP_FRH, /** front right high */
|
|
||||||
+ SND_CHMAP_TC, /** top center */
|
|
||||||
+ SND_CHMAP_LAST = SND_CHMAP_TC, /** last entry */
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
int **snd_pcm_query_chmaps(snd_pcm_t *pcm);
|
|
||||||
void snd_pcm_free_chmaps(int **maps);
|
|
||||||
int *snd_pcm_get_chmap(snd_pcm_t *pcm);
|
|
@ -1,110 +0,0 @@
|
|||||||
From 0f36270dd315b9baf3a93f5586776b91c0bcf589 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Tue, 21 Aug 2012 15:07:44 +0200
|
|
||||||
Subject: [PATCH 07/30] Follow channel position definitions to mixer channel
|
|
||||||
in mixer.h
|
|
||||||
|
|
||||||
mixer.h already contains some channel position definitions.
|
|
||||||
To be more consistent over all systems, better to follow the same
|
|
||||||
order for the new channel map, too. But since UNKNOWN channel must be
|
|
||||||
zero but the definition in mixer.h contains -1 as UNKNOWN, simply
|
|
||||||
shift the value with 1.
|
|
||||||
|
|
||||||
If the conversion is required between SND_CHMAP and SND_MIXER_SCHN,
|
|
||||||
just increment/decrement 1. Eventually I'll provide helper functions
|
|
||||||
for that...
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/pcm.h | 14 +++++++-------
|
|
||||||
include/sound/asound.h | 16 +++++++++-------
|
|
||||||
test/chmap.c | 11 ++++-------
|
|
||||||
3 files changed, 20 insertions(+), 21 deletions(-)
|
|
||||||
|
|
||||||
--- a/include/pcm.h
|
|
||||||
+++ b/include/pcm.h
|
|
||||||
@@ -486,18 +486,18 @@ enum snd_pcm_chmap_type {
|
|
||||||
enum snd_pcm_chmap_position {
|
|
||||||
SND_CHMAP_UNKNOWN = 0, /** unspecified */
|
|
||||||
SND_CHMAP_FL, /** front left */
|
|
||||||
- SND_CHMAP_FC, /** front center */
|
|
||||||
SND_CHMAP_FR, /** front right */
|
|
||||||
- SND_CHMAP_FLC, /** front left center */
|
|
||||||
- SND_CHMAP_FRC, /* front right center */
|
|
||||||
SND_CHMAP_RL, /** rear left */
|
|
||||||
- SND_CHMAP_RC, /** rear center */
|
|
||||||
SND_CHMAP_RR, /** rear right */
|
|
||||||
- SND_CHMAP_RLC, /** rear left center */
|
|
||||||
- SND_CHMAP_RRC, /** rear right center */
|
|
||||||
+ SND_CHMAP_FC, /** front center */
|
|
||||||
+ SND_CHMAP_LFE, /** LFE */
|
|
||||||
SND_CHMAP_SL, /** side left */
|
|
||||||
SND_CHMAP_SR, /** side right */
|
|
||||||
- SND_CHMAP_LFE, /** LFE */
|
|
||||||
+ SND_CHMAP_RC, /** rear center */
|
|
||||||
+ SND_CHMAP_FLC, /** front left center */
|
|
||||||
+ SND_CHMAP_FRC, /** front right center */
|
|
||||||
+ SND_CHMAP_RLC, /** rear left center */
|
|
||||||
+ SND_CHMAP_RRC, /** rear right center */
|
|
||||||
SND_CHMAP_FLW, /** front left wide */
|
|
||||||
SND_CHMAP_FRW, /** front right wide */
|
|
||||||
SND_CHMAP_FLH, /** front left high */
|
|
||||||
--- a/include/sound/asound.h
|
|
||||||
+++ b/include/sound/asound.h
|
|
||||||
@@ -479,20 +479,22 @@ enum {
|
|
||||||
|
|
||||||
/* channel positions */
|
|
||||||
enum {
|
|
||||||
+ /* this follows the alsa-lib mixer channel value + 1*/
|
|
||||||
SNDRV_CHMAP_UNKNOWN = 0,
|
|
||||||
SNDRV_CHMAP_FL, /* front left */
|
|
||||||
- SNDRV_CHMAP_FC, /* front center */
|
|
||||||
SNDRV_CHMAP_FR, /* front right */
|
|
||||||
- SNDRV_CHMAP_FLC, /* front left center */
|
|
||||||
- SNDRV_CHMAP_FRC, /* front right center */
|
|
||||||
SNDRV_CHMAP_RL, /* rear left */
|
|
||||||
- SNDRV_CHMAP_RC, /* rear center */
|
|
||||||
SNDRV_CHMAP_RR, /* rear right */
|
|
||||||
- SNDRV_CHMAP_RLC, /* rear left center */
|
|
||||||
- SNDRV_CHMAP_RRC, /* rear right center */
|
|
||||||
+ SNDRV_CHMAP_FC, /* front center */
|
|
||||||
+ SNDRV_CHMAP_LFE, /* LFE */
|
|
||||||
SNDRV_CHMAP_SL, /* side left */
|
|
||||||
SNDRV_CHMAP_SR, /* side right */
|
|
||||||
- SNDRV_CHMAP_LFE, /* LFE */
|
|
||||||
+ SNDRV_CHMAP_RC, /* rear center */
|
|
||||||
+ /* new definitions */
|
|
||||||
+ SNDRV_CHMAP_FLC, /* front left center */
|
|
||||||
+ SNDRV_CHMAP_FRC, /* front right center */
|
|
||||||
+ SNDRV_CHMAP_RLC, /* rear left center */
|
|
||||||
+ SNDRV_CHMAP_RRC, /* rear right center */
|
|
||||||
SNDRV_CHMAP_FLW, /* front left wide */
|
|
||||||
SNDRV_CHMAP_FRW, /* front right wide */
|
|
||||||
SNDRV_CHMAP_FLH, /* front left high */
|
|
||||||
--- a/test/chmap.c
|
|
||||||
+++ b/test/chmap.c
|
|
||||||
@@ -23,12 +23,9 @@ static void usage(void)
|
|
||||||
|
|
||||||
static const char * const chname[] = {
|
|
||||||
"Unknown",
|
|
||||||
- "FL", "FC", "FR",
|
|
||||||
- "FLC", "FRC", "RL", "RC", "RR",
|
|
||||||
- "RLC", "RRC", "SL", "SR", "LFE",
|
|
||||||
- "FLW", "FRW", "FLH",
|
|
||||||
- "FCH", "FCH", "FRH",
|
|
||||||
- "TC"
|
|
||||||
+ "FL", "FR", "RL", "RR", "FC", "LFE", "SL", "SR", "RC",
|
|
||||||
+ "FLC", "FRC", "RLC", "RRC", "FLW", "FRW", "FLH",
|
|
||||||
+ "FCH", "FCH", "FRH", "TC"
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
|
||||||
@@ -56,7 +53,7 @@ static int to_channel(const char *name)
|
|
||||||
for (i = 0; i < ARRAY_SIZE(chname); i++)
|
|
||||||
if (!strcmp(chname[i], name))
|
|
||||||
return i;
|
|
||||||
- return 0;
|
|
||||||
+ return SND_CHMAP_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *chmap_type(int type)
|
|
@ -1,88 +0,0 @@
|
|||||||
From 48c2c90f19f07d02082d9fb84fb36ac1fcfa84e1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Fri, 31 Aug 2012 13:53:22 -0700
|
|
||||||
Subject: [PATCH 08/30] Add SND_CHMAP_NA and bit flag definitions
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/pcm.h | 7 ++++++-
|
|
||||||
include/sound/asound.h | 9 +++++++--
|
|
||||||
test/chmap.c | 14 ++++++++++----
|
|
||||||
3 files changed, 23 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
--- a/include/pcm.h
|
|
||||||
+++ b/include/pcm.h
|
|
||||||
@@ -504,9 +504,14 @@ enum snd_pcm_chmap_position {
|
|
||||||
SND_CHMAP_FCH, /** front center high */
|
|
||||||
SND_CHMAP_FRH, /** front right high */
|
|
||||||
SND_CHMAP_TC, /** top center */
|
|
||||||
- SND_CHMAP_LAST = SND_CHMAP_TC, /** last entry */
|
|
||||||
+ SND_CHMAP_NA, /** N/A, silent */
|
|
||||||
+ SND_CHMAP_LAST = SND_CHMAP_NA, /** last entry */
|
|
||||||
};
|
|
||||||
|
|
||||||
+#define SND_CHMAP_POSITION_MASK 0xffff /** bitmask for channel position */
|
|
||||||
+#define SND_CHMAP_PHASE_INVERSE (0x01 << 16) /* the channel is phase inverted */
|
|
||||||
+#define SND_CHMAP_DRIVER_SPEC (0x02 << 16) /* non-standard channel value */
|
|
||||||
+
|
|
||||||
int **snd_pcm_query_chmaps(snd_pcm_t *pcm);
|
|
||||||
void snd_pcm_free_chmaps(int **maps);
|
|
||||||
int *snd_pcm_get_chmap(snd_pcm_t *pcm);
|
|
||||||
--- a/include/sound/asound.h
|
|
||||||
+++ b/include/sound/asound.h
|
|
||||||
@@ -479,7 +479,7 @@ enum {
|
|
||||||
|
|
||||||
/* channel positions */
|
|
||||||
enum {
|
|
||||||
- /* this follows the alsa-lib mixer channel value + 1*/
|
|
||||||
+ /* this follows the alsa-lib mixer channel value + 1 */
|
|
||||||
SNDRV_CHMAP_UNKNOWN = 0,
|
|
||||||
SNDRV_CHMAP_FL, /* front left */
|
|
||||||
SNDRV_CHMAP_FR, /* front right */
|
|
||||||
@@ -501,9 +501,14 @@ enum {
|
|
||||||
SNDRV_CHMAP_FCH, /* front center high */
|
|
||||||
SNDRV_CHMAP_FRH, /* front right high */
|
|
||||||
SNDRV_CHMAP_TC, /* top center */
|
|
||||||
- SNDRV_CHMAP_LAST = SNDRV_CHMAP_TC,
|
|
||||||
+ SNDRV_CHMAP_NA, /* N/A, silent */
|
|
||||||
+ SNDRV_CHMAP_LAST = SNDRV_CHMAP_NA,
|
|
||||||
};
|
|
||||||
|
|
||||||
+#define SNDRV_CHMAP_POSITION_MASK 0xffff
|
|
||||||
+#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16)
|
|
||||||
+#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16)
|
|
||||||
+
|
|
||||||
enum {
|
|
||||||
SNDRV_PCM_IOCTL_PVERSION = _IOR('A', 0x00, int),
|
|
||||||
SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct sndrv_pcm_info),
|
|
||||||
--- a/test/chmap.c
|
|
||||||
+++ b/test/chmap.c
|
|
||||||
@@ -25,7 +25,8 @@ static const char * const chname[] = {
|
|
||||||
"Unknown",
|
|
||||||
"FL", "FR", "RL", "RR", "FC", "LFE", "SL", "SR", "RC",
|
|
||||||
"FLC", "FRC", "RLC", "RRC", "FLW", "FRW", "FLH",
|
|
||||||
- "FCH", "FCH", "FRH", "TC"
|
|
||||||
+ "FCH", "FCH", "FRH", "TC",
|
|
||||||
+ "N/A",
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
|
||||||
@@ -36,10 +37,15 @@ static void print_channels(int channels,
|
|
||||||
printf(" ");
|
|
||||||
for (i = 0; i < channels; i++) {
|
|
||||||
unsigned int c = *map++;
|
|
||||||
- if (c >= ARRAY_SIZE(chname))
|
|
||||||
- printf(" Ch%d", c);
|
|
||||||
+ unsigned int pos = c & SND_CHMAP_POSITION_MASK;
|
|
||||||
+ if (c & SND_CHMAP_DRIVER_SPEC)
|
|
||||||
+ printf(" %d", p);
|
|
||||||
+ else if (p >= ARRAY_SIZE(chname))
|
|
||||||
+ printf(" Ch%d", p);
|
|
||||||
else
|
|
||||||
- printf(" %s", chname[c]);
|
|
||||||
+ printf(" %s", chname[p]);
|
|
||||||
+ if (c & SND_CHMAP_PHASE_INVERSE)
|
|
||||||
+ printf("[INV]");
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
@ -1,587 +0,0 @@
|
|||||||
From 9c1a0ce72d71e4728d45dcd3986dd0ef0201dd67 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Tue, 4 Sep 2012 17:26:43 +0200
|
|
||||||
Subject: [PATCH 09/30] PCM: Introduce snd_pcm_chmap_t and
|
|
||||||
snd_pcm_chmap_query_t
|
|
||||||
|
|
||||||
Instead of passing ambiguous integer array, define snd_pcm_chmap_t and
|
|
||||||
snd_pcm_chmap_query_t so that user can understand more easily which
|
|
||||||
element is for what.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/pcm.h | 21 +++++++++++++++++----
|
|
||||||
include/pcm_extplug.h | 6 +++---
|
|
||||||
include/pcm_ioplug.h | 6 +++---
|
|
||||||
src/pcm/pcm.c | 10 +++++-----
|
|
||||||
src/pcm/pcm_direct.c | 6 +++---
|
|
||||||
src/pcm/pcm_direct.h | 6 +++---
|
|
||||||
src/pcm/pcm_extplug.c | 6 +++---
|
|
||||||
src/pcm/pcm_generic.c | 6 +++---
|
|
||||||
src/pcm/pcm_generic.h | 6 +++---
|
|
||||||
src/pcm/pcm_hw.c | 31 ++++++++++++++++---------------
|
|
||||||
src/pcm/pcm_ioplug.c | 6 +++---
|
|
||||||
src/pcm/pcm_local.h | 6 +++---
|
|
||||||
src/pcm/pcm_multi.c | 25 ++++++++++++++-----------
|
|
||||||
src/pcm/pcm_route.c | 10 +++++-----
|
|
||||||
test/chmap.c | 35 ++++++++++++++++++-----------------
|
|
||||||
15 files changed, 102 insertions(+), 84 deletions(-)
|
|
||||||
|
|
||||||
--- a/include/pcm.h
|
|
||||||
+++ b/include/pcm.h
|
|
||||||
@@ -512,10 +512,23 @@ enum snd_pcm_chmap_position {
|
|
||||||
#define SND_CHMAP_PHASE_INVERSE (0x01 << 16) /* the channel is phase inverted */
|
|
||||||
#define SND_CHMAP_DRIVER_SPEC (0x02 << 16) /* non-standard channel value */
|
|
||||||
|
|
||||||
-int **snd_pcm_query_chmaps(snd_pcm_t *pcm);
|
|
||||||
-void snd_pcm_free_chmaps(int **maps);
|
|
||||||
-int *snd_pcm_get_chmap(snd_pcm_t *pcm);
|
|
||||||
-int snd_pcm_set_chmap(snd_pcm_t *pcm, const int *map);
|
|
||||||
+/** the channel map header */
|
|
||||||
+typedef struct snd_pcm_chmap {
|
|
||||||
+ unsigned int channels;
|
|
||||||
+ unsigned int pos[0];
|
|
||||||
+} snd_pcm_chmap_t;
|
|
||||||
+
|
|
||||||
+/** the header of array items returned from snd_pcm_query_chmaps() */
|
|
||||||
+typedef struct snd_pcm_chmap_query {
|
|
||||||
+ enum snd_pcm_chmap_type type;
|
|
||||||
+ snd_pcm_chmap_t map;
|
|
||||||
+} snd_pcm_chmap_query_t;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+snd_pcm_chmap_query_t **snd_pcm_query_chmaps(snd_pcm_t *pcm);
|
|
||||||
+void snd_pcm_free_chmaps(snd_pcm_chmap_query_t **maps);
|
|
||||||
+snd_pcm_chmap_t *snd_pcm_get_chmap(snd_pcm_t *pcm);
|
|
||||||
+int snd_pcm_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
|
|
||||||
|
|
||||||
//int snd_pcm_mixer_element(snd_pcm_t *pcm, snd_mixer_t *mixer, snd_mixer_elem_t **elem);
|
|
||||||
|
|
||||||
--- a/include/pcm_extplug.h
|
|
||||||
+++ b/include/pcm_extplug.h
|
|
||||||
@@ -154,15 +154,15 @@ struct snd_pcm_extplug_callback {
|
|
||||||
/**
|
|
||||||
* query the channel maps; optional; since v1.0.2
|
|
||||||
*/
|
|
||||||
- int **(*query_chmaps)(snd_pcm_extplug_t *ext);
|
|
||||||
+ snd_pcm_chmap_query_t **(*query_chmaps)(snd_pcm_extplug_t *ext);
|
|
||||||
/**
|
|
||||||
* get the channel map; optional; since v1.0.2
|
|
||||||
*/
|
|
||||||
- int *(*get_chmap)(snd_pcm_extplug_t *ext);
|
|
||||||
+ snd_pcm_chmap_t *(*get_chmap)(snd_pcm_extplug_t *ext);
|
|
||||||
/**
|
|
||||||
* set the channel map; optional; since v1.0.2
|
|
||||||
*/
|
|
||||||
- int (*set_chmap)(snd_pcm_extplug_t *ext, const int *map);
|
|
||||||
+ int (*set_chmap)(snd_pcm_extplug_t *ext, const snd_pcm_chmap_t *map);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
--- a/include/pcm_ioplug.h
|
|
||||||
+++ b/include/pcm_ioplug.h
|
|
||||||
@@ -192,15 +192,15 @@ struct snd_pcm_ioplug_callback {
|
|
||||||
/**
|
|
||||||
* query the channel maps; optional; since v1.0.2
|
|
||||||
*/
|
|
||||||
- int **(*query_chmaps)(snd_pcm_ioplug_t *io);
|
|
||||||
+ snd_pcm_chmap_query_t **(*query_chmaps)(snd_pcm_ioplug_t *io);
|
|
||||||
/**
|
|
||||||
* get the channel map; optional; since v1.0.2
|
|
||||||
*/
|
|
||||||
- int *(*get_chmap)(snd_pcm_ioplug_t *io);
|
|
||||||
+ snd_pcm_chmap_t *(*get_chmap)(snd_pcm_ioplug_t *io);
|
|
||||||
/**
|
|
||||||
* set the channel map; optional; since v1.0.2
|
|
||||||
*/
|
|
||||||
- int (*set_chmap)(snd_pcm_ioplug_t *io, const int *map);
|
|
||||||
+ int (*set_chmap)(snd_pcm_ioplug_t *io, const snd_pcm_chmap_t *map);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm.c
|
|
||||||
+++ b/src/pcm/pcm.c
|
|
||||||
@@ -7310,7 +7310,7 @@ OBSOLETE1(snd_pcm_sw_params_get_silence_
|
|
||||||
* integer array, beginning with the channel map type, followed by the
|
|
||||||
* number of channels, and the position of each channel.
|
|
||||||
*/
|
|
||||||
-int **snd_pcm_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+snd_pcm_chmap_query_t **snd_pcm_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
if (!pcm->ops->query_chmaps)
|
|
||||||
return NULL;
|
|
||||||
@@ -7321,9 +7321,9 @@ int **snd_pcm_query_chmaps(snd_pcm_t *pc
|
|
||||||
* \!brief Release the channel map array allocated via #snd_pcm_query_chmaps
|
|
||||||
* \param maps the array pointer to release
|
|
||||||
*/
|
|
||||||
-void snd_pcm_free_chmaps(int **maps)
|
|
||||||
+void snd_pcm_free_chmaps(snd_pcm_chmap_query_t **maps)
|
|
||||||
{
|
|
||||||
- int **p;
|
|
||||||
+ snd_pcm_chmap_query_t **p = maps;
|
|
||||||
if (!maps)
|
|
||||||
return;
|
|
||||||
for (p = maps; *p; p++)
|
|
||||||
@@ -7336,7 +7336,7 @@ void snd_pcm_free_chmaps(int **maps)
|
|
||||||
* \param pcm PCM instance
|
|
||||||
* \return the current channel map, or NULL if error
|
|
||||||
*/
|
|
||||||
-int *snd_pcm_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+snd_pcm_chmap_t *snd_pcm_get_chmap(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
if (!pcm->ops->get_chmap)
|
|
||||||
return NULL;
|
|
||||||
@@ -7349,7 +7349,7 @@ int *snd_pcm_get_chmap(snd_pcm_t *pcm)
|
|
||||||
* \param map the channel map to write
|
|
||||||
* \return zero if succeeded, or a negative error code
|
|
||||||
*/
|
|
||||||
-int snd_pcm_set_chmap(snd_pcm_t *pcm, const int *map)
|
|
||||||
+int snd_pcm_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
|
|
||||||
{
|
|
||||||
if (!pcm->ops->set_chmap)
|
|
||||||
return -ENXIO;
|
|
||||||
--- a/src/pcm/pcm_direct.c
|
|
||||||
+++ b/src/pcm/pcm_direct.c
|
|
||||||
@@ -789,19 +789,19 @@ int snd_pcm_direct_munmap(snd_pcm_t *pcm
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-int **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+snd_pcm_chmap_query_t **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
snd_pcm_direct_t *dmix = pcm->private_data;
|
|
||||||
return snd_pcm_query_chmaps(dmix->spcm);
|
|
||||||
}
|
|
||||||
|
|
||||||
-int *snd_pcm_direct_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+snd_pcm_chmap_t *snd_pcm_direct_get_chmap(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
snd_pcm_direct_t *dmix = pcm->private_data;
|
|
||||||
return snd_pcm_get_chmap(dmix->spcm);
|
|
||||||
}
|
|
||||||
|
|
||||||
-int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const int *map)
|
|
||||||
+int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
|
|
||||||
{
|
|
||||||
snd_pcm_direct_t *dmix = pcm->private_data;
|
|
||||||
return snd_pcm_set_chmap(dmix->spcm, map);
|
|
||||||
--- a/src/pcm/pcm_direct.h
|
|
||||||
+++ b/src/pcm/pcm_direct.h
|
|
||||||
@@ -296,9 +296,9 @@ void snd_pcm_direct_clear_timer_queue(sn
|
|
||||||
int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix);
|
|
||||||
int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name);
|
|
||||||
|
|
||||||
-int **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm);
|
|
||||||
-int *snd_pcm_direct_get_chmap(snd_pcm_t *pcm);
|
|
||||||
-int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const int *map);
|
|
||||||
+snd_pcm_chmap_query_t **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm);
|
|
||||||
+snd_pcm_chmap_t *snd_pcm_direct_get_chmap(snd_pcm_t *pcm);
|
|
||||||
+int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
|
|
||||||
|
|
||||||
int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
|
|
||||||
struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);
|
|
||||||
--- a/src/pcm/pcm_extplug.c
|
|
||||||
+++ b/src/pcm/pcm_extplug.c
|
|
||||||
@@ -425,7 +425,7 @@ static int snd_pcm_extplug_close(snd_pcm
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int **snd_pcm_extplug_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+static snd_pcm_chmap_query_t **snd_pcm_extplug_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
extplug_priv_t *ext = pcm->private_data;
|
|
||||||
|
|
||||||
@@ -435,7 +435,7 @@ static int **snd_pcm_extplug_query_chmap
|
|
||||||
return snd_pcm_generic_query_chmaps(pcm);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int *snd_pcm_extplug_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+static snd_pcm_chmap_t *snd_pcm_extplug_get_chmap(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
extplug_priv_t *ext = pcm->private_data;
|
|
||||||
|
|
||||||
@@ -445,7 +445,7 @@ static int *snd_pcm_extplug_get_chmap(sn
|
|
||||||
return snd_pcm_generic_get_chmap(pcm);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int snd_pcm_extplug_set_chmap(snd_pcm_t *pcm, const int *map)
|
|
||||||
+static int snd_pcm_extplug_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
|
|
||||||
{
|
|
||||||
extplug_priv_t *ext = pcm->private_data;
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm_generic.c
|
|
||||||
+++ b/src/pcm/pcm_generic.c
|
|
||||||
@@ -323,19 +323,19 @@ int snd_pcm_generic_munmap(snd_pcm_t *pc
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-int **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+snd_pcm_chmap_query_t **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
snd_pcm_generic_t *generic = pcm->private_data;
|
|
||||||
return snd_pcm_query_chmaps(generic->slave);
|
|
||||||
}
|
|
||||||
|
|
||||||
-int *snd_pcm_generic_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+snd_pcm_chmap_t *snd_pcm_generic_get_chmap(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
snd_pcm_generic_t *generic = pcm->private_data;
|
|
||||||
return snd_pcm_get_chmap(generic->slave);
|
|
||||||
}
|
|
||||||
|
|
||||||
-int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const int *map)
|
|
||||||
+int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
|
|
||||||
{
|
|
||||||
snd_pcm_generic_t *generic = pcm->private_data;
|
|
||||||
return snd_pcm_set_chmap(generic->slave, map);
|
|
||||||
--- a/src/pcm/pcm_generic.h
|
|
||||||
+++ b/src/pcm/pcm_generic.h
|
|
||||||
@@ -155,8 +155,8 @@ int snd_pcm_generic_real_htimestamp(snd_
|
|
||||||
snd_htimestamp_t *tstamp);
|
|
||||||
int snd_pcm_generic_mmap(snd_pcm_t *pcm);
|
|
||||||
int snd_pcm_generic_munmap(snd_pcm_t *pcm);
|
|
||||||
-int **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm);
|
|
||||||
-int *snd_pcm_generic_get_chmap(snd_pcm_t *pcm);
|
|
||||||
-int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const int *map);
|
|
||||||
+snd_pcm_chmap_query_t **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm);
|
|
||||||
+snd_pcm_chmap_t *snd_pcm_generic_get_chmap(snd_pcm_t *pcm);
|
|
||||||
+int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
|
|
||||||
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm_hw.c
|
|
||||||
+++ b/src/pcm/pcm_hw.c
|
|
||||||
@@ -1045,13 +1045,13 @@ static void chmap_caps_set_error(snd_pcm
|
|
||||||
hw->chmap_caps |= (1 << (type + 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int **snd_pcm_hw_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+static snd_pcm_chmap_query_t **snd_pcm_hw_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
snd_pcm_hw_t *hw = pcm->private_data;
|
|
||||||
snd_ctl_t *ctl;
|
|
||||||
snd_ctl_elem_id_t *id;
|
|
||||||
unsigned int tlv[256], *start;
|
|
||||||
- int **map;
|
|
||||||
+ snd_pcm_chmap_query_t **map;
|
|
||||||
int i, ret, nums;
|
|
||||||
|
|
||||||
if (!chmap_caps(hw, CHMAP_CTL_QUERY))
|
|
||||||
@@ -1108,9 +1108,9 @@ static int **snd_pcm_hw_query_chmaps(snd
|
|
||||||
snd_pcm_free_chmaps(map);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
- map[i][0] = start[0] - 0x100;
|
|
||||||
- map[i][1] = start[1] / 4;
|
|
||||||
- memcpy(map[i] + 2, start + 2, start[1]);
|
|
||||||
+ map[i]->type = start[0] - 0x100;
|
|
||||||
+ map[i]->map.channels = start[1] / 4;
|
|
||||||
+ memcpy(map[i]->map.pos, start + 2, start[1]);
|
|
||||||
start += start[1] / 4 + 2;
|
|
||||||
}
|
|
||||||
chmap_caps_set_ok(hw, CHMAP_CTL_QUERY);
|
|
||||||
@@ -1121,10 +1121,10 @@ static int **snd_pcm_hw_query_chmaps(snd
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int *snd_pcm_hw_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+static snd_pcm_chmap_t *snd_pcm_hw_get_chmap(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
snd_pcm_hw_t *hw = pcm->private_data;
|
|
||||||
- int *map;
|
|
||||||
+ snd_pcm_chmap_t *map;
|
|
||||||
snd_ctl_t *ctl;
|
|
||||||
snd_ctl_elem_id_t *id;
|
|
||||||
snd_ctl_elem_value_t *val;
|
|
||||||
@@ -1150,7 +1150,7 @@ static int *snd_pcm_hw_get_chmap(snd_pcm
|
|
||||||
map = malloc(pcm->channels + 1);
|
|
||||||
if (!map)
|
|
||||||
return NULL;
|
|
||||||
- *map = pcm->channels;
|
|
||||||
+ map->channels = pcm->channels;
|
|
||||||
ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
|
|
||||||
if (ret < 0) {
|
|
||||||
free(map);
|
|
||||||
@@ -1171,24 +1171,25 @@ static int *snd_pcm_hw_get_chmap(snd_pcm
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
for (i = 0; i < pcm->channels; i++)
|
|
||||||
- map[i + 1] = snd_ctl_elem_value_get_integer(val, i);
|
|
||||||
+ map->pos[i] = snd_ctl_elem_value_get_integer(val, i);
|
|
||||||
chmap_caps_set_ok(hw, CHMAP_CTL_GET);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int snd_pcm_hw_set_chmap(snd_pcm_t *pcm, const int *map)
|
|
||||||
+static int snd_pcm_hw_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
|
|
||||||
{
|
|
||||||
snd_pcm_hw_t *hw = pcm->private_data;
|
|
||||||
snd_ctl_t *ctl;
|
|
||||||
snd_ctl_elem_id_t *id;
|
|
||||||
snd_ctl_elem_value_t *val;
|
|
||||||
- int i, ret;
|
|
||||||
+ unsigned int i;
|
|
||||||
+ int ret;
|
|
||||||
|
|
||||||
if (!chmap_caps(hw, CHMAP_CTL_SET))
|
|
||||||
return -ENXIO;
|
|
||||||
|
|
||||||
- if (*map < 0 || *map > 128) {
|
|
||||||
- SYSMSG("Invalid number of channels %d\n", *map);
|
|
||||||
+ if (map->channels > 128) {
|
|
||||||
+ SYSMSG("Invalid number of channels %d\n", map->channels);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if (FAST_PCM_STATE(hw) != SNDRV_PCM_STATE_PREPARED) {
|
|
||||||
@@ -1206,8 +1207,8 @@ static int snd_pcm_hw_set_chmap(snd_pcm_
|
|
||||||
snd_ctl_elem_value_alloca(&val);
|
|
||||||
fill_chmap_ctl_id(pcm, id);
|
|
||||||
snd_ctl_elem_value_set_id(val, id);
|
|
||||||
- for (i = 0; i < *map; i++)
|
|
||||||
- snd_ctl_elem_value_set_integer(val, i, map[i + 1]);
|
|
||||||
+ for (i = 0; i < map->channels; i++)
|
|
||||||
+ snd_ctl_elem_value_set_integer(val, i, map->pos[i]);
|
|
||||||
ret = snd_ctl_elem_write(ctl, val);
|
|
||||||
snd_ctl_close(ctl);
|
|
||||||
if (ret >= 0)
|
|
||||||
--- a/src/pcm/pcm_ioplug.c
|
|
||||||
+++ b/src/pcm/pcm_ioplug.c
|
|
||||||
@@ -710,7 +710,7 @@ static int snd_pcm_ioplug_munmap(snd_pcm
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int **snd_pcm_ioplug_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+static snd_pcm_chmap_query_t **snd_pcm_ioplug_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
ioplug_priv_t *io = pcm->private_data;
|
|
||||||
|
|
||||||
@@ -720,7 +720,7 @@ static int **snd_pcm_ioplug_query_chmaps
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int *snd_pcm_ioplug_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+static snd_pcm_chmap_t *snd_pcm_ioplug_get_chmap(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
ioplug_priv_t *io = pcm->private_data;
|
|
||||||
|
|
||||||
@@ -730,7 +730,7 @@ static int *snd_pcm_ioplug_get_chmap(snd
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int snd_pcm_ioplug_set_chmap(snd_pcm_t *pcm, const int *map)
|
|
||||||
+static int snd_pcm_ioplug_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
|
|
||||||
{
|
|
||||||
ioplug_priv_t *io = pcm->private_data;
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm_local.h
|
|
||||||
+++ b/src/pcm/pcm_local.h
|
|
||||||
@@ -143,9 +143,9 @@ typedef struct {
|
|
||||||
void (*dump)(snd_pcm_t *pcm, snd_output_t *out);
|
|
||||||
int (*mmap)(snd_pcm_t *pcm);
|
|
||||||
int (*munmap)(snd_pcm_t *pcm);
|
|
||||||
- int **(*query_chmaps)(snd_pcm_t *pcm);
|
|
||||||
- int *(*get_chmap)(snd_pcm_t *pcm);
|
|
||||||
- int (*set_chmap)(snd_pcm_t *pcm, const int *map);
|
|
||||||
+ snd_pcm_chmap_query_t **(*query_chmaps)(snd_pcm_t *pcm);
|
|
||||||
+ snd_pcm_chmap_t *(*get_chmap)(snd_pcm_t *pcm);
|
|
||||||
+ int (*set_chmap)(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
|
|
||||||
} snd_pcm_ops_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
--- a/src/pcm/pcm_multi.c
|
|
||||||
+++ b/src/pcm/pcm_multi.c
|
|
||||||
@@ -739,10 +739,10 @@ static int snd_pcm_multi_mmap(snd_pcm_t
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int *snd_pcm_multi_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+static snd_pcm_chmap_t *snd_pcm_multi_get_chmap(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
|
||||||
- int *map;
|
|
||||||
+ snd_pcm_chmap_t *map;
|
|
||||||
unsigned int i, idx;
|
|
||||||
|
|
||||||
map = malloc(pcm->channels + 4);
|
|
||||||
@@ -750,34 +750,37 @@ static int *snd_pcm_multi_get_chmap(snd_
|
|
||||||
return NULL;
|
|
||||||
idx = 0;
|
|
||||||
for (i = 0; i < multi->slaves_count; ++i) {
|
|
||||||
- int c, *slave_map;
|
|
||||||
+ unsigned int c;
|
|
||||||
+ snd_pcm_chmap_t *slave_map;
|
|
||||||
slave_map = snd_pcm_get_chmap(multi->slaves[i].pcm);
|
|
||||||
if (!slave_map) {
|
|
||||||
free(map);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
- for (c = 0; c < *slave_map; c++) {
|
|
||||||
+ for (c = 0; c < slave_map->channels; c++) {
|
|
||||||
if (idx >= pcm->channels)
|
|
||||||
break;
|
|
||||||
- map[idx++] = slave_map[c + 1];
|
|
||||||
+ map->pos[idx++] = slave_map->pos[c];
|
|
||||||
}
|
|
||||||
free(slave_map);
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int snd_pcm_multi_set_chmap(snd_pcm_t *pcm, const int *map)
|
|
||||||
+static int snd_pcm_multi_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
|
|
||||||
{
|
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
|
||||||
+ const unsigned int *pos;
|
|
||||||
unsigned int i, idx, chs;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
- chs = *map;
|
|
||||||
+ chs = map->channels;
|
|
||||||
if (chs != pcm->channels)
|
|
||||||
return -EINVAL;
|
|
||||||
- map++;
|
|
||||||
+ pos = map->pos;
|
|
||||||
+ idx = 0;
|
|
||||||
for (i = 0; i < multi->slaves_count; ++i) {
|
|
||||||
- int *slave_map;
|
|
||||||
+ snd_pcm_chmap_t *slave_map;
|
|
||||||
unsigned int slave_chs;
|
|
||||||
slave_chs = multi->slaves[i].channels_count;
|
|
||||||
if (idx + slave_chs > chs)
|
|
||||||
@@ -785,8 +788,8 @@ static int snd_pcm_multi_set_chmap(snd_p
|
|
||||||
slave_map = malloc(slave_chs * 4 + 4);
|
|
||||||
if (!slave_map)
|
|
||||||
return -ENOMEM;
|
|
||||||
- *slave_map = slave_chs;
|
|
||||||
- memcpy(slave_map, map + idx, slave_chs * 4);
|
|
||||||
+ slave_map->channels = slave_chs;
|
|
||||||
+ memcpy(slave_map->pos, pos + idx, slave_chs * 4);
|
|
||||||
err = snd_pcm_set_chmap(multi->slaves[i].pcm, slave_map);
|
|
||||||
free(slave_map);
|
|
||||||
if (err < 0)
|
|
||||||
--- a/src/pcm/pcm_route.c
|
|
||||||
+++ b/src/pcm/pcm_route.c
|
|
||||||
@@ -703,10 +703,10 @@ snd_pcm_route_read_areas(snd_pcm_t *pcm,
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int *snd_pcm_route_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+static snd_pcm_chmap_t *snd_pcm_route_get_chmap(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
snd_pcm_route_t *route = pcm->private_data;
|
|
||||||
- int *map, *slave_map;
|
|
||||||
+ snd_pcm_chmap_t *map, *slave_map;
|
|
||||||
unsigned int src, dst;
|
|
||||||
|
|
||||||
slave_map = snd_pcm_generic_get_chmap(pcm);
|
|
||||||
@@ -717,13 +717,13 @@ static int *snd_pcm_route_get_chmap(snd_
|
|
||||||
free(slave_map);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
- *map = route->schannels;
|
|
||||||
+ map->channels = route->schannels;
|
|
||||||
for (dst = 0; dst < route->params.ndsts; dst++) {
|
|
||||||
snd_pcm_route_ttable_dst_t *d = &route->params.dsts[dst];
|
|
||||||
for (src = 0; src < d->nsrcs; src++) {
|
|
||||||
int c = d->srcs[src].channel;
|
|
||||||
- if (c < route->schannels && !map[c + 1])
|
|
||||||
- map[c + 1] = slave_map[dst + 1];
|
|
||||||
+ if (c < route->schannels && !map->pos[c])
|
|
||||||
+ map->pos[c] = slave_map->pos[dst];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(slave_map);
|
|
||||||
--- a/test/chmap.c
|
|
||||||
+++ b/test/chmap.c
|
|
||||||
@@ -31,13 +31,14 @@ static const char * const chname[] = {
|
|
||||||
|
|
||||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
|
||||||
|
|
||||||
-static void print_channels(int channels, int *map)
|
|
||||||
+static void print_channels(const snd_pcm_chmap_t *map)
|
|
||||||
{
|
|
||||||
- int i;
|
|
||||||
+ unsigned int i;
|
|
||||||
+
|
|
||||||
printf(" ");
|
|
||||||
- for (i = 0; i < channels; i++) {
|
|
||||||
- unsigned int c = *map++;
|
|
||||||
- unsigned int pos = c & SND_CHMAP_POSITION_MASK;
|
|
||||||
+ for (i = 0; i < map->channels; i++) {
|
|
||||||
+ unsigned int c = map->pos[i];
|
|
||||||
+ unsigned int p = c & SND_CHMAP_POSITION_MASK;
|
|
||||||
if (c & SND_CHMAP_DRIVER_SPEC)
|
|
||||||
printf(" %d", p);
|
|
||||||
else if (p >= ARRAY_SIZE(chname))
|
|
||||||
@@ -80,16 +81,16 @@ static const char *chmap_type(int type)
|
|
||||||
|
|
||||||
static int query_chmaps(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
- int **maps = snd_pcm_query_chmaps(pcm);
|
|
||||||
- int **p, *v;
|
|
||||||
+ snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps(pcm);
|
|
||||||
+ snd_pcm_chmap_query_t **p, *v;
|
|
||||||
|
|
||||||
if (!maps) {
|
|
||||||
printf("Cannot query maps\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
for (p = maps; (v = *p) != NULL; p++) {
|
|
||||||
- printf("Type = %s, Channels = %d\n", chmap_type(v[0]), v[1]);
|
|
||||||
- print_channels(v[1], v + 2);
|
|
||||||
+ printf("Type = %s, Channels = %d\n", chmap_type(v->type), v->map.channels);
|
|
||||||
+ print_channels(&v->map);
|
|
||||||
}
|
|
||||||
snd_pcm_free_chmaps(maps);
|
|
||||||
return 0;
|
|
||||||
@@ -132,7 +133,7 @@ static int setup_pcm(snd_pcm_t *pcm, int
|
|
||||||
|
|
||||||
static int get_chmap(snd_pcm_t *pcm, int format, int channels, int rate)
|
|
||||||
{
|
|
||||||
- int *map;
|
|
||||||
+ snd_pcm_chmap_t *map;
|
|
||||||
|
|
||||||
if (setup_pcm(pcm, format, channels, rate))
|
|
||||||
return 1;
|
|
||||||
@@ -141,8 +142,8 @@ static int get_chmap(snd_pcm_t *pcm, int
|
|
||||||
printf("Cannot get chmap\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
- printf("Channels = %d\n", *map);
|
|
||||||
- print_channels(*map, map + 1);
|
|
||||||
+ printf("Channels = %d\n", map->channels);
|
|
||||||
+ print_channels(map);
|
|
||||||
free(map);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -151,7 +152,7 @@ static int set_chmap(snd_pcm_t *pcm, int
|
|
||||||
int nargs, char **arg)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
- int *map;
|
|
||||||
+ snd_pcm_chmap_t *map;
|
|
||||||
|
|
||||||
if (channels && channels != nargs) {
|
|
||||||
printf("Inconsistent channels %d vs %d\n", channels, nargs);
|
|
||||||
@@ -171,9 +172,9 @@ static int set_chmap(snd_pcm_t *pcm, int
|
|
||||||
printf("cannot malloc\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
- *map = channels;
|
|
||||||
+ map->channels = channels;
|
|
||||||
for (i = 0; i < channels; i++)
|
|
||||||
- map[i + 1] = to_channel(arg[i]);
|
|
||||||
+ map->pos[i] = to_channel(arg[i]);
|
|
||||||
if (snd_pcm_set_chmap(pcm, map) < 0) {
|
|
||||||
printf("Cannot set chmap\n");
|
|
||||||
return 1;
|
|
||||||
@@ -185,8 +186,8 @@ static int set_chmap(snd_pcm_t *pcm, int
|
|
||||||
printf("Cannot get chmap\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
- printf("Get channels = %d\n", *map);
|
|
||||||
- print_channels(*map, map + 1);
|
|
||||||
+ printf("Get channels = %d\n", map->channels);
|
|
||||||
+ print_channels(map);
|
|
||||||
free(map);
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,207 +0,0 @@
|
|||||||
From 01dc0e6825b5620510faaefaef40ff8cfb692b6e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Fri, 7 Sep 2012 14:15:04 +0200
|
|
||||||
Subject: [PATCH 10/30] PCM: Implement snd_pcm_query_chmaps_from_hw()
|
|
||||||
|
|
||||||
This is a function similar like snd_pcm_query_chmaps() but performs
|
|
||||||
the query without a PCM handle. The card, device and substream
|
|
||||||
numbers are passed as well as stream direction.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/pcm.h | 3 +
|
|
||||||
src/pcm/pcm_hw.c | 117 +++++++++++++++++++++++++++++++++++--------------------
|
|
||||||
2 files changed, 79 insertions(+), 41 deletions(-)
|
|
||||||
|
|
||||||
--- a/include/pcm.h
|
|
||||||
+++ b/include/pcm.h
|
|
||||||
@@ -526,6 +526,9 @@ typedef struct snd_pcm_chmap_query {
|
|
||||||
|
|
||||||
|
|
||||||
snd_pcm_chmap_query_t **snd_pcm_query_chmaps(snd_pcm_t *pcm);
|
|
||||||
+snd_pcm_chmap_query_t **snd_pcm_query_chmaps_from_hw(int card, int dev,
|
|
||||||
+ int subdev,
|
|
||||||
+ snd_pcm_stream_t stream);
|
|
||||||
void snd_pcm_free_chmaps(snd_pcm_chmap_query_t **maps);
|
|
||||||
snd_pcm_chmap_t *snd_pcm_get_chmap(snd_pcm_t *pcm);
|
|
||||||
int snd_pcm_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
|
|
||||||
--- a/src/pcm/pcm_hw.c
|
|
||||||
+++ b/src/pcm/pcm_hw.c
|
|
||||||
@@ -1006,80 +1006,82 @@ static int snd_pcm_hw_htimestamp(snd_pcm
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void fill_chmap_ctl_id(snd_pcm_t *pcm, snd_ctl_elem_id_t *id)
|
|
||||||
+static void __fill_chmap_ctl_id(snd_ctl_elem_id_t *id, int dev, int subdev,
|
|
||||||
+ int stream)
|
|
||||||
{
|
|
||||||
- snd_pcm_hw_t *hw = pcm->private_data;
|
|
||||||
snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
|
|
||||||
- if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
|
|
||||||
+ if (stream == SND_PCM_STREAM_PLAYBACK)
|
|
||||||
snd_ctl_elem_id_set_name(id, "Playback Channel Map");
|
|
||||||
else
|
|
||||||
snd_ctl_elem_id_set_name(id, "Capture Channel Map");
|
|
||||||
- snd_ctl_elem_id_set_device(id, hw->device);
|
|
||||||
- snd_ctl_elem_id_set_index(id, hw->subdevice);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static int is_chmap_type(int type)
|
|
||||||
-{
|
|
||||||
- return (type >= SND_CTL_TLVT_CHMAP_FIXED &&
|
|
||||||
- type <= SND_CTL_TLVT_CHMAP_PAIRED);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-enum { CHMAP_CTL_QUERY, CHMAP_CTL_GET, CHMAP_CTL_SET };
|
|
||||||
-
|
|
||||||
-static int chmap_caps(snd_pcm_hw_t *hw, int type)
|
|
||||||
-{
|
|
||||||
- if (hw->chmap_caps & (1 << type))
|
|
||||||
- return 1;
|
|
||||||
- if (hw->chmap_caps & (1 << (type + 8)))
|
|
||||||
- return 0;
|
|
||||||
- return 1;
|
|
||||||
+ snd_ctl_elem_id_set_device(id, dev);
|
|
||||||
+ snd_ctl_elem_id_set_index(id, subdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void chmap_caps_set_ok(snd_pcm_hw_t *hw, int type)
|
|
||||||
+static void fill_chmap_ctl_id(snd_pcm_t *pcm, snd_ctl_elem_id_t *id)
|
|
||||||
{
|
|
||||||
- hw->chmap_caps |= (1 << type);
|
|
||||||
+ snd_pcm_hw_t *hw = pcm->private_data;
|
|
||||||
+ return __fill_chmap_ctl_id(id, hw->device, hw->subdevice, pcm->stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void chmap_caps_set_error(snd_pcm_hw_t *hw, int type)
|
|
||||||
+static int is_chmap_type(int type)
|
|
||||||
{
|
|
||||||
- hw->chmap_caps |= (1 << (type + 8));
|
|
||||||
+ return (type >= SND_CTL_TLVT_CHMAP_FIXED &&
|
|
||||||
+ type <= SND_CTL_TLVT_CHMAP_PAIRED);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static snd_pcm_chmap_query_t **snd_pcm_hw_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+/**
|
|
||||||
+ * \!brief Query the available channel maps
|
|
||||||
+ * \param card the card number
|
|
||||||
+ * \param dev the PCM device number
|
|
||||||
+ * \param subdev the PCM substream index
|
|
||||||
+ * \param stream the direction of PCM stream
|
|
||||||
+ * \return the NULL-terminated array of integer pointers, or NULL at error.
|
|
||||||
+ *
|
|
||||||
+ * This function works like snd_pcm_query_chmaps() but it takes the card,
|
|
||||||
+ * device, substream and stream numbers instead of the already opened
|
|
||||||
+ * snd_pcm_t instance, so that you can query available channel maps of
|
|
||||||
+ * a PCM before actually opening it.
|
|
||||||
+ *
|
|
||||||
+ * As the parameters stand, the query is performed only to the hw PCM
|
|
||||||
+ * devices, not the abstracted PCM object in alsa-lib.
|
|
||||||
+ */
|
|
||||||
+snd_pcm_chmap_query_t **
|
|
||||||
+snd_pcm_query_chmaps_from_hw(int card, int dev, int subdev,
|
|
||||||
+ snd_pcm_stream_t stream)
|
|
||||||
{
|
|
||||||
- snd_pcm_hw_t *hw = pcm->private_data;
|
|
||||||
snd_ctl_t *ctl;
|
|
||||||
snd_ctl_elem_id_t *id;
|
|
||||||
unsigned int tlv[256], *start;
|
|
||||||
snd_pcm_chmap_query_t **map;
|
|
||||||
int i, ret, nums;
|
|
||||||
|
|
||||||
- if (!chmap_caps(hw, CHMAP_CTL_QUERY))
|
|
||||||
- return NULL;
|
|
||||||
-
|
|
||||||
- ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
|
|
||||||
+ ret = snd_ctl_hw_open(&ctl, NULL, card, 0);
|
|
||||||
if (ret < 0) {
|
|
||||||
SYSMSG("Cannot open the associated CTL\n");
|
|
||||||
- goto error;
|
|
||||||
+ return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
snd_ctl_elem_id_alloca(&id);
|
|
||||||
- fill_chmap_ctl_id(pcm, id);
|
|
||||||
+ __fill_chmap_ctl_id(id, dev, subdev, stream);
|
|
||||||
ret = snd_ctl_elem_tlv_read(ctl, id, tlv, sizeof(tlv));
|
|
||||||
snd_ctl_close(ctl);
|
|
||||||
if (ret < 0) {
|
|
||||||
SYSMSG("Cannot read Channel Map TLV\n");
|
|
||||||
- goto error;
|
|
||||||
+ return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
for (i = 0; i < 32; i++)
|
|
||||||
fprintf(stderr, "%02x: %08x\n", i, tlv[i]);
|
|
||||||
#endif
|
|
||||||
+ /* FIXME: the parser below assumes that the TLV only contains
|
|
||||||
+ * chmap-related blocks
|
|
||||||
+ */
|
|
||||||
if (tlv[0] != SND_CTL_TLVT_CONTAINER) {
|
|
||||||
if (!is_chmap_type(tlv[0])) {
|
|
||||||
SYSMSG("Invalid TLV type %d\n", tlv[0]);
|
|
||||||
- goto error;
|
|
||||||
+ return NULL;
|
|
||||||
}
|
|
||||||
start = tlv;
|
|
||||||
nums = 1;
|
|
||||||
@@ -1092,7 +1094,7 @@ static snd_pcm_chmap_query_t **snd_pcm_h
|
|
||||||
for (p = start; size > 0; ) {
|
|
||||||
if (!is_chmap_type(p[0])) {
|
|
||||||
SYSMSG("Invalid TLV type %d\n", p[0]);
|
|
||||||
- goto error;
|
|
||||||
+ return NULL;
|
|
||||||
}
|
|
||||||
nums++;
|
|
||||||
size -= p[1] + 8;
|
|
||||||
@@ -1113,12 +1115,45 @@ static snd_pcm_chmap_query_t **snd_pcm_h
|
|
||||||
memcpy(map[i]->map.pos, start + 2, start[1]);
|
|
||||||
start += start[1] / 4 + 2;
|
|
||||||
}
|
|
||||||
- chmap_caps_set_ok(hw, CHMAP_CTL_QUERY);
|
|
||||||
return map;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+enum { CHMAP_CTL_QUERY, CHMAP_CTL_GET, CHMAP_CTL_SET };
|
|
||||||
+
|
|
||||||
+static int chmap_caps(snd_pcm_hw_t *hw, int type)
|
|
||||||
+{
|
|
||||||
+ if (hw->chmap_caps & (1 << type))
|
|
||||||
+ return 1;
|
|
||||||
+ if (hw->chmap_caps & (1 << (type + 8)))
|
|
||||||
+ return 0;
|
|
||||||
+ return 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void chmap_caps_set_ok(snd_pcm_hw_t *hw, int type)
|
|
||||||
+{
|
|
||||||
+ hw->chmap_caps |= (1 << type);
|
|
||||||
+}
|
|
||||||
|
|
||||||
- error:
|
|
||||||
- chmap_caps_set_error(hw, CHMAP_CTL_QUERY);
|
|
||||||
- return NULL;
|
|
||||||
+static void chmap_caps_set_error(snd_pcm_hw_t *hw, int type)
|
|
||||||
+{
|
|
||||||
+ hw->chmap_caps |= (1 << (type + 8));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static snd_pcm_chmap_query_t **snd_pcm_hw_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_hw_t *hw = pcm->private_data;
|
|
||||||
+ snd_pcm_chmap_query_t **map;
|
|
||||||
+
|
|
||||||
+ if (!chmap_caps(hw, CHMAP_CTL_QUERY))
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ map = snd_pcm_query_chmaps_from_hw(hw->card, hw->device,
|
|
||||||
+ hw->subdevice, pcm->stream);
|
|
||||||
+ if (map)
|
|
||||||
+ chmap_caps_set_ok(hw, CHMAP_CTL_QUERY);
|
|
||||||
+ else
|
|
||||||
+ chmap_caps_set_error(hw, CHMAP_CTL_QUERY);
|
|
||||||
+ return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
static snd_pcm_chmap_t *snd_pcm_hw_get_chmap(snd_pcm_t *pcm)
|
|
@ -1,21 +0,0 @@
|
|||||||
From ec96740d9919b5e0c050a4b91aebee4b1dbb8298 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Fri, 7 Sep 2012 14:31:39 +0200
|
|
||||||
Subject: [PATCH 11/30] Fix duplicated channel entry in test/chmap.c
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
test/chmap.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/test/chmap.c
|
|
||||||
+++ b/test/chmap.c
|
|
||||||
@@ -25,7 +25,7 @@ static const char * const chname[] = {
|
|
||||||
"Unknown",
|
|
||||||
"FL", "FR", "RL", "RR", "FC", "LFE", "SL", "SR", "RC",
|
|
||||||
"FLC", "FRC", "RLC", "RRC", "FLW", "FRW", "FLH",
|
|
||||||
- "FCH", "FCH", "FRH", "TC",
|
|
||||||
+ "FCH", "FRH", "TC",
|
|
||||||
"N/A",
|
|
||||||
};
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
From 6950a1030c4f878b51104268e3cd13401d56bf60 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Mon, 10 Sep 2012 16:59:36 +0200
|
|
||||||
Subject: [PATCH 12/30] PCM: Fix prefix for snd_pcm_chmap_type enum members
|
|
||||||
|
|
||||||
Add _TYPE prefix to distinguish from the channel position.
|
|
||||||
Also add SND_CHMAP_TYPE_LAST entry pointing the last one like other
|
|
||||||
enums.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/pcm.h | 9 +++++----
|
|
||||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
--- a/include/pcm.h
|
|
||||||
+++ b/include/pcm.h
|
|
||||||
@@ -476,10 +476,11 @@ int snd_pcm_unlink(snd_pcm_t *pcm);
|
|
||||||
|
|
||||||
/** channel map list type */
|
|
||||||
enum snd_pcm_chmap_type {
|
|
||||||
- SND_CHMAP_NONE = 0, /** unspecified channel position */
|
|
||||||
- SND_CHMAP_FIXED, /** fixed channel position */
|
|
||||||
- SND_CHMAP_VAR, /** freely swappable channel position */
|
|
||||||
- SND_CHMAP_PAIRED, /** pair-wise swappable channel position */
|
|
||||||
+ SND_CHMAP_TYPE_NONE = 0,/** unspecified channel position */
|
|
||||||
+ SND_CHMAP_TYPE_FIXED, /** fixed channel position */
|
|
||||||
+ SND_CHMAP_TYPE_VAR, /** freely swappable channel position */
|
|
||||||
+ SND_CHMAP_TYPE_PAIRED, /** pair-wise swappable channel position */
|
|
||||||
+ SND_CHMAP_TYPE_LAST = SND_CHMAP_TYPE_PAIRED, /** last entry */
|
|
||||||
};
|
|
||||||
|
|
||||||
/** channel positions */
|
|
@ -1,286 +0,0 @@
|
|||||||
From b4c64e815a051e711798be1d772f123d19c1ff6e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Mon, 10 Sep 2012 18:07:36 +0200
|
|
||||||
Subject: [PATCH 13/30] PCM: Add string conversion helper functions for chmap
|
|
||||||
|
|
||||||
Added a few helper functions between chmap and string.
|
|
||||||
snd_pcm_chmap_type_name() -- a string of the given chmap type
|
|
||||||
snd_pcm_chmap_name() -- a string of the given channel position
|
|
||||||
snd_pcm_chmap_print() -- print channel map on the given buffer
|
|
||||||
snd_pcm_chmap_from_string() -- get a channel position from string
|
|
||||||
snd_pcm_parse_string() -- parse the whole channel map from string
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/pcm.h | 6 ++
|
|
||||||
src/pcm/pcm.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
test/chmap.c | 69 ++++------------------------
|
|
||||||
3 files changed, 160 insertions(+), 57 deletions(-)
|
|
||||||
|
|
||||||
--- a/include/pcm.h
|
|
||||||
+++ b/include/pcm.h
|
|
||||||
@@ -534,6 +534,12 @@ void snd_pcm_free_chmaps(snd_pcm_chmap_q
|
|
||||||
snd_pcm_chmap_t *snd_pcm_get_chmap(snd_pcm_t *pcm);
|
|
||||||
int snd_pcm_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
|
|
||||||
|
|
||||||
+const char *snd_pcm_chmap_type_name(enum snd_pcm_chmap_type val);
|
|
||||||
+const char *snd_pcm_chmap_name(enum snd_pcm_chmap_position val);
|
|
||||||
+int snd_pcm_chmap_print(const snd_pcm_chmap_t *map, size_t maxlen, char *buf);
|
|
||||||
+unsigned int snd_pcm_chmap_from_string(const char *str);
|
|
||||||
+snd_pcm_chmap_t *snd_pcm_chmap_parse_string(const char *str);
|
|
||||||
+
|
|
||||||
//int snd_pcm_mixer_element(snd_pcm_t *pcm, snd_mixer_t *mixer, snd_mixer_elem_t **elem);
|
|
||||||
|
|
||||||
/*
|
|
||||||
--- a/src/pcm/pcm.c
|
|
||||||
+++ b/src/pcm/pcm.c
|
|
||||||
@@ -633,6 +633,7 @@ playback devices.
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <signal.h>
|
|
||||||
+#include <ctype.h>
|
|
||||||
#include <sys/poll.h>
|
|
||||||
#include <sys/shm.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
@@ -7356,6 +7357,147 @@ int snd_pcm_set_chmap(snd_pcm_t *pcm, co
|
|
||||||
return pcm->ops->set_chmap(pcm, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ */
|
|
||||||
+#define _NAME(n) [SND_CHMAP_TYPE_##n] = #n
|
|
||||||
+static const char *chmap_type_names[SND_CHMAP_TYPE_LAST + 1] = {
|
|
||||||
+ _NAME(NONE), _NAME(FIXED), _NAME(VAR), _NAME(PAIRED),
|
|
||||||
+};
|
|
||||||
+#undef _NAME
|
|
||||||
+
|
|
||||||
+const char *snd_pcm_chmap_type_name(enum snd_pcm_chmap_type val)
|
|
||||||
+{
|
|
||||||
+ if (val <= SND_CHMAP_TYPE_LAST)
|
|
||||||
+ return chmap_type_names[val];
|
|
||||||
+ else
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define _NAME(n) [SND_CHMAP_##n] = #n
|
|
||||||
+static const char *chmap_names[SND_CHMAP_LAST + 1] = {
|
|
||||||
+ _NAME(UNKNOWN),
|
|
||||||
+ _NAME(FL), _NAME(FR),
|
|
||||||
+ _NAME(RL), _NAME(RR),
|
|
||||||
+ _NAME(FC), _NAME(LFE),
|
|
||||||
+ _NAME(SL), _NAME(SR),
|
|
||||||
+ _NAME(RC), _NAME(FLC), _NAME(FRC), _NAME(RLC), _NAME(RRC),
|
|
||||||
+ _NAME(FLW), _NAME(FRW),
|
|
||||||
+ _NAME(FLH), _NAME(FCH), _NAME(FRH), _NAME(TC),
|
|
||||||
+ _NAME(NA),
|
|
||||||
+};
|
|
||||||
+#undef _NAME
|
|
||||||
+
|
|
||||||
+const char *snd_pcm_chmap_name(enum snd_pcm_chmap_position val)
|
|
||||||
+{
|
|
||||||
+ if (val <= SND_CHMAP_LAST)
|
|
||||||
+ return chmap_names[val];
|
|
||||||
+ else
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int snd_pcm_chmap_print(const snd_pcm_chmap_t *map, size_t maxlen, char *buf)
|
|
||||||
+{
|
|
||||||
+ unsigned int i, len = 0;
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < map->channels; i++) {
|
|
||||||
+ unsigned int p = map->pos[i] & SND_CHMAP_POSITION_MASK;
|
|
||||||
+ if (i > 0) {
|
|
||||||
+ len += snprintf(buf + len, maxlen - len, " ");
|
|
||||||
+ if (len >= maxlen)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+ }
|
|
||||||
+ if (map->pos[i] & SND_CHMAP_DRIVER_SPEC)
|
|
||||||
+ len += snprintf(buf + len, maxlen, "%d", p);
|
|
||||||
+ else {
|
|
||||||
+ const char *name = chmap_names[p];
|
|
||||||
+ if (name)
|
|
||||||
+ len += snprintf(buf + len, maxlen - len,
|
|
||||||
+ "%s", name);
|
|
||||||
+ else
|
|
||||||
+ len += snprintf(buf + len, maxlen - len,
|
|
||||||
+ "Ch%d", p);
|
|
||||||
+ }
|
|
||||||
+ if (len >= maxlen)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+ if (map->pos[i] & SND_CHMAP_PHASE_INVERSE) {
|
|
||||||
+ len += snprintf(buf + len, maxlen - len, "[INV]");
|
|
||||||
+ if (len >= maxlen)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return len;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int str_to_chmap(const char *str, int len)
|
|
||||||
+{
|
|
||||||
+ int val;
|
|
||||||
+
|
|
||||||
+ if (isdigit(*str)) {
|
|
||||||
+ val = atoi(str);
|
|
||||||
+ if (val < 0)
|
|
||||||
+ return -1;
|
|
||||||
+ return val | SND_CHMAP_DRIVER_SPEC;
|
|
||||||
+ } else if (str[0] == 'C' && str[1] == 'h') {
|
|
||||||
+ val = atoi(str + 2);
|
|
||||||
+ if (val < 0)
|
|
||||||
+ return -1;
|
|
||||||
+ return val;
|
|
||||||
+ } else {
|
|
||||||
+ for (val = 0; val <= SND_CHMAP_LAST; val++) {
|
|
||||||
+ if (!strncmp(str, chmap_names[val], len))
|
|
||||||
+ return val;
|
|
||||||
+ }
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+unsigned int snd_pcm_chmap_from_string(const char *str)
|
|
||||||
+{
|
|
||||||
+ return str_to_chmap(str, strlen(str));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+snd_pcm_chmap_t *snd_pcm_chmap_parse_string(const char *str)
|
|
||||||
+{
|
|
||||||
+ int i, ch = 0;
|
|
||||||
+ int tmp_map[64];
|
|
||||||
+ snd_pcm_chmap_t *map;
|
|
||||||
+
|
|
||||||
+ for (;;) {
|
|
||||||
+ const char *p;
|
|
||||||
+ int len, val;
|
|
||||||
+
|
|
||||||
+ if (ch >= (int)(sizeof(tmp_map) / sizeof(tmp_map[0])))
|
|
||||||
+ return NULL;
|
|
||||||
+ for (p = str; *p && isalnum(*p); p++)
|
|
||||||
+ ;
|
|
||||||
+ len = p - str;
|
|
||||||
+ if (!len)
|
|
||||||
+ return NULL;
|
|
||||||
+ val = str_to_chmap(str, len);
|
|
||||||
+ if (val < 0)
|
|
||||||
+ return NULL;
|
|
||||||
+ str += len;
|
|
||||||
+ if (*str == '[') {
|
|
||||||
+ if (!strncmp(str, "[INV]", 5)) {
|
|
||||||
+ val |= SND_CHMAP_PHASE_INVERSE;
|
|
||||||
+ str += 5;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ tmp_map[ch] = val;
|
|
||||||
+ ch++;
|
|
||||||
+ for (; *str && !isalnum(*str); str++)
|
|
||||||
+ ;
|
|
||||||
+ if (!*str)
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ map = malloc(sizeof(*map) + ch * sizeof(int));
|
|
||||||
+ if (!map)
|
|
||||||
+ return NULL;
|
|
||||||
+ map->channels = ch;
|
|
||||||
+ for (i = 0; i < ch; i++)
|
|
||||||
+ map->pos[i] = tmp_map[i];
|
|
||||||
+ return map;
|
|
||||||
+}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* basic helpers
|
|
||||||
--- a/test/chmap.c
|
|
||||||
+++ b/test/chmap.c
|
|
||||||
@@ -21,62 +21,11 @@ static void usage(void)
|
|
||||||
" -r rate Sample rate\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
-static const char * const chname[] = {
|
|
||||||
- "Unknown",
|
|
||||||
- "FL", "FR", "RL", "RR", "FC", "LFE", "SL", "SR", "RC",
|
|
||||||
- "FLC", "FRC", "RLC", "RRC", "FLW", "FRW", "FLH",
|
|
||||||
- "FCH", "FRH", "TC",
|
|
||||||
- "N/A",
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
|
||||||
-
|
|
||||||
static void print_channels(const snd_pcm_chmap_t *map)
|
|
||||||
{
|
|
||||||
- unsigned int i;
|
|
||||||
-
|
|
||||||
- printf(" ");
|
|
||||||
- for (i = 0; i < map->channels; i++) {
|
|
||||||
- unsigned int c = map->pos[i];
|
|
||||||
- unsigned int p = c & SND_CHMAP_POSITION_MASK;
|
|
||||||
- if (c & SND_CHMAP_DRIVER_SPEC)
|
|
||||||
- printf(" %d", p);
|
|
||||||
- else if (p >= ARRAY_SIZE(chname))
|
|
||||||
- printf(" Ch%d", p);
|
|
||||||
- else
|
|
||||||
- printf(" %s", chname[p]);
|
|
||||||
- if (c & SND_CHMAP_PHASE_INVERSE)
|
|
||||||
- printf("[INV]");
|
|
||||||
- }
|
|
||||||
- printf("\n");
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static int to_channel(const char *name)
|
|
||||||
-{
|
|
||||||
- unsigned int i;
|
|
||||||
-
|
|
||||||
- if (isdigit(*name))
|
|
||||||
- return atoi(name);
|
|
||||||
- for (i = 0; i < ARRAY_SIZE(chname); i++)
|
|
||||||
- if (!strcmp(chname[i], name))
|
|
||||||
- return i;
|
|
||||||
- return SND_CHMAP_UNKNOWN;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static const char *chmap_type(int type)
|
|
||||||
-{
|
|
||||||
- switch (type) {
|
|
||||||
- case SND_CHMAP_NONE:
|
|
||||||
- return "None";
|
|
||||||
- case SND_CHMAP_FIXED:
|
|
||||||
- return "Fixed";
|
|
||||||
- case SND_CHMAP_VAR:
|
|
||||||
- return "Variable";
|
|
||||||
- case SND_CHMAP_PAIRED:
|
|
||||||
- return "Paired";
|
|
||||||
- default:
|
|
||||||
- return "Unknown";
|
|
||||||
- }
|
|
||||||
+ char tmp[128];
|
|
||||||
+ if (snd_pcm_chmap_print(map, sizeof(tmp), tmp) > 0)
|
|
||||||
+ printf(" %s\n", tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int query_chmaps(snd_pcm_t *pcm)
|
|
||||||
@@ -89,7 +38,9 @@ static int query_chmaps(snd_pcm_t *pcm)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
for (p = maps; (v = *p) != NULL; p++) {
|
|
||||||
- printf("Type = %s, Channels = %d\n", chmap_type(v->type), v->map.channels);
|
|
||||||
+ printf("Type = %s, Channels = %d\n",
|
|
||||||
+ snd_pcm_chmap_type_name(v->type),
|
|
||||||
+ v->map.channels);
|
|
||||||
print_channels(&v->map);
|
|
||||||
}
|
|
||||||
snd_pcm_free_chmaps(maps);
|
|
||||||
@@ -173,8 +124,12 @@ static int set_chmap(snd_pcm_t *pcm, int
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
map->channels = channels;
|
|
||||||
- for (i = 0; i < channels; i++)
|
|
||||||
- map->pos[i] = to_channel(arg[i]);
|
|
||||||
+ for (i = 0; i < channels; i++) {
|
|
||||||
+ int val = snd_pcm_chmap_from_string(arg[i]);
|
|
||||||
+ if (val < 0)
|
|
||||||
+ val = SND_CHMAP_UNKNOWN;
|
|
||||||
+ map->pos[i] = val;
|
|
||||||
+ }
|
|
||||||
if (snd_pcm_set_chmap(pcm, map) < 0) {
|
|
||||||
printf("Cannot set chmap\n");
|
|
||||||
return 1;
|
|
@ -1,25 +0,0 @@
|
|||||||
From fe81684745e5c121e2d110bf6955e3f2858d2c7c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Tue, 11 Sep 2012 11:33:31 +0200
|
|
||||||
Subject: [PATCH 14/30] PCM: Add SND_CHMAP_API_VERSION definition
|
|
||||||
|
|
||||||
Just to make it easier for apps to support chmap conditionally via
|
|
||||||
simple ifdefs.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/pcm.h | 3 +++
|
|
||||||
1 file changed, 3 insertions(+)
|
|
||||||
|
|
||||||
--- a/include/pcm.h
|
|
||||||
+++ b/include/pcm.h
|
|
||||||
@@ -474,6 +474,9 @@ int snd_pcm_wait(snd_pcm_t *pcm, int tim
|
|
||||||
int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
|
|
||||||
int snd_pcm_unlink(snd_pcm_t *pcm);
|
|
||||||
|
|
||||||
+/** channel mapping API version number */
|
|
||||||
+#define SND_CHMAP_API_VERSION ((1 << 16) | (0 << 8) | 0)
|
|
||||||
+
|
|
||||||
/** channel map list type */
|
|
||||||
enum snd_pcm_chmap_type {
|
|
||||||
SND_CHMAP_TYPE_NONE = 0,/** unspecified channel position */
|
|
@ -1,65 +0,0 @@
|
|||||||
From 25f3259b48e921886bda58075936de3d53b84bc1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Tue, 11 Sep 2012 12:48:46 +0200
|
|
||||||
Subject: [PATCH 15/30] PCM: Add snd_pcm_chmap_long_name()
|
|
||||||
|
|
||||||
Just return a more verbose name than snd_pcm_chmap_name(), but
|
|
||||||
including white spaces.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/pcm.h | 1 +
|
|
||||||
src/pcm/pcm.c | 32 ++++++++++++++++++++++++++++++++
|
|
||||||
2 files changed, 33 insertions(+)
|
|
||||||
|
|
||||||
--- a/include/pcm.h
|
|
||||||
+++ b/include/pcm.h
|
|
||||||
@@ -539,6 +539,7 @@ int snd_pcm_set_chmap(snd_pcm_t *pcm, co
|
|
||||||
|
|
||||||
const char *snd_pcm_chmap_type_name(enum snd_pcm_chmap_type val);
|
|
||||||
const char *snd_pcm_chmap_name(enum snd_pcm_chmap_position val);
|
|
||||||
+const char *snd_pcm_chmap_long_name(enum snd_pcm_chmap_position val);
|
|
||||||
int snd_pcm_chmap_print(const snd_pcm_chmap_t *map, size_t maxlen, char *buf);
|
|
||||||
unsigned int snd_pcm_chmap_from_string(const char *str);
|
|
||||||
snd_pcm_chmap_t *snd_pcm_chmap_parse_string(const char *str);
|
|
||||||
--- a/src/pcm/pcm.c
|
|
||||||
+++ b/src/pcm/pcm.c
|
|
||||||
@@ -7395,6 +7395,38 @@ const char *snd_pcm_chmap_name(enum snd_
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static const char *chmap_long_names[SND_CHMAP_LAST + 1] = {
|
|
||||||
+ [SND_CHMAP_UNKNOWN] = "Unknown",
|
|
||||||
+ [SND_CHMAP_FL] = "Front Left",
|
|
||||||
+ [SND_CHMAP_FR] = "Front Right",
|
|
||||||
+ [SND_CHMAP_RL] = "Rear Left",
|
|
||||||
+ [SND_CHMAP_RR] = "Rear Right",
|
|
||||||
+ [SND_CHMAP_FC] = "Front Center",
|
|
||||||
+ [SND_CHMAP_LFE] = "LFE",
|
|
||||||
+ [SND_CHMAP_SL] = "Side Left",
|
|
||||||
+ [SND_CHMAP_SR] = "Side Right",
|
|
||||||
+ [SND_CHMAP_RC] = "Rear Center",
|
|
||||||
+ [SND_CHMAP_FLC] = "Front Left Center",
|
|
||||||
+ [SND_CHMAP_FRC] = "Front Right Center",
|
|
||||||
+ [SND_CHMAP_RLC] = "Rear Left Center",
|
|
||||||
+ [SND_CHMAP_RRC] = "Rear Right Center",
|
|
||||||
+ [SND_CHMAP_FLW] = "Front Left Wide",
|
|
||||||
+ [SND_CHMAP_FRW] = "Front Right Wide",
|
|
||||||
+ [SND_CHMAP_FLH] = "Front Left High",
|
|
||||||
+ [SND_CHMAP_FCH] = "Front Center High",
|
|
||||||
+ [SND_CHMAP_FRH] = "Front Right High",
|
|
||||||
+ [SND_CHMAP_TC] = "Top Center",
|
|
||||||
+ [SND_CHMAP_NA] = "Unused",
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+const char *snd_pcm_chmap_long_name(enum snd_pcm_chmap_position val)
|
|
||||||
+{
|
|
||||||
+ if (val <= SND_CHMAP_LAST)
|
|
||||||
+ return chmap_long_names[val];
|
|
||||||
+ else
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int snd_pcm_chmap_print(const snd_pcm_chmap_t *map, size_t maxlen, char *buf)
|
|
||||||
{
|
|
||||||
unsigned int i, len = 0;
|
|
@ -1,198 +0,0 @@
|
|||||||
From 81135aac49c8a3b547181d44f78ffe2594db5dbe Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Wed, 12 Sep 2012 12:56:14 +0200
|
|
||||||
Subject: [PATCH 16/30] PCM: Add query_chmaps support to multi plugin
|
|
||||||
|
|
||||||
Also fix some bugs in get_chmap().
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/pcm/pcm_multi.c | 152 +++++++++++++++++++++++++++++++++++++---------------
|
|
||||||
1 file changed, 111 insertions(+), 41 deletions(-)
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm_multi.c
|
|
||||||
+++ b/src/pcm/pcm_multi.c
|
|
||||||
@@ -739,64 +739,134 @@ static int snd_pcm_multi_mmap(snd_pcm_t
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static snd_pcm_chmap_query_t **snd_pcm_multi_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_multi_t *multi = pcm->private_data;
|
|
||||||
+ snd_pcm_chmap_query_t **slave_maps[multi->slaves_count];
|
|
||||||
+ snd_pcm_chmap_query_t **maps;
|
|
||||||
+ unsigned int i;
|
|
||||||
+ int err = -ENOMEM;
|
|
||||||
+
|
|
||||||
+ memset(slave_maps, 0, sizeof(slave_maps));
|
|
||||||
+ maps = calloc(2, sizeof(*maps));
|
|
||||||
+ if (!maps)
|
|
||||||
+ return NULL;
|
|
||||||
+ maps[0] = calloc(multi->channels_count + 2, sizeof(int *));
|
|
||||||
+ if (!maps[0])
|
|
||||||
+ goto error;
|
|
||||||
+ maps[0]->type = SND_CHMAP_TYPE_FIXED;
|
|
||||||
+ maps[0]->map.channels = multi->channels_count;
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < multi->slaves_count; i++) {
|
|
||||||
+ slave_maps[i] = snd_pcm_query_chmaps(multi->slaves[i].pcm);
|
|
||||||
+ if (!slave_maps[i])
|
|
||||||
+ goto error;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < multi->channels_count; i++) {
|
|
||||||
+ snd_pcm_multi_channel_t *bind = &multi->channels[i];
|
|
||||||
+ unsigned int slave_channels =
|
|
||||||
+ multi->slaves[bind->slave_idx].channels_count;
|
|
||||||
+ snd_pcm_chmap_query_t **p;
|
|
||||||
+
|
|
||||||
+ for (p = slave_maps[bind->slave_idx]; *p; p++) {
|
|
||||||
+ if ((*p)->map.channels == slave_channels) {
|
|
||||||
+ maps[0]->map.pos[i] =
|
|
||||||
+ (*p)->map.pos[bind->slave_channel];
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ err = 0;
|
|
||||||
+
|
|
||||||
+ error:
|
|
||||||
+ for (i = 0; i < multi->slaves_count; i++) {
|
|
||||||
+ if (slave_maps[i])
|
|
||||||
+ snd_pcm_free_chmaps(slave_maps[i]);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (err) {
|
|
||||||
+ snd_pcm_free_chmaps(maps);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return maps;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static snd_pcm_chmap_t *snd_pcm_multi_get_chmap(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
|
||||||
snd_pcm_chmap_t *map;
|
|
||||||
- unsigned int i, idx;
|
|
||||||
+ snd_pcm_chmap_t *slave_maps[multi->slaves_count];
|
|
||||||
+ unsigned int i;
|
|
||||||
+ int err = -ENOMEM;
|
|
||||||
|
|
||||||
- map = malloc(pcm->channels + 4);
|
|
||||||
+ memset(slave_maps, 0, sizeof(slave_maps));
|
|
||||||
+ map = calloc(multi->channels_count + 1, sizeof(int));
|
|
||||||
if (!map)
|
|
||||||
return NULL;
|
|
||||||
- idx = 0;
|
|
||||||
- for (i = 0; i < multi->slaves_count; ++i) {
|
|
||||||
- unsigned int c;
|
|
||||||
- snd_pcm_chmap_t *slave_map;
|
|
||||||
- slave_map = snd_pcm_get_chmap(multi->slaves[i].pcm);
|
|
||||||
- if (!slave_map) {
|
|
||||||
- free(map);
|
|
||||||
- return NULL;
|
|
||||||
- }
|
|
||||||
- for (c = 0; c < slave_map->channels; c++) {
|
|
||||||
- if (idx >= pcm->channels)
|
|
||||||
- break;
|
|
||||||
- map->pos[idx++] = slave_map->pos[c];
|
|
||||||
- }
|
|
||||||
- free(slave_map);
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < multi->slaves_count; i++) {
|
|
||||||
+ slave_maps[i] = snd_pcm_get_chmap(multi->slaves[i].pcm);
|
|
||||||
+ if (!slave_maps[i])
|
|
||||||
+ goto error;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ map->channels = multi->channels_count;
|
|
||||||
+ for (i = 0; i < multi->channels_count; i++) {
|
|
||||||
+ snd_pcm_multi_channel_t *bind = &multi->channels[i];
|
|
||||||
+ map->pos[i] = slave_maps[bind->slave_idx]->pos[bind->slave_channel];
|
|
||||||
+ }
|
|
||||||
+ err = 0;
|
|
||||||
+
|
|
||||||
+ error:
|
|
||||||
+ for (i = 0; i < multi->slaves_count; i++)
|
|
||||||
+ free(slave_maps[i]);
|
|
||||||
+
|
|
||||||
+ if (err) {
|
|
||||||
+ free(map);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int snd_pcm_multi_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
|
|
||||||
{
|
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
|
||||||
- const unsigned int *pos;
|
|
||||||
- unsigned int i, idx, chs;
|
|
||||||
- int err;
|
|
||||||
+ snd_pcm_chmap_t *slave_maps[multi->slaves_count];
|
|
||||||
+ unsigned int i;
|
|
||||||
+ int err = 0;
|
|
||||||
|
|
||||||
- chs = map->channels;
|
|
||||||
- if (chs != pcm->channels)
|
|
||||||
+ if (map->channels != multi->channels_count)
|
|
||||||
return -EINVAL;
|
|
||||||
- pos = map->pos;
|
|
||||||
- idx = 0;
|
|
||||||
- for (i = 0; i < multi->slaves_count; ++i) {
|
|
||||||
- snd_pcm_chmap_t *slave_map;
|
|
||||||
- unsigned int slave_chs;
|
|
||||||
- slave_chs = multi->slaves[i].channels_count;
|
|
||||||
- if (idx + slave_chs > chs)
|
|
||||||
- break;
|
|
||||||
- slave_map = malloc(slave_chs * 4 + 4);
|
|
||||||
- if (!slave_map)
|
|
||||||
- return -ENOMEM;
|
|
||||||
- slave_map->channels = slave_chs;
|
|
||||||
- memcpy(slave_map->pos, pos + idx, slave_chs * 4);
|
|
||||||
- err = snd_pcm_set_chmap(multi->slaves[i].pcm, slave_map);
|
|
||||||
- free(slave_map);
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < multi->slaves_count; i++) {
|
|
||||||
+ slave_maps[i] = calloc(multi->slaves[i].channels_count + 1,
|
|
||||||
+ sizeof(int));
|
|
||||||
+ if (!slave_maps[i]) {
|
|
||||||
+ err = -ENOMEM;
|
|
||||||
+ goto error;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < multi->channels_count; i++) {
|
|
||||||
+ snd_pcm_multi_channel_t *bind = &multi->channels[i];
|
|
||||||
+ slave_maps[bind->slave_idx]->pos[bind->slave_channel] =
|
|
||||||
+ map->pos[i];
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < multi->slaves_count; i++) {
|
|
||||||
+ err = snd_pcm_set_chmap(multi->slaves[i].pcm, slave_maps[i]);
|
|
||||||
if (err < 0)
|
|
||||||
- return err;
|
|
||||||
- idx += slave_chs;
|
|
||||||
+ goto error;
|
|
||||||
}
|
|
||||||
- return 0;
|
|
||||||
+
|
|
||||||
+ error:
|
|
||||||
+ for (i = 0; i < multi->slaves_count; i++)
|
|
||||||
+ free(slave_maps[i]);
|
|
||||||
+
|
|
||||||
+ return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void snd_pcm_multi_dump(snd_pcm_t *pcm, snd_output_t *out)
|
|
||||||
@@ -835,7 +905,7 @@ static const snd_pcm_ops_t snd_pcm_multi
|
|
||||||
.async = snd_pcm_multi_async,
|
|
||||||
.mmap = snd_pcm_multi_mmap,
|
|
||||||
.munmap = snd_pcm_multi_munmap,
|
|
||||||
- .query_chmaps = NULL, /* NYI */
|
|
||||||
+ .query_chmaps = snd_pcm_multi_query_chmaps,
|
|
||||||
.get_chmap = snd_pcm_multi_get_chmap,
|
|
||||||
.set_chmap = snd_pcm_multi_set_chmap,
|
|
||||||
};
|
|
@ -1,249 +0,0 @@
|
|||||||
From e1975d20f5d52b370b5e78f5eb5f80a33f55a656 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Wed, 12 Sep 2012 14:47:17 +0200
|
|
||||||
Subject: [PATCH 17/30] PCM: Add chmap options to hw and null plugins
|
|
||||||
|
|
||||||
Add a config definition "chmap" to override (or enhance) the channel
|
|
||||||
maps. So far, only a single channel map can be provided, and the
|
|
||||||
channel count consistency isn't strictly tested at all.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/pcm/pcm.c | 29 +++++++++++++++++++++++++++++
|
|
||||||
src/pcm/pcm_hw.c | 28 ++++++++++++++++++++++++++++
|
|
||||||
src/pcm/pcm_local.h | 5 +++++
|
|
||||||
src/pcm/pcm_null.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
||||||
4 files changed, 111 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm.c
|
|
||||||
+++ b/src/pcm/pcm.c
|
|
||||||
@@ -7531,6 +7531,35 @@ snd_pcm_chmap_t *snd_pcm_chmap_parse_str
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
+snd_pcm_chmap_query_t **
|
|
||||||
+_snd_pcm_make_single_query_chmaps(snd_pcm_chmap_t *src)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_chmap_query_t **maps;
|
|
||||||
+
|
|
||||||
+ maps = calloc(2, sizeof(*maps));
|
|
||||||
+ if (!maps)
|
|
||||||
+ return NULL;
|
|
||||||
+ *maps = malloc((src->channels + 2) * sizeof(int));
|
|
||||||
+ if (!*maps) {
|
|
||||||
+ free(maps);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+ (*maps)->type = SND_CHMAP_TYPE_FIXED;
|
|
||||||
+ memcpy(&(*maps)->map, src, (src->channels + 1) * sizeof(int));
|
|
||||||
+ return maps;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+snd_pcm_chmap_t *_snd_pcm_copy_chmap(snd_pcm_chmap_t *src)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_chmap_t *map;
|
|
||||||
+
|
|
||||||
+ map = malloc((src->channels + 1) * sizeof(int));
|
|
||||||
+ if (!map)
|
|
||||||
+ return NULL;
|
|
||||||
+ memcpy(map, src, (src->channels + 1) * sizeof(int));
|
|
||||||
+ return map;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* basic helpers
|
|
||||||
*/
|
|
||||||
--- a/src/pcm/pcm_hw.c
|
|
||||||
+++ b/src/pcm/pcm_hw.c
|
|
||||||
@@ -107,6 +107,7 @@ typedef struct {
|
|
||||||
int channels;
|
|
||||||
/* for chmap */
|
|
||||||
unsigned int chmap_caps;
|
|
||||||
+ snd_pcm_chmap_t *chmap_override;
|
|
||||||
} snd_pcm_hw_t;
|
|
||||||
|
|
||||||
#define SNDRV_FILE_PCM_STREAM_PLAYBACK ALSA_DEVICE_DIRECTORY "pcmC%iD%ip"
|
|
||||||
@@ -1144,6 +1145,9 @@ static snd_pcm_chmap_query_t **snd_pcm_h
|
|
||||||
snd_pcm_hw_t *hw = pcm->private_data;
|
|
||||||
snd_pcm_chmap_query_t **map;
|
|
||||||
|
|
||||||
+ if (hw->chmap_override)
|
|
||||||
+ return _snd_pcm_make_single_query_chmaps(hw->chmap_override);
|
|
||||||
+
|
|
||||||
if (!chmap_caps(hw, CHMAP_CTL_QUERY))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
@@ -1166,6 +1170,9 @@ static snd_pcm_chmap_t *snd_pcm_hw_get_c
|
|
||||||
unsigned int i;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
+ if (hw->chmap_override)
|
|
||||||
+ return _snd_pcm_copy_chmap(hw->chmap_override);
|
|
||||||
+
|
|
||||||
if (!chmap_caps(hw, CHMAP_CTL_GET))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
@@ -1220,6 +1227,9 @@ static int snd_pcm_hw_set_chmap(snd_pcm_
|
|
||||||
unsigned int i;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
+ if (hw->chmap_override)
|
|
||||||
+ return -ENXIO;
|
|
||||||
+
|
|
||||||
if (!chmap_caps(hw, CHMAP_CTL_SET))
|
|
||||||
return -ENXIO;
|
|
||||||
|
|
||||||
@@ -1593,6 +1603,7 @@ pcm.name {
|
|
||||||
[format STR] # Restrict only to the given format
|
|
||||||
[channels INT] # Restrict only to the given channels
|
|
||||||
[rate INT] # Restrict only to the given rate
|
|
||||||
+ [chmap MAP] # Override channel map
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
@@ -1629,6 +1640,7 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, c
|
|
||||||
snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
|
|
||||||
snd_config_t *n;
|
|
||||||
int nonblock = 1; /* non-block per default */
|
|
||||||
+ snd_pcm_chmap_t *chmap = NULL;
|
|
||||||
snd_pcm_hw_t *hw;
|
|
||||||
|
|
||||||
/* look for defaults.pcm.nonblock definition */
|
|
||||||
@@ -1719,6 +1731,20 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, c
|
|
||||||
channels = val;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
+ if (strcmp(id, "chmap") == 0) {
|
|
||||||
+ err = snd_config_get_string(n, &str);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ SNDERR("Invalid type for %s", id);
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ }
|
|
||||||
+ free(chmap);
|
|
||||||
+ chmap = snd_pcm_chmap_parse_string(str);
|
|
||||||
+ if (!chmap) {
|
|
||||||
+ SNDERR("Invalid channel map for %s", id);
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ }
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
SNDERR("Unknown field %s", id);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
@@ -1750,6 +1776,8 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, c
|
|
||||||
hw->channels = channels;
|
|
||||||
if (rate > 0)
|
|
||||||
hw->rate = rate;
|
|
||||||
+ if (chmap)
|
|
||||||
+ hw->chmap_override = chmap;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
--- a/src/pcm/pcm_local.h
|
|
||||||
+++ b/src/pcm/pcm_local.h
|
|
||||||
@@ -973,3 +973,8 @@ static inline void gettimestamp(snd_htim
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+snd_pcm_chmap_query_t **
|
|
||||||
+_snd_pcm_make_single_query_chmaps(snd_pcm_chmap_t *src);
|
|
||||||
+snd_pcm_chmap_t *_snd_pcm_copy_chmap(snd_pcm_chmap_t *src);
|
|
||||||
+
|
|
||||||
--- a/src/pcm/pcm_null.c
|
|
||||||
+++ b/src/pcm/pcm_null.c
|
|
||||||
@@ -44,6 +44,7 @@ typedef struct {
|
|
||||||
snd_pcm_uframes_t appl_ptr;
|
|
||||||
snd_pcm_uframes_t hw_ptr;
|
|
||||||
int poll_fd;
|
|
||||||
+ snd_pcm_chmap_t *chmap;
|
|
||||||
} snd_pcm_null_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -268,6 +269,24 @@ static int snd_pcm_null_sw_params(snd_pc
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static snd_pcm_chmap_query_t **snd_pcm_null_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_null_t *null = pcm->private_data;
|
|
||||||
+
|
|
||||||
+ if (null->chmap)
|
|
||||||
+ return _snd_pcm_make_single_query_chmaps(null->chmap);
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static snd_pcm_chmap_t *snd_pcm_null_get_chmap(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_null_t *null = pcm->private_data;
|
|
||||||
+
|
|
||||||
+ if (null->chmap)
|
|
||||||
+ return _snd_pcm_copy_chmap(null->chmap);
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void snd_pcm_null_dump(snd_pcm_t *pcm, snd_output_t *out)
|
|
||||||
{
|
|
||||||
snd_output_printf(out, "Null PCM\n");
|
|
||||||
@@ -290,6 +309,9 @@ static const snd_pcm_ops_t snd_pcm_null_
|
|
||||||
.async = snd_pcm_null_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
+ .query_chmaps = snd_pcm_null_query_chmaps,
|
|
||||||
+ .get_chmap = snd_pcm_null_get_chmap,
|
|
||||||
+ .set_chmap = NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const snd_pcm_fast_ops_t snd_pcm_null_fast_ops = {
|
|
||||||
@@ -385,6 +407,7 @@ and /dev/full (capture, must be readable
|
|
||||||
\code
|
|
||||||
pcm.name {
|
|
||||||
type null # Null PCM
|
|
||||||
+ [chmap MAP]
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
@@ -415,6 +438,10 @@ int _snd_pcm_null_open(snd_pcm_t **pcmp,
|
|
||||||
snd_pcm_stream_t stream, int mode)
|
|
||||||
{
|
|
||||||
snd_config_iterator_t i, next;
|
|
||||||
+ snd_pcm_null_t *null;
|
|
||||||
+ snd_pcm_chmap_t *chmap = NULL;
|
|
||||||
+ int err;
|
|
||||||
+
|
|
||||||
snd_config_for_each(i, next, conf) {
|
|
||||||
snd_config_t *n = snd_config_iterator_entry(i);
|
|
||||||
const char *id;
|
|
||||||
@@ -422,10 +449,31 @@ int _snd_pcm_null_open(snd_pcm_t **pcmp,
|
|
||||||
continue;
|
|
||||||
if (snd_pcm_conf_generic_id(id))
|
|
||||||
continue;
|
|
||||||
+ if (strcmp(id, "chmap") == 0) {
|
|
||||||
+ const char *str;
|
|
||||||
+ err = snd_config_get_string(n, &str);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ SNDERR("Invalid type for %s", id);
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ }
|
|
||||||
+ free(chmap);
|
|
||||||
+ chmap = snd_pcm_chmap_parse_string(str);
|
|
||||||
+ if (!chmap) {
|
|
||||||
+ SNDERR("Invalid channel map for %s", id);
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ }
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
SNDERR("Unknown field %s", id);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
- return snd_pcm_null_open(pcmp, name, stream, mode);
|
|
||||||
+ err = snd_pcm_null_open(pcmp, name, stream, mode);
|
|
||||||
+ if (err < 0)
|
|
||||||
+ return err;
|
|
||||||
+
|
|
||||||
+ null = (*pcmp)->private_data;
|
|
||||||
+ null->chmap = chmap;
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
#ifndef DOC_HIDDEN
|
|
||||||
SND_DLSYM_BUILD_VERSION(_snd_pcm_null_open, SND_PCM_DLSYM_VERSION);
|
|
@ -1,85 +0,0 @@
|
|||||||
From a102028a5a747ecdf1d6fcd16aef0994477a951b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Wed, 12 Sep 2012 15:09:57 +0200
|
|
||||||
Subject: [PATCH 18/30] PCM: Add the missing query_chmaps for route plugin
|
|
||||||
|
|
||||||
Also fix the channel count in get_chmap for route plugin.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/pcm/pcm_route.c | 24 +++++++++++++++++++-----
|
|
||||||
1 file changed, 19 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm_route.c
|
|
||||||
+++ b/src/pcm/pcm_route.c
|
|
||||||
@@ -67,6 +67,7 @@ typedef struct {
|
|
||||||
int use_getput;
|
|
||||||
unsigned int src_size;
|
|
||||||
snd_pcm_format_t dst_sfmt;
|
|
||||||
+ unsigned int nsrcs;
|
|
||||||
unsigned int ndsts;
|
|
||||||
snd_pcm_route_ttable_dst_t *dsts;
|
|
||||||
} snd_pcm_route_params_t;
|
|
||||||
@@ -707,22 +708,23 @@ static snd_pcm_chmap_t *snd_pcm_route_ge
|
|
||||||
{
|
|
||||||
snd_pcm_route_t *route = pcm->private_data;
|
|
||||||
snd_pcm_chmap_t *map, *slave_map;
|
|
||||||
- unsigned int src, dst;
|
|
||||||
+ unsigned int src, dst, nsrcs;
|
|
||||||
|
|
||||||
slave_map = snd_pcm_generic_get_chmap(pcm);
|
|
||||||
if (!slave_map)
|
|
||||||
return NULL;
|
|
||||||
- map = calloc(4, route->schannels + 1);
|
|
||||||
+ nsrcs = route->params.nsrcs;
|
|
||||||
+ map = calloc(4, nsrcs + 1);
|
|
||||||
if (!map) {
|
|
||||||
free(slave_map);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
- map->channels = route->schannels;
|
|
||||||
+ map->channels = nsrcs;
|
|
||||||
for (dst = 0; dst < route->params.ndsts; dst++) {
|
|
||||||
snd_pcm_route_ttable_dst_t *d = &route->params.dsts[dst];
|
|
||||||
for (src = 0; src < d->nsrcs; src++) {
|
|
||||||
int c = d->srcs[src].channel;
|
|
||||||
- if (c < route->schannels && !map->pos[c])
|
|
||||||
+ if (c < nsrcs && !map->pos[c])
|
|
||||||
map->pos[c] = slave_map->pos[dst];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -730,6 +732,17 @@ static snd_pcm_chmap_t *snd_pcm_route_ge
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static snd_pcm_chmap_query_t **snd_pcm_route_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_chmap_query_t **maps;
|
|
||||||
+ snd_pcm_chmap_t *map = snd_pcm_route_get_chmap(pcm);
|
|
||||||
+ if (!map)
|
|
||||||
+ return NULL;
|
|
||||||
+ maps = _snd_pcm_make_single_query_chmaps(map);
|
|
||||||
+ free(map);
|
|
||||||
+ return maps;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void snd_pcm_route_dump(snd_pcm_t *pcm, snd_output_t *out)
|
|
||||||
{
|
|
||||||
snd_pcm_route_t *route = pcm->private_data;
|
|
||||||
@@ -787,7 +800,7 @@ static const snd_pcm_ops_t snd_pcm_route
|
|
||||||
.async = snd_pcm_generic_async,
|
|
||||||
.mmap = snd_pcm_generic_mmap,
|
|
||||||
.munmap = snd_pcm_generic_munmap,
|
|
||||||
- .query_chmaps = NULL, /* NYI */
|
|
||||||
+ .query_chmaps = snd_pcm_route_query_chmaps,
|
|
||||||
.get_chmap = snd_pcm_route_get_chmap,
|
|
||||||
.set_chmap = NULL, /* NYI */
|
|
||||||
};
|
|
||||||
@@ -812,6 +825,7 @@ static int route_load_ttable(snd_pcm_rou
|
|
||||||
dmul = tt_ssize;
|
|
||||||
}
|
|
||||||
params->ndsts = dused;
|
|
||||||
+ params->nsrcs = sused;
|
|
||||||
dptr = calloc(dused, sizeof(*params->dsts));
|
|
||||||
if (!dptr)
|
|
||||||
return -ENOMEM;
|
|
@ -1,104 +0,0 @@
|
|||||||
From 5ba11d69dafbd4502469fd957b4580169779664c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Wed, 12 Sep 2012 15:15:32 +0200
|
|
||||||
Subject: [PATCH 19/30] Add chmap override definitions for Emu10k1, Audigy and
|
|
||||||
Audigy2 cards
|
|
||||||
|
|
||||||
These cards won't provide the channel maps from the driver itself
|
|
||||||
because of the dynamic routing. For simplicity, define chmaps in the
|
|
||||||
configurations, so that chmap querying of individual stereo streams
|
|
||||||
and combined multi streams works properly.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/conf/cards/Audigy.conf | 3 +++
|
|
||||||
src/conf/cards/Audigy2.conf | 4 ++++
|
|
||||||
src/conf/cards/EMU10K1.conf | 3 +++
|
|
||||||
3 files changed, 10 insertions(+)
|
|
||||||
|
|
||||||
--- a/src/conf/cards/Audigy.conf
|
|
||||||
+++ b/src/conf/cards/Audigy.conf
|
|
||||||
@@ -13,6 +13,7 @@ Audigy.pcm.front.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
+ chmap "FL,FR"
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
@@ -65,6 +66,7 @@ Audigy.pcm.rear.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
+ chmap "RL,RR"
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
@@ -100,6 +102,7 @@ Audigy.pcm.center_lfe.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
+ chmap "FC,LFE"
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
--- a/src/conf/cards/Audigy2.conf
|
|
||||||
+++ b/src/conf/cards/Audigy2.conf
|
|
||||||
@@ -13,6 +13,7 @@ Audigy2.pcm.front.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
+ chmap "FL,FR"
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
@@ -65,6 +66,7 @@ Audigy2.pcm.rear.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
+ chmap "RL,RR"
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
@@ -100,6 +102,7 @@ Audigy2.pcm.center_lfe.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
+ chmap "FC,LFE"
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
@@ -151,6 +154,7 @@ Audigy2.pcm.side.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
+ chmap "SL,SR"
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
--- a/src/conf/cards/EMU10K1.conf
|
|
||||||
+++ b/src/conf/cards/EMU10K1.conf
|
|
||||||
@@ -15,6 +15,7 @@ EMU10K1.pcm.front.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
+ chmap "FL,FR"
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
@@ -73,6 +74,7 @@ EMU10K1.pcm.rear.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
+ chmap "RL,RR"
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
@@ -111,6 +113,7 @@ EMU10K1.pcm.center_lfe.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
+ chmap "FC,LFE"
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
@ -1,438 +0,0 @@
|
|||||||
From ec7acfc408856cfe71a122e3b5387463d7b3d919 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Wed, 12 Sep 2012 17:13:22 +0200
|
|
||||||
Subject: [PATCH 20/30] PCM: Use compounds for overriding / enhancing chmaps
|
|
||||||
|
|
||||||
Instead of a single channel map, multiple channel maps can be provided
|
|
||||||
in a form of compound (array) to hw and null plugins. In null
|
|
||||||
get_chmap, the channel map corresponding to the current channels is
|
|
||||||
copied from the given channel maps.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/conf/cards/Audigy.conf | 6 +-
|
|
||||||
src/conf/cards/Audigy2.conf | 8 +--
|
|
||||||
src/conf/cards/EMU10K1.conf | 6 +-
|
|
||||||
src/pcm/pcm.c | 109 +++++++++++++++++++++++++++++++++++++++++---
|
|
||||||
src/pcm/pcm_hw.c | 25 ++++------
|
|
||||||
src/pcm/pcm_local.h | 10 +++-
|
|
||||||
src/pcm/pcm_null.c | 25 ++++------
|
|
||||||
7 files changed, 144 insertions(+), 45 deletions(-)
|
|
||||||
|
|
||||||
--- a/src/conf/cards/Audigy.conf
|
|
||||||
+++ b/src/conf/cards/Audigy.conf
|
|
||||||
@@ -13,7 +13,7 @@ Audigy.pcm.front.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
- chmap "FL,FR"
|
|
||||||
+ chmap [ "UNKNOWN" "FL,FR" ]
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
@@ -66,7 +66,7 @@ Audigy.pcm.rear.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
- chmap "RL,RR"
|
|
||||||
+ chmap [ "UNKNOWN" "RL,RR" ]
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
@@ -102,7 +102,7 @@ Audigy.pcm.center_lfe.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
- chmap "FC,LFE"
|
|
||||||
+ chmap [ "UNKNOWN" "FC,LFE" ]
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
--- a/src/conf/cards/Audigy2.conf
|
|
||||||
+++ b/src/conf/cards/Audigy2.conf
|
|
||||||
@@ -13,7 +13,7 @@ Audigy2.pcm.front.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
- chmap "FL,FR"
|
|
||||||
+ chmap [ "UNKNOWN" "FL,FR" ]
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
@@ -66,7 +66,7 @@ Audigy2.pcm.rear.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
- chmap "RL,RR"
|
|
||||||
+ chmap [ "UNKNOWN" "RL,RR" ]
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
@@ -102,7 +102,7 @@ Audigy2.pcm.center_lfe.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
- chmap "FC,LFE"
|
|
||||||
+ chmap [ "UNKNOWN" "FC,LFE" ]
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
@@ -154,7 +154,7 @@ Audigy2.pcm.side.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
- chmap "SL,SR"
|
|
||||||
+ chmap [ "UNKNOWN" "SL,SR" ]
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
--- a/src/conf/cards/EMU10K1.conf
|
|
||||||
+++ b/src/conf/cards/EMU10K1.conf
|
|
||||||
@@ -15,7 +15,7 @@ EMU10K1.pcm.front.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
- chmap "FL,FR"
|
|
||||||
+ chmap [ "UNKNOWN" "FL,FR" ]
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
@@ -74,7 +74,7 @@ EMU10K1.pcm.rear.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
- chmap "RL,RR"
|
|
||||||
+ chmap [ "UNKNOWN" "RL,RR" ]
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
@@ -113,7 +113,7 @@ EMU10K1.pcm.center_lfe.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
- chmap "FC,LFE"
|
|
||||||
+ chmap [ "UNKNOWN" "FC,LFE" ]
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
--- a/src/pcm/pcm.c
|
|
||||||
+++ b/src/pcm/pcm.c
|
|
||||||
@@ -7531,25 +7531,37 @@ snd_pcm_chmap_t *snd_pcm_chmap_parse_str
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
+/* copy a single channel map with the fixed type to chmap_query pointer */
|
|
||||||
+static int _copy_to_fixed_query_map(snd_pcm_chmap_query_t **dst,
|
|
||||||
+ const snd_pcm_chmap_t *src)
|
|
||||||
+{
|
|
||||||
+ *dst = malloc((src->channels + 2) * sizeof(int));
|
|
||||||
+ if (!*dst)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+ (*dst)->type = SND_CHMAP_TYPE_FIXED;
|
|
||||||
+ memcpy(&(*dst)->map, src, (src->channels + 1) * sizeof(int));
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#ifndef DOC_HIDDEN
|
|
||||||
+/* make a chmap_query array from a single channel map */
|
|
||||||
snd_pcm_chmap_query_t **
|
|
||||||
-_snd_pcm_make_single_query_chmaps(snd_pcm_chmap_t *src)
|
|
||||||
+_snd_pcm_make_single_query_chmaps(const snd_pcm_chmap_t *src)
|
|
||||||
{
|
|
||||||
snd_pcm_chmap_query_t **maps;
|
|
||||||
|
|
||||||
maps = calloc(2, sizeof(*maps));
|
|
||||||
if (!maps)
|
|
||||||
return NULL;
|
|
||||||
- *maps = malloc((src->channels + 2) * sizeof(int));
|
|
||||||
- if (!*maps) {
|
|
||||||
+ if (_copy_to_fixed_query_map(maps, src)) {
|
|
||||||
free(maps);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
- (*maps)->type = SND_CHMAP_TYPE_FIXED;
|
|
||||||
- memcpy(&(*maps)->map, src, (src->channels + 1) * sizeof(int));
|
|
||||||
return maps;
|
|
||||||
}
|
|
||||||
|
|
||||||
-snd_pcm_chmap_t *_snd_pcm_copy_chmap(snd_pcm_chmap_t *src)
|
|
||||||
+/* make a copy of chmap */
|
|
||||||
+snd_pcm_chmap_t *_snd_pcm_copy_chmap(const snd_pcm_chmap_t *src)
|
|
||||||
{
|
|
||||||
snd_pcm_chmap_t *map;
|
|
||||||
|
|
||||||
@@ -7560,6 +7572,91 @@ snd_pcm_chmap_t *_snd_pcm_copy_chmap(snd
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
+/* make a copy of channel maps */
|
|
||||||
+snd_pcm_chmap_query_t **
|
|
||||||
+_snd_pcm_copy_chmap_query(snd_pcm_chmap_query_t * const *src)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_chmap_query_t * const *p;
|
|
||||||
+ snd_pcm_chmap_query_t **maps;
|
|
||||||
+ int i, nums;
|
|
||||||
+
|
|
||||||
+ for (nums = 0, p = src; *p; p++)
|
|
||||||
+ nums++;
|
|
||||||
+
|
|
||||||
+ maps = calloc(nums + 1, sizeof(*maps));
|
|
||||||
+ if (!maps)
|
|
||||||
+ return NULL;
|
|
||||||
+ for (i = 0; i < nums; i++) {
|
|
||||||
+ maps[i] = malloc((src[i]->map.channels + 2) * sizeof(int));
|
|
||||||
+ if (!maps[i]) {
|
|
||||||
+ snd_pcm_free_chmaps(maps);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+ memcpy(maps[i], src[i], (src[i]->map.channels + 2) * sizeof(int));
|
|
||||||
+ }
|
|
||||||
+ return maps;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* select the channel map with the current PCM channels and make a copy */
|
|
||||||
+snd_pcm_chmap_t *
|
|
||||||
+_snd_pcm_choose_fixed_chmap(snd_pcm_t *pcm, snd_pcm_chmap_query_t * const *maps)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_chmap_query_t * const *p;
|
|
||||||
+
|
|
||||||
+ for (p = maps; *p; p++) {
|
|
||||||
+ if ((*p)->map.channels == pcm->channels)
|
|
||||||
+ return _snd_pcm_copy_chmap(&(*p)->map);
|
|
||||||
+ }
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* make chmap_query array from the config tree;
|
|
||||||
+ * conf must be a compound (array)
|
|
||||||
+ */
|
|
||||||
+snd_pcm_chmap_query_t **
|
|
||||||
+_snd_pcm_parse_config_chmaps(snd_config_t *conf)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_chmap_t *chmap;
|
|
||||||
+ snd_pcm_chmap_query_t **maps;
|
|
||||||
+ snd_config_iterator_t i, next;
|
|
||||||
+ const char *str;
|
|
||||||
+ int nums, err;
|
|
||||||
+
|
|
||||||
+ if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ nums = 0;
|
|
||||||
+ snd_config_for_each(i, next, conf) {
|
|
||||||
+ nums++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ maps = calloc(nums + 1, sizeof(*maps));
|
|
||||||
+ if (!maps)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ nums = 0;
|
|
||||||
+ snd_config_for_each(i, next, conf) {
|
|
||||||
+ snd_config_t *n = snd_config_iterator_entry(i);
|
|
||||||
+ err = snd_config_get_string(n, &str);
|
|
||||||
+ if (err < 0)
|
|
||||||
+ goto error;
|
|
||||||
+ chmap = snd_pcm_chmap_parse_string(str);
|
|
||||||
+ if (!chmap)
|
|
||||||
+ goto error;
|
|
||||||
+ if (_copy_to_fixed_query_map(maps + nums, chmap)) {
|
|
||||||
+ free(chmap);
|
|
||||||
+ goto error;
|
|
||||||
+ }
|
|
||||||
+ nums++;
|
|
||||||
+ }
|
|
||||||
+ return maps;
|
|
||||||
+
|
|
||||||
+ error:
|
|
||||||
+ snd_pcm_free_chmaps(maps);
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+#endif /* DOC_HIDDEN */
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* basic helpers
|
|
||||||
*/
|
|
||||||
--- a/src/pcm/pcm_hw.c
|
|
||||||
+++ b/src/pcm/pcm_hw.c
|
|
||||||
@@ -107,7 +107,7 @@ typedef struct {
|
|
||||||
int channels;
|
|
||||||
/* for chmap */
|
|
||||||
unsigned int chmap_caps;
|
|
||||||
- snd_pcm_chmap_t *chmap_override;
|
|
||||||
+ snd_pcm_chmap_query_t **chmap_override;
|
|
||||||
} snd_pcm_hw_t;
|
|
||||||
|
|
||||||
#define SNDRV_FILE_PCM_STREAM_PLAYBACK ALSA_DEVICE_DIRECTORY "pcmC%iD%ip"
|
|
||||||
@@ -1146,7 +1146,7 @@ static snd_pcm_chmap_query_t **snd_pcm_h
|
|
||||||
snd_pcm_chmap_query_t **map;
|
|
||||||
|
|
||||||
if (hw->chmap_override)
|
|
||||||
- return _snd_pcm_make_single_query_chmaps(hw->chmap_override);
|
|
||||||
+ return _snd_pcm_copy_chmap_query(hw->chmap_override);
|
|
||||||
|
|
||||||
if (!chmap_caps(hw, CHMAP_CTL_QUERY))
|
|
||||||
return NULL;
|
|
||||||
@@ -1171,7 +1171,7 @@ static snd_pcm_chmap_t *snd_pcm_hw_get_c
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (hw->chmap_override)
|
|
||||||
- return _snd_pcm_copy_chmap(hw->chmap_override);
|
|
||||||
+ return _snd_pcm_choose_fixed_chmap(pcm, hw->chmap_override);
|
|
||||||
|
|
||||||
if (!chmap_caps(hw, CHMAP_CTL_GET))
|
|
||||||
return NULL;
|
|
||||||
@@ -1603,7 +1603,7 @@ pcm.name {
|
|
||||||
[format STR] # Restrict only to the given format
|
|
||||||
[channels INT] # Restrict only to the given channels
|
|
||||||
[rate INT] # Restrict only to the given rate
|
|
||||||
- [chmap MAP] # Override channel map
|
|
||||||
+ [chmap MAP] # Override channel maps; MAP is a string array
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
@@ -1640,7 +1640,7 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, c
|
|
||||||
snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
|
|
||||||
snd_config_t *n;
|
|
||||||
int nonblock = 1; /* non-block per default */
|
|
||||||
- snd_pcm_chmap_t *chmap = NULL;
|
|
||||||
+ snd_pcm_chmap_query_t **chmap = NULL;
|
|
||||||
snd_pcm_hw_t *hw;
|
|
||||||
|
|
||||||
/* look for defaults.pcm.nonblock definition */
|
|
||||||
@@ -1732,13 +1732,8 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, c
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (strcmp(id, "chmap") == 0) {
|
|
||||||
- err = snd_config_get_string(n, &str);
|
|
||||||
- if (err < 0) {
|
|
||||||
- SNDERR("Invalid type for %s", id);
|
|
||||||
- return -EINVAL;
|
|
||||||
- }
|
|
||||||
- free(chmap);
|
|
||||||
- chmap = snd_pcm_chmap_parse_string(str);
|
|
||||||
+ snd_pcm_free_chmaps(chmap);
|
|
||||||
+ chmap = _snd_pcm_parse_config_chmaps(n);
|
|
||||||
if (!chmap) {
|
|
||||||
SNDERR("Invalid channel map for %s", id);
|
|
||||||
return -EINVAL;
|
|
||||||
@@ -1746,17 +1741,21 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, c
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SNDERR("Unknown field %s", id);
|
|
||||||
+ snd_pcm_free_chmaps(chmap);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if (card < 0) {
|
|
||||||
SNDERR("card is not defined");
|
|
||||||
+ snd_pcm_free_chmaps(chmap);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
err = snd_pcm_hw_open(pcmp, name, card, device, subdevice, stream,
|
|
||||||
mode | (nonblock ? SND_PCM_NONBLOCK : 0),
|
|
||||||
0, sync_ptr_ioctl);
|
|
||||||
- if (err < 0)
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ snd_pcm_free_chmaps(chmap);
|
|
||||||
return err;
|
|
||||||
+ }
|
|
||||||
if (nonblock && ! (mode & SND_PCM_NONBLOCK)) {
|
|
||||||
/* revert to blocking mode for read/write access */
|
|
||||||
snd_pcm_hw_nonblock(*pcmp, 0);
|
|
||||||
--- a/src/pcm/pcm_local.h
|
|
||||||
+++ b/src/pcm/pcm_local.h
|
|
||||||
@@ -975,6 +975,12 @@ static inline void gettimestamp(snd_htim
|
|
||||||
}
|
|
||||||
|
|
||||||
snd_pcm_chmap_query_t **
|
|
||||||
-_snd_pcm_make_single_query_chmaps(snd_pcm_chmap_t *src);
|
|
||||||
-snd_pcm_chmap_t *_snd_pcm_copy_chmap(snd_pcm_chmap_t *src);
|
|
||||||
+_snd_pcm_make_single_query_chmaps(const snd_pcm_chmap_t *src);
|
|
||||||
+snd_pcm_chmap_t *_snd_pcm_copy_chmap(const snd_pcm_chmap_t *src);
|
|
||||||
+snd_pcm_chmap_query_t **
|
|
||||||
+_snd_pcm_copy_chmap_query(snd_pcm_chmap_query_t * const *src);
|
|
||||||
+snd_pcm_chmap_query_t **
|
|
||||||
+_snd_pcm_parse_config_chmaps(snd_config_t *conf);
|
|
||||||
+snd_pcm_chmap_t *
|
|
||||||
+_snd_pcm_choose_fixed_chmap(snd_pcm_t *pcm, snd_pcm_chmap_query_t * const *maps);
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm_null.c
|
|
||||||
+++ b/src/pcm/pcm_null.c
|
|
||||||
@@ -44,7 +44,7 @@ typedef struct {
|
|
||||||
snd_pcm_uframes_t appl_ptr;
|
|
||||||
snd_pcm_uframes_t hw_ptr;
|
|
||||||
int poll_fd;
|
|
||||||
- snd_pcm_chmap_t *chmap;
|
|
||||||
+ snd_pcm_chmap_query_t **chmap;
|
|
||||||
} snd_pcm_null_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -274,7 +274,7 @@ static snd_pcm_chmap_query_t **snd_pcm_n
|
|
||||||
snd_pcm_null_t *null = pcm->private_data;
|
|
||||||
|
|
||||||
if (null->chmap)
|
|
||||||
- return _snd_pcm_make_single_query_chmaps(null->chmap);
|
|
||||||
+ return _snd_pcm_copy_chmap_query(null->chmap);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -283,7 +283,7 @@ static snd_pcm_chmap_t *snd_pcm_null_get
|
|
||||||
snd_pcm_null_t *null = pcm->private_data;
|
|
||||||
|
|
||||||
if (null->chmap)
|
|
||||||
- return _snd_pcm_copy_chmap(null->chmap);
|
|
||||||
+ return _snd_pcm_choose_fixed_chmap(pcm, null->chmap);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -407,7 +407,7 @@ and /dev/full (capture, must be readable
|
|
||||||
\code
|
|
||||||
pcm.name {
|
|
||||||
type null # Null PCM
|
|
||||||
- [chmap MAP]
|
|
||||||
+ [chmap MAP] # Provide channel maps; MAP is a string array
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
@@ -439,7 +439,7 @@ int _snd_pcm_null_open(snd_pcm_t **pcmp,
|
|
||||||
{
|
|
||||||
snd_config_iterator_t i, next;
|
|
||||||
snd_pcm_null_t *null;
|
|
||||||
- snd_pcm_chmap_t *chmap = NULL;
|
|
||||||
+ snd_pcm_chmap_query_t **chmap = NULL;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
snd_config_for_each(i, next, conf) {
|
|
||||||
@@ -450,14 +450,8 @@ int _snd_pcm_null_open(snd_pcm_t **pcmp,
|
|
||||||
if (snd_pcm_conf_generic_id(id))
|
|
||||||
continue;
|
|
||||||
if (strcmp(id, "chmap") == 0) {
|
|
||||||
- const char *str;
|
|
||||||
- err = snd_config_get_string(n, &str);
|
|
||||||
- if (err < 0) {
|
|
||||||
- SNDERR("Invalid type for %s", id);
|
|
||||||
- return -EINVAL;
|
|
||||||
- }
|
|
||||||
- free(chmap);
|
|
||||||
- chmap = snd_pcm_chmap_parse_string(str);
|
|
||||||
+ snd_pcm_free_chmaps(chmap);
|
|
||||||
+ chmap = _snd_pcm_parse_config_chmaps(n);
|
|
||||||
if (!chmap) {
|
|
||||||
SNDERR("Invalid channel map for %s", id);
|
|
||||||
return -EINVAL;
|
|
||||||
@@ -465,11 +459,14 @@ int _snd_pcm_null_open(snd_pcm_t **pcmp,
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SNDERR("Unknown field %s", id);
|
|
||||||
+ snd_pcm_free_chmaps(chmap);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
err = snd_pcm_null_open(pcmp, name, stream, mode);
|
|
||||||
- if (err < 0)
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ snd_pcm_free_chmaps(chmap);
|
|
||||||
return err;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
null = (*pcmp)->private_data;
|
|
||||||
null->chmap = chmap;
|
|
@ -1,51 +0,0 @@
|
|||||||
From 2c61a4173ff2c3d57eb77b3f66e0d0e517c799d6 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Wed, 12 Sep 2012 17:34:49 +0200
|
|
||||||
Subject: [PATCH 21/30] conf: Add chmap definitions to TRIDENT and SI7018
|
|
||||||
configurations
|
|
||||||
|
|
||||||
Manually add the channel map definitions as the channel front/rear is
|
|
||||||
determined dynamically.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/conf/cards/SI7018.conf | 2 ++
|
|
||||||
src/conf/cards/TRID4DWAVENX.conf | 2 ++
|
|
||||||
2 files changed, 4 insertions(+)
|
|
||||||
|
|
||||||
--- a/src/conf/cards/SI7018.conf
|
|
||||||
+++ b/src/conf/cards/SI7018.conf
|
|
||||||
@@ -13,6 +13,7 @@ SI7018.pcm.front.0 {
|
|
||||||
}
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
+ chmap [ "UNKNOWN" "FL,FR" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
<confdir:pcm/rear.conf>
|
|
||||||
@@ -26,6 +27,7 @@ SI7018.pcm.rear.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
+ chmap [ "UNKNOWN" "RL,RR" ]
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
||||||
--- a/src/conf/cards/TRID4DWAVENX.conf
|
|
||||||
+++ b/src/conf/cards/TRID4DWAVENX.conf
|
|
||||||
@@ -11,6 +11,7 @@ TRID4DWAVENX.pcm.front.0 {
|
|
||||||
}
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
+ chmap [ "UNKNOWN" "FL,FR" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
<confdir:pcm/rear.conf>
|
|
||||||
@@ -24,6 +25,7 @@ TRID4DWAVENX.pcm.rear.0 {
|
|
||||||
slave.pcm {
|
|
||||||
type hw
|
|
||||||
card $CARD
|
|
||||||
+ chmap [ "UNKNOWN" "RL,RR" ]
|
|
||||||
}
|
|
||||||
hooks.0 {
|
|
||||||
type ctl_elems
|
|
@ -1,21 +0,0 @@
|
|||||||
From 58c45b30309a1dd255c8b9e5cb34398658867b81 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Thu, 13 Sep 2012 08:06:26 +0200
|
|
||||||
Subject: [PATCH 22/30] test/chmap: Fix wrong malloc size
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
test/chmap.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/test/chmap.c
|
|
||||||
+++ b/test/chmap.c
|
|
||||||
@@ -118,7 +118,7 @@ static int set_chmap(snd_pcm_t *pcm, int
|
|
||||||
}
|
|
||||||
if (setup_pcm(pcm, format, channels, rate))
|
|
||||||
return 1;
|
|
||||||
- map = malloc(sizeof(int) * channels + 1);
|
|
||||||
+ map = malloc(sizeof(int) * (channels + 1));
|
|
||||||
if (!map) {
|
|
||||||
printf("cannot malloc\n");
|
|
||||||
return 1;
|
|
@ -1,116 +0,0 @@
|
|||||||
From f7300682dc0fe9faec94461af6fdcf098047a0d1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Wed, 12 Sep 2012 18:43:59 +0200
|
|
||||||
Subject: [PATCH 23/30] PCM: Define MONO and other channel map positions
|
|
||||||
|
|
||||||
Follow the new definitions in the kernel side. MONO and others have
|
|
||||||
been added, and the order of position table was changed again.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/pcm.h | 11 +++++++++--
|
|
||||||
include/sound/asound.h | 13 ++++++++++---
|
|
||||||
src/pcm/pcm.c | 14 +++++++++++---
|
|
||||||
3 files changed, 30 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
--- a/include/pcm.h
|
|
||||||
+++ b/include/pcm.h
|
|
||||||
@@ -489,6 +489,8 @@ enum snd_pcm_chmap_type {
|
|
||||||
/** channel positions */
|
|
||||||
enum snd_pcm_chmap_position {
|
|
||||||
SND_CHMAP_UNKNOWN = 0, /** unspecified */
|
|
||||||
+ SND_CHMAP_NA, /** N/A, silent */
|
|
||||||
+ SND_CHMAP_MONO, /** mono stream */
|
|
||||||
SND_CHMAP_FL, /** front left */
|
|
||||||
SND_CHMAP_FR, /** front right */
|
|
||||||
SND_CHMAP_RL, /** rear left */
|
|
||||||
@@ -508,8 +510,13 @@ enum snd_pcm_chmap_position {
|
|
||||||
SND_CHMAP_FCH, /** front center high */
|
|
||||||
SND_CHMAP_FRH, /** front right high */
|
|
||||||
SND_CHMAP_TC, /** top center */
|
|
||||||
- SND_CHMAP_NA, /** N/A, silent */
|
|
||||||
- SND_CHMAP_LAST = SND_CHMAP_NA, /** last entry */
|
|
||||||
+ SND_CHMAP_TFL, /** top front left */
|
|
||||||
+ SND_CHMAP_TFR, /** top front right */
|
|
||||||
+ SND_CHMAP_TFC, /** top front center */
|
|
||||||
+ SND_CHMAP_TRL, /** top rear left */
|
|
||||||
+ SND_CHMAP_TRR, /** top rear right */
|
|
||||||
+ SND_CHMAP_TRC, /** top rear center */
|
|
||||||
+ SND_CHMAP_LAST = SND_CHMAP_TRC, /** last entry */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SND_CHMAP_POSITION_MASK 0xffff /** bitmask for channel position */
|
|
||||||
--- a/include/sound/asound.h
|
|
||||||
+++ b/include/sound/asound.h
|
|
||||||
@@ -479,8 +479,10 @@ enum {
|
|
||||||
|
|
||||||
/* channel positions */
|
|
||||||
enum {
|
|
||||||
- /* this follows the alsa-lib mixer channel value + 1 */
|
|
||||||
SNDRV_CHMAP_UNKNOWN = 0,
|
|
||||||
+ SNDRV_CHMAP_NA, /* N/A, silent */
|
|
||||||
+ SNDRV_CHMAP_MONO, /* mono stream */
|
|
||||||
+ /* this follows the alsa-lib mixer channel value + 3 */
|
|
||||||
SNDRV_CHMAP_FL, /* front left */
|
|
||||||
SNDRV_CHMAP_FR, /* front right */
|
|
||||||
SNDRV_CHMAP_RL, /* rear left */
|
|
||||||
@@ -501,8 +503,13 @@ enum {
|
|
||||||
SNDRV_CHMAP_FCH, /* front center high */
|
|
||||||
SNDRV_CHMAP_FRH, /* front right high */
|
|
||||||
SNDRV_CHMAP_TC, /* top center */
|
|
||||||
- SNDRV_CHMAP_NA, /* N/A, silent */
|
|
||||||
- SNDRV_CHMAP_LAST = SNDRV_CHMAP_NA,
|
|
||||||
+ SNDRV_CHMAP_TFL, /* top front left */
|
|
||||||
+ SNDRV_CHMAP_TFR, /* top front right */
|
|
||||||
+ SNDRV_CHMAP_TFC, /* top front center */
|
|
||||||
+ SNDRV_CHMAP_TRL, /* top rear left */
|
|
||||||
+ SNDRV_CHMAP_TRR, /* top rear right */
|
|
||||||
+ SNDRV_CHMAP_TRC, /* top rear center */
|
|
||||||
+ SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SNDRV_CHMAP_POSITION_MASK 0xffff
|
|
||||||
--- a/src/pcm/pcm.c
|
|
||||||
+++ b/src/pcm/pcm.c
|
|
||||||
@@ -7375,7 +7375,7 @@ const char *snd_pcm_chmap_type_name(enum
|
|
||||||
|
|
||||||
#define _NAME(n) [SND_CHMAP_##n] = #n
|
|
||||||
static const char *chmap_names[SND_CHMAP_LAST + 1] = {
|
|
||||||
- _NAME(UNKNOWN),
|
|
||||||
+ _NAME(UNKNOWN), _NAME(NA), _NAME(MONO),
|
|
||||||
_NAME(FL), _NAME(FR),
|
|
||||||
_NAME(RL), _NAME(RR),
|
|
||||||
_NAME(FC), _NAME(LFE),
|
|
||||||
@@ -7383,7 +7383,8 @@ static const char *chmap_names[SND_CHMAP
|
|
||||||
_NAME(RC), _NAME(FLC), _NAME(FRC), _NAME(RLC), _NAME(RRC),
|
|
||||||
_NAME(FLW), _NAME(FRW),
|
|
||||||
_NAME(FLH), _NAME(FCH), _NAME(FRH), _NAME(TC),
|
|
||||||
- _NAME(NA),
|
|
||||||
+ _NAME(TFL), _NAME(TFR), _NAME(TFC),
|
|
||||||
+ _NAME(TRL), _NAME(TRR), _NAME(TRC),
|
|
||||||
};
|
|
||||||
#undef _NAME
|
|
||||||
|
|
||||||
@@ -7397,6 +7398,8 @@ const char *snd_pcm_chmap_name(enum snd_
|
|
||||||
|
|
||||||
static const char *chmap_long_names[SND_CHMAP_LAST + 1] = {
|
|
||||||
[SND_CHMAP_UNKNOWN] = "Unknown",
|
|
||||||
+ [SND_CHMAP_NA] = "Unused",
|
|
||||||
+ [SND_CHMAP_MONO] = "Mono",
|
|
||||||
[SND_CHMAP_FL] = "Front Left",
|
|
||||||
[SND_CHMAP_FR] = "Front Right",
|
|
||||||
[SND_CHMAP_RL] = "Rear Left",
|
|
||||||
@@ -7416,7 +7419,12 @@ static const char *chmap_long_names[SND_
|
|
||||||
[SND_CHMAP_FCH] = "Front Center High",
|
|
||||||
[SND_CHMAP_FRH] = "Front Right High",
|
|
||||||
[SND_CHMAP_TC] = "Top Center",
|
|
||||||
- [SND_CHMAP_NA] = "Unused",
|
|
||||||
+ [SND_CHMAP_TFL] = "Top Front Left",
|
|
||||||
+ [SND_CHMAP_TFR] = "Top Front Right",
|
|
||||||
+ [SND_CHMAP_TFC] = "Top Front Center",
|
|
||||||
+ [SND_CHMAP_TRL] = "Top Rear Left",
|
|
||||||
+ [SND_CHMAP_TRR] = "Top Rear Right",
|
|
||||||
+ [SND_CHMAP_TRC] = "Top Rear Center",
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *snd_pcm_chmap_long_name(enum snd_pcm_chmap_position val)
|
|
@ -1,67 +0,0 @@
|
|||||||
From c6db60e32758e8f4bb6f066a5c6fc7758a0f4c49 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Wed, 12 Sep 2012 18:44:42 +0200
|
|
||||||
Subject: [PATCH 24/30] PCM: Fix the conversion from string to chmap position
|
|
||||||
|
|
||||||
Use strncasecmp() to allow lower cases, and also evaluate the inverted
|
|
||||||
phase suffix, too.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/pcm/pcm.c | 37 +++++++++++++++++++++++++++----------
|
|
||||||
1 file changed, 27 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm.c
|
|
||||||
+++ b/src/pcm/pcm.c
|
|
||||||
@@ -7471,24 +7471,41 @@ int snd_pcm_chmap_print(const snd_pcm_ch
|
|
||||||
static int str_to_chmap(const char *str, int len)
|
|
||||||
{
|
|
||||||
int val;
|
|
||||||
+ unsigned long v;
|
|
||||||
+ char *p;
|
|
||||||
|
|
||||||
if (isdigit(*str)) {
|
|
||||||
- val = atoi(str);
|
|
||||||
- if (val < 0)
|
|
||||||
+ v = strtoul(str, &p, 0);
|
|
||||||
+ if (v == ULONG_MAX)
|
|
||||||
return -1;
|
|
||||||
- return val | SND_CHMAP_DRIVER_SPEC;
|
|
||||||
- } else if (str[0] == 'C' && str[1] == 'h') {
|
|
||||||
- val = atoi(str + 2);
|
|
||||||
- if (val < 0)
|
|
||||||
+ val = v;
|
|
||||||
+ val |= SND_CHMAP_DRIVER_SPEC;
|
|
||||||
+ str = p;
|
|
||||||
+ } else if (!strncasecmp(str, "ch", 2)) {
|
|
||||||
+ v = strtoul(str + 2, &p, 0);
|
|
||||||
+ if (v == ULONG_MAX)
|
|
||||||
return -1;
|
|
||||||
- return val;
|
|
||||||
+ val = v;
|
|
||||||
+ str = p;
|
|
||||||
} else {
|
|
||||||
for (val = 0; val <= SND_CHMAP_LAST; val++) {
|
|
||||||
- if (!strncmp(str, chmap_names[val], len))
|
|
||||||
- return val;
|
|
||||||
+ int slen;
|
|
||||||
+ assert(chmap_names[val]);
|
|
||||||
+ slen = strlen(chmap_names[val]);
|
|
||||||
+ if (slen > len)
|
|
||||||
+ continue;
|
|
||||||
+ if (!strncasecmp(str, chmap_names[val], slen) &&
|
|
||||||
+ !isalpha(str[slen])) {
|
|
||||||
+ str += slen;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
- return -1;
|
|
||||||
+ if (val > SND_CHMAP_LAST)
|
|
||||||
+ return -1;
|
|
||||||
}
|
|
||||||
+ if (str && !strncasecmp(str, "[INV]", 5))
|
|
||||||
+ val |= SND_CHMAP_PHASE_INVERSE;
|
|
||||||
+ return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int snd_pcm_chmap_from_string(const char *str)
|
|
@ -1,158 +0,0 @@
|
|||||||
From 63f6f4a6103e55d242440488999e648beb5e4e4d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Thu, 13 Sep 2012 08:38:59 +0200
|
|
||||||
Subject: [PATCH 25/30] PCM: A few doxygen fixes for chmap stuff
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/pcm.h | 18 +++++++++++-------
|
|
||||||
src/pcm/pcm.c | 43 +++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
2 files changed, 54 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
--- a/include/pcm.h
|
|
||||||
+++ b/include/pcm.h
|
|
||||||
@@ -519,20 +519,24 @@ enum snd_pcm_chmap_position {
|
|
||||||
SND_CHMAP_LAST = SND_CHMAP_TRC, /** last entry */
|
|
||||||
};
|
|
||||||
|
|
||||||
-#define SND_CHMAP_POSITION_MASK 0xffff /** bitmask for channel position */
|
|
||||||
-#define SND_CHMAP_PHASE_INVERSE (0x01 << 16) /* the channel is phase inverted */
|
|
||||||
-#define SND_CHMAP_DRIVER_SPEC (0x02 << 16) /* non-standard channel value */
|
|
||||||
+/** bitmask for channel position */
|
|
||||||
+#define SND_CHMAP_POSITION_MASK 0xffff
|
|
||||||
+
|
|
||||||
+/** bit flag indicating the channel is phase inverted */
|
|
||||||
+#define SND_CHMAP_PHASE_INVERSE (0x01 << 16)
|
|
||||||
+/** bit flag indicating the non-standard channel value */
|
|
||||||
+#define SND_CHMAP_DRIVER_SPEC (0x02 << 16)
|
|
||||||
|
|
||||||
/** the channel map header */
|
|
||||||
typedef struct snd_pcm_chmap {
|
|
||||||
- unsigned int channels;
|
|
||||||
- unsigned int pos[0];
|
|
||||||
+ unsigned int channels; /** number of channels */
|
|
||||||
+ unsigned int pos[0]; /** channel position array */
|
|
||||||
} snd_pcm_chmap_t;
|
|
||||||
|
|
||||||
/** the header of array items returned from snd_pcm_query_chmaps() */
|
|
||||||
typedef struct snd_pcm_chmap_query {
|
|
||||||
- enum snd_pcm_chmap_type type;
|
|
||||||
- snd_pcm_chmap_t map;
|
|
||||||
+ enum snd_pcm_chmap_type type; /** channel map type */
|
|
||||||
+ snd_pcm_chmap_t map; /** available channel map */
|
|
||||||
} snd_pcm_chmap_query_t;
|
|
||||||
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm.c
|
|
||||||
+++ b/src/pcm/pcm.c
|
|
||||||
@@ -7310,6 +7310,9 @@ OBSOLETE1(snd_pcm_sw_params_get_silence_
|
|
||||||
* which contains the channel map. A channel map is represented by an
|
|
||||||
* integer array, beginning with the channel map type, followed by the
|
|
||||||
* number of channels, and the position of each channel.
|
|
||||||
+ *
|
|
||||||
+ * Note: the caller is requested to release the returned value via
|
|
||||||
+ * snd_pcm_free_chmaps().
|
|
||||||
*/
|
|
||||||
snd_pcm_chmap_query_t **snd_pcm_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
@@ -7336,6 +7339,8 @@ void snd_pcm_free_chmaps(snd_pcm_chmap_q
|
|
||||||
* \!brief Get the current channel map
|
|
||||||
* \param pcm PCM instance
|
|
||||||
* \return the current channel map, or NULL if error
|
|
||||||
+ *
|
|
||||||
+ * Note: the caller is requested to release the returned value via free()
|
|
||||||
*/
|
|
||||||
snd_pcm_chmap_t *snd_pcm_get_chmap(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
@@ -7359,12 +7364,19 @@ int snd_pcm_set_chmap(snd_pcm_t *pcm, co
|
|
||||||
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
+#ifndef DOC_HIDDEN
|
|
||||||
#define _NAME(n) [SND_CHMAP_TYPE_##n] = #n
|
|
||||||
static const char *chmap_type_names[SND_CHMAP_TYPE_LAST + 1] = {
|
|
||||||
_NAME(NONE), _NAME(FIXED), _NAME(VAR), _NAME(PAIRED),
|
|
||||||
};
|
|
||||||
#undef _NAME
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * \!brief Get a name string for a channel map type as query results
|
|
||||||
+ * \param val Channel position
|
|
||||||
+ * \return The string corresponding to the given type, or NULL
|
|
||||||
+ */
|
|
||||||
const char *snd_pcm_chmap_type_name(enum snd_pcm_chmap_type val)
|
|
||||||
{
|
|
||||||
if (val <= SND_CHMAP_TYPE_LAST)
|
|
||||||
@@ -7373,6 +7385,7 @@ const char *snd_pcm_chmap_type_name(enum
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifndef DOC_HIDDEN
|
|
||||||
#define _NAME(n) [SND_CHMAP_##n] = #n
|
|
||||||
static const char *chmap_names[SND_CHMAP_LAST + 1] = {
|
|
||||||
_NAME(UNKNOWN), _NAME(NA), _NAME(MONO),
|
|
||||||
@@ -7387,7 +7400,13 @@ static const char *chmap_names[SND_CHMAP
|
|
||||||
_NAME(TRL), _NAME(TRR), _NAME(TRC),
|
|
||||||
};
|
|
||||||
#undef _NAME
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * \!brief Get a name string for a standard channel map position
|
|
||||||
+ * \param val Channel position
|
|
||||||
+ * \return The string corresponding to the given position, or NULL
|
|
||||||
+ */
|
|
||||||
const char *snd_pcm_chmap_name(enum snd_pcm_chmap_position val)
|
|
||||||
{
|
|
||||||
if (val <= SND_CHMAP_LAST)
|
|
||||||
@@ -7427,6 +7446,11 @@ static const char *chmap_long_names[SND_
|
|
||||||
[SND_CHMAP_TRC] = "Top Rear Center",
|
|
||||||
};
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * \!brief Get a longer name string for a standard channel map position
|
|
||||||
+ * \param val Channel position
|
|
||||||
+ * \return The string corresponding to the given position, or NULL
|
|
||||||
+ */
|
|
||||||
const char *snd_pcm_chmap_long_name(enum snd_pcm_chmap_position val)
|
|
||||||
{
|
|
||||||
if (val <= SND_CHMAP_LAST)
|
|
||||||
@@ -7435,6 +7459,13 @@ const char *snd_pcm_chmap_long_name(enum
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * \!brief Print the channels in chmap on the buffer
|
|
||||||
+ * \param map The channel map to print
|
|
||||||
+ * \param maxlen The maximal length to write (including NUL letter)
|
|
||||||
+ * \param buf The buffer to write
|
|
||||||
+ * \return The actual string length or a negative error code
|
|
||||||
+ */
|
|
||||||
int snd_pcm_chmap_print(const snd_pcm_chmap_t *map, size_t maxlen, char *buf)
|
|
||||||
{
|
|
||||||
unsigned int i, len = 0;
|
|
||||||
@@ -7508,11 +7539,23 @@ static int str_to_chmap(const char *str,
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * \!brief Convert from string to channel position
|
|
||||||
+ * \param str The string to parse
|
|
||||||
+ * \return The channel position value or -1 as an error
|
|
||||||
+ */
|
|
||||||
unsigned int snd_pcm_chmap_from_string(const char *str)
|
|
||||||
{
|
|
||||||
return str_to_chmap(str, strlen(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * \!brief Convert from string to channel map
|
|
||||||
+ * \param str The string to parse
|
|
||||||
+ * \return The channel map
|
|
||||||
+ *
|
|
||||||
+ * Note: the caller is requested to release the returned value via free()
|
|
||||||
+ */
|
|
||||||
snd_pcm_chmap_t *snd_pcm_chmap_parse_string(const char *str)
|
|
||||||
{
|
|
||||||
int i, ch = 0;
|
|
@ -1,30 +0,0 @@
|
|||||||
From 5a2daef19225478df7e3c1f8c6c9cb847e574b44 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Thu, 20 Sep 2012 13:43:12 +0200
|
|
||||||
Subject: [PATCH 26/30] PCM: Fill SND_CHMAP_NA to silent channels in route
|
|
||||||
plugin
|
|
||||||
|
|
||||||
Instead of SND_CHMAP_UNKNOWN, fill SND_CHMAP_NA to the silent channels.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/pcm/pcm_route.c | 4 +++-
|
|
||||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm_route.c
|
|
||||||
+++ b/src/pcm/pcm_route.c
|
|
||||||
@@ -720,11 +720,13 @@ static snd_pcm_chmap_t *snd_pcm_route_ge
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
map->channels = nsrcs;
|
|
||||||
+ for (src = 0; src < nsrcs; src++)
|
|
||||||
+ map->pos[src] = SND_CHMAP_NA;
|
|
||||||
for (dst = 0; dst < route->params.ndsts; dst++) {
|
|
||||||
snd_pcm_route_ttable_dst_t *d = &route->params.dsts[dst];
|
|
||||||
for (src = 0; src < d->nsrcs; src++) {
|
|
||||||
int c = d->srcs[src].channel;
|
|
||||||
- if (c < nsrcs && !map->pos[c])
|
|
||||||
+ if (c < nsrcs && map->pos[c] == SND_CHMAP_NA)
|
|
||||||
map->pos[c] = slave_map->pos[dst];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
From 5a6ce315201f9e2abee51f4f890c1f5c6592c998 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Fri, 21 Sep 2012 17:59:42 +0200
|
|
||||||
Subject: [PATCH 27/30] PCM: Fix infinite loop in htimestamp of dmix, dsnoop
|
|
||||||
and dshare plugins
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/pcm/pcm_dmix.c | 1 +
|
|
||||||
src/pcm/pcm_dshare.c | 1 +
|
|
||||||
src/pcm/pcm_dsnoop.c | 1 +
|
|
||||||
3 files changed, 3 insertions(+)
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm_dmix.c
|
|
||||||
+++ b/src/pcm/pcm_dmix.c
|
|
||||||
@@ -853,6 +853,7 @@ static int snd_pcm_dmix_htimestamp(snd_p
|
|
||||||
break;
|
|
||||||
*avail = avail1;
|
|
||||||
*tstamp = snd_pcm_hw_fast_tstamp(dmix->spcm);
|
|
||||||
+ ok = 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
--- a/src/pcm/pcm_dshare.c
|
|
||||||
+++ b/src/pcm/pcm_dshare.c
|
|
||||||
@@ -543,6 +543,7 @@ static int snd_pcm_dshare_htimestamp(snd
|
|
||||||
break;
|
|
||||||
*avail = avail1;
|
|
||||||
*tstamp = snd_pcm_hw_fast_tstamp(dshare->spcm);
|
|
||||||
+ ok = 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
--- a/src/pcm/pcm_dsnoop.c
|
|
||||||
+++ b/src/pcm/pcm_dsnoop.c
|
|
||||||
@@ -458,6 +458,7 @@ static int snd_pcm_dsnoop_htimestamp(snd
|
|
||||||
break;
|
|
||||||
*avail = avail1;
|
|
||||||
*tstamp = snd_pcm_hw_fast_tstamp(dsnoop->spcm);
|
|
||||||
+ ok = 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,287 +0,0 @@
|
|||||||
From 6429a450a315e00d9e00af46eb42784a4cc5dce1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
|
||||||
Date: Fri, 21 Sep 2012 20:05:18 -0500
|
|
||||||
Subject: [PATCH 28/30] test: add audio_time
|
|
||||||
|
|
||||||
Simple test to create playback and capture streams, and
|
|
||||||
check elapsed time vs. sample counts reported by driver.
|
|
||||||
This should be helpful for driver developers and anyone
|
|
||||||
interested in system/audio time drift.
|
|
||||||
|
|
||||||
tested only on HDAudio
|
|
||||||
|
|
||||||
[added Makefile.am change by tiwai]
|
|
||||||
|
|
||||||
TODO:
|
|
||||||
- make period configurable
|
|
||||||
- better output messages
|
|
||||||
- support for wall clock when it's in the mainline
|
|
||||||
|
|
||||||
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
test/Makefile.am | 4
|
|
||||||
test/audio_time.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
2 files changed, 240 insertions(+), 1 deletion(-)
|
|
||||||
create mode 100644 test/audio_time.c
|
|
||||||
|
|
||||||
--- a/test/Makefile.am
|
|
||||||
+++ b/test/Makefile.am
|
|
||||||
@@ -2,7 +2,8 @@ SUBDIRS=. lsb
|
|
||||||
|
|
||||||
check_PROGRAMS=control pcm pcm_min latency seq \
|
|
||||||
playmidi1 timer rawmidi midiloop \
|
|
||||||
- oldapi queue_timer namehint client_event_filter chmap
|
|
||||||
+ oldapi queue_timer namehint client_event_filter \
|
|
||||||
+ chmap audio_time
|
|
||||||
|
|
||||||
control_LDADD=../src/libasound.la
|
|
||||||
pcm_LDADD=../src/libasound.la
|
|
||||||
@@ -19,6 +20,7 @@ namehint_LDADD=../src/libasound.la
|
|
||||||
client_event_filter_LDADD=../src/libasound.la
|
|
||||||
code_CFLAGS=-Wall -pipe -g -O2
|
|
||||||
chmap_LDADD=../src/libasound.la
|
|
||||||
+audio_time_LDADD=../src/libasound.la
|
|
||||||
|
|
||||||
INCLUDES=-I$(top_srcdir)/include
|
|
||||||
AM_CFLAGS=-Wall -pipe -g
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/test/audio_time.c
|
|
||||||
@@ -0,0 +1,237 @@
|
|
||||||
+/*
|
|
||||||
+ * This program only tracks the difference between system time
|
|
||||||
+ * and audio time, as reported in snd_pcm_status(). It should be
|
|
||||||
+ * helpful to verify the information reported by drivers.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include "../include/asoundlib.h"
|
|
||||||
+#include <math.h>
|
|
||||||
+
|
|
||||||
+static char *device = "hw:0,0";
|
|
||||||
+
|
|
||||||
+snd_output_t *output = NULL;
|
|
||||||
+
|
|
||||||
+long long timestamp2ns(snd_htimestamp_t t)
|
|
||||||
+{
|
|
||||||
+ long long nsec;
|
|
||||||
+
|
|
||||||
+ nsec = t.tv_sec * 1000000000;
|
|
||||||
+ nsec += t.tv_nsec;
|
|
||||||
+
|
|
||||||
+ return nsec;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+long long timediff(snd_htimestamp_t t1, snd_htimestamp_t t2)
|
|
||||||
+{
|
|
||||||
+ long long nsec1, nsec2;
|
|
||||||
+
|
|
||||||
+ nsec1 = timestamp2ns(t1);
|
|
||||||
+ nsec2 = timestamp2ns(t2);
|
|
||||||
+
|
|
||||||
+ return nsec1 - nsec2;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void gettimestamp(snd_pcm_t *handle, snd_htimestamp_t *timestamp,
|
|
||||||
+ snd_htimestamp_t *trigger_timestamp,
|
|
||||||
+ snd_pcm_uframes_t *avail, snd_pcm_sframes_t *delay)
|
|
||||||
+{
|
|
||||||
+ int err;
|
|
||||||
+ snd_pcm_status_t *status;
|
|
||||||
+
|
|
||||||
+ snd_pcm_status_alloca(&status);
|
|
||||||
+ if ((err = snd_pcm_status(handle, status)) < 0) {
|
|
||||||
+ printf("Stream status error: %s\n", snd_strerror(err));
|
|
||||||
+ exit(0);
|
|
||||||
+ }
|
|
||||||
+ snd_pcm_status_get_trigger_htstamp(status, trigger_timestamp);
|
|
||||||
+ snd_pcm_status_get_htstamp(status, timestamp);
|
|
||||||
+ *avail = snd_pcm_status_get_avail(status);
|
|
||||||
+ *delay = snd_pcm_status_get_delay(status);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define PERIOD 6000
|
|
||||||
+#define PCM_LINK /* sync start for playback and capture */
|
|
||||||
+#define TRACK_CAPTURE /* dump capture timing info */
|
|
||||||
+#define TRACK_PLAYBACK /* dump playback timing info */
|
|
||||||
+#define PLAYBACK_BUFFERS 4
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+int main(void)
|
|
||||||
+{
|
|
||||||
+ int err;
|
|
||||||
+ unsigned int i;
|
|
||||||
+ snd_pcm_t *handle_p = NULL;
|
|
||||||
+ snd_pcm_t *handle_c = NULL;
|
|
||||||
+ snd_pcm_sframes_t frames;
|
|
||||||
+ snd_htimestamp_t tstamp_c, tstamp_p;
|
|
||||||
+ snd_htimestamp_t trigger_tstamp_c, trigger_tstamp_p;
|
|
||||||
+ unsigned char buffer_p[PERIOD*4*4];
|
|
||||||
+ unsigned char buffer_c[PERIOD*4*4];
|
|
||||||
+
|
|
||||||
+ snd_pcm_sw_params_t *swparams_p;
|
|
||||||
+ snd_pcm_sw_params_t *swparams_c;
|
|
||||||
+
|
|
||||||
+ snd_pcm_uframes_t curr_count_c;
|
|
||||||
+ snd_pcm_uframes_t frame_count_c = 0;
|
|
||||||
+ snd_pcm_uframes_t curr_count_p;
|
|
||||||
+ snd_pcm_uframes_t frame_count_p = 0;
|
|
||||||
+
|
|
||||||
+ snd_pcm_sframes_t delay_p, delay_c;
|
|
||||||
+ snd_pcm_uframes_t avail_p, avail_c;
|
|
||||||
+
|
|
||||||
+ if ((err = snd_pcm_open(&handle_p, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
|
|
||||||
+ printf("Playback open error: %s\n", snd_strerror(err));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+ if ((err = snd_pcm_set_params(handle_p,
|
|
||||||
+ SND_PCM_FORMAT_S16,
|
|
||||||
+ SND_PCM_ACCESS_RW_INTERLEAVED,
|
|
||||||
+ 2,
|
|
||||||
+ 48000,
|
|
||||||
+ 0,
|
|
||||||
+ 500000)) < 0) { /* 0.5sec */
|
|
||||||
+ printf("Playback open error: %s\n", snd_strerror(err));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ snd_pcm_sw_params_alloca(&swparams_p);
|
|
||||||
+ /* get the current swparams */
|
|
||||||
+ err = snd_pcm_sw_params_current(handle_p, swparams_p);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ printf("Unable to determine current swparams_p: %s\n", snd_strerror(err));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* enable tstamp */
|
|
||||||
+ err = snd_pcm_sw_params_set_tstamp_mode(handle_p, swparams_p, SND_PCM_TSTAMP_ENABLE);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ printf("Unable to set tstamp mode : %s\n", snd_strerror(err));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* write the sw parameters */
|
|
||||||
+ err = snd_pcm_sw_params(handle_p, swparams_p);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ printf("Unable to set swparams_p : %s\n", snd_strerror(err));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if ((err = snd_pcm_open(&handle_c, device, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) {
|
|
||||||
+ printf("Capture open error: %s\n", snd_strerror(err));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+ if ((err = snd_pcm_set_params(handle_c,
|
|
||||||
+ SND_PCM_FORMAT_S16,
|
|
||||||
+ SND_PCM_ACCESS_RW_INTERLEAVED,
|
|
||||||
+ 2,
|
|
||||||
+ 48000,
|
|
||||||
+ 0,
|
|
||||||
+ 500000)) < 0) { /* 0.5sec */
|
|
||||||
+ printf("Capture open error: %s\n", snd_strerror(err));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ snd_pcm_sw_params_alloca(&swparams_c);
|
|
||||||
+ /* get the current swparams */
|
|
||||||
+ err = snd_pcm_sw_params_current(handle_c, swparams_c);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ printf("Unable to determine current swparams_c: %s\n", snd_strerror(err));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* enable tstamp */
|
|
||||||
+ err = snd_pcm_sw_params_set_tstamp_mode(handle_c, swparams_c, SND_PCM_TSTAMP_ENABLE);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ printf("Unable to set tstamp mode : %s\n", snd_strerror(err));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* write the sw parameters */
|
|
||||||
+ err = snd_pcm_sw_params(handle_c, swparams_c);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ printf("Unable to set swparams_c : %s\n", snd_strerror(err));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+#ifdef PCM_LINK
|
|
||||||
+ if ((err = snd_pcm_link(handle_c, handle_p)) < 0) {
|
|
||||||
+ printf("Streams link error: %s\n", snd_strerror(err));
|
|
||||||
+ exit(0);
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ i = PLAYBACK_BUFFERS;
|
|
||||||
+ while (i--) {
|
|
||||||
+ frames = snd_pcm_writei(handle_p, buffer_p, PERIOD);
|
|
||||||
+ if (frames < 0) {
|
|
||||||
+ printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+ frame_count_p += frames;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (PLAYBACK_BUFFERS != 4)
|
|
||||||
+ snd_pcm_start(handle_p);
|
|
||||||
+
|
|
||||||
+#ifndef PCM_LINK
|
|
||||||
+ /* need to start capture explicitly */
|
|
||||||
+ snd_pcm_start(handle_c);
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ while (1) {
|
|
||||||
+
|
|
||||||
+ frames = snd_pcm_wait(handle_c, -1);
|
|
||||||
+ if (frames < 0) {
|
|
||||||
+ printf("snd_pcm_wait failed: %s\n", snd_strerror(frames));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ frames = snd_pcm_readi(handle_c, buffer_c, PERIOD);
|
|
||||||
+ if (frames < 0) {
|
|
||||||
+ printf("snd_pcm_readi failed: %s\n", snd_strerror(frames));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+ frame_count_c += frames;
|
|
||||||
+
|
|
||||||
+ frames = snd_pcm_writei(handle_p, buffer_p, PERIOD);
|
|
||||||
+ if (frames < 0) {
|
|
||||||
+ printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ frame_count_p += frames;
|
|
||||||
+
|
|
||||||
+#if defined(TRACK_PLAYBACK)
|
|
||||||
+ gettimestamp(handle_p, &tstamp_p, &trigger_tstamp_p, &avail_p, &delay_p);
|
|
||||||
+
|
|
||||||
+ curr_count_p = frame_count_p - delay_p; /* written minus queued */
|
|
||||||
+
|
|
||||||
+ printf("playback: systime: %lli nsec, sample time %lli nsec \tsystime delta %lli \n",
|
|
||||||
+ timediff(tstamp_p,trigger_tstamp_p),
|
|
||||||
+ (long long)round(((float)curr_count_p * 1000000000.0 / 48000.0)),
|
|
||||||
+ timediff(tstamp_p, trigger_tstamp_p) - (long long)round((double)curr_count_p * 1000000000.0 / 48000.0)
|
|
||||||
+ );
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#if defined(TRACK_CAPTURE)
|
|
||||||
+ gettimestamp(handle_c, &tstamp_c, &trigger_tstamp_c, &avail_c, &delay_c);
|
|
||||||
+
|
|
||||||
+ curr_count_c = frame_count_c + delay_c; /* read plus queued */
|
|
||||||
+
|
|
||||||
+ printf("\t capture: systime: %lli nsec, sample time %lli nsec \tsystime delta %lli \n",
|
|
||||||
+ timediff(tstamp_c,trigger_tstamp_c),
|
|
||||||
+ (long long)round(((float)curr_count_c * 1000000000.0 / 48000.0)),
|
|
||||||
+ timediff(tstamp_c, trigger_tstamp_c) - (long long)round((double)curr_count_c * 1000000000.0 / 48000.0)
|
|
||||||
+ );
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+_exit:
|
|
||||||
+ if (handle_p)
|
|
||||||
+ snd_pcm_close(handle_p);
|
|
||||||
+ if (handle_c)
|
|
||||||
+ snd_pcm_close(handle_c);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
@ -1,49 +0,0 @@
|
|||||||
From 4bdb09126a32feb4394eaeb1d400d87e7c968770 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Wed, 10 Oct 2012 10:22:54 +0200
|
|
||||||
Subject: [PATCH 30/30] PCM: Fix the invalid snd_pcm_close() calls in rate
|
|
||||||
plugin
|
|
||||||
|
|
||||||
It happens in the error path, should call snd_pcm_free() instead.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/pcm/pcm_rate.c | 8 ++++----
|
|
||||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm_rate.c
|
|
||||||
+++ b/src/pcm/pcm_rate.c
|
|
||||||
@@ -1394,13 +1394,13 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SNDERR("Invalid type for rate converter");
|
|
||||||
- snd_pcm_close(pcm);
|
|
||||||
+ snd_pcm_free(pcm);
|
|
||||||
free(rate);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if (err < 0) {
|
|
||||||
SNDERR("Cannot find rate converter");
|
|
||||||
- snd_pcm_close(pcm);
|
|
||||||
+ snd_pcm_free(pcm);
|
|
||||||
free(rate);
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
@@ -1409,7 +1409,7 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp,
|
|
||||||
open_func = SND_PCM_RATE_PLUGIN_ENTRY(linear);
|
|
||||||
err = open_func(SND_PCM_RATE_PLUGIN_VERSION, &rate->obj, &rate->ops);
|
|
||||||
if (err < 0) {
|
|
||||||
- snd_pcm_close(pcm);
|
|
||||||
+ snd_pcm_free(pcm);
|
|
||||||
free(rate);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
@@ -1418,7 +1418,7 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp,
|
|
||||||
if (! rate->ops.init || ! (rate->ops.convert || rate->ops.convert_s16) ||
|
|
||||||
! rate->ops.input_frames || ! rate->ops.output_frames) {
|
|
||||||
SNDERR("Inproper rate plugin %s initialization", type);
|
|
||||||
- snd_pcm_close(pcm);
|
|
||||||
+ snd_pcm_free(pcm);
|
|
||||||
free(rate);
|
|
||||||
return err;
|
|
||||||
}
|
|
@ -1,272 +0,0 @@
|
|||||||
From cf40ea169aad366b222283f431addafea6327149 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
|
||||||
Date: Tue, 12 Jun 2012 14:36:40 -0500
|
|
||||||
Subject: [PATCH 31/35] pcm: support for audio timestamps
|
|
||||||
|
|
||||||
add new snd_pcm_status_get_audio_htstamp() routine to
|
|
||||||
query the audio timestamps provided by the kernel.
|
|
||||||
|
|
||||||
This change provides applications with better ways
|
|
||||||
to track elapsed time. Before this patch, applications
|
|
||||||
would subtract queued samples (delay) from written samples,
|
|
||||||
resulting in a 1-2 sample error.
|
|
||||||
|
|
||||||
Also add snd_pcm_hw_params_supports_audio_wallclock_ts()
|
|
||||||
to query what the hardware supports.
|
|
||||||
|
|
||||||
TODO: check protocol compatibility?
|
|
||||||
|
|
||||||
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/pcm.h | 2 ++
|
|
||||||
include/sound/asound.h | 7 ++++--
|
|
||||||
src/pcm/pcm.c | 31 +++++++++++++++++++++++
|
|
||||||
test/audio_time.c | 68 ++++++++++++++++++++++++++++++++++++++++++--------
|
|
||||||
4 files changed, 96 insertions(+), 12 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/include/pcm.h b/include/pcm.h
|
|
||||||
index 290593b..1ce91e7 100644
|
|
||||||
--- a/include/pcm.h
|
|
||||||
+++ b/include/pcm.h
|
|
||||||
@@ -631,6 +631,7 @@ int snd_pcm_hw_params_is_half_duplex(const snd_pcm_hw_params_t *params);
|
|
||||||
int snd_pcm_hw_params_is_joint_duplex(const snd_pcm_hw_params_t *params);
|
|
||||||
int snd_pcm_hw_params_can_sync_start(const snd_pcm_hw_params_t *params);
|
|
||||||
int snd_pcm_hw_params_can_disable_period_wakeup(const snd_pcm_hw_params_t *params);
|
|
||||||
+int snd_pcm_hw_params_supports_audio_wallclock_ts(const snd_pcm_hw_params_t *params);
|
|
||||||
int snd_pcm_hw_params_get_rate_numden(const snd_pcm_hw_params_t *params,
|
|
||||||
unsigned int *rate_num,
|
|
||||||
unsigned int *rate_den);
|
|
||||||
@@ -939,6 +940,7 @@ void snd_pcm_status_get_trigger_tstamp(const snd_pcm_status_t *obj, snd_timestam
|
|
||||||
void snd_pcm_status_get_trigger_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr);
|
|
||||||
void snd_pcm_status_get_tstamp(const snd_pcm_status_t *obj, snd_timestamp_t *ptr);
|
|
||||||
void snd_pcm_status_get_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr);
|
|
||||||
+void snd_pcm_status_get_audio_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr);
|
|
||||||
snd_pcm_sframes_t snd_pcm_status_get_delay(const snd_pcm_status_t *obj);
|
|
||||||
snd_pcm_uframes_t snd_pcm_status_get_avail(const snd_pcm_status_t *obj);
|
|
||||||
snd_pcm_uframes_t snd_pcm_status_get_avail_max(const snd_pcm_status_t *obj);
|
|
||||||
diff --git a/include/sound/asound.h b/include/sound/asound.h
|
|
||||||
index e24d144..16d03e8 100644
|
|
||||||
--- a/include/sound/asound.h
|
|
||||||
+++ b/include/sound/asound.h
|
|
||||||
@@ -160,7 +160,7 @@ enum {
|
|
||||||
* *
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
-#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10)
|
|
||||||
+#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 11)
|
|
||||||
|
|
||||||
typedef unsigned long sndrv_pcm_uframes_t;
|
|
||||||
typedef long sndrv_pcm_sframes_t;
|
|
||||||
@@ -285,6 +285,7 @@ enum sndrv_pcm_subformat {
|
|
||||||
#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */
|
|
||||||
#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */
|
|
||||||
#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */
|
|
||||||
+#define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* has audio wall clock for audio/system time sync */
|
|
||||||
|
|
||||||
enum sndrv_pcm_state {
|
|
||||||
SNDRV_PCM_STATE_OPEN = 0, /* stream is open */
|
|
||||||
@@ -426,7 +427,8 @@ struct sndrv_pcm_status {
|
|
||||||
sndrv_pcm_uframes_t avail_max; /* max frames available on hw since last status */
|
|
||||||
sndrv_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */
|
|
||||||
int suspended_state; /* suspended stream state */
|
|
||||||
- unsigned char reserved[60]; /* must be filled with zero */
|
|
||||||
+ struct timespec audio_tstamp; /* from sample counter or wall clock */
|
|
||||||
+ unsigned char reserved[60-sizeof(struct timespec)]; /* must be filled with zero */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sndrv_pcm_mmap_status {
|
|
||||||
@@ -435,6 +437,7 @@ struct sndrv_pcm_mmap_status {
|
|
||||||
sndrv_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */
|
|
||||||
struct timespec tstamp; /* Timestamp */
|
|
||||||
int suspended_state; /* RO: suspended stream state */
|
|
||||||
+ struct timespec audio_tstamp; /* from sample counter or wall clock */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sndrv_pcm_mmap_control {
|
|
||||||
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
|
|
||||||
index 65c7646..5880057 100644
|
|
||||||
--- a/src/pcm/pcm.c
|
|
||||||
+++ b/src/pcm/pcm.c
|
|
||||||
@@ -3124,6 +3124,26 @@ int snd_pcm_hw_params_can_disable_period_wakeup(const snd_pcm_hw_params_t *param
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
+ * \brief Check if hardware supports audio wallclock timestamps
|
|
||||||
+ * \param params Configuration space
|
|
||||||
+ * \retval 0 Hardware doesn't support audio wallclock timestamps
|
|
||||||
+ * \retval 1 Hardware supports audio wallclock timestamps
|
|
||||||
+ *
|
|
||||||
+ * This function should only be called when the configuration space
|
|
||||||
+ * contains a single configuration. Call #snd_pcm_hw_params to choose
|
|
||||||
+ * a single configuration from the configuration space.
|
|
||||||
+ */
|
|
||||||
+int snd_pcm_hw_params_supports_audio_wallclock_ts(const snd_pcm_hw_params_t *params)
|
|
||||||
+{
|
|
||||||
+ assert(params);
|
|
||||||
+ if (CHECK_SANITY(params->info == ~0U)) {
|
|
||||||
+ SNDMSG("invalid PCM info field");
|
|
||||||
+ return 0; /* FIXME: should be a negative error? */
|
|
||||||
+ }
|
|
||||||
+ return !!(params->info & SNDRV_PCM_INFO_HAS_WALL_CLOCK);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
* \brief Get rate exact info from a configuration space
|
|
||||||
* \param params Configuration space
|
|
||||||
* \param rate_num Pointer to returned rate numerator
|
|
||||||
@@ -6214,6 +6234,17 @@ void snd_pcm_status_get_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *p
|
|
||||||
use_default_symbol_version(__snd_pcm_status_get_htstamp, snd_pcm_status_get_htstamp, ALSA_0.9.0rc8);
|
|
||||||
|
|
||||||
/**
|
|
||||||
+ * \brief Get "now" hi-res audio timestamp from a PCM status container
|
|
||||||
+ * \param obj pointer to #snd_pcm_status_t
|
|
||||||
+ * \param ptr Pointer to returned timestamp
|
|
||||||
+ */
|
|
||||||
+void snd_pcm_status_get_audio_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr)
|
|
||||||
+{
|
|
||||||
+ assert(obj && ptr);
|
|
||||||
+ *ptr = obj->audio_tstamp;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
* \brief Get delay from a PCM status container (see #snd_pcm_delay)
|
|
||||||
* \return Delay in frames
|
|
||||||
*
|
|
||||||
diff --git a/test/audio_time.c b/test/audio_time.c
|
|
||||||
index a910783..03817c7 100644
|
|
||||||
--- a/test/audio_time.c
|
|
||||||
+++ b/test/audio_time.c
|
|
||||||
@@ -33,6 +33,7 @@ long long timediff(snd_htimestamp_t t1, snd_htimestamp_t t2)
|
|
||||||
|
|
||||||
void gettimestamp(snd_pcm_t *handle, snd_htimestamp_t *timestamp,
|
|
||||||
snd_htimestamp_t *trigger_timestamp,
|
|
||||||
+ snd_htimestamp_t *audio_timestamp,
|
|
||||||
snd_pcm_uframes_t *avail, snd_pcm_sframes_t *delay)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
@@ -45,6 +46,7 @@ void gettimestamp(snd_pcm_t *handle, snd_htimestamp_t *timestamp,
|
|
||||||
}
|
|
||||||
snd_pcm_status_get_trigger_htstamp(status, trigger_timestamp);
|
|
||||||
snd_pcm_status_get_htstamp(status, timestamp);
|
|
||||||
+ snd_pcm_status_get_audio_htstamp(status, audio_timestamp);
|
|
||||||
*avail = snd_pcm_status_get_avail(status);
|
|
||||||
*delay = snd_pcm_status_get_delay(status);
|
|
||||||
}
|
|
||||||
@@ -53,6 +55,7 @@ void gettimestamp(snd_pcm_t *handle, snd_htimestamp_t *timestamp,
|
|
||||||
#define PCM_LINK /* sync start for playback and capture */
|
|
||||||
#define TRACK_CAPTURE /* dump capture timing info */
|
|
||||||
#define TRACK_PLAYBACK /* dump playback timing info */
|
|
||||||
+#define TRACK_SAMPLE_COUNTS /* show difference between sample counters and audiotimestamps returned by driver */
|
|
||||||
#define PLAYBACK_BUFFERS 4
|
|
||||||
|
|
||||||
|
|
||||||
@@ -65,9 +68,13 @@ int main(void)
|
|
||||||
snd_pcm_sframes_t frames;
|
|
||||||
snd_htimestamp_t tstamp_c, tstamp_p;
|
|
||||||
snd_htimestamp_t trigger_tstamp_c, trigger_tstamp_p;
|
|
||||||
+ snd_htimestamp_t audio_tstamp_c, audio_tstamp_p;
|
|
||||||
unsigned char buffer_p[PERIOD*4*4];
|
|
||||||
unsigned char buffer_c[PERIOD*4*4];
|
|
||||||
|
|
||||||
+ snd_pcm_hw_params_t *hwparams_p;
|
|
||||||
+ snd_pcm_hw_params_t *hwparams_c;
|
|
||||||
+
|
|
||||||
snd_pcm_sw_params_t *swparams_p;
|
|
||||||
snd_pcm_sw_params_t *swparams_c;
|
|
||||||
|
|
||||||
@@ -94,6 +101,18 @@ int main(void)
|
|
||||||
goto _exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ snd_pcm_hw_params_alloca(&hwparams_p);
|
|
||||||
+ /* get the current hwparams */
|
|
||||||
+ err = snd_pcm_hw_params_current(handle_p, hwparams_p);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ printf("Unable to determine current hwparams_p: %s\n", snd_strerror(err));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+ if (snd_pcm_hw_params_supports_audio_wallclock_ts(hwparams_p))
|
|
||||||
+ printf("Playback relies on audio wallclock timestamps\n");
|
|
||||||
+ else
|
|
||||||
+ printf("Playback relies on audio sample counter timestamps\n");
|
|
||||||
+
|
|
||||||
snd_pcm_sw_params_alloca(&swparams_p);
|
|
||||||
/* get the current swparams */
|
|
||||||
err = snd_pcm_sw_params_current(handle_p, swparams_p);
|
|
||||||
@@ -131,6 +150,18 @@ int main(void)
|
|
||||||
goto _exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ snd_pcm_hw_params_alloca(&hwparams_c);
|
|
||||||
+ /* get the current hwparams */
|
|
||||||
+ err = snd_pcm_hw_params_current(handle_c, hwparams_c);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ printf("Unable to determine current hwparams_c: %s\n", snd_strerror(err));
|
|
||||||
+ goto _exit;
|
|
||||||
+ }
|
|
||||||
+ if (snd_pcm_hw_params_supports_audio_wallclock_ts(hwparams_c))
|
|
||||||
+ printf("Capture relies on audio wallclock timestamps\n");
|
|
||||||
+ else
|
|
||||||
+ printf("Capture relies on audio sample counter timestamps\n");
|
|
||||||
+
|
|
||||||
snd_pcm_sw_params_alloca(&swparams_c);
|
|
||||||
/* get the current swparams */
|
|
||||||
err = snd_pcm_sw_params_current(handle_c, swparams_c);
|
|
||||||
@@ -202,26 +233,43 @@ int main(void)
|
|
||||||
frame_count_p += frames;
|
|
||||||
|
|
||||||
#if defined(TRACK_PLAYBACK)
|
|
||||||
- gettimestamp(handle_p, &tstamp_p, &trigger_tstamp_p, &avail_p, &delay_p);
|
|
||||||
+ gettimestamp(handle_p, &tstamp_p, &trigger_tstamp_p, &audio_tstamp_p, &avail_p, &delay_p);
|
|
||||||
|
|
||||||
+#if defined(TRACK_SAMPLE_COUNTS)
|
|
||||||
curr_count_p = frame_count_p - delay_p; /* written minus queued */
|
|
||||||
|
|
||||||
- printf("playback: systime: %lli nsec, sample time %lli nsec \tsystime delta %lli \n",
|
|
||||||
- timediff(tstamp_p,trigger_tstamp_p),
|
|
||||||
- (long long)round(((float)curr_count_p * 1000000000.0 / 48000.0)),
|
|
||||||
- timediff(tstamp_p, trigger_tstamp_p) - (long long)round((double)curr_count_p * 1000000000.0 / 48000.0)
|
|
||||||
+ printf("playback: curr_count %lli driver count %lli, delta %lli\n",
|
|
||||||
+ (long long)curr_count_p * 1000000000LL / 48000 ,
|
|
||||||
+ timestamp2ns(audio_tstamp_p),
|
|
||||||
+ (long long)curr_count_p * 1000000000LL / 48000 - timestamp2ns(audio_tstamp_p)
|
|
||||||
+ );
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ printf("playback: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli\n",
|
|
||||||
+ timediff(tstamp_p, trigger_tstamp_p),
|
|
||||||
+ timestamp2ns(audio_tstamp_p),
|
|
||||||
+ timediff(tstamp_p, trigger_tstamp_p) - timestamp2ns(audio_tstamp_p)
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(TRACK_CAPTURE)
|
|
||||||
- gettimestamp(handle_c, &tstamp_c, &trigger_tstamp_c, &avail_c, &delay_c);
|
|
||||||
+ gettimestamp(handle_c, &tstamp_c, &trigger_tstamp_c, &audio_tstamp_c, &avail_c, &delay_c);
|
|
||||||
|
|
||||||
+#if defined(TRACK_SAMPLE_COUNTS)
|
|
||||||
curr_count_c = frame_count_c + delay_c; /* read plus queued */
|
|
||||||
|
|
||||||
- printf("\t capture: systime: %lli nsec, sample time %lli nsec \tsystime delta %lli \n",
|
|
||||||
- timediff(tstamp_c,trigger_tstamp_c),
|
|
||||||
- (long long)round(((float)curr_count_c * 1000000000.0 / 48000.0)),
|
|
||||||
- timediff(tstamp_c, trigger_tstamp_c) - (long long)round((double)curr_count_c * 1000000000.0 / 48000.0)
|
|
||||||
+
|
|
||||||
+ printf("capture: curr_count %lli driver count %lli, delta %lli\n",
|
|
||||||
+ (long long)curr_count_c * 1000000000LL / 48000 ,
|
|
||||||
+ timestamp2ns(audio_tstamp_c),
|
|
||||||
+ (long long)curr_count_c * 1000000000LL / 48000 - timestamp2ns(audio_tstamp_c)
|
|
||||||
+ );
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ printf("\t capture: systime: %lli nsec, audio time %lli nsec, \tsystime delta %lli\n",
|
|
||||||
+ timediff(tstamp_c, trigger_tstamp_c),
|
|
||||||
+ timestamp2ns(audio_tstamp_c),
|
|
||||||
+ timediff(tstamp_c, trigger_tstamp_c) - timestamp2ns(audio_tstamp_c)
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.0
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
From 2b49df0c554cb9c7fc717dcf82d1b8f5310eef62 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Clemens Ladisch <clemens@ladisch.de>
|
|
||||||
Date: Sun, 28 Oct 2012 12:30:29 +0100
|
|
||||||
Subject: [PATCH 32/35] pcm: fix 64-bit SNDRV_PCM_IOCTL_STATUS ABI breakage
|
|
||||||
|
|
||||||
Commit cf40ea169aad (pcm: support for audio timestamps) added the new
|
|
||||||
audio_tstamp field to struct sndrv_pcm_status. However, struct timespec
|
|
||||||
requires 64-bit alignment, so the 64-bit compiler would insert
|
|
||||||
32 bits of padding before this field, which broke SNDRV_PCM_IOCTL_STATUS
|
|
||||||
with error messages like this:
|
|
||||||
|
|
||||||
kernel: unknown ioctl = 0x80984120
|
|
||||||
|
|
||||||
To solve this, insert the padding explicitly so that it can be taken
|
|
||||||
into account when calculating the ABI structure size.
|
|
||||||
|
|
||||||
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
|
|
||||||
---
|
|
||||||
include/sound/asound.h | 3 ++-
|
|
||||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/include/sound/asound.h b/include/sound/asound.h
|
|
||||||
index 16d03e8..8fdad91 100644
|
|
||||||
--- a/include/sound/asound.h
|
|
||||||
+++ b/include/sound/asound.h
|
|
||||||
@@ -427,8 +427,9 @@ struct sndrv_pcm_status {
|
|
||||||
sndrv_pcm_uframes_t avail_max; /* max frames available on hw since last status */
|
|
||||||
sndrv_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */
|
|
||||||
int suspended_state; /* suspended stream state */
|
|
||||||
+ u_int32_t reserved_alignment; /* must be filled with zero */
|
|
||||||
struct timespec audio_tstamp; /* from sample counter or wall clock */
|
|
||||||
- unsigned char reserved[60-sizeof(struct timespec)]; /* must be filled with zero */
|
|
||||||
+ unsigned char reserved[56-sizeof(struct timespec)]; /* must be filled with zero */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sndrv_pcm_mmap_status {
|
|
||||||
--
|
|
||||||
1.8.0
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
|||||||
From edcd677bf2065c560ef578940bab8f0aacddf0e6 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jaroslav Kysela <perex@perex.cz>
|
|
||||||
Date: Tue, 30 Oct 2012 11:43:07 +0100
|
|
||||||
Subject: [PATCH 33/35] PCM: Fix memory leak for pcm empty and asym plugins
|
|
||||||
|
|
||||||
The init-only plugins do not have own pcm handle, so free the references
|
|
||||||
to open function immediately after open.
|
|
||||||
|
|
||||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
||||||
---
|
|
||||||
src/pcm/pcm.c | 7 ++++++-
|
|
||||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
|
|
||||||
index 5880057..359d295 100644
|
|
||||||
--- a/src/pcm/pcm.c
|
|
||||||
+++ b/src/pcm/pcm.c
|
|
||||||
@@ -2171,7 +2171,12 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
|
|
||||||
if (open_func) {
|
|
||||||
err = open_func(pcmp, name, pcm_root, pcm_conf, stream, mode);
|
|
||||||
if (err >= 0) {
|
|
||||||
- (*pcmp)->open_func = open_func;
|
|
||||||
+ if ((*pcmp)->open_func) {
|
|
||||||
+ /* only init plugin (like empty, asym) */
|
|
||||||
+ snd_dlobj_cache_put(open_func);
|
|
||||||
+ } else {
|
|
||||||
+ (*pcmp)->open_func = open_func;
|
|
||||||
+ }
|
|
||||||
err = 0;
|
|
||||||
} else {
|
|
||||||
snd_dlobj_cache_put(open_func);
|
|
||||||
--
|
|
||||||
1.8.0
|
|
||||||
|
|
@ -1,179 +0,0 @@
|
|||||||
From 49dde08641f8c6b480c0d410d4fdb2160752dd9a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jaroslav Kysela <perex@perex.cz>
|
|
||||||
Date: Tue, 30 Oct 2012 13:07:48 +0100
|
|
||||||
Subject: [PATCH 34/35] Reduce compilation warnings
|
|
||||||
|
|
||||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
||||||
---
|
|
||||||
src/alisp/alisp.c | 2 +-
|
|
||||||
src/mixer/simple_none.c | 2 --
|
|
||||||
src/pcm/pcm_generic.c | 2 +-
|
|
||||||
src/pcm/pcm_ioplug.c | 2 +-
|
|
||||||
src/pcm/pcm_ladspa.c | 8 +-------
|
|
||||||
src/pcm/pcm_mmap_emul.c | 2 --
|
|
||||||
src/pcm/pcm_route.c | 2 +-
|
|
||||||
src/pcm/pcm_share.c | 5 +----
|
|
||||||
src/seq/seqmid.c | 2 +-
|
|
||||||
9 files changed, 7 insertions(+), 20 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/alisp/alisp.c b/src/alisp/alisp.c
|
|
||||||
index 7575f55..5dd5b06 100644
|
|
||||||
--- a/src/alisp/alisp.c
|
|
||||||
+++ b/src/alisp/alisp.c
|
|
||||||
@@ -3256,7 +3256,7 @@ int alsa_lisp(struct alisp_cfg *cfg, struct alisp_instance **_instance)
|
|
||||||
else
|
|
||||||
alsa_lisp_free(instance);
|
|
||||||
|
|
||||||
- return 0;
|
|
||||||
+ return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
void alsa_lisp_free(struct alisp_instance *instance)
|
|
||||||
diff --git a/src/mixer/simple_none.c b/src/mixer/simple_none.c
|
|
||||||
index b11e9e8..1c2774a 100644
|
|
||||||
--- a/src/mixer/simple_none.c
|
|
||||||
+++ b/src/mixer/simple_none.c
|
|
||||||
@@ -672,7 +672,6 @@ static int simple_update(snd_mixer_elem_t *melem)
|
|
||||||
unsigned int caps, pchannels, cchannels;
|
|
||||||
long pmin, pmax, cmin, cmax;
|
|
||||||
selem_ctl_t *ctl;
|
|
||||||
- const char *name;
|
|
||||||
|
|
||||||
caps = 0;
|
|
||||||
pchannels = 0;
|
|
||||||
@@ -683,7 +682,6 @@ static int simple_update(snd_mixer_elem_t *melem)
|
|
||||||
cmax = LONG_MIN;
|
|
||||||
assert(snd_mixer_elem_get_type(melem) == SND_MIXER_ELEM_SIMPLE);
|
|
||||||
simple = snd_mixer_elem_get_private(melem);
|
|
||||||
- name = snd_mixer_selem_get_name(melem);
|
|
||||||
ctl = &simple->ctls[CTL_SINGLE];
|
|
||||||
if (ctl->elem) {
|
|
||||||
pchannels = cchannels = ctl->values;
|
|
||||||
diff --git a/src/pcm/pcm_generic.c b/src/pcm/pcm_generic.c
|
|
||||||
index 0436439..d56e5d3 100644
|
|
||||||
--- a/src/pcm/pcm_generic.c
|
|
||||||
+++ b/src/pcm/pcm_generic.c
|
|
||||||
@@ -41,7 +41,7 @@ int snd_pcm_generic_close(snd_pcm_t *pcm)
|
|
||||||
if (generic->close_slave)
|
|
||||||
err = snd_pcm_close(generic->slave);
|
|
||||||
free(generic);
|
|
||||||
- return 0;
|
|
||||||
+ return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
int snd_pcm_generic_nonblock(snd_pcm_t *pcm, int nonblock)
|
|
||||||
diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c
|
|
||||||
index 9c6275a..a90c844 100644
|
|
||||||
--- a/src/pcm/pcm_ioplug.c
|
|
||||||
+++ b/src/pcm/pcm_ioplug.c
|
|
||||||
@@ -625,7 +625,7 @@ static snd_pcm_sframes_t snd_pcm_ioplug_avail_update(snd_pcm_t *pcm)
|
|
||||||
snd_pcm_uframes_t avail;
|
|
||||||
|
|
||||||
snd_pcm_ioplug_hw_ptr_update(pcm);
|
|
||||||
- if (io->data->state == SNDRV_PCM_STATE_XRUN)
|
|
||||||
+ if (io->data->state == SND_PCM_STATE_XRUN)
|
|
||||||
return -EPIPE;
|
|
||||||
if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
|
|
||||||
pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
|
|
||||||
diff --git a/src/pcm/pcm_ladspa.c b/src/pcm/pcm_ladspa.c
|
|
||||||
index 31e2875..0a9c52e 100644
|
|
||||||
--- a/src/pcm/pcm_ladspa.c
|
|
||||||
+++ b/src/pcm/pcm_ladspa.c
|
|
||||||
@@ -612,8 +612,7 @@ static int snd_pcm_ladspa_allocate_instances(snd_pcm_t *pcm, snd_pcm_ladspa_t *l
|
|
||||||
{
|
|
||||||
struct list_head *list, *pos;
|
|
||||||
unsigned int depth, idx, count;
|
|
||||||
- unsigned int in_channel, out_channel;
|
|
||||||
- unsigned int in_channels, out_channels;
|
|
||||||
+ unsigned int in_channels;
|
|
||||||
unsigned int in_ports, out_ports;
|
|
||||||
snd_pcm_ladspa_instance_t *instance = NULL;
|
|
||||||
int err;
|
|
||||||
@@ -622,11 +621,8 @@ static int snd_pcm_ladspa_allocate_instances(snd_pcm_t *pcm, snd_pcm_ladspa_t *l
|
|
||||||
in_channels = ladspa->channels > 0 ? ladspa->channels :
|
|
||||||
(pcm->stream == SND_PCM_STREAM_PLAYBACK ? pcm->channels : ladspa->plug.gen.slave->channels);
|
|
||||||
depth = 0;
|
|
||||||
- out_channels = 0;
|
|
||||||
list_for_each(pos, list) {
|
|
||||||
snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
|
|
||||||
- if (pos->next == list) /* last entry */
|
|
||||||
- out_channels = pcm->stream == SND_PCM_STREAM_PLAYBACK ? ladspa->plug.gen.slave->channels : pcm->channels;
|
|
||||||
in_ports = snd_pcm_ladspa_count_ports(plugin, LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO);
|
|
||||||
out_ports = snd_pcm_ladspa_count_ports(plugin, LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO);
|
|
||||||
count = 1;
|
|
||||||
@@ -636,8 +632,6 @@ static int snd_pcm_ladspa_allocate_instances(snd_pcm_t *pcm, snd_pcm_ladspa_t *l
|
|
||||||
else
|
|
||||||
plugin->policy = SND_PCM_LADSPA_POLICY_NONE;
|
|
||||||
}
|
|
||||||
- in_channel = 0;
|
|
||||||
- out_channel = 0;
|
|
||||||
for (idx = 0; idx < count; idx++) {
|
|
||||||
instance = (snd_pcm_ladspa_instance_t *)calloc(1, sizeof(snd_pcm_ladspa_instance_t));
|
|
||||||
if (instance == NULL)
|
|
||||||
diff --git a/src/pcm/pcm_mmap_emul.c b/src/pcm/pcm_mmap_emul.c
|
|
||||||
index 236fe69..811cb1c 100644
|
|
||||||
--- a/src/pcm/pcm_mmap_emul.c
|
|
||||||
+++ b/src/pcm/pcm_mmap_emul.c
|
|
||||||
@@ -332,9 +332,7 @@ static snd_pcm_sframes_t snd_pcm_mmap_emul_avail_update(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
mmap_emul_t *map = pcm->private_data;
|
|
||||||
snd_pcm_t *slave = map->gen.slave;
|
|
||||||
- snd_pcm_sframes_t avail;
|
|
||||||
|
|
||||||
- avail = snd_pcm_avail_update(slave);
|
|
||||||
if (!map->mmap_emul || pcm->stream == SND_PCM_STREAM_PLAYBACK)
|
|
||||||
map->hw_ptr = *slave->hw.ptr;
|
|
||||||
else
|
|
||||||
diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c
|
|
||||||
index a3d1695..2beedf6 100644
|
|
||||||
--- a/src/pcm/pcm_route.c
|
|
||||||
+++ b/src/pcm/pcm_route.c
|
|
||||||
@@ -725,7 +725,7 @@ static snd_pcm_chmap_t *snd_pcm_route_get_chmap(snd_pcm_t *pcm)
|
|
||||||
for (dst = 0; dst < route->params.ndsts; dst++) {
|
|
||||||
snd_pcm_route_ttable_dst_t *d = &route->params.dsts[dst];
|
|
||||||
for (src = 0; src < d->nsrcs; src++) {
|
|
||||||
- int c = d->srcs[src].channel;
|
|
||||||
+ unsigned int c = d->srcs[src].channel;
|
|
||||||
if (c < nsrcs && map->pos[c] == SND_CHMAP_NA)
|
|
||||||
map->pos[c] = slave_map->pos[dst];
|
|
||||||
}
|
|
||||||
diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c
|
|
||||||
index 56a8685..936e2f9 100644
|
|
||||||
--- a/src/pcm/pcm_share.c
|
|
||||||
+++ b/src/pcm/pcm_share.c
|
|
||||||
@@ -136,18 +136,15 @@ static snd_pcm_uframes_t snd_pcm_share_slave_avail(snd_pcm_share_slave_t *slave)
|
|
||||||
static snd_pcm_uframes_t _snd_pcm_share_slave_forward(snd_pcm_share_slave_t *slave)
|
|
||||||
{
|
|
||||||
struct list_head *i;
|
|
||||||
- snd_pcm_uframes_t buffer_size, boundary;
|
|
||||||
- snd_pcm_uframes_t slave_appl_ptr;
|
|
||||||
+ snd_pcm_uframes_t buffer_size;
|
|
||||||
snd_pcm_sframes_t frames, safety_frames;
|
|
||||||
snd_pcm_sframes_t min_frames, max_frames;
|
|
||||||
snd_pcm_uframes_t avail, slave_avail;
|
|
||||||
snd_pcm_uframes_t slave_hw_avail;
|
|
||||||
slave_avail = snd_pcm_share_slave_avail(slave);
|
|
||||||
- boundary = slave->pcm->boundary;
|
|
||||||
buffer_size = slave->pcm->buffer_size;
|
|
||||||
min_frames = slave_avail;
|
|
||||||
max_frames = 0;
|
|
||||||
- slave_appl_ptr = *slave->pcm->appl.ptr;
|
|
||||||
list_for_each(i, &slave->clients) {
|
|
||||||
snd_pcm_share_t *share = list_entry(i, snd_pcm_share_t, list);
|
|
||||||
snd_pcm_t *pcm = share->pcm;
|
|
||||||
diff --git a/src/seq/seqmid.c b/src/seq/seqmid.c
|
|
||||||
index 2ff7e8d..7d8bf1a 100644
|
|
||||||
--- a/src/seq/seqmid.c
|
|
||||||
+++ b/src/seq/seqmid.c
|
|
||||||
@@ -423,7 +423,7 @@ int snd_seq_parse_address(snd_seq_t *seq, snd_seq_addr_t *addr, const char *arg)
|
|
||||||
return -EINVAL;
|
|
||||||
cinfo.client = -1;
|
|
||||||
while (snd_seq_query_next_client(seq, &cinfo) >= 0) {
|
|
||||||
- if ((strlen(cinfo.name) == len) &&
|
|
||||||
+ if ((strlen(cinfo.name) == (size_t)len) &&
|
|
||||||
! strncmp(arg, cinfo.name, len)) {
|
|
||||||
addr->client = cinfo.client;
|
|
||||||
return 0;
|
|
||||||
--
|
|
||||||
1.8.0
|
|
||||||
|
|
@ -1,222 +0,0 @@
|
|||||||
From 3fd4ab9be0db7c7430ebd258f2717a976381715d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Tue, 13 Nov 2012 16:16:26 +0100
|
|
||||||
Subject: [PATCH 35/35] PCM: Avoid busy loop in snd_pcm_write_areas() with
|
|
||||||
rate plugin
|
|
||||||
|
|
||||||
snd_pcm_write_areas() tries to wait until avail >= avail_min condition
|
|
||||||
is satisfied. This doesn't work always well when a rate plugin is in
|
|
||||||
the play.
|
|
||||||
|
|
||||||
When a partial data with a smaller size than a period is written, the
|
|
||||||
rate plugin doesn't transfer the data immediately to the slave PCM,
|
|
||||||
but kept in an internal buffer and it changes only the hwptr of the
|
|
||||||
plugin. Thus, the condition "avail < avail_min" is triggered for a
|
|
||||||
wait check although the underlying slave PCM has enough room. This
|
|
||||||
results in a call of snd_pcm_wait() which returns immediately after
|
|
||||||
poll() call, and the snd_pcm_write_areas() loop continues. As a
|
|
||||||
consequence, it falls into a CPU hog.
|
|
||||||
|
|
||||||
This patch fixes that busy loop by introducing a new fast_ops to check
|
|
||||||
the availability for wait of avail_min. Then a plugin can ask the
|
|
||||||
slave PCM whether the wait is required (or possible).
|
|
||||||
|
|
||||||
A few plugins like multi plugin need a special handling. Otherwise a
|
|
||||||
generic plugin function can be used.
|
|
||||||
|
|
||||||
Reported-by: Trent Piepho <tpiepho@gmail.com>
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/pcm/pcm.c | 8 ++++----
|
|
||||||
src/pcm/pcm_generic.c | 6 ++++++
|
|
||||||
src/pcm/pcm_generic.h | 4 +++-
|
|
||||||
src/pcm/pcm_hooks.c | 1 +
|
|
||||||
src/pcm/pcm_local.h | 11 +++++++++++
|
|
||||||
src/pcm/pcm_meter.c | 1 +
|
|
||||||
src/pcm/pcm_mmap_emul.c | 1 +
|
|
||||||
src/pcm/pcm_multi.c | 8 ++++++++
|
|
||||||
src/pcm/pcm_plugin.c | 1 +
|
|
||||||
src/pcm/pcm_rate.c | 1 +
|
|
||||||
10 files changed, 37 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
|
|
||||||
index 359d295..f8b68ed 100644
|
|
||||||
--- a/src/pcm/pcm.c
|
|
||||||
+++ b/src/pcm/pcm.c
|
|
||||||
@@ -2357,7 +2357,7 @@ int snd_pcm_open_named_slave(snd_pcm_t **pcmp, const char *name,
|
|
||||||
*/
|
|
||||||
int snd_pcm_wait(snd_pcm_t *pcm, int timeout)
|
|
||||||
{
|
|
||||||
- if (snd_pcm_mmap_avail(pcm) >= pcm->avail_min) {
|
|
||||||
+ if (!snd_pcm_may_wait_for_avail_min(pcm, snd_pcm_mmap_avail(pcm))) {
|
|
||||||
/* check more precisely */
|
|
||||||
switch (snd_pcm_state(pcm)) {
|
|
||||||
case SND_PCM_STATE_XRUN:
|
|
||||||
@@ -6776,14 +6776,14 @@ snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area
|
|
||||||
goto _end;
|
|
||||||
}
|
|
||||||
if ((state == SND_PCM_STATE_RUNNING &&
|
|
||||||
- (snd_pcm_uframes_t)avail < pcm->avail_min &&
|
|
||||||
- size > (snd_pcm_uframes_t)avail)) {
|
|
||||||
+ size > (snd_pcm_uframes_t)avail &&
|
|
||||||
+ snd_pcm_may_wait_for_avail_min(pcm, avail))) {
|
|
||||||
if (pcm->mode & SND_PCM_NONBLOCK) {
|
|
||||||
err = -EAGAIN;
|
|
||||||
goto _end;
|
|
||||||
}
|
|
||||||
|
|
||||||
- err = snd_pcm_wait(pcm, -1);
|
|
||||||
+ err = snd_pcm_wait_nocheck(pcm, -1);
|
|
||||||
if (err < 0)
|
|
||||||
break;
|
|
||||||
goto _again;
|
|
||||||
diff --git a/src/pcm/pcm_generic.c b/src/pcm/pcm_generic.c
|
|
||||||
index d56e5d3..5fc4888 100644
|
|
||||||
--- a/src/pcm/pcm_generic.c
|
|
||||||
+++ b/src/pcm/pcm_generic.c
|
|
||||||
@@ -341,4 +341,10 @@ int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
|
|
||||||
return snd_pcm_set_chmap(generic->slave, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
+int snd_pcm_generic_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail ATTRIBUTE_UNUSED)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_generic_t *generic = pcm->private_data;
|
|
||||||
+ return snd_pcm_may_wait_for_avail_min(generic->slave, snd_pcm_mmap_avail(generic->slave));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
#endif /* DOC_HIDDEN */
|
|
||||||
diff --git a/src/pcm/pcm_generic.h b/src/pcm/pcm_generic.h
|
|
||||||
index 916c6ec..d189077 100644
|
|
||||||
--- a/src/pcm/pcm_generic.h
|
|
||||||
+++ b/src/pcm/pcm_generic.h
|
|
||||||
@@ -109,6 +109,8 @@ typedef struct {
|
|
||||||
snd1_pcm_generic_get_chmap
|
|
||||||
#define snd_pcm_generic_set_chmap \
|
|
||||||
snd1_pcm_generic_set_chmap
|
|
||||||
+#define snd_pcm_generic_may_wait_for_avail_min \
|
|
||||||
+ snd1_pcm_generic_may_wait_for_avail_min
|
|
||||||
|
|
||||||
int snd_pcm_generic_close(snd_pcm_t *pcm);
|
|
||||||
int snd_pcm_generic_nonblock(snd_pcm_t *pcm, int nonblock);
|
|
||||||
@@ -158,5 +160,5 @@ int snd_pcm_generic_munmap(snd_pcm_t *pcm);
|
|
||||||
snd_pcm_chmap_query_t **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm);
|
|
||||||
snd_pcm_chmap_t *snd_pcm_generic_get_chmap(snd_pcm_t *pcm);
|
|
||||||
int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
|
|
||||||
-
|
|
||||||
+int snd_pcm_generic_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail);
|
|
||||||
|
|
||||||
diff --git a/src/pcm/pcm_hooks.c b/src/pcm/pcm_hooks.c
|
|
||||||
index 0feb4a3..f837282 100644
|
|
||||||
--- a/src/pcm/pcm_hooks.c
|
|
||||||
+++ b/src/pcm/pcm_hooks.c
|
|
||||||
@@ -199,6 +199,7 @@ static const snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
|
|
||||||
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
|
|
||||||
.poll_descriptors = snd_pcm_generic_poll_descriptors,
|
|
||||||
.poll_revents = snd_pcm_generic_poll_revents,
|
|
||||||
+ .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
|
|
||||||
index e7798fd..8cf7c3d 100644
|
|
||||||
--- a/src/pcm/pcm_local.h
|
|
||||||
+++ b/src/pcm/pcm_local.h
|
|
||||||
@@ -177,6 +177,7 @@ typedef struct {
|
|
||||||
int (*poll_descriptors_count)(snd_pcm_t *pcm);
|
|
||||||
int (*poll_descriptors)(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space);
|
|
||||||
int (*poll_revents)(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
|
|
||||||
+ int (*may_wait_for_avail_min)(snd_pcm_t *pcm, snd_pcm_uframes_t avail);
|
|
||||||
} snd_pcm_fast_ops_t;
|
|
||||||
|
|
||||||
struct _snd_pcm {
|
|
||||||
@@ -984,3 +985,13 @@ _snd_pcm_parse_config_chmaps(snd_config_t *conf);
|
|
||||||
snd_pcm_chmap_t *
|
|
||||||
_snd_pcm_choose_fixed_chmap(snd_pcm_t *pcm, snd_pcm_chmap_query_t * const *maps);
|
|
||||||
|
|
||||||
+/* return true if the PCM stream may wait to get avail_min space */
|
|
||||||
+static inline int snd_pcm_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail)
|
|
||||||
+{
|
|
||||||
+ if (avail >= pcm->avail_min)
|
|
||||||
+ return 0;
|
|
||||||
+ if (pcm->fast_ops->may_wait_for_avail_min)
|
|
||||||
+ return pcm->fast_ops->may_wait_for_avail_min(pcm, avail);
|
|
||||||
+ return 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
diff --git a/src/pcm/pcm_meter.c b/src/pcm/pcm_meter.c
|
|
||||||
index 42a125e..e60b92d 100644
|
|
||||||
--- a/src/pcm/pcm_meter.c
|
|
||||||
+++ b/src/pcm/pcm_meter.c
|
|
||||||
@@ -545,6 +545,7 @@ static const snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
|
|
||||||
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
|
|
||||||
.poll_descriptors = snd_pcm_generic_poll_descriptors,
|
|
||||||
.poll_revents = snd_pcm_generic_poll_revents,
|
|
||||||
+ .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
diff --git a/src/pcm/pcm_mmap_emul.c b/src/pcm/pcm_mmap_emul.c
|
|
||||||
index 811cb1c..67d2e05 100644
|
|
||||||
--- a/src/pcm/pcm_mmap_emul.c
|
|
||||||
+++ b/src/pcm/pcm_mmap_emul.c
|
|
||||||
@@ -400,6 +400,7 @@ static const snd_pcm_fast_ops_t snd_pcm_mmap_emul_fast_ops = {
|
|
||||||
.poll_descriptors = snd_pcm_generic_poll_descriptors,
|
|
||||||
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
|
|
||||||
.poll_revents = snd_pcm_generic_poll_revents,
|
|
||||||
+ .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef DOC_HIDDEN
|
|
||||||
diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c
|
|
||||||
index ffb1b53..2db82c0 100644
|
|
||||||
--- a/src/pcm/pcm_multi.c
|
|
||||||
+++ b/src/pcm/pcm_multi.c
|
|
||||||
@@ -739,6 +739,13 @@ static int snd_pcm_multi_mmap(snd_pcm_t *pcm)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int snd_pcm_multi_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail)
|
|
||||||
+{
|
|
||||||
+ snd_pcm_multi_t *multi = pcm->private_data;
|
|
||||||
+ snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm;
|
|
||||||
+ return snd_pcm_may_wait_for_avail_min(slave, snd_pcm_mmap_avail(slave));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static snd_pcm_chmap_query_t **snd_pcm_multi_query_chmaps(snd_pcm_t *pcm)
|
|
||||||
{
|
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
|
||||||
@@ -937,6 +944,7 @@ static const snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
|
|
||||||
.poll_descriptors_count = snd_pcm_multi_poll_descriptors_count,
|
|
||||||
.poll_descriptors = snd_pcm_multi_poll_descriptors,
|
|
||||||
.poll_revents = snd_pcm_multi_poll_revents,
|
|
||||||
+ .may_wait_for_avail_min = snd_pcm_multi_may_wait_for_avail_min,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
|
|
||||||
index d88e117..96218a8 100644
|
|
||||||
--- a/src/pcm/pcm_plugin.c
|
|
||||||
+++ b/src/pcm/pcm_plugin.c
|
|
||||||
@@ -570,6 +570,7 @@ const snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
|
|
||||||
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
|
|
||||||
.poll_descriptors = snd_pcm_generic_poll_descriptors,
|
|
||||||
.poll_revents = snd_pcm_generic_poll_revents,
|
|
||||||
+ .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
|
|
||||||
index 4ba8521..54a3e67 100644
|
|
||||||
--- a/src/pcm/pcm_rate.c
|
|
||||||
+++ b/src/pcm/pcm_rate.c
|
|
||||||
@@ -1234,6 +1234,7 @@ static const snd_pcm_fast_ops_t snd_pcm_rate_fast_ops = {
|
|
||||||
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
|
|
||||||
.poll_descriptors = snd_pcm_generic_poll_descriptors,
|
|
||||||
.poll_revents = snd_pcm_rate_poll_revents,
|
|
||||||
+ .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const snd_pcm_ops_t snd_pcm_rate_ops = {
|
|
||||||
--
|
|
||||||
1.8.0
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,102 +0,0 @@
|
|||||||
From 67d692af480ed0656fb0fe7fdc6451374447dc7c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Mon, 26 Nov 2012 18:10:26 +0100
|
|
||||||
Subject: [PATCH 37/38] PCM: Add more chmap definitions for UAC2
|
|
||||||
|
|
||||||
The new PCM chmap positions have been added in (to be) 3.8-rc1 kernel,
|
|
||||||
and now updated alsa-lib, too.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/pcm.h | 13 +++++++++++--
|
|
||||||
include/sound/asound.h | 12 +++++++++++-
|
|
||||||
src/pcm/pcm.c | 12 ++++++++++++
|
|
||||||
3 files changed, 34 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/include/pcm.h b/include/pcm.h
|
|
||||||
index 1ce91e7..2235678 100644
|
|
||||||
--- a/include/pcm.h
|
|
||||||
+++ b/include/pcm.h
|
|
||||||
@@ -475,7 +475,7 @@ int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
|
|
||||||
int snd_pcm_unlink(snd_pcm_t *pcm);
|
|
||||||
|
|
||||||
/** channel mapping API version number */
|
|
||||||
-#define SND_CHMAP_API_VERSION ((1 << 16) | (0 << 8) | 0)
|
|
||||||
+#define SND_CHMAP_API_VERSION ((1 << 16) | (0 << 8) | 1)
|
|
||||||
|
|
||||||
/** channel map list type */
|
|
||||||
enum snd_pcm_chmap_type {
|
|
||||||
@@ -516,7 +516,16 @@ enum snd_pcm_chmap_position {
|
|
||||||
SND_CHMAP_TRL, /** top rear left */
|
|
||||||
SND_CHMAP_TRR, /** top rear right */
|
|
||||||
SND_CHMAP_TRC, /** top rear center */
|
|
||||||
- SND_CHMAP_LAST = SND_CHMAP_TRC, /** last entry */
|
|
||||||
+ SND_CHMAP_TFLC, /* top front left center */
|
|
||||||
+ SND_CHMAP_TFRC, /* top front right center */
|
|
||||||
+ SND_CHMAP_TSL, /* top side left */
|
|
||||||
+ SND_CHMAP_TSR, /* top side right */
|
|
||||||
+ SND_CHMAP_LLFE, /* left LFE */
|
|
||||||
+ SND_CHMAP_RLFE, /* right LFE */
|
|
||||||
+ SND_CHMAP_BC, /* bottom center */
|
|
||||||
+ SND_CHMAP_BLC, /* bottom left center */
|
|
||||||
+ SND_CHMAP_BRC, /* bottom right center */
|
|
||||||
+ SND_CHMAP_LAST = SND_CHMAP_BRC,
|
|
||||||
};
|
|
||||||
|
|
||||||
/** bitmask for channel position */
|
|
||||||
diff --git a/include/sound/asound.h b/include/sound/asound.h
|
|
||||||
index 515b8fc..1774a5c 100644
|
|
||||||
--- a/include/sound/asound.h
|
|
||||||
+++ b/include/sound/asound.h
|
|
||||||
@@ -492,7 +492,17 @@ enum {
|
|
||||||
SNDRV_CHMAP_TRL, /* top rear left */
|
|
||||||
SNDRV_CHMAP_TRR, /* top rear right */
|
|
||||||
SNDRV_CHMAP_TRC, /* top rear center */
|
|
||||||
- SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
|
|
||||||
+ /* new definitions for UAC2 */
|
|
||||||
+ SNDRV_CHMAP_TFLC, /* top front left center */
|
|
||||||
+ SNDRV_CHMAP_TFRC, /* top front right center */
|
|
||||||
+ SNDRV_CHMAP_TSL, /* top side left */
|
|
||||||
+ SNDRV_CHMAP_TSR, /* top side right */
|
|
||||||
+ SNDRV_CHMAP_LLFE, /* left LFE */
|
|
||||||
+ SNDRV_CHMAP_RLFE, /* right LFE */
|
|
||||||
+ SNDRV_CHMAP_BC, /* bottom center */
|
|
||||||
+ SNDRV_CHMAP_BLC, /* bottom left center */
|
|
||||||
+ SNDRV_CHMAP_BRC, /* bottom right center */
|
|
||||||
+ SNDRV_CHMAP_LAST = SNDRV_CHMAP_BRC,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SNDRV_CHMAP_POSITION_MASK 0xffff
|
|
||||||
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
|
|
||||||
index e16b07f..d616705 100644
|
|
||||||
--- a/src/pcm/pcm.c
|
|
||||||
+++ b/src/pcm/pcm.c
|
|
||||||
@@ -7434,6 +7434,9 @@ static const char *chmap_names[SND_CHMAP_LAST + 1] = {
|
|
||||||
_NAME(FLH), _NAME(FCH), _NAME(FRH), _NAME(TC),
|
|
||||||
_NAME(TFL), _NAME(TFR), _NAME(TFC),
|
|
||||||
_NAME(TRL), _NAME(TRR), _NAME(TRC),
|
|
||||||
+ _NAME(TFLC), _NAME(TFRC), _NAME(TSL), _NAME(TSR),
|
|
||||||
+ _NAME(LLFE), _NAME(RLFE),
|
|
||||||
+ _NAME(BC), _NAME(BLC), _NAME(BRC),
|
|
||||||
};
|
|
||||||
#undef _NAME
|
|
||||||
#endif
|
|
||||||
@@ -7480,6 +7483,15 @@ static const char *chmap_long_names[SND_CHMAP_LAST + 1] = {
|
|
||||||
[SND_CHMAP_TRL] = "Top Rear Left",
|
|
||||||
[SND_CHMAP_TRR] = "Top Rear Right",
|
|
||||||
[SND_CHMAP_TRC] = "Top Rear Center",
|
|
||||||
+ [SND_CHMAP_TFLC] = "Top Front Left Center",
|
|
||||||
+ [SND_CHMAP_TFRC] = "Top Front Right Center",
|
|
||||||
+ [SND_CHMAP_TSL] = "Top Side Left",
|
|
||||||
+ [SND_CHMAP_TSR] = "Top Side Right",
|
|
||||||
+ [SND_CHMAP_LLFE] = "Left LFE",
|
|
||||||
+ [SND_CHMAP_RLFE] = "Right LFE",
|
|
||||||
+ [SND_CHMAP_BC] = "Bottom Center",
|
|
||||||
+ [SND_CHMAP_BLC] = "Bottom Left Center",
|
|
||||||
+ [SND_CHMAP_BRC] = "Bottom Right Center",
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
--
|
|
||||||
1.8.0.1
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
|||||||
From f47816d6b78003b5161ffb67b3b5c1b62b8a2a00 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Mon, 26 Nov 2012 18:13:01 +0100
|
|
||||||
Subject: [PATCH 38/38] PCM: shut up a compile "unused parameter" compile
|
|
||||||
warning in pcm_multi.c
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/pcm/pcm_multi.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c
|
|
||||||
index 2db82c0..f58852c 100644
|
|
||||||
--- a/src/pcm/pcm_multi.c
|
|
||||||
+++ b/src/pcm/pcm_multi.c
|
|
||||||
@@ -739,7 +739,7 @@ static int snd_pcm_multi_mmap(snd_pcm_t *pcm)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int snd_pcm_multi_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail)
|
|
||||||
+static int snd_pcm_multi_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail ATTRIBUTE_UNUSED)
|
|
||||||
{
|
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
|
||||||
snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm;
|
|
||||||
--
|
|
||||||
1.8.0.1
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
|||||||
From 22d6b6e643d81467bcd2b0d8934c6b84bed51787 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Fri, 30 Nov 2012 14:33:54 +0100
|
|
||||||
Subject: [PATCH] Add workaround for conflicting snd_seq_event_t definitions
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/local.h | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/include/local.h b/include/local.h
|
|
||||||
index b0a9368..268970a 100644
|
|
||||||
--- a/include/local.h
|
|
||||||
+++ b/include/local.h
|
|
||||||
@@ -144,6 +144,7 @@
|
|
||||||
#define snd_seq_tick_time_t sndrv_seq_tick_time_t
|
|
||||||
#define snd_seq_real_time sndrv_seq_real_time
|
|
||||||
#define snd_seq_timestamp sndrv_seq_timestamp
|
|
||||||
+#define snd_seq_event_type_t sndrv_seq_event_type_t
|
|
||||||
#define snd_seq_event sndrv_seq_event
|
|
||||||
#define snd_seq_connect sndrv_seq_connect
|
|
||||||
#define snd_seq_ev_note sndrv_seq_ev_note
|
|
||||||
--
|
|
||||||
1.8.0.1
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
|||||||
From 03c26d0edeeefb7550ba8cca91167343677022ab Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Tue, 4 Dec 2012 12:17:00 +0100
|
|
||||||
Subject: [PATCH] PCM: Fix conflict of _snd_pcm_hw_params definitions
|
|
||||||
|
|
||||||
Fix the call of _snd_pcm_hw_params() to _snd_pcm_hw_params_internal().
|
|
||||||
The build passed wrongly because of _snd_pcm_hw_params define.
|
|
||||||
Having the same function name as the struct name is is simply
|
|
||||||
confusing...
|
|
||||||
|
|
||||||
Also, to be sure, _snd_pcm_hw_params is undef'ed in pcm_local.h, too.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/pcm/pcm.c | 2 +-
|
|
||||||
src/pcm/pcm_file.c | 2 +-
|
|
||||||
src/pcm/pcm_generic.c | 2 +-
|
|
||||||
src/pcm/pcm_local.h | 1 +
|
|
||||||
src/pcm/pcm_meter.c | 2 +-
|
|
||||||
src/pcm/pcm_mmap_emul.c | 4 ++--
|
|
||||||
src/pcm/pcm_plug.c | 2 +-
|
|
||||||
src/pcm/pcm_share.c | 2 +-
|
|
||||||
8 files changed, 9 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
|
|
||||||
index d616705..5053a7b 100644
|
|
||||||
--- a/src/pcm/pcm.c
|
|
||||||
+++ b/src/pcm/pcm.c
|
|
||||||
@@ -828,7 +828,7 @@ int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
assert(pcm && params);
|
|
||||||
- err = _snd_pcm_hw_params(pcm, params);
|
|
||||||
+ err = _snd_pcm_hw_params_internal(pcm, params);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
err = snd_pcm_prepare(pcm);
|
|
||||||
diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c
|
|
||||||
index c8214b4..5950401 100644
|
|
||||||
--- a/src/pcm/pcm_file.c
|
|
||||||
+++ b/src/pcm/pcm_file.c
|
|
||||||
@@ -602,7 +602,7 @@ static int snd_pcm_file_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
|
|
||||||
snd_pcm_file_t *file = pcm->private_data;
|
|
||||||
unsigned int channel;
|
|
||||||
snd_pcm_t *slave = file->gen.slave;
|
|
||||||
- int err = _snd_pcm_hw_params(slave, params);
|
|
||||||
+ int err = _snd_pcm_hw_params_internal(slave, params);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
file->buffer_bytes = snd_pcm_frames_to_bytes(slave, slave->buffer_size);
|
|
||||||
diff --git a/src/pcm/pcm_generic.c b/src/pcm/pcm_generic.c
|
|
||||||
index 5fc4888..f068ee2 100644
|
|
||||||
--- a/src/pcm/pcm_generic.c
|
|
||||||
+++ b/src/pcm/pcm_generic.c
|
|
||||||
@@ -101,7 +101,7 @@ int snd_pcm_generic_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
|
||||||
int snd_pcm_generic_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
|
||||||
{
|
|
||||||
snd_pcm_generic_t *generic = pcm->private_data;
|
|
||||||
- return _snd_pcm_hw_params(generic->slave, params);
|
|
||||||
+ return _snd_pcm_hw_params_internal(generic->slave, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
int snd_pcm_generic_prepare(snd_pcm_t *pcm)
|
|
||||||
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
|
|
||||||
index c616e56..63b9036 100644
|
|
||||||
--- a/src/pcm/pcm_local.h
|
|
||||||
+++ b/src/pcm/pcm_local.h
|
|
||||||
@@ -579,6 +579,7 @@ static inline int muldiv_near(int a, int b, int c)
|
|
||||||
|
|
||||||
int snd_pcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
|
|
||||||
int _snd_pcm_hw_params_internal(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
|
|
||||||
+#undef _snd_pcm_hw_params
|
|
||||||
int snd_pcm_hw_refine_soft(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
|
|
||||||
int snd_pcm_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
|
||||||
int (*cprepare)(snd_pcm_t *pcm,
|
|
||||||
diff --git a/src/pcm/pcm_meter.c b/src/pcm/pcm_meter.c
|
|
||||||
index e60b92d..573b6fe 100644
|
|
||||||
--- a/src/pcm/pcm_meter.c
|
|
||||||
+++ b/src/pcm/pcm_meter.c
|
|
||||||
@@ -419,7 +419,7 @@ static int snd_pcm_meter_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *pa
|
|
||||||
static int snd_pcm_meter_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
|
||||||
{
|
|
||||||
snd_pcm_meter_t *meter = pcm->private_data;
|
|
||||||
- return _snd_pcm_hw_params(meter->gen.slave, params);
|
|
||||||
+ return _snd_pcm_hw_params_internal(meter->gen.slave, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int snd_pcm_meter_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
|
||||||
diff --git a/src/pcm/pcm_mmap_emul.c b/src/pcm/pcm_mmap_emul.c
|
|
||||||
index 67d2e05..63789bc 100644
|
|
||||||
--- a/src/pcm/pcm_mmap_emul.c
|
|
||||||
+++ b/src/pcm/pcm_mmap_emul.c
|
|
||||||
@@ -160,7 +160,7 @@ static int snd_pcm_mmap_emul_hw_params(snd_pcm_t *pcm,
|
|
||||||
snd_pcm_access_mask_t *pmask;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
- err = _snd_pcm_hw_params(map->gen.slave, params);
|
|
||||||
+ err = _snd_pcm_hw_params_internal(map->gen.slave, params);
|
|
||||||
if (err >= 0) {
|
|
||||||
map->mmap_emul = 0;
|
|
||||||
return err;
|
|
||||||
@@ -186,7 +186,7 @@ static int snd_pcm_mmap_emul_hw_params(snd_pcm_t *pcm,
|
|
||||||
default:
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
- err = _snd_pcm_hw_params(map->gen.slave, params);
|
|
||||||
+ err = _snd_pcm_hw_params_internal(map->gen.slave, params);
|
|
||||||
if (err < 0)
|
|
||||||
goto _err;
|
|
||||||
|
|
||||||
diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c
|
|
||||||
index 0bd8850..fa84eaa 100644
|
|
||||||
--- a/src/pcm/pcm_plug.c
|
|
||||||
+++ b/src/pcm/pcm_plug.c
|
|
||||||
@@ -1040,7 +1040,7 @@ static int snd_pcm_plug_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
slave = plug->gen.slave;
|
|
||||||
- err = _snd_pcm_hw_params(slave, params);
|
|
||||||
+ err = _snd_pcm_hw_params_internal(slave, params);
|
|
||||||
if (err < 0) {
|
|
||||||
snd_pcm_plug_clear(pcm);
|
|
||||||
return err;
|
|
||||||
diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c
|
|
||||||
index 936e2f9..118ab26 100644
|
|
||||||
--- a/src/pcm/pcm_share.c
|
|
||||||
+++ b/src/pcm/pcm_share.c
|
|
||||||
@@ -595,7 +595,7 @@ static int snd_pcm_share_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *pa
|
|
||||||
static int snd_pcm_share_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
|
||||||
{
|
|
||||||
snd_pcm_share_t *share = pcm->private_data;
|
|
||||||
- return _snd_pcm_hw_params(share->slave->pcm, params);
|
|
||||||
+ return _snd_pcm_hw_params_internal(share->slave->pcm, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int snd_pcm_share_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
|
||||||
--
|
|
||||||
1.8.0.1
|
|
||||||
|
|
@ -1,180 +0,0 @@
|
|||||||
From 8d14698931d6c319c42c4bc39886e92d13d19f1e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Fri, 7 Dec 2012 09:27:11 +0100
|
|
||||||
Subject: [PATCH 41/43] configure: Quite AM_CONDITIONAL() arguments
|
|
||||||
|
|
||||||
Otherwise it won't be processed properly with the recent automake.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
configure.in | 91 ++++++++++++++++++++++++++++++------------------------------
|
|
||||||
1 file changed, 46 insertions(+), 45 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/configure.in b/configure.in
|
|
||||||
index 383f5de..e397dad 100644
|
|
||||||
--- a/configure.in
|
|
||||||
+++ b/configure.in
|
|
||||||
@@ -15,7 +15,7 @@ AC_CANONICAL_HOST
|
|
||||||
AM_INIT_AUTOMAKE(alsa-lib, 1.0.26)
|
|
||||||
eval LIBTOOL_VERSION_INFO="2:0:0"
|
|
||||||
dnl *************************************************
|
|
||||||
-AM_CONDITIONAL(INSTALL_M4, test -n "${ACLOCAL}")
|
|
||||||
+AM_CONDITIONAL([INSTALL_M4], [test -n "${ACLOCAL}"])
|
|
||||||
|
|
||||||
# Test for new silent rules and enable only if they are available
|
|
||||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
|
||||||
@@ -63,7 +63,7 @@ AC_HEADER_TIME
|
|
||||||
dnl Checks for library functions.
|
|
||||||
AC_PROG_GCC_TRADITIONAL
|
|
||||||
AC_CHECK_FUNC([hsearch_r], [HAVE_HSEARCH_R=yes])
|
|
||||||
-AM_CONDITIONAL(ALSA_HSEARCH_R, [test "x$HAVE_HSEARCH_R" != xyes])
|
|
||||||
+AM_CONDITIONAL([ALSA_HSEARCH_R], [test "x$HAVE_HSEARCH_R" != xyes])
|
|
||||||
AC_CHECK_FUNCS([uselocale])
|
|
||||||
|
|
||||||
SAVE_LIBRARY_VERSION
|
|
||||||
@@ -161,7 +161,7 @@ if test "$versioned" = "yes"; then
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
fi
|
|
||||||
-AM_CONDITIONAL(VERSIONED_SYMBOLS, test x$versioned = xyes)
|
|
||||||
+AM_CONDITIONAL([VERSIONED_SYMBOLS], [test x$versioned = xyes])
|
|
||||||
|
|
||||||
dnl Check for symbolic-functions
|
|
||||||
AC_MSG_CHECKING(for symbolic-functions)
|
|
||||||
@@ -179,7 +179,7 @@ if test "$symfuncs" = "yes"; then
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
fi
|
|
||||||
-AM_CONDITIONAL(SYMBOLIC_FUNCTIONS, test x"$symfuncs" = xyes)
|
|
||||||
+AM_CONDITIONAL([SYMBOLIC_FUNCTIONS], [test x"$symfuncs" = xyes])
|
|
||||||
|
|
||||||
dnl See if toolchain has a custom prefix for symbols ...
|
|
||||||
AC_MSG_CHECKING(for custom symbol prefixes)
|
|
||||||
@@ -254,6 +254,7 @@ AC_MSG_CHECKING(for libdl)
|
|
||||||
AC_ARG_WITH(libdl,
|
|
||||||
AS_HELP_STRING([--with-libdl], [Use libdl for plugins (default = yes)]),
|
|
||||||
[ have_libdl="$withval" ], [ have_libdl="yes" ])
|
|
||||||
+HAVE_LIBDL=
|
|
||||||
if test "$have_libdl" = "yes"; then
|
|
||||||
AC_CHECK_LIB([dl], [dlsym], [HAVE_LIBDL="yes"])
|
|
||||||
if test "$HAVE_LIBDL" = "yes" ; then
|
|
||||||
@@ -263,7 +264,7 @@ if test "$have_libdl" = "yes"; then
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
fi
|
|
||||||
-AM_CONDITIONAL(BUILD_MODULES, test "$HAVE_LIBDL"="yes")
|
|
||||||
+AM_CONDITIONAL([BUILD_MODULES], [test "$HAVE_LIBDL" = "yes"])
|
|
||||||
|
|
||||||
dnl Check for pthread
|
|
||||||
AC_MSG_CHECKING(for pthread)
|
|
||||||
@@ -409,7 +410,7 @@ test "$softfloat" = "yes" && build_alisp="no"
|
|
||||||
AC_ARG_ENABLE(old-symbols,
|
|
||||||
AS_HELP_STRING([--disable-old-symbols], [disable old obsoleted symbols]),
|
|
||||||
[keep_old_symbols="$enableval"], [keep_old_symbols="yes"])
|
|
||||||
-AM_CONDITIONAL(KEEP_OLD_SYMBOLS, test x$keep_old_symbols = xyes)
|
|
||||||
+AM_CONDITIONAL([KEEP_OLD_SYMBOLS], [test x$keep_old_symbols = xyes])
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(python,
|
|
||||||
AS_HELP_STRING([--disable-python], [disable the python components]),
|
|
||||||
@@ -438,14 +439,14 @@ fi
|
|
||||||
AC_SUBST(PYTHON_LIBS)
|
|
||||||
AC_SUBST(PYTHON_INCLUDES)
|
|
||||||
|
|
||||||
-AM_CONDITIONAL(BUILD_MIXER, test x$build_mixer = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM, test x$build_pcm = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_RAWMIDI, test x$build_rawmidi = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_HWDEP, test x$build_hwdep = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_SEQ, test x$build_seq = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_UCM, test x$build_ucm = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_ALISP, test x$build_alisp = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PYTHON, test x$build_python = xyes)
|
|
||||||
+AM_CONDITIONAL([BUILD_MIXER], [test x$build_mixer = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM], [test x$build_pcm = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_RAWMIDI], [test x$build_rawmidi = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_HWDEP], [test x$build_hwdep = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_SEQ], [test x$build_seq = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_UCM], [test x$build_ucm = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_ALISP], [test x$build_alisp = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PYTHON], [test x$build_python = xyes])
|
|
||||||
|
|
||||||
if test "$build_mixer" = "yes"; then
|
|
||||||
AC_DEFINE([BUILD_MIXER], "1", [Build mixer component])
|
|
||||||
@@ -520,34 +521,34 @@ if test "$softfloat" = "yes"; then
|
|
||||||
build_pcm_ladspa="no"
|
|
||||||
fi
|
|
||||||
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN, test x$build_pcm_plugin = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_COPY, test x$build_pcm_copy = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_LINEAR, test x$build_pcm_linear = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_ROUTE, test x$build_pcm_route = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_MULAW, test x$build_pcm_mulaw = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_ALAW, test x$build_pcm_alaw = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_ADPCM, test x$build_pcm_adpcm = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_RATE, test x$build_pcm_rate = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_PLUG, test x$build_pcm_plug = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_MULTI, test x$build_pcm_multi = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_SHM, test x$build_pcm_shm = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_FILE, test x$build_pcm_file = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_NULL, test x$build_pcm_null = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_EMPTY, test x$build_pcm_empty = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_SHARE, test x$build_pcm_share = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_METER, test x$build_pcm_meter = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_HOOKS, test x$build_pcm_hooks = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_LFLOAT, test x$build_pcm_lfloat = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_LADSPA, test x$build_pcm_ladspa = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_DMIX, test x$build_pcm_dmix = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_DSHARE, test x$build_pcm_dshare = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_DSNOOP, test x$build_pcm_dsnoop = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_ASYM, test x$build_pcm_asym = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_IEC958, test x$build_pcm_iec958 = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_SOFTVOL, test x$build_pcm_softvol = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_EXTPLUG, test x$build_pcm_extplug = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_IOPLUG, test x$build_pcm_ioplug = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_PCM_PLUGIN_MMAP_EMUL, test x$build_pcm_mmap_emul = xyes)
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN], [test x$build_pcm_plugin = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_COPY], [test x$build_pcm_copy = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_LINEAR], [test x$build_pcm_linear = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_ROUTE], [test x$build_pcm_route = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_MULAW], [test x$build_pcm_mulaw = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_ALAW], [test x$build_pcm_alaw = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_ADPCM], [test x$build_pcm_adpcm = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_RATE], [test x$build_pcm_rate = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_PLUG], [test x$build_pcm_plug = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_MULTI], [test x$build_pcm_multi = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_SHM], [test x$build_pcm_shm = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_FILE], [test x$build_pcm_file = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_NULL], [test x$build_pcm_null = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_EMPTY], [test x$build_pcm_empty = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_SHARE], [test x$build_pcm_share = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_METER], [test x$build_pcm_meter = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_HOOKS], [test x$build_pcm_hooks = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_LFLOAT], [test x$build_pcm_lfloat = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_LADSPA], [test x$build_pcm_ladspa = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_DMIX], [test x$build_pcm_dmix = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_DSHARE], [test x$build_pcm_dshare = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_DSNOOP], [test x$build_pcm_dsnoop = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_ASYM], [test x$build_pcm_asym = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_IEC958], [test x$build_pcm_iec958 = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_SOFTVOL], [test x$build_pcm_softvol = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_EXTPLUG], [test x$build_pcm_extplug = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_IOPLUG], [test x$build_pcm_ioplug = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_PCM_PLUGIN_MMAP_EMUL], [test x$build_pcm_mmap_emul = xyes])
|
|
||||||
|
|
||||||
dnl Defines for plug plugin
|
|
||||||
if test "$build_pcm_rate" = "yes"; then
|
|
||||||
@@ -606,9 +607,9 @@ for p in $ctl_plugins; do
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
-AM_CONDITIONAL(BUILD_CTL_PLUGIN, test x$build_ctl_plugin = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_CTL_PLUGIN_SHM, test x$build_ctl_shm = xyes)
|
|
||||||
-AM_CONDITIONAL(BUILD_CTL_PLUGIN_EXT, test x$build_ctl_ext = xyes)
|
|
||||||
+AM_CONDITIONAL([BUILD_CTL_PLUGIN], [test x$build_ctl_plugin = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_CTL_PLUGIN_SHM], [test x$build_ctl_shm = xyes])
|
|
||||||
+AM_CONDITIONAL([BUILD_CTL_PLUGIN_EXT], [test x$build_ctl_ext = xyes])
|
|
||||||
|
|
||||||
dnl Create ctl plugin symbol list for static library
|
|
||||||
rm -f "$srcdir"/src/control/ctl_symbols_list.c
|
|
||||||
--
|
|
||||||
1.8.0.1
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
|||||||
From 1b428e7719fdec1b5e3206b8e55a86c4891d1849 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Fri, 7 Dec 2012 09:28:06 +0100
|
|
||||||
Subject: [PATCH 42/43] mixer: Don't build simple_abst when no libdl is
|
|
||||||
available
|
|
||||||
|
|
||||||
Check BUILD_MODULES conditional not to compile simple_abst.c.
|
|
||||||
Also return -ENXIO to caller statically in that case.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/mixer/Makefile.am | 6 +++++-
|
|
||||||
src/mixer/mixer_simple.h | 10 ++++++++++
|
|
||||||
2 files changed, 15 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/src/mixer/Makefile.am b/src/mixer/Makefile.am
|
|
||||||
index bb466ed..c0749a4 100644
|
|
||||||
--- a/src/mixer/Makefile.am
|
|
||||||
+++ b/src/mixer/Makefile.am
|
|
||||||
@@ -1,6 +1,10 @@
|
|
||||||
EXTRA_LTLIBRARIES=libmixer.la
|
|
||||||
|
|
||||||
-libmixer_la_SOURCES = bag.c mixer.c simple.c simple_none.c simple_abst.c
|
|
||||||
+libmixer_la_SOURCES = bag.c mixer.c simple.c simple_none.c
|
|
||||||
+
|
|
||||||
+if BUILD_MODULES
|
|
||||||
+libmixer_la_SOURCES += simple_abst.c
|
|
||||||
+endif
|
|
||||||
|
|
||||||
noinst_HEADERS = mixer_local.h mixer_simple.h
|
|
||||||
|
|
||||||
diff --git a/src/mixer/mixer_simple.h b/src/mixer/mixer_simple.h
|
|
||||||
index e88b007..116eebd 100644
|
|
||||||
--- a/src/mixer/mixer_simple.h
|
|
||||||
+++ b/src/mixer/mixer_simple.h
|
|
||||||
@@ -28,4 +28,14 @@
|
|
||||||
snd1_mixer_simple_basic_register
|
|
||||||
|
|
||||||
int snd_mixer_simple_none_register(snd_mixer_t *mixer, struct snd_mixer_selem_regopt *options, snd_mixer_class_t **classp);
|
|
||||||
+
|
|
||||||
+#ifdef HAVE_LIBDL
|
|
||||||
int snd_mixer_simple_basic_register(snd_mixer_t *mixer, struct snd_mixer_selem_regopt *options, snd_mixer_class_t **classp);
|
|
||||||
+#else
|
|
||||||
+static inline int snd_mixer_simple_basic_register(snd_mixer_t *mixer,
|
|
||||||
+ struct snd_mixer_selem_regopt *options,
|
|
||||||
+ snd_mixer_class_t **classp)
|
|
||||||
+{
|
|
||||||
+ return -ENXIO;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
--
|
|
||||||
1.8.0.1
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
|||||||
From 72bbf96e1fa0be63892343b331fac42414fdc8da Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Thu, 13 Dec 2012 09:55:44 +0100
|
|
||||||
Subject: [PATCH 43/43] Fix endian check in local.h
|
|
||||||
|
|
||||||
SNDRV_LITTLE_ENDIAN and SNDRV_BIG_ENDIAN checks have been removed from
|
|
||||||
sound/asound.h during UAPI header move, and this resulted in a wrong
|
|
||||||
detected endian.
|
|
||||||
|
|
||||||
Move together with the similar check for SND_*_ENDIAN at the earlier
|
|
||||||
place in local.h.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/local.h | 17 ++++++++++-------
|
|
||||||
1 file changed, 10 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/include/local.h b/include/local.h
|
|
||||||
index 268970a..53cb647 100644
|
|
||||||
--- a/include/local.h
|
|
||||||
+++ b/include/local.h
|
|
||||||
@@ -44,6 +44,16 @@
|
|
||||||
#define RTLD_NOW 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
+#define SND_LITTLE_ENDIAN
|
|
||||||
+#define SNDRV_LITTLE_ENDIAN
|
|
||||||
+#elif __BYTE_ORDER == __BIG_ENDIAN
|
|
||||||
+#define SND_BIG_ENDIAN
|
|
||||||
+#define SNDRV_BIG_ENDIAN
|
|
||||||
+#else
|
|
||||||
+#error "Unsupported endian..."
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
#define _snd_config_iterator list_head
|
|
||||||
#define _snd_interval snd_interval
|
|
||||||
#define _snd_pcm_info snd_pcm_info
|
|
||||||
@@ -168,13 +178,6 @@
|
|
||||||
#include "seq_midi_event.h"
|
|
||||||
#include "list.h"
|
|
||||||
|
|
||||||
-#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
-#define SND_LITTLE_ENDIAN
|
|
||||||
-#endif
|
|
||||||
-#if __BYTE_ORDER == __BIG_ENDIAN
|
|
||||||
-#define SND_BIG_ENDIAN
|
|
||||||
-#endif
|
|
||||||
-
|
|
||||||
struct _snd_async_handler {
|
|
||||||
enum {
|
|
||||||
SND_ASYNC_HANDLER_GENERIC,
|
|
||||||
--
|
|
||||||
1.8.0.1
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
From b11911dddf2fd58e24c808da26105cb1e1bce722 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Olivier Blin <dev@blino.org>
|
|
||||||
Date: Sat, 15 Dec 2012 01:58:59 +0100
|
|
||||||
Subject: [PATCH 44/50] configure: do not detect incorrect cross-compiler
|
|
||||||
|
|
||||||
On Ubuntu 11.04, configuring with --build=x86_64-unknown-linux-gnu
|
|
||||||
--host=x86_64-linux-gnu finds a wrong cross-compiler:
|
|
||||||
checking for cross-compiler... x86_64-x86_64-pc-linux-gnu-gcc
|
|
||||||
|
|
||||||
This happens because of a dash vs underscore inconsistency in configure.in:
|
|
||||||
host=x86_64-pc-linux-gnu
|
|
||||||
host_cpu=x86_64
|
|
||||||
host_os=linux-gnu
|
|
||||||
which ${host_cpu}-${host_os}-gcc >/dev/null 2>&1 && echo ${host_cpu}-${host-os}-gcc
|
|
||||||
|
|
||||||
This bug has been introduced in the initial --with-host support from
|
|
||||||
2002, commit eb267ade29c9a49c07b1c33dc9bf7a6790217400
|
|
||||||
|
|
||||||
This configure command is about "cross-compiling for i586", where the
|
|
||||||
system compiler is used, which just -m32 additional options.
|
|
||||||
The --build value comes from config.guess.
|
|
||||||
---
|
|
||||||
configure.in | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/configure.in
|
|
||||||
+++ b/configure.in
|
|
||||||
@@ -31,7 +31,7 @@ then
|
|
||||||
|
|
||||||
which ${program_prefix}gcc >/dev/null 2>&1 && CC=${program_prefix}gcc
|
|
||||||
which ${host_cpu}-${host_os}-gcc >/dev/null 2>&1 \
|
|
||||||
- && CC=${host_cpu}-${host-os}-gcc
|
|
||||||
+ && CC=${host_cpu}-${host_os}-gcc
|
|
||||||
which ${host_cpu}-${host_vendor}-${host_os}-gcc >/dev/null 2>&1 \
|
|
||||||
&& CC=${host_cpu}-${host_vendor}-${host_os}-gcc
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
|||||||
From 1629e2fbf3dc211eceb37f980e11e5babe1cefe4 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Tanu Kaskinen <tanuk@iki.fi>
|
|
||||||
Date: Sat, 26 Jan 2013 14:20:20 +0200
|
|
||||||
Subject: [PATCH 45/50] ucm: Set uc_mgr->ctl to NULL after closing it.
|
|
||||||
|
|
||||||
Fixes a double-free bug.
|
|
||||||
|
|
||||||
Signed-off-by: Tanu Kaskinen <tanuk@iki.fi>
|
|
||||||
Acked-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/ucm/main.c | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
--- a/src/ucm/main.c
|
|
||||||
+++ b/src/ucm/main.c
|
|
||||||
@@ -145,6 +145,7 @@ static int open_ctl(snd_use_case_mgr_t *
|
|
||||||
free(uc_mgr->ctl_dev);
|
|
||||||
uc_mgr->ctl_dev = NULL;
|
|
||||||
snd_ctl_close(uc_mgr->ctl);
|
|
||||||
+ uc_mgr->ctl = NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
err = snd_ctl_open(ctl, ctl_dev, 0);
|
|
@ -1,41 +0,0 @@
|
|||||||
From 2cfc8b9b44a8e493c41b3d63d5a00b306a18a5ed Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jerome Forissier <jerome@taodyne.com>
|
|
||||||
Date: Wed, 30 Jan 2013 16:22:17 +0100
|
|
||||||
Subject: [PATCH 46/50] snd_pcm_direct_parse_open_conf(): use thread-safe
|
|
||||||
getgrnam_r()
|
|
||||||
|
|
||||||
Fixes a thread safety issue with snd_pcm_open().
|
|
||||||
|
|
||||||
Signed-off-by: Jerome Forissier <jerome@taodyne.com>
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/pcm/pcm_direct.c | 15 +++++++++++----
|
|
||||||
1 file changed, 11 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
--- a/src/pcm/pcm_direct.c
|
|
||||||
+++ b/src/pcm/pcm_direct.c
|
|
||||||
@@ -1629,13 +1629,20 @@ int snd_pcm_direct_parse_open_conf(snd_c
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (isdigit(*group) == 0) {
|
|
||||||
- struct group *grp = getgrnam(group);
|
|
||||||
- if (grp == NULL) {
|
|
||||||
+ long clen = sysconf(_SC_GETGR_R_SIZE_MAX);
|
|
||||||
+ size_t len = (clen == -1) ? 1024 : (size_t)clen;
|
|
||||||
+ struct group grp, *pgrp;
|
|
||||||
+ char *buffer = (char *)malloc(len);
|
|
||||||
+ if (buffer == NULL)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+ int st = getgrnam_r(group, &grp, buffer, len, &pgrp);
|
|
||||||
+ if (st != 0) {
|
|
||||||
SNDERR("The field ipc_gid must be a valid group (create group %s)", group);
|
|
||||||
- free(group);
|
|
||||||
+ free(buffer);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
- rec->ipc_gid = grp->gr_gid;
|
|
||||||
+ rec->ipc_gid = pgrp->gr_gid;
|
|
||||||
+ free(buffer);
|
|
||||||
} else {
|
|
||||||
rec->ipc_gid = strtol(group, &endp, 10);
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
From 44c1a623dd1fc9e831616b663bebc54ca98df994 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jerome Forissier <jerome@taodyne.com>
|
|
||||||
Date: Thu, 31 Jan 2013 15:47:23 +0100
|
|
||||||
Subject: [PATCH 47/50] Add snd_lib_error_set_local() to install a thread-local
|
|
||||||
error handler.
|
|
||||||
|
|
||||||
This is required so we can make other functions reentrant (such as
|
|
||||||
snd_device_name_hint()).
|
|
||||||
The default error handling function snd_lib_error_default() now checks
|
|
||||||
if a local handler exists, and if so, calls it. Otherwise, the previous
|
|
||||||
behavior is unchanged.
|
|
||||||
|
|
||||||
Signed-off-by: Jerome Forissier <jerome@taodyne.com>
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
configure.in | 10 ++++++++++
|
|
||||||
include/error.h | 6 ++++++
|
|
||||||
src/error.c | 24 +++++++++++++++++++++++-
|
|
||||||
3 files changed, 39 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/configure.in
|
|
||||||
+++ b/configure.in
|
|
||||||
@@ -281,6 +281,16 @@ else
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
fi
|
|
||||||
|
|
||||||
+dnl Check for __thread
|
|
||||||
+AC_MSG_CHECKING([for __thread])
|
|
||||||
+AC_LINK_IFELSE([AC_LANG_PROGRAM([#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 1) || (__GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ < 2))
|
|
||||||
+#error gcc has this bug: http://gcc.gnu.org/ml/gcc-bugs/2006-09/msg02275.html
|
|
||||||
+#endif], [static __thread int p = 0])],
|
|
||||||
+[AC_DEFINE(HAVE___THREAD, 1,
|
|
||||||
+Define to 1 if compiler supports __thread)
|
|
||||||
+AC_MSG_RESULT([yes])],
|
|
||||||
+[AC_MSG_RESULT([no])])
|
|
||||||
+
|
|
||||||
dnl Check for librt
|
|
||||||
AC_MSG_CHECKING(for librt)
|
|
||||||
AC_ARG_WITH(librt,
|
|
||||||
--- a/include/error.h
|
|
||||||
+++ b/include/error.h
|
|
||||||
@@ -74,5 +74,11 @@ extern int snd_lib_error_set_handler(snd
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+typedef void (*snd_local_error_handler_t)(const char *file, int line,
|
|
||||||
+ const char *func, int err,
|
|
||||||
+ const char *fmt, va_list arg);
|
|
||||||
+
|
|
||||||
+snd_local_error_handler_t snd_lib_error_set_local(snd_local_error_handler_t func);
|
|
||||||
+
|
|
||||||
#endif /* __ALSA_ERROR_H */
|
|
||||||
|
|
||||||
--- a/src/error.c
|
|
||||||
+++ b/src/error.c
|
|
||||||
@@ -60,6 +60,21 @@ const char *snd_strerror(int errnum)
|
|
||||||
return snd_error_codes[errnum];
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef HAVE___THREAD
|
|
||||||
+#define TLS_PFX __thread
|
|
||||||
+#else
|
|
||||||
+#define TLS_PFX /* NOP */
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+static TLS_PFX snd_local_error_handler_t local_error = NULL;
|
|
||||||
+
|
|
||||||
+snd_local_error_handler_t snd_lib_error_set_local(snd_local_error_handler_t func)
|
|
||||||
+{
|
|
||||||
+ snd_local_error_handler_t old = local_error;
|
|
||||||
+ local_error = func;
|
|
||||||
+ return old;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* \brief The default error handler function.
|
|
||||||
* \param file The filename where the error was hit.
|
|
||||||
@@ -69,12 +84,19 @@ const char *snd_strerror(int errnum)
|
|
||||||
* \param fmt The message (including the format characters).
|
|
||||||
* \param ... Optional arguments.
|
|
||||||
*
|
|
||||||
- * Prints the error message including location to \c stderr.
|
|
||||||
+ * If a local error function has been installed for the current thread by
|
|
||||||
+ * \ref snd_lib_error_set_local, it is called. Otherwise, prints the error
|
|
||||||
+ * message including location to \c stderr.
|
|
||||||
*/
|
|
||||||
static void snd_lib_error_default(const char *file, int line, const char *function, int err, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list arg;
|
|
||||||
va_start(arg, fmt);
|
|
||||||
+ if (local_error) {
|
|
||||||
+ local_error(file, line, function, err, fmt, arg);
|
|
||||||
+ va_end(arg);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
fprintf(stderr, "ALSA lib %s:%i:(%s) ", file, line, function);
|
|
||||||
vfprintf(stderr, fmt, arg);
|
|
||||||
if (err)
|
|
@ -1,61 +0,0 @@
|
|||||||
From 25dbb102810b31c02358904d70d53c960fb0a10e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jerome Forissier <jerome@taodyne.com>
|
|
||||||
Date: Thu, 31 Jan 2013 15:47:24 +0100
|
|
||||||
Subject: [PATCH 48/50] snd_device_name_hint(): do not change the global error
|
|
||||||
handler.
|
|
||||||
|
|
||||||
This is the first step towards making this function reentrant.
|
|
||||||
|
|
||||||
Signed-off-by: Jerome Forissier <jerome@taodyne.com>
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/control/namehint.c | 15 +++++++--------
|
|
||||||
1 file changed, 7 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
--- a/src/control/namehint.c
|
|
||||||
+++ b/src/control/namehint.c
|
|
||||||
@@ -80,7 +80,8 @@ static void zero_handler(const char *fil
|
|
||||||
int line ATTRIBUTE_UNUSED,
|
|
||||||
const char *function ATTRIBUTE_UNUSED,
|
|
||||||
int err ATTRIBUTE_UNUSED,
|
|
||||||
- const char *fmt ATTRIBUTE_UNUSED, ...)
|
|
||||||
+ const char *fmt ATTRIBUTE_UNUSED,
|
|
||||||
+ va_list arg ATTRIBUTE_UNUSED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -212,7 +213,7 @@ static int try_config(struct hint_list *
|
|
||||||
const char *base,
|
|
||||||
const char *name)
|
|
||||||
{
|
|
||||||
- snd_lib_error_handler_t eh;
|
|
||||||
+ snd_local_error_handler_t eh;
|
|
||||||
snd_config_t *res = NULL, *cfg, *cfg1, *n;
|
|
||||||
snd_config_iterator_t i, next;
|
|
||||||
char *buf, *buf1 = NULL, *buf2;
|
|
||||||
@@ -239,10 +240,9 @@ static int try_config(struct hint_list *
|
|
||||||
sprintf(buf, "%s:CARD=%s", name, snd_ctl_card_info_get_id(list->info));
|
|
||||||
else
|
|
||||||
strcpy(buf, name);
|
|
||||||
- eh = snd_lib_error;
|
|
||||||
- snd_lib_error_set_handler(&zero_handler);
|
|
||||||
+ eh = snd_lib_error_set_local(&zero_handler);
|
|
||||||
err = snd_config_search_definition(snd_config, base, buf, &res);
|
|
||||||
- snd_lib_error_set_handler(eh);
|
|
||||||
+ snd_lib_error_set_local(eh);
|
|
||||||
if (err < 0)
|
|
||||||
goto __skip_add;
|
|
||||||
cleanup_res = 1;
|
|
||||||
@@ -337,10 +337,9 @@ static int try_config(struct hint_list *
|
|
||||||
goto __ok;
|
|
||||||
/* find, if all parameters have a default, */
|
|
||||||
/* otherwise filter this definition */
|
|
||||||
- eh = snd_lib_error;
|
|
||||||
- snd_lib_error_set_handler(&zero_handler);
|
|
||||||
+ eh = snd_lib_error_set_local(&zero_handler);
|
|
||||||
err = snd_config_search_alias_hooks(snd_config, base, buf, &res);
|
|
||||||
- snd_lib_error_set_handler(eh);
|
|
||||||
+ snd_lib_error_set_local(eh);
|
|
||||||
if (err < 0)
|
|
||||||
goto __cleanup;
|
|
||||||
if (snd_config_search(res, "@args", &cfg) >= 0) {
|
|
@ -1,197 +0,0 @@
|
|||||||
From f49b2dc522a2564315c76d075203b15a39941e8a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jerome Forissier <jerome@taodyne.com>
|
|
||||||
Date: Thu, 31 Jan 2013 15:47:25 +0100
|
|
||||||
Subject: [PATCH 49/50] snd_device_name_hint(): do not use global snd_config.
|
|
||||||
|
|
||||||
This commit and its parent make the function reentrant.
|
|
||||||
|
|
||||||
Signed-off-by: Jerome Forissier <jerome@taodyne.com>
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/control/namehint.c | 52 ++++++++++++++++++++++++++++---------------------
|
|
||||||
1 file changed, 30 insertions(+), 22 deletions(-)
|
|
||||||
|
|
||||||
--- a/src/control/namehint.c
|
|
||||||
+++ b/src/control/namehint.c
|
|
||||||
@@ -209,7 +209,8 @@ static char *get_dev_name(struct hint_li
|
|
||||||
#define BUF_SIZE 128
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-static int try_config(struct hint_list *list,
|
|
||||||
+static int try_config(snd_config_t *config,
|
|
||||||
+ struct hint_list *list,
|
|
||||||
const char *base,
|
|
||||||
const char *name)
|
|
||||||
{
|
|
||||||
@@ -229,7 +230,7 @@ static int try_config(struct hint_list *
|
|
||||||
return -ENOMEM;
|
|
||||||
sprintf(buf, "%s.%s", base, name);
|
|
||||||
/* look for redirection */
|
|
||||||
- if (snd_config_search(snd_config, buf, &cfg) >= 0 &&
|
|
||||||
+ if (snd_config_search(config, buf, &cfg) >= 0 &&
|
|
||||||
snd_config_get_string(cfg, &str) >= 0 &&
|
|
||||||
((strncmp(base, str, strlen(base)) == 0 &&
|
|
||||||
str[strlen(base)] == '.') || strchr(str, '.') == NULL))
|
|
||||||
@@ -241,7 +242,7 @@ static int try_config(struct hint_list *
|
|
||||||
else
|
|
||||||
strcpy(buf, name);
|
|
||||||
eh = snd_lib_error_set_local(&zero_handler);
|
|
||||||
- err = snd_config_search_definition(snd_config, base, buf, &res);
|
|
||||||
+ err = snd_config_search_definition(config, base, buf, &res);
|
|
||||||
snd_lib_error_set_local(eh);
|
|
||||||
if (err < 0)
|
|
||||||
goto __skip_add;
|
|
||||||
@@ -338,7 +339,7 @@ static int try_config(struct hint_list *
|
|
||||||
/* find, if all parameters have a default, */
|
|
||||||
/* otherwise filter this definition */
|
|
||||||
eh = snd_lib_error_set_local(&zero_handler);
|
|
||||||
- err = snd_config_search_alias_hooks(snd_config, base, buf, &res);
|
|
||||||
+ err = snd_config_search_alias_hooks(config, base, buf, &res);
|
|
||||||
snd_lib_error_set_local(eh);
|
|
||||||
if (err < 0)
|
|
||||||
goto __cleanup;
|
|
||||||
@@ -405,7 +406,7 @@ static const next_devices_t next_devices
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-static int add_card(struct hint_list *list, int card)
|
|
||||||
+static int add_card(snd_config_t *config, struct hint_list *list, int card)
|
|
||||||
{
|
|
||||||
int err, ok;
|
|
||||||
snd_config_t *conf, *n;
|
|
||||||
@@ -417,7 +418,7 @@ static int add_card(struct hint_list *li
|
|
||||||
|
|
||||||
snd_ctl_card_info_alloca(&info);
|
|
||||||
list->info = info;
|
|
||||||
- err = snd_config_search(snd_config, list->siface, &conf);
|
|
||||||
+ err = snd_config_search(config, list->siface, &conf);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
sprintf(ctl_name, "hw:%i", card);
|
|
||||||
@@ -448,7 +449,7 @@ static int add_card(struct hint_list *li
|
|
||||||
ok = 0;
|
|
||||||
for (device = 0; err >= 0 && device <= max_device; device++) {
|
|
||||||
list->device = device;
|
|
||||||
- err = try_config(list, list->siface, str);
|
|
||||||
+ err = try_config(config, list, list->siface, str);
|
|
||||||
if (err < 0)
|
|
||||||
break;
|
|
||||||
ok++;
|
|
||||||
@@ -463,7 +464,7 @@ static int add_card(struct hint_list *li
|
|
||||||
if (err < 0) {
|
|
||||||
list->card = card;
|
|
||||||
list->device = -1;
|
|
||||||
- err = try_config(list, list->siface, str);
|
|
||||||
+ err = try_config(config, list, list->siface, str);
|
|
||||||
}
|
|
||||||
if (err == -ENOMEM)
|
|
||||||
goto __error;
|
|
||||||
@@ -492,14 +493,14 @@ static int get_card_name(struct hint_lis
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int add_software_devices(struct hint_list *list)
|
|
||||||
+static int add_software_devices(snd_config_t *config, struct hint_list *list)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
snd_config_t *conf, *n;
|
|
||||||
snd_config_iterator_t i, next;
|
|
||||||
const char *str;
|
|
||||||
|
|
||||||
- err = snd_config_search(snd_config, list->siface, &conf);
|
|
||||||
+ err = snd_config_search(config, list->siface, &conf);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
snd_config_for_each(i, next, conf) {
|
|
||||||
@@ -508,7 +509,7 @@ static int add_software_devices(struct h
|
|
||||||
continue;
|
|
||||||
list->card = -1;
|
|
||||||
list->device = -1;
|
|
||||||
- err = try_config(list, list->siface, str);
|
|
||||||
+ err = try_config(config, list, list->siface, str);
|
|
||||||
if (err == -ENOMEM)
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
@@ -546,13 +547,14 @@ int snd_device_name_hint(int card, const
|
|
||||||
struct hint_list list;
|
|
||||||
char ehints[24];
|
|
||||||
const char *str;
|
|
||||||
- snd_config_t *conf;
|
|
||||||
+ snd_config_t *conf, *local_config = NULL;
|
|
||||||
+ snd_config_update_t *local_config_update = NULL;
|
|
||||||
snd_config_iterator_t i, next;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (hints == NULL)
|
|
||||||
return -EINVAL;
|
|
||||||
- err = snd_config_update();
|
|
||||||
+ err = snd_config_update_r(&local_config, &local_config_update, NULL);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
list.list = NULL;
|
|
||||||
@@ -572,18 +574,21 @@ int snd_device_name_hint(int card, const
|
|
||||||
list.iface = SND_CTL_ELEM_IFACE_HWDEP;
|
|
||||||
else if (strcmp(iface, "ctl") == 0)
|
|
||||||
list.iface = SND_CTL_ELEM_IFACE_MIXER;
|
|
||||||
- else
|
|
||||||
- return -EINVAL;
|
|
||||||
+ else {
|
|
||||||
+ err = -EINVAL;
|
|
||||||
+ goto __error;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
list.show_all = 0;
|
|
||||||
list.cardname = NULL;
|
|
||||||
- if (snd_config_search(snd_config, "defaults.namehint.showall", &conf) >= 0)
|
|
||||||
+ if (snd_config_search(local_config, "defaults.namehint.showall", &conf) >= 0)
|
|
||||||
list.show_all = snd_config_get_bool(conf) > 0;
|
|
||||||
if (card >= 0) {
|
|
||||||
err = get_card_name(&list, card);
|
|
||||||
if (err >= 0)
|
|
||||||
- err = add_card(&list, card);
|
|
||||||
+ err = add_card(local_config, &list, card);
|
|
||||||
} else {
|
|
||||||
- add_software_devices(&list);
|
|
||||||
+ add_software_devices(local_config, &list);
|
|
||||||
err = snd_card_next(&card);
|
|
||||||
if (err < 0)
|
|
||||||
goto __error;
|
|
||||||
@@ -591,7 +596,7 @@ int snd_device_name_hint(int card, const
|
|
||||||
err = get_card_name(&list, card);
|
|
||||||
if (err < 0)
|
|
||||||
goto __error;
|
|
||||||
- err = add_card(&list, card);
|
|
||||||
+ err = add_card(local_config, &list, card);
|
|
||||||
if (err < 0)
|
|
||||||
goto __error;
|
|
||||||
err = snd_card_next(&card);
|
|
||||||
@@ -600,7 +605,7 @@ int snd_device_name_hint(int card, const
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sprintf(ehints, "namehint.%s", list.siface);
|
|
||||||
- err = snd_config_search(snd_config, ehints, &conf);
|
|
||||||
+ err = snd_config_search(local_config, ehints, &conf);
|
|
||||||
if (err >= 0) {
|
|
||||||
snd_config_for_each(i, next, conf) {
|
|
||||||
if (snd_config_get_string(snd_config_iterator_entry(i),
|
|
||||||
@@ -617,7 +622,6 @@ int snd_device_name_hint(int card, const
|
|
||||||
snd_device_name_free_hint((void **)list.list);
|
|
||||||
if (list.cardname)
|
|
||||||
free(list.cardname);
|
|
||||||
- return err;
|
|
||||||
} else {
|
|
||||||
err = hint_list_add(&list, NULL, NULL);
|
|
||||||
if (err < 0)
|
|
||||||
@@ -626,7 +630,11 @@ int snd_device_name_hint(int card, const
|
|
||||||
if (list.cardname)
|
|
||||||
free(list.cardname);
|
|
||||||
}
|
|
||||||
- return 0;
|
|
||||||
+ if (local_config)
|
|
||||||
+ snd_config_delete(local_config);
|
|
||||||
+ if (local_config_update)
|
|
||||||
+ snd_config_update_free(local_config_update);
|
|
||||||
+ return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
@ -1,27 +0,0 @@
|
|||||||
From 7f2b2c8c1650a1883b48abfcdb455138943854f9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Allan Wirth <allan@allanwirth.com>
|
|
||||||
Date: Thu, 31 Jan 2013 13:55:33 -0500
|
|
||||||
Subject: [PATCH 50/50] conf: Fix a memory access violation resulting from
|
|
||||||
improper error propogation
|
|
||||||
|
|
||||||
Fixes an issue where a variable is used undeclared, which can cause seg
|
|
||||||
faults on some systems if the configuration file is not formatted
|
|
||||||
properly.
|
|
||||||
|
|
||||||
Signed-off-by: Allan Wirth <allan@allanwirth.com>
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/conf.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/src/conf.c
|
|
||||||
+++ b/src/conf.c
|
|
||||||
@@ -3530,7 +3530,7 @@ int snd_config_hook_load(snd_config_t *r
|
|
||||||
if (err < 0)
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
- } else if (config_file_open(root, fi[idx].name) < 0)
|
|
||||||
+ } else if ((err = config_file_open(root, fi[idx].name)) < 0)
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
*dst = NULL;
|
|
@ -1,35 +0,0 @@
|
|||||||
From 3e7dc283ed2d3ed2341f0657811c588f4dbcba6d Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Henningsson <david.henningsson@canonical.com>
|
|
||||||
Date: Tue, 12 Feb 2013 10:06:11 +0100
|
|
||||||
Subject: [PATCH 51/54] Add sys/types.h to include list
|
|
||||||
|
|
||||||
This is needed by snd_pcm_format_silence* functions which
|
|
||||||
return u_int*_t. It was discovered while trying to compile ALSA
|
|
||||||
programs with eglibc 2.17.
|
|
||||||
|
|
||||||
Credits to Richard Shaw, Gary Buhrmaster, Matthieu Baerts and
|
|
||||||
Adam Conrad for this fix.
|
|
||||||
|
|
||||||
BugLink: https://bugs.launchpad.net/bugs/1109298
|
|
||||||
BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=885306
|
|
||||||
Signed-off-by: David Henningsson <david.henningsson@canonical.com>
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
include/asoundlib-head.h | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/include/asoundlib-head.h b/include/asoundlib-head.h
|
|
||||||
index 20c8a68..6edbab0 100644
|
|
||||||
--- a/include/asoundlib-head.h
|
|
||||||
+++ b/include/asoundlib-head.h
|
|
||||||
@@ -31,6 +31,7 @@
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
+#include <sys/types.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <assert.h>
|
|
||||||
--
|
|
||||||
1.8.1.4
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
|||||||
From 8c6da54073b2c966d9a4e137ba4d521eac92816f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Fri, 12 Oct 2012 12:22:53 +0200
|
|
||||||
Subject: [PATCH 52/54] control: Simplify using snd_config_get_bool()
|
|
||||||
|
|
||||||
snd_config_get_bool() was improved to parse also ASCII strings now,
|
|
||||||
so we don't have to open-code the boolean parser in
|
|
||||||
src/control/setup.c any longer.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/control/setup.c | 37 ++++++-------------------------------
|
|
||||||
1 file changed, 6 insertions(+), 31 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/control/setup.c b/src/control/setup.c
|
|
||||||
index eecda45..bd3599d 100644
|
|
||||||
--- a/src/control/setup.c
|
|
||||||
+++ b/src/control/setup.c
|
|
||||||
@@ -400,7 +400,6 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da
|
|
||||||
{
|
|
||||||
snd_config_t *conf;
|
|
||||||
snd_config_iterator_t i, next;
|
|
||||||
- char *tmp;
|
|
||||||
int iface = SND_CTL_ELEM_IFACE_MIXER;
|
|
||||||
const char *name = NULL;
|
|
||||||
long index = 0;
|
|
||||||
@@ -464,33 +463,17 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (strcmp(id, "lock") == 0) {
|
|
||||||
- if ((err = snd_config_get_ascii(n, &tmp)) < 0) {
|
|
||||||
- SNDERR("field %s has an invalid type", id);
|
|
||||||
- goto _err;
|
|
||||||
- }
|
|
||||||
- err = snd_config_get_bool_ascii(tmp);
|
|
||||||
- if (err < 0) {
|
|
||||||
- SNDERR("field %s is not a boolean", id);
|
|
||||||
- free(tmp);
|
|
||||||
+ err = snd_config_get_bool(n);
|
|
||||||
+ if (err < 0)
|
|
||||||
goto _err;
|
|
||||||
- }
|
|
||||||
lock = err;
|
|
||||||
- free(tmp);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (strcmp(id, "preserve") == 0) {
|
|
||||||
- if ((err = snd_config_get_ascii(n, &tmp)) < 0) {
|
|
||||||
- SNDERR("field %s has an invalid type", id);
|
|
||||||
- goto _err;
|
|
||||||
- }
|
|
||||||
- err = snd_config_get_bool_ascii(tmp);
|
|
||||||
- if (err < 0) {
|
|
||||||
- SNDERR("field %s is not a boolean", id);
|
|
||||||
- free(tmp);
|
|
||||||
+ err = snd_config_get_bool(n);
|
|
||||||
+ if (err < 0)
|
|
||||||
goto _err;
|
|
||||||
- }
|
|
||||||
preserve = err;
|
|
||||||
- free(tmp);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (strcmp(id, "value") == 0) {
|
|
||||||
@@ -502,18 +485,10 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (strcmp(id, "optional") == 0) {
|
|
||||||
- if ((err = snd_config_get_ascii(n, &tmp)) < 0) {
|
|
||||||
- SNDERR("field %s has an invalid type", id);
|
|
||||||
- goto _err;
|
|
||||||
- }
|
|
||||||
- err = snd_config_get_bool_ascii(tmp);
|
|
||||||
- if (err < 0) {
|
|
||||||
- SNDERR("field %s is not a boolean", id);
|
|
||||||
- free(tmp);
|
|
||||||
+ err = snd_config_get_bool(n);
|
|
||||||
+ if (err < 0)
|
|
||||||
goto _err;
|
|
||||||
- }
|
|
||||||
optional = err;
|
|
||||||
- free(tmp);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SNDERR("Unknown field %s", id);
|
|
||||||
--
|
|
||||||
1.8.1.4
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
|||||||
From f5f45589f81c46d4ca4cbbe089441a0f7ac5e197 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Takashi Iwai <tiwai@suse.de>
|
|
||||||
Date: Mon, 11 Feb 2013 12:28:45 +0100
|
|
||||||
Subject: [PATCH 53/54] Add workaround for conflicting IEC958 controls for
|
|
||||||
HD-audio
|
|
||||||
|
|
||||||
When both an SPDIF and an HDMI output are present on HD-audio, both
|
|
||||||
try to access IEC958 controls with index=0 although one of them must
|
|
||||||
be wrong. For avoiding this conflict, the recent kernel code (3.9 and
|
|
||||||
3.8 stable) moves the IEC958 controls of an SPDIF with index=16 once
|
|
||||||
when the conflict happens.
|
|
||||||
|
|
||||||
In this patch, the corresponding support is added in alsa-lib side.
|
|
||||||
The new "skip_rest" boolean flag is added to the hooked element
|
|
||||||
definition which indicates that the rest of element array will be
|
|
||||||
ignored once when this element is present and evaluated. With this
|
|
||||||
new flag, the HD-audio config takes index=16 primarily, then take
|
|
||||||
index=0 as fallback.
|
|
||||||
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/conf/cards/HDA-Intel.conf | 16 ++++++++++++++++
|
|
||||||
src/control/setup.c | 19 ++++++++++++++++---
|
|
||||||
2 files changed, 32 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/conf/cards/HDA-Intel.conf b/src/conf/cards/HDA-Intel.conf
|
|
||||||
index d4f2667..3957c12 100644
|
|
||||||
--- a/src/conf/cards/HDA-Intel.conf
|
|
||||||
+++ b/src/conf/cards/HDA-Intel.conf
|
|
||||||
@@ -113,6 +113,22 @@ HDA-Intel.pcm.iec958.0 {
|
|
||||||
hook_args [
|
|
||||||
{
|
|
||||||
name "IEC958 Playback Default"
|
|
||||||
+ index 16
|
|
||||||
+ optional true
|
|
||||||
+ lock true
|
|
||||||
+ preserve true
|
|
||||||
+ value [ $AES0 $AES1 $AES2 $AES3 ]
|
|
||||||
+ }
|
|
||||||
+ {
|
|
||||||
+ name "IEC958 Playback Switch"
|
|
||||||
+ index 16
|
|
||||||
+ optional true
|
|
||||||
+ value true
|
|
||||||
+ # if this element is present, skip the rest
|
|
||||||
+ skip_rest true
|
|
||||||
+ }
|
|
||||||
+ {
|
|
||||||
+ name "IEC958 Playback Default"
|
|
||||||
lock true
|
|
||||||
preserve true
|
|
||||||
value [ $AES0 $AES1 $AES2 $AES3 ]
|
|
||||||
diff --git a/src/control/setup.c b/src/control/setup.c
|
|
||||||
index bd3599d..f23bf2c 100644
|
|
||||||
--- a/src/control/setup.c
|
|
||||||
+++ b/src/control/setup.c
|
|
||||||
@@ -396,7 +396,7 @@ static int snd_config_get_ctl_elem_value(snd_config_t *conf,
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_data)
|
|
||||||
+static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_data, int *quit)
|
|
||||||
{
|
|
||||||
snd_config_t *conf;
|
|
||||||
snd_config_iterator_t i, next;
|
|
||||||
@@ -408,6 +408,7 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da
|
|
||||||
int lock = 0;
|
|
||||||
int preserve = 0;
|
|
||||||
int optional = 0;
|
|
||||||
+ int skip_rest = 0;
|
|
||||||
snd_config_t *value = NULL, *mask = NULL;
|
|
||||||
snd_sctl_elem_t *elem = NULL;
|
|
||||||
int err;
|
|
||||||
@@ -491,6 +492,13 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da
|
|
||||||
optional = err;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
+ if (strcmp(id, "skip_rest") == 0) {
|
|
||||||
+ err = snd_config_get_bool(n);
|
|
||||||
+ if (err < 0)
|
|
||||||
+ goto _err;
|
|
||||||
+ skip_rest = err;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
SNDERR("Unknown field %s", id);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
@@ -539,6 +547,9 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da
|
|
||||||
if (! optional)
|
|
||||||
SNDERR("Cannot obtain info for CTL elem (%s,'%s',%li,%li,%li): %s", snd_ctl_elem_iface_name(iface), name, index, device, subdevice, snd_strerror(err));
|
|
||||||
goto _err;
|
|
||||||
+ } else {
|
|
||||||
+ if (skip_rest)
|
|
||||||
+ *quit = 1;
|
|
||||||
}
|
|
||||||
snd_ctl_elem_value_set_id(elem->val, elem->id);
|
|
||||||
snd_ctl_elem_value_set_id(elem->old, elem->id);
|
|
||||||
@@ -594,7 +605,7 @@ int snd_sctl_build(snd_sctl_t **sctl, snd_ctl_t *handle, snd_config_t *conf, snd
|
|
||||||
{
|
|
||||||
snd_sctl_t *h;
|
|
||||||
snd_config_iterator_t i, next;
|
|
||||||
- int err;
|
|
||||||
+ int err, quit = 0;
|
|
||||||
|
|
||||||
assert(sctl);
|
|
||||||
assert(handle);
|
|
||||||
@@ -614,11 +625,13 @@ int snd_sctl_build(snd_sctl_t **sctl, snd_ctl_t *handle, snd_config_t *conf, snd
|
|
||||||
INIT_LIST_HEAD(&h->elems);
|
|
||||||
snd_config_for_each(i, next, conf) {
|
|
||||||
snd_config_t *n = snd_config_iterator_entry(i);
|
|
||||||
- err = add_elem(h, n, private_data);
|
|
||||||
+ err = add_elem(h, n, private_data, &quit);
|
|
||||||
if (err < 0) {
|
|
||||||
free_elems(h);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
+ if (quit)
|
|
||||||
+ break;
|
|
||||||
}
|
|
||||||
*sctl = h;
|
|
||||||
return 0;
|
|
||||||
--
|
|
||||||
1.8.1.4
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
|||||||
From 28493d9d693b1387ed38a849b2d256b34baba2b4 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Sander Jansen <s.jansen@gmail.com>
|
|
||||||
Date: Mon, 25 Feb 2013 10:41:40 -0600
|
|
||||||
Subject: [PATCH 54/54] snd_mixer_poll_descriptors_revents should loop over
|
|
||||||
pollfd
|
|
||||||
|
|
||||||
Signed-off-by: Sander Jansen <s.jansen@gmail.com>
|
|
||||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
||||||
---
|
|
||||||
src/mixer/mixer.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c
|
|
||||||
index 85d843f..8deceac 100644
|
|
||||||
--- a/src/mixer/mixer.c
|
|
||||||
+++ b/src/mixer/mixer.c
|
|
||||||
@@ -743,7 +743,7 @@ int snd_mixer_poll_descriptors_revents(snd_mixer_t *mixer, struct pollfd *pfds,
|
|
||||||
if (nfds == 0)
|
|
||||||
return -EINVAL;
|
|
||||||
res = 0;
|
|
||||||
- for (idx = 0; idx < nfds; idx++)
|
|
||||||
+ for (idx = 0; idx < nfds; idx++, pfds++)
|
|
||||||
res |= pfds->revents & (POLLIN|POLLERR|POLLNVAL);
|
|
||||||
*revents = res;
|
|
||||||
return 0;
|
|
||||||
--
|
|
||||||
1.8.1.4
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:8c9f8161603cc3db640619650401292c3e110da63429ab6938aac763319f6e7d
|
|
||||||
size 883076
|
|
3
alsa-lib-1.0.27.tar.bz2
Normal file
3
alsa-lib-1.0.27.tar.bz2
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:947caa14cf53c614d0a206fe9f5964de6ee9617f9007e8fceffd6b3cfd89bc5d
|
||||||
|
size 898132
|
26
alsa.changes
26
alsa.changes
@ -1,3 +1,29 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Fri Apr 12 15:26:38 CEST 2013 - tiwai@suse.de
|
||||||
|
|
||||||
|
- Updated to version 1.0.27:
|
||||||
|
including all previous fixes; all 00*-* patches dropped
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Tue Apr 9 15:04:10 CEST 2013 - tiwai@suse.de
|
||||||
|
|
||||||
|
- Backport upstream fixes:
|
||||||
|
0058-control-pcm-implement-snd_ctl_abort-and-snd_pcm_abor.patch
|
||||||
|
0059-all-places-doxygen-cleanups.patch
|
||||||
|
0060-pcm-direct-plugins-do-more-safe-IPC-semaphore-handli.patch
|
||||||
|
- Fix segfault with openal-soft (bnc#814250):
|
||||||
|
0061-Clean-up-dlobj-cache-only-when-no-user-is-present.patch
|
||||||
|
0062-Optimize-NULL-check-in-snd_dlobj_cache_put.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Fri Apr 5 12:42:57 CEST 2013 - tiwai@suse.de
|
||||||
|
|
||||||
|
- Backport upstream fix patches:
|
||||||
|
0055-pcm-fix-and-optimize-snd_pcm_areas_copy-function.patch
|
||||||
|
0056-USB-audio-Add-HP-Digital-Stereo-Headset-to-SPDIF-bla.patch
|
||||||
|
0057-pcm-fix-typo-should-be-SND_PCM_STATE_PREPARED.patch
|
||||||
|
- Fix typos in comments in joystick script (bnc#805765)
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Mon Mar 11 11:08:30 CET 2013 - tiwai@suse.de
|
Mon Mar 11 11:08:30 CET 2013 - tiwai@suse.de
|
||||||
|
|
||||||
|
111
alsa.spec
111
alsa.spec
@ -20,7 +20,7 @@ Name: alsa
|
|||||||
BuildRequires: doxygen
|
BuildRequires: doxygen
|
||||||
BuildRequires: libtool
|
BuildRequires: libtool
|
||||||
BuildRequires: pkg-config
|
BuildRequires: pkg-config
|
||||||
%define package_version 1.0.26
|
%define package_version 1.0.27
|
||||||
Requires: alsa-utils
|
Requires: alsa-utils
|
||||||
Recommends: alsa-plugins alsa-oss
|
Recommends: alsa-plugins alsa-oss
|
||||||
PreReq: %insserv_prereq %fillup_prereq
|
PreReq: %insserv_prereq %fillup_prereq
|
||||||
@ -32,7 +32,7 @@ Obsoletes: alsa-64bit
|
|||||||
Summary: Advanced Linux Sound Architecture
|
Summary: Advanced Linux Sound Architecture
|
||||||
License: LGPL-2.1+
|
License: LGPL-2.1+
|
||||||
Group: System/Libraries
|
Group: System/Libraries
|
||||||
Version: 1.0.26
|
Version: 1.0.27
|
||||||
Release: 0
|
Release: 0
|
||||||
Source: ftp://ftp.alsa-project.org/pub/lib/alsa-lib-%{package_version}.tar.bz2
|
Source: ftp://ftp.alsa-project.org/pub/lib/alsa-lib-%{package_version}.tar.bz2
|
||||||
Source2: baselibs.conf
|
Source2: baselibs.conf
|
||||||
@ -53,60 +53,6 @@ Source34: alsa-init.sh
|
|||||||
Source40: 50-alsa.conf
|
Source40: 50-alsa.conf
|
||||||
Source41: install-snd-module
|
Source41: install-snd-module
|
||||||
# Patch: alsa-lib-git-fixes.diff
|
# Patch: alsa-lib-git-fixes.diff
|
||||||
Patch1: 0001-Implement-the-channel-mapping-API.patch
|
|
||||||
Patch2: 0002-Implement-get_chmap-set_chmap-for-PCM-plug-route-and.patch
|
|
||||||
Patch3: 0003-Implement-get_chmap-set_chmap-for-PCM-extplug-ioplug.patch
|
|
||||||
Patch4: 0004-Add-test-chmap-program.patch
|
|
||||||
Patch5: 0005-Cache-the-chmap-operation-errors.patch
|
|
||||||
Patch6: 0006-Define-channel-map-position-enum-in-pcm.h.patch
|
|
||||||
Patch7: 0007-Follow-channel-position-definitions-to-mixer-channel.patch
|
|
||||||
Patch8: 0008-Add-SND_CHMAP_NA-and-bit-flag-definitions.patch
|
|
||||||
Patch9: 0009-PCM-Introduce-snd_pcm_chmap_t-and-snd_pcm_chmap_quer.patch
|
|
||||||
Patch10: 0010-PCM-Implement-snd_pcm_query_chmaps_from_hw.patch
|
|
||||||
Patch11: 0011-Fix-duplicated-channel-entry-in-test-chmap.c.patch
|
|
||||||
Patch12: 0012-PCM-Fix-prefix-for-snd_pcm_chmap_type-enum-members.patch
|
|
||||||
Patch13: 0013-PCM-Add-string-conversion-helper-functions-for-chmap.patch
|
|
||||||
Patch14: 0014-PCM-Add-SND_CHMAP_API_VERSION-definition.patch
|
|
||||||
Patch15: 0015-PCM-Add-snd_pcm_chmap_long_name.patch
|
|
||||||
Patch16: 0016-PCM-Add-query_chmaps-support-to-multi-plugin.patch
|
|
||||||
Patch17: 0017-PCM-Add-chmap-options-to-hw-and-null-plugins.patch
|
|
||||||
Patch18: 0018-PCM-Add-the-missing-query_chmaps-for-route-plugin.patch
|
|
||||||
Patch19: 0019-Add-chmap-override-definitions-for-Emu10k1-Audigy-an.patch
|
|
||||||
Patch20: 0020-PCM-Use-compounds-for-overriding-enhancing-chmaps.patch
|
|
||||||
Patch21: 0021-conf-Add-chmap-definitions-to-TRIDENT-and-SI7018-con.patch
|
|
||||||
Patch22: 0022-test-chmap-Fix-wrong-malloc-size.patch
|
|
||||||
Patch23: 0023-PCM-Define-MONO-and-other-channel-map-positions.patch
|
|
||||||
Patch24: 0024-PCM-Fix-the-conversion-from-string-to-chmap-position.patch
|
|
||||||
Patch25: 0025-PCM-A-few-doxygen-fixes-for-chmap-stuff.patch
|
|
||||||
Patch26: 0026-PCM-Fill-SND_CHMAP_NA-to-silent-channels-in-route-pl.patch
|
|
||||||
Patch27: 0027-PCM-Fix-infinite-loop-in-htimestamp-of-dmix-dsnoop-a.patch
|
|
||||||
Patch28: 0028-test-add-audio_time.patch
|
|
||||||
Patch30: 0030-PCM-Fix-the-invalid-snd_pcm_close-calls-in-rate-plug.patch
|
|
||||||
Patch31: 0031-pcm-support-for-audio-timestamps.patch
|
|
||||||
Patch32: 0032-pcm-fix-64-bit-SNDRV_PCM_IOCTL_STATUS-ABI-breakage.patch
|
|
||||||
Patch33: 0033-PCM-Fix-memory-leak-for-pcm-empty-and-asym-plugins.patch
|
|
||||||
Patch34: 0034-Reduce-compilation-warnings.patch
|
|
||||||
Patch35: 0035-PCM-Avoid-busy-loop-in-snd_pcm_write_areas-with-rate.patch
|
|
||||||
Patch36: 0036-Merge-kernel-uapi-sound-asound.h-and-asequencer.h.patch
|
|
||||||
Patch37: 0037-PCM-Add-more-chmap-definitions-for-UAC2.patch
|
|
||||||
Patch38: 0038-PCM-shut-up-a-compile-unused-parameter-compile-warni.patch
|
|
||||||
Patch39: 0039-Add-workaround-for-conflicting-snd_seq_event_t-defin.patch
|
|
||||||
Patch40: 0040-PCM-Fix-conflict-of-_snd_pcm_hw_params-definitions.patch
|
|
||||||
Patch41: 0041-configure-Quite-AM_CONDITIONAL-arguments.patch
|
|
||||||
Patch42: 0042-mixer-Don-t-build-simple_abst-when-no-libdl-is-avail.patch
|
|
||||||
Patch43: 0043-Fix-endian-check-in-local.h.patch
|
|
||||||
Patch44: 0044-configure-do-not-detect-incorrect-cross-compiler.patch
|
|
||||||
Patch45: 0045-ucm-Set-uc_mgr-ctl-to-NULL-after-closing-it.patch
|
|
||||||
Patch46: 0046-snd_pcm_direct_parse_open_conf-use-thread-safe-getgr.patch
|
|
||||||
Patch47: 0047-Add-snd_lib_error_set_local-to-install-a-thread-loca.patch
|
|
||||||
Patch48: 0048-snd_device_name_hint-do-not-change-the-global-error-.patch
|
|
||||||
Patch49: 0049-snd_device_name_hint-do-not-use-global-snd_config.patch
|
|
||||||
Patch50: 0050-conf-Fix-a-memory-access-violation-resulting-from-im.patch
|
|
||||||
Patch51: 0051-Add-sys-types.h-to-include-list.patch
|
|
||||||
Patch52: 0052-control-Simplify-using-snd_config_get_bool.patch
|
|
||||||
Patch53: 0053-Add-workaround-for-conflicting-IEC958-controls-for-H.patch
|
|
||||||
Patch54: 0054-snd_mixer_poll_descriptors_revents-should-loop-over-.patch
|
|
||||||
#
|
|
||||||
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
|
||||||
@ -157,59 +103,6 @@ Architecture.
|
|||||||
%prep
|
%prep
|
||||||
%setup -q -n alsa-lib-%{package_version}
|
%setup -q -n alsa-lib-%{package_version}
|
||||||
# %patch -p1
|
# %patch -p1
|
||||||
%patch1 -p1
|
|
||||||
%patch2 -p1
|
|
||||||
%patch3 -p1
|
|
||||||
%patch4 -p1
|
|
||||||
%patch5 -p1
|
|
||||||
%patch6 -p1
|
|
||||||
%patch7 -p1
|
|
||||||
%patch8 -p1
|
|
||||||
%patch9 -p1
|
|
||||||
%patch10 -p1
|
|
||||||
%patch11 -p1
|
|
||||||
%patch12 -p1
|
|
||||||
%patch13 -p1
|
|
||||||
%patch14 -p1
|
|
||||||
%patch15 -p1
|
|
||||||
%patch16 -p1
|
|
||||||
%patch17 -p1
|
|
||||||
%patch18 -p1
|
|
||||||
%patch19 -p1
|
|
||||||
%patch20 -p1
|
|
||||||
%patch21 -p1
|
|
||||||
%patch22 -p1
|
|
||||||
%patch23 -p1
|
|
||||||
%patch24 -p1
|
|
||||||
%patch25 -p1
|
|
||||||
%patch26 -p1
|
|
||||||
%patch27 -p1
|
|
||||||
%patch28 -p1
|
|
||||||
%patch30 -p1
|
|
||||||
%patch31 -p1
|
|
||||||
%patch32 -p1
|
|
||||||
%patch33 -p1
|
|
||||||
%patch34 -p1
|
|
||||||
%patch35 -p1
|
|
||||||
%patch36 -p1
|
|
||||||
%patch37 -p1
|
|
||||||
%patch38 -p1
|
|
||||||
%patch39 -p1
|
|
||||||
%patch40 -p1
|
|
||||||
%patch41 -p1
|
|
||||||
%patch42 -p1
|
|
||||||
%patch43 -p1
|
|
||||||
%patch44 -p1
|
|
||||||
%patch45 -p1
|
|
||||||
%patch46 -p1
|
|
||||||
%patch47 -p1
|
|
||||||
%patch48 -p1
|
|
||||||
%patch49 -p1
|
|
||||||
%patch50 -p1
|
|
||||||
%patch51 -p1
|
|
||||||
%patch52 -p1
|
|
||||||
%patch53 -p1
|
|
||||||
%patch54 -p1
|
|
||||||
%if %suse_version == 1130
|
%if %suse_version == 1130
|
||||||
%patch99 -p1
|
%patch99 -p1
|
||||||
%endif
|
%endif
|
||||||
|
4
joystick
4
joystick
@ -40,7 +40,7 @@ function start () {
|
|||||||
if [ -n "$jsmod" -a "$jsmod" != off ]; then
|
if [ -n "$jsmod" -a "$jsmod" != off ]; then
|
||||||
/sbin/modprobe $jsmod >/dev/null 2>&1
|
/sbin/modprobe $jsmod >/dev/null 2>&1
|
||||||
fi
|
fi
|
||||||
# load joystick moulde
|
# load joystick module
|
||||||
eval jsdev=\$JOYSTICK_MODULE_$js
|
eval jsdev=\$JOYSTICK_MODULE_$js
|
||||||
eval jsdev_opts=\$JOYSTICK_MODULE_OPTION_$js
|
eval jsdev_opts=\$JOYSTICK_MODULE_OPTION_$js
|
||||||
if [ -n "$jsdev" -a "$jsdev" != off ]; then
|
if [ -n "$jsdev" -a "$jsdev" != off ]; then
|
||||||
@ -56,7 +56,7 @@ function stop () {
|
|||||||
if [ -n "$jsmod" -a "$jsmod" != off ]; then
|
if [ -n "$jsmod" -a "$jsmod" != off ]; then
|
||||||
/sbin/modprobe -r $jsmod
|
/sbin/modprobe -r $jsmod
|
||||||
fi
|
fi
|
||||||
# remove joystick moulde
|
# remove joystick module
|
||||||
eval jsdev=\$JOYSTICK_MODULE_$js
|
eval jsdev=\$JOYSTICK_MODULE_$js
|
||||||
if [ -n "$jsdev" -a "$jsdev" != off ]; then
|
if [ -n "$jsdev" -a "$jsdev" != off ]; then
|
||||||
/sbin/modprobe -r $jsdev
|
/sbin/modprobe -r $jsdev
|
||||||
|
Loading…
Reference in New Issue
Block a user