diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-07-25 15:05:15 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-09-11 11:34:50 +0200 |
commit | 3c4a22ea49a881cdbfe2d50eef94b17e38104734 (patch) | |
tree | 6c7faa47907ac3e2d166734e33364cdab93218c4 | |
parent | 1ef1c5cdb4301898499c0391cdfac2117c7d4684 (diff) | |
download | alsa-lib-3c4a22ea49a881cdbfe2d50eef94b17e38104734.tar.gz |
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>
-rw-r--r-- | include/control.h | 7 | ||||
-rw-r--r-- | include/pcm.h | 12 | ||||
-rw-r--r-- | include/sound/asound.h | 25 | ||||
-rw-r--r-- | src/pcm/pcm.c | 55 | ||||
-rw-r--r-- | src/pcm/pcm_adpcm.c | 3 | ||||
-rw-r--r-- | src/pcm/pcm_alaw.c | 3 | ||||
-rw-r--r-- | src/pcm/pcm_copy.c | 3 | ||||
-rw-r--r-- | src/pcm/pcm_direct.c | 18 | ||||
-rw-r--r-- | src/pcm/pcm_direct.h | 10 | ||||
-rw-r--r-- | src/pcm/pcm_dmix.c | 3 | ||||
-rw-r--r-- | src/pcm/pcm_dshare.c | 2 | ||||
-rw-r--r-- | src/pcm/pcm_dsnoop.c | 3 | ||||
-rw-r--r-- | src/pcm/pcm_file.c | 3 | ||||
-rw-r--r-- | src/pcm/pcm_generic.c | 18 | ||||
-rw-r--r-- | src/pcm/pcm_generic.h | 11 | ||||
-rw-r--r-- | src/pcm/pcm_hooks.c | 3 | ||||
-rw-r--r-- | src/pcm/pcm_hw.c | 178 | ||||
-rw-r--r-- | src/pcm/pcm_iec958.c | 3 | ||||
-rw-r--r-- | src/pcm/pcm_ladspa.c | 3 | ||||
-rw-r--r-- | src/pcm/pcm_lfloat.c | 3 | ||||
-rw-r--r-- | src/pcm/pcm_linear.c | 3 | ||||
-rw-r--r-- | src/pcm/pcm_local.h | 3 | ||||
-rw-r--r-- | src/pcm/pcm_meter.c | 3 | ||||
-rw-r--r-- | src/pcm/pcm_mmap_emul.c | 3 | ||||
-rw-r--r-- | src/pcm/pcm_mulaw.c | 2 | ||||
-rw-r--r-- | src/pcm/pcm_rate.c | 3 | ||||
-rw-r--r-- | src/pcm/pcm_softvol.c | 3 |
27 files changed, 386 insertions, 0 deletions
diff --git a/include/control.h b/include/control.h index 488629d9..e8408355 100644 --- 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 */ diff --git a/include/pcm.h b/include/pcm.h index 49975570..c47717b8 100644 --- a/include/pcm.h +++ b/include/pcm.h @@ -474,6 +474,18 @@ int snd_pcm_wait(snd_pcm_t *pcm, int timeout); 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); /* diff --git a/include/sound/asound.h b/include/sound/asound.h index 07c03faa..e635c99b 100644 --- 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), diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index 18b43b3e..64adce9b 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -7302,6 +7302,61 @@ OBSOLETE1(snd_pcm_sw_params_get_silence_size, ALSA_0.9, ALSA_0.9.0rc4); #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 */ diff --git a/src/pcm/pcm_adpcm.c b/src/pcm/pcm_adpcm.c index b68007f9..6f0e7c4c 100644 --- 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_ops = { .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, }; /** diff --git a/src/pcm/pcm_alaw.c b/src/pcm/pcm_alaw.c index 09ad4819..1b1bab83 100644 --- 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_ops = { .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, }; /** diff --git a/src/pcm/pcm_copy.c b/src/pcm/pcm_copy.c index 072bb125..56a1f6bc 100644 --- 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_ops = { .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, }; /** diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c index 0a9047dd..d649c3b0 100644 --- 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 ATTRIBUTE_UNUSED) 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; diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h index 7f16481b..f8a674e5 100644 --- 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(snd_pcm_direct_t *dmix); 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); diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c index 434fc65b..8c71edba 100644 --- 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_ops = { .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 = { diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c index 77789a52..6638dc4a 100644 --- a/src/pcm/pcm_dshare.c +++ b/src/pcm/pcm_dshare.c @@ -573,6 +573,8 @@ static const snd_pcm_ops_t snd_pcm_dshare_ops = { .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 = { diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c index bacb4aea..9df6c7e8 100644 --- a/src/pcm/pcm_dsnoop.c +++ b/src/pcm/pcm_dsnoop.c @@ -488,6 +488,9 @@ static const snd_pcm_ops_t snd_pcm_dsnoop_ops = { .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 = { diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c index bfa1cc8b..c8214b4a 100644 --- 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_ops = { .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 = { diff --git a/src/pcm/pcm_generic.c b/src/pcm/pcm_generic.c index 84ea85f1..2abde5be 100644 --- a/src/pcm/pcm_generic.c +++ b/src/pcm/pcm_generic.c @@ -323,4 +323,22 @@ int snd_pcm_generic_munmap(snd_pcm_t *pcm) 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 */ diff --git a/src/pcm/pcm_generic.h b/src/pcm/pcm_generic.h index 430b8cfd..2f17593d 100644 --- 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_pcm_t *pcm, snd_pcm_uframes_t *avail, 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); + + diff --git a/src/pcm/pcm_hooks.c b/src/pcm/pcm_hooks.c index 404d51e7..0feb4a3a 100644 --- 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_ops = { .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 = { diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index 9d243d53..4a57ad32 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -1004,6 +1004,181 @@ static int snd_pcm_hw_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail, 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_ops = { .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 = { diff --git a/src/pcm/pcm_iec958.c b/src/pcm/pcm_iec958.c index 3d70ed0f..d81b0a14 100644 --- a/src/pcm/pcm_iec958.c +++ b/src/pcm/pcm_iec958.c @@ -429,6 +429,9 @@ static const snd_pcm_ops_t snd_pcm_iec958_ops = { .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, }; /** diff --git a/src/pcm/pcm_ladspa.c b/src/pcm/pcm_ladspa.c index 84ebaa5d..31e28758 100644 --- a/src/pcm/pcm_ladspa.c +++ b/src/pcm/pcm_ladspa.c @@ -1084,6 +1084,9 @@ static const snd_pcm_ops_t snd_pcm_ladspa_ops = { .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, diff --git a/src/pcm/pcm_lfloat.c b/src/pcm/pcm_lfloat.c index 62eb398e..bbf72c27 100644 --- a/src/pcm/pcm_lfloat.c +++ b/src/pcm/pcm_lfloat.c @@ -363,6 +363,9 @@ static const snd_pcm_ops_t snd_pcm_lfloat_ops = { .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, }; /** diff --git a/src/pcm/pcm_linear.c b/src/pcm/pcm_linear.c index e85dfaaa..7aa89418 100644 --- a/src/pcm/pcm_linear.c +++ b/src/pcm/pcm_linear.c @@ -435,6 +435,9 @@ static const snd_pcm_ops_t snd_pcm_linear_ops = { .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, }; diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index 2e901d54..95967992 100644 --- 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 { diff --git a/src/pcm/pcm_meter.c b/src/pcm/pcm_meter.c index 5acc7bc8..42a125e5 100644 --- 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_ops = { .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 = { diff --git a/src/pcm/pcm_mmap_emul.c b/src/pcm/pcm_mmap_emul.c index 664e9077..236fe696 100644 --- 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_emul_ops = { .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 = { diff --git a/src/pcm/pcm_mulaw.c b/src/pcm/pcm_mulaw.c index 22e7d969..7adce38e 100644 --- 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_ops = { .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, }; /** diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index eb35e4ad..a15c3afd 100644 --- 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_ops = { .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, }; /** diff --git a/src/pcm/pcm_softvol.c b/src/pcm/pcm_softvol.c index 2c7c006e..5da92049 100644 --- a/src/pcm/pcm_softvol.c +++ b/src/pcm/pcm_softvol.c @@ -818,6 +818,9 @@ static const snd_pcm_ops_t snd_pcm_softvol_ops = { .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, }; /** |