OSDN Git Service

Implement the channel mapping API
authorTakashi Iwai <tiwai@suse.de>
Wed, 25 Jul 2012 13:05:15 +0000 (15:05 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 11 Sep 2012 09:34:50 +0000 (11:34 +0200)
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>
27 files changed:
include/control.h
include/pcm.h
include/sound/asound.h
src/pcm/pcm.c
src/pcm/pcm_adpcm.c
src/pcm/pcm_alaw.c
src/pcm/pcm_copy.c
src/pcm/pcm_direct.c
src/pcm/pcm_direct.h
src/pcm/pcm_dmix.c
src/pcm/pcm_dshare.c
src/pcm/pcm_dsnoop.c
src/pcm/pcm_file.c
src/pcm/pcm_generic.c
src/pcm/pcm_generic.h
src/pcm/pcm_hooks.c
src/pcm/pcm_hw.c
src/pcm/pcm_iec958.c
src/pcm/pcm_ladspa.c
src/pcm/pcm_lfloat.c
src/pcm/pcm_linear.c
src/pcm/pcm_local.h
src/pcm/pcm_meter.c
src/pcm/pcm_mmap_emul.c
src/pcm/pcm_mulaw.c
src/pcm/pcm_rate.c
src/pcm/pcm_softvol.c

index 488629d..e840835 100644 (file)
@@ -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 */
index 4997557..c47717b 100644 (file)
@@ -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);
 
 /*
index 07c03fa..e635c99 100644 (file)
@@ -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),
index 18b43b3..64adce9 100644 (file)
@@ -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
  */
index b68007f..6f0e7c4 100644 (file)
@@ -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,
 };
 
 /**
index 09ad481..1b1bab8 100644 (file)
@@ -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,
 };
 
 /**
index 072bb12..56a1f6b 100644 (file)
@@ -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,
 };
 
 /**
index 0a9047d..d649c3b 100644 (file)
@@ -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;
index 7f16481..f8a674e 100644 (file)
@@ -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);
 
index 434fc65..8c71edb 100644 (file)
@@ -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 = {
index 77789a5..6638dc4 100644 (file)
@@ -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 = {
index bacb4ae..9df6c7e 100644 (file)
@@ -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 = {
index bfa1cc8..c8214b4 100644 (file)
@@ -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 = {
index 84ea85f..2abde5b 100644 (file)
@@ -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 */
index 430b8cf..2f17593 100644 (file)
@@ -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);
+
+
index 404d51e..0feb4a3 100644 (file)
@@ -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 = {
index 9d243d5..4a57ad3 100644 (file)
@@ -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 = {
index 3d70ed0..d81b0a1 100644 (file)
@@ -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,
 };
 
 /**
index 84ebaa5..31e2875 100644 (file)
@@ -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,
index 62eb398..bbf72c2 100644 (file)
@@ -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,
 };
 
 /**
index e85dfaa..7aa8941 100644 (file)
@@ -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,
 };
 
 
index 2e901d5..9596799 100644 (file)
@@ -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 {
index 5acc7bc..42a125e 100644 (file)
@@ -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 = {
index 664e907..236fe69 100644 (file)
@@ -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 = {
index 22e7d96..7adce38 100644 (file)
@@ -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,
 };
 
 /**
index eb35e4a..a15c3af 100644 (file)
@@ -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,
 };
 
 /**
index 2c7c006..5da9204 100644 (file)
@@ -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,
 };
 
 /**