#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);
/**
* 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);
};
/**
* 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);
};
* 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;
* \!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++)
* \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;
* \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;
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);
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);
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;
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;
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;
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);
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);
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))
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);
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;
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);
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) {
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)
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;
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;
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;
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 {
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);
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)
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)
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);
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);
#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))
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;
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;
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;
}
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);
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;
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;
}