Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:12.3
alsa
0020-PCM-Use-compounds-for-overriding-enhancing...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0020-PCM-Use-compounds-for-overriding-enhancing-chmaps.patch of Package alsa
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;
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor