mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-31 22:25:35 -04:00
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>
This commit is contained in:
parent
1ef1c5cdb4
commit
3c4a22ea49
27 changed files with 386 additions and 0 deletions
|
|
@ -182,6 +182,13 @@ typedef enum _snd_ctl_event_type {
|
||||||
/** Mute state */
|
/** Mute state */
|
||||||
#define SND_CTL_TLV_DB_GAIN_MUTE -9999999
|
#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 */
|
/** CTL type */
|
||||||
typedef enum _snd_ctl_type {
|
typedef enum _snd_ctl_type {
|
||||||
/** Kernel level CTL */
|
/** Kernel level CTL */
|
||||||
|
|
|
||||||
|
|
@ -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_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
|
||||||
int snd_pcm_unlink(snd_pcm_t *pcm);
|
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);
|
//int snd_pcm_mixer_element(snd_pcm_t *pcm, snd_mixer_t *mixer, snd_mixer_elem_t **elem);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -477,6 +477,31 @@ enum {
|
||||||
SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
|
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 {
|
enum {
|
||||||
SNDRV_PCM_IOCTL_PVERSION = _IOR('A', 0x00, int),
|
SNDRV_PCM_IOCTL_PVERSION = _IOR('A', 0x00, int),
|
||||||
SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct sndrv_pcm_info),
|
SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct sndrv_pcm_info),
|
||||||
|
|
|
||||||
|
|
@ -7302,6 +7302,61 @@ OBSOLETE1(snd_pcm_sw_params_get_silence_size, ALSA_0.9, ALSA_0.9.0rc4);
|
||||||
|
|
||||||
#endif /* DOC_HIDDEN */
|
#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
|
* basic helpers
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -531,6 +531,9 @@ static const snd_pcm_ops_t snd_pcm_adpcm_ops = {
|
||||||
.async = snd_pcm_generic_async,
|
.async = snd_pcm_generic_async,
|
||||||
.mmap = snd_pcm_generic_mmap,
|
.mmap = snd_pcm_generic_mmap,
|
||||||
.munmap = snd_pcm_generic_munmap,
|
.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,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -404,6 +404,9 @@ static const snd_pcm_ops_t snd_pcm_alaw_ops = {
|
||||||
.async = snd_pcm_generic_async,
|
.async = snd_pcm_generic_async,
|
||||||
.mmap = snd_pcm_generic_mmap,
|
.mmap = snd_pcm_generic_mmap,
|
||||||
.munmap = snd_pcm_generic_munmap,
|
.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,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,9 @@ static const snd_pcm_ops_t snd_pcm_copy_ops = {
|
||||||
.async = snd_pcm_generic_async,
|
.async = snd_pcm_generic_async,
|
||||||
.mmap = snd_pcm_generic_mmap,
|
.mmap = snd_pcm_generic_mmap,
|
||||||
.munmap = snd_pcm_generic_munmap,
|
.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,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -789,6 +789,24 @@ int snd_pcm_direct_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
|
||||||
return 0;
|
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)
|
int snd_pcm_direct_resume(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_direct_t *dmix = pcm->private_data;
|
snd_pcm_direct_t *dmix = pcm->private_data;
|
||||||
|
|
|
||||||
|
|
@ -235,6 +235,12 @@ struct snd_pcm_direct {
|
||||||
snd1_pcm_direct_open_secondary_client
|
snd1_pcm_direct_open_secondary_client
|
||||||
#define snd_pcm_direct_parse_open_conf \
|
#define snd_pcm_direct_parse_open_conf \
|
||||||
snd1_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);
|
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_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_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);
|
int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
|
||||||
struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);
|
struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -892,6 +892,9 @@ static const snd_pcm_ops_t snd_pcm_dmix_ops = {
|
||||||
.async = snd_pcm_direct_async,
|
.async = snd_pcm_direct_async,
|
||||||
.mmap = snd_pcm_direct_mmap,
|
.mmap = snd_pcm_direct_mmap,
|
||||||
.munmap = snd_pcm_direct_munmap,
|
.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 = {
|
static const snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
|
||||||
|
|
|
||||||
|
|
@ -573,6 +573,8 @@ static const snd_pcm_ops_t snd_pcm_dshare_ops = {
|
||||||
.async = snd_pcm_direct_async,
|
.async = snd_pcm_direct_async,
|
||||||
.mmap = snd_pcm_direct_mmap,
|
.mmap = snd_pcm_direct_mmap,
|
||||||
.munmap = snd_pcm_direct_munmap,
|
.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 = {
|
static const snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = {
|
||||||
|
|
|
||||||
|
|
@ -488,6 +488,9 @@ static const snd_pcm_ops_t snd_pcm_dsnoop_ops = {
|
||||||
.async = snd_pcm_direct_async,
|
.async = snd_pcm_direct_async,
|
||||||
.mmap = snd_pcm_direct_mmap,
|
.mmap = snd_pcm_direct_mmap,
|
||||||
.munmap = snd_pcm_direct_munmap,
|
.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 = {
|
static const snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = {
|
||||||
|
|
|
||||||
|
|
@ -669,6 +669,9 @@ static const snd_pcm_ops_t snd_pcm_file_ops = {
|
||||||
.async = snd_pcm_generic_async,
|
.async = snd_pcm_generic_async,
|
||||||
.mmap = snd_pcm_generic_mmap,
|
.mmap = snd_pcm_generic_mmap,
|
||||||
.munmap = snd_pcm_generic_munmap,
|
.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 = {
|
static const snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
|
||||||
|
|
|
||||||
|
|
@ -323,4 +323,22 @@ int snd_pcm_generic_munmap(snd_pcm_t *pcm)
|
||||||
return 0;
|
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 */
|
#endif /* DOC_HIDDEN */
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,12 @@ typedef struct {
|
||||||
snd1_pcm_generic_mmap
|
snd1_pcm_generic_mmap
|
||||||
#define snd_pcm_generic_munmap \
|
#define snd_pcm_generic_munmap \
|
||||||
snd1_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_close(snd_pcm_t *pcm);
|
||||||
int snd_pcm_generic_nonblock(snd_pcm_t *pcm, int nonblock);
|
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);
|
snd_htimestamp_t *tstamp);
|
||||||
int snd_pcm_generic_mmap(snd_pcm_t *pcm);
|
int snd_pcm_generic_mmap(snd_pcm_t *pcm);
|
||||||
int snd_pcm_generic_munmap(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);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,9 @@ static const snd_pcm_ops_t snd_pcm_hooks_ops = {
|
||||||
.async = snd_pcm_generic_async,
|
.async = snd_pcm_generic_async,
|
||||||
.mmap = snd_pcm_generic_mmap,
|
.mmap = snd_pcm_generic_mmap,
|
||||||
.munmap = snd_pcm_generic_munmap,
|
.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 = {
|
static const snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
|
||||||
|
|
|
||||||
178
src/pcm/pcm_hw.c
178
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;
|
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)
|
static void snd_pcm_hw_dump(snd_pcm_t *pcm, snd_output_t *out)
|
||||||
{
|
{
|
||||||
snd_pcm_hw_t *hw = pcm->private_data;
|
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,
|
.async = snd_pcm_hw_async,
|
||||||
.mmap = snd_pcm_hw_mmap,
|
.mmap = snd_pcm_hw_mmap,
|
||||||
.munmap = snd_pcm_hw_munmap,
|
.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 = {
|
static const snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
|
||||||
|
|
|
||||||
|
|
@ -429,6 +429,9 @@ static const snd_pcm_ops_t snd_pcm_iec958_ops = {
|
||||||
.async = snd_pcm_generic_async,
|
.async = snd_pcm_generic_async,
|
||||||
.mmap = snd_pcm_generic_mmap,
|
.mmap = snd_pcm_generic_mmap,
|
||||||
.munmap = snd_pcm_generic_munmap,
|
.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,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1084,6 +1084,9 @@ static const snd_pcm_ops_t snd_pcm_ladspa_ops = {
|
||||||
.async = snd_pcm_generic_async,
|
.async = snd_pcm_generic_async,
|
||||||
.mmap = snd_pcm_generic_mmap,
|
.mmap = snd_pcm_generic_mmap,
|
||||||
.munmap = snd_pcm_generic_munmap,
|
.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,
|
static int snd_pcm_ladspa_check_file(snd_pcm_ladspa_plugin_t * const plugin,
|
||||||
|
|
|
||||||
|
|
@ -363,6 +363,9 @@ static const snd_pcm_ops_t snd_pcm_lfloat_ops = {
|
||||||
.async = snd_pcm_generic_async,
|
.async = snd_pcm_generic_async,
|
||||||
.mmap = snd_pcm_generic_mmap,
|
.mmap = snd_pcm_generic_mmap,
|
||||||
.munmap = snd_pcm_generic_munmap,
|
.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,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -435,6 +435,9 @@ static const snd_pcm_ops_t snd_pcm_linear_ops = {
|
||||||
.async = snd_pcm_generic_async,
|
.async = snd_pcm_generic_async,
|
||||||
.mmap = snd_pcm_generic_mmap,
|
.mmap = snd_pcm_generic_mmap,
|
||||||
.munmap = snd_pcm_generic_munmap,
|
.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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,9 @@ typedef struct {
|
||||||
void (*dump)(snd_pcm_t *pcm, snd_output_t *out);
|
void (*dump)(snd_pcm_t *pcm, snd_output_t *out);
|
||||||
int (*mmap)(snd_pcm_t *pcm);
|
int (*mmap)(snd_pcm_t *pcm);
|
||||||
int (*munmap)(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;
|
} snd_pcm_ops_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
||||||
|
|
@ -514,6 +514,9 @@ static const snd_pcm_ops_t snd_pcm_meter_ops = {
|
||||||
.async = snd_pcm_generic_async,
|
.async = snd_pcm_generic_async,
|
||||||
.mmap = snd_pcm_generic_mmap,
|
.mmap = snd_pcm_generic_mmap,
|
||||||
.munmap = snd_pcm_generic_munmap,
|
.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 = {
|
static const snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
|
||||||
|
|
|
||||||
|
|
@ -368,6 +368,9 @@ static const snd_pcm_ops_t snd_pcm_mmap_emul_ops = {
|
||||||
.async = snd_pcm_generic_async,
|
.async = snd_pcm_generic_async,
|
||||||
.mmap = snd_pcm_generic_mmap,
|
.mmap = snd_pcm_generic_mmap,
|
||||||
.munmap = snd_pcm_generic_munmap,
|
.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 = {
|
static const snd_pcm_fast_ops_t snd_pcm_mmap_emul_fast_ops = {
|
||||||
|
|
|
||||||
|
|
@ -419,6 +419,8 @@ static const snd_pcm_ops_t snd_pcm_mulaw_ops = {
|
||||||
.async = snd_pcm_generic_async,
|
.async = snd_pcm_generic_async,
|
||||||
.mmap = snd_pcm_generic_mmap,
|
.mmap = snd_pcm_generic_mmap,
|
||||||
.munmap = snd_pcm_generic_munmap,
|
.munmap = snd_pcm_generic_munmap,
|
||||||
|
.get_chmap = snd_pcm_generic_get_chmap,
|
||||||
|
.set_chmap = snd_pcm_generic_set_chmap,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1249,6 +1249,9 @@ static const snd_pcm_ops_t snd_pcm_rate_ops = {
|
||||||
.async = snd_pcm_generic_async,
|
.async = snd_pcm_generic_async,
|
||||||
.mmap = snd_pcm_generic_mmap,
|
.mmap = snd_pcm_generic_mmap,
|
||||||
.munmap = snd_pcm_generic_munmap,
|
.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,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -818,6 +818,9 @@ static const snd_pcm_ops_t snd_pcm_softvol_ops = {
|
||||||
.async = snd_pcm_generic_async,
|
.async = snd_pcm_generic_async,
|
||||||
.mmap = snd_pcm_generic_mmap,
|
.mmap = snd_pcm_generic_mmap,
|
||||||
.munmap = snd_pcm_generic_munmap,
|
.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,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue