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
*/
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"
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;
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;
unsigned int i;
int ret;
+ if (hw->chmap_override)
+ return -ENXIO;
+
if (!chmap_caps(hw, CHMAP_CTL_SET))
return -ENXIO;
[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
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 */
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;
}
hw->channels = channels;
if (rate > 0)
hw->rate = rate;
+ if (chmap)
+ hw->chmap_override = chmap;
return 0;
}
}
#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);
+
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
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");
.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 = {
\code
pcm.name {
type null # Null PCM
+ [chmap MAP]
}
\endcode
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;
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);