]> git.alsa-project.org Git - alsa-lib.git/commitdiff
PCM SUBDEVICE selection enhancements
authorJaroslav Kysela <perex@perex.cz>
Sun, 22 Aug 1999 13:34:31 +0000 (13:34 +0000)
committerJaroslav Kysela <perex@perex.cz>
Sun, 22 Aug 1999 13:34:31 +0000 (13:34 +0000)
include/control.h
include/pcm.h
src/control/control.c
src/pcm/pcm.c

index 44720cf16d56514085e5ff7ae728647aa4f2de7e..8247f0ec91d1be99bb85d55c94ce2e1423a4bf52 100644 (file)
@@ -40,14 +40,15 @@ int snd_ctl_switch_read(snd_ctl_t *handle, snd_switch_t * sw);
 int snd_ctl_switch_write(snd_ctl_t *handle, snd_switch_t * sw);
 int snd_ctl_hwdep_info(snd_ctl_t *handle, int dev, snd_hwdep_info_t * info);
 int snd_ctl_pcm_info(snd_ctl_t *handle, int dev, snd_pcm_info_t * info);
-int snd_ctl_pcm_playback_info(snd_ctl_t *handle, int dev, snd_pcm_playback_info_t * info);
-int snd_ctl_pcm_capture_info(snd_ctl_t *handle, int dev, snd_pcm_capture_info_t * info);
+int snd_ctl_pcm_playback_info(snd_ctl_t *handle, int dev, int subdev, snd_pcm_playback_info_t * info);
+int snd_ctl_pcm_capture_info(snd_ctl_t *handle, int dev, int subdev, snd_pcm_capture_info_t * info);
 int snd_ctl_pcm_playback_switch_list(snd_ctl_t *handle, int dev, snd_switch_list_t * list);
 int snd_ctl_pcm_playback_switch_read(snd_ctl_t *handle, int dev, snd_switch_t * sw);
 int snd_ctl_pcm_playback_switch_write(snd_ctl_t *handle, int dev, snd_switch_t * sw);
 int snd_ctl_pcm_capture_switch_list(snd_ctl_t *handle, int dev, snd_switch_list_t * list);
 int snd_ctl_pcm_capture_switch_read(snd_ctl_t *handle, int dev, snd_switch_t * sw);
 int snd_ctl_pcm_capture_switch_write(snd_ctl_t *handle, int dev, snd_switch_t * sw);
+int snd_ctl_pcm_prefer_subdevice(snd_ctl_t *handle, int dev, int subdev);
 int snd_ctl_mixer_info(snd_ctl_t *handle, int dev, snd_mixer_info_t * info);
 int snd_ctl_mixer_switch_list(snd_ctl_t *handle, int dev, snd_switch_list_t *list);
 int snd_ctl_mixer_switch_read(snd_ctl_t *handle, int dev, snd_switch_t * sw);
index 69707810348867ef9a7d6e9d0da7ba5dd33e9620..85fba847d2f3b7ac42c465dfd6df41608381cd65 100644 (file)
@@ -17,6 +17,7 @@ typedef struct snd_pcm snd_pcm_t;
 typedef struct snd_pcm_loopback snd_pcm_loopback_t;
 
 int snd_pcm_open(snd_pcm_t **handle, int card, int device, int mode);
+int snd_pcm_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int mode);
 int snd_pcm_close(snd_pcm_t *handle);
 int snd_pcm_file_descriptor(snd_pcm_t *handle);
 int snd_pcm_block_mode(snd_pcm_t *handle, int enable);
index 8fd59880de651115bb8761cf5793f63716460608..ff1c8af69c65ea4a86cedf3ac1bf0cb38e16a919 100644 (file)
@@ -29,7 +29,7 @@
 #include "asoundlib.h"
 
 #define SND_FILE_CONTROL       "/dev/snd/controlC%i"
-#define SND_CTL_VERSION_MAX    SND_PROTOCOL_VERSION(2, 0, 0)
+#define SND_CTL_VERSION_MAX    SND_PROTOCOL_VERSION(2, 0, 1)
 
 struct snd_ctl {
        int card;
@@ -171,29 +171,33 @@ int snd_ctl_pcm_info(snd_ctl_t *handle, int dev, snd_pcm_info_t * info)
        return 0;
 }
 
-int snd_ctl_pcm_playback_info(snd_ctl_t *handle, int dev, snd_pcm_playback_info_t * info)
+int snd_ctl_pcm_playback_info(snd_ctl_t *handle, int dev, int subdev, snd_pcm_playback_info_t * info)
 {
        snd_ctl_t *ctl;
 
        ctl = handle;
-       if (!ctl || !info || dev < 0)
+       if (!ctl || !info || dev < 0 || subdev < 0)
                return -EINVAL;
        if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_DEVICE, &dev) < 0)
                return -errno;
+       if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_SUBDEVICE, &subdev) < 0)
+               return -errno;
        if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_PLAYBACK_INFO, info) < 0)
                return -errno;
        return 0;
 }
 
-int snd_ctl_pcm_capture_info(snd_ctl_t *handle, int dev, snd_pcm_capture_info_t * info)
+int snd_ctl_pcm_capture_info(snd_ctl_t *handle, int dev, int subdev, snd_pcm_capture_info_t * info)
 {
        snd_ctl_t *ctl;
 
        ctl = handle;
-       if (!ctl || !info || dev < 0)
+       if (!ctl || !info || dev < 0 || subdev < 0)
                return -EINVAL;
        if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_DEVICE, &dev) < 0)
                return -errno;
+       if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_SUBDEVICE, &subdev) < 0)
+               return -errno;
        if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_CAPTURE_INFO, info) < 0)
                return -errno;
        return 0;
@@ -250,7 +254,7 @@ int snd_ctl_pcm_capture_switch_list(snd_ctl_t *handle, int dev, snd_switch_list_
                return -EINVAL;
        if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_DEVICE, &dev) < 0)
                return -errno;
-       if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_RSWITCH_LIST, list) < 0)
+       if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_CSWITCH_LIST, list) < 0)
                return -errno;
        return 0;
 }
@@ -264,7 +268,7 @@ int snd_ctl_pcm_capture_switch_read(snd_ctl_t *handle, int dev, snd_switch_t * s
                return -EINVAL;
        if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_DEVICE, &dev) < 0)
                return -errno;
-       if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_RSWITCH_READ, sw) < 0)
+       if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_CSWITCH_READ, sw) < 0)
                return -errno;
        return 0;
 }
@@ -278,7 +282,21 @@ int snd_ctl_pcm_capture_switch_write(snd_ctl_t *handle, int dev, snd_switch_t *
                return -EINVAL;
        if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_DEVICE, &dev) < 0)
                return -errno;
-       if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_RSWITCH_WRITE, sw) < 0)
+       if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_CSWITCH_WRITE, sw) < 0)
+               return -errno;
+       return 0;
+}
+
+int snd_ctl_pcm_prefer_subdevice(snd_ctl_t *handle, int dev, int subdev)
+{
+       snd_ctl_t *ctl;
+
+       ctl = handle;
+       if (!ctl || dev < 0)
+               return -EINVAL;
+       if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_DEVICE, &dev) < 0)
+               return -errno;
+       if (ioctl(ctl->fd, SND_CTL_IOCTL_PCM_PREFER_SUBDEVICE, &subdev) < 0)
                return -errno;
        return 0;
 }
index 350b4ad3a7a349936d50b0b85ec3e621136f8c20..7046df8b9bd27a923cf8b16e6616b68c05babcbf 100644 (file)
@@ -35,32 +35,79 @@ struct snd_pcm {
        int card;
        int device;
        int fd;
+       int mode;
 };
 
 int snd_pcm_open(snd_pcm_t **handle, int card, int device, int mode)
 {
-       int fd, ver;
+       return snd_pcm_open_subdevice(handle, card, device, -1, mode);
+}
+
+int snd_pcm_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int mode)
+{
+       int fd, ver, err, attempt = 0;
        char filename[32];
        snd_pcm_t *pcm;
+       snd_ctl_t *ctl;
+       snd_pcm_playback_info_t pinfo;
+       snd_pcm_capture_info_t cinfo;
 
        *handle = NULL;
        
        if (card < 0 || card >= SND_CARDS)
                return -EINVAL;
+       if ((err = snd_ctl_open(&ctl, card)) < 0)
+               return err;
+      __again:
+       if (attempt++ > 3) {
+               snd_ctl_close(ctl);
+               return -EBUSY;
+       }
+       if ((err = snd_ctl_pcm_prefer_subdevice(ctl, device, subdevice)) < 0) {
+               snd_ctl_close(ctl);
+               return err;
+       }
        sprintf(filename, SND_FILE_PCM, card, device);
        if ((fd = open(filename, mode)) < 0) {
-               snd_card_load(card);
-               if ((fd = open(filename, mode)) < 0) 
-                       return -errno;
+               err = -errno;
+               snd_ctl_close(ctl);
+               return err;
        }
        if (ioctl(fd, SND_PCM_IOCTL_PVERSION, &ver) < 0) {
+               err = -errno;
                close(fd);
-               return -errno;
+               snd_ctl_close(ctl);
+               return err;
        }
        if (SND_PROTOCOL_INCOMPATIBLE(ver, SND_PCM_VERSION_MAX)) {
                close(fd);
+               snd_ctl_close(ctl);
                return -SND_ERROR_INCOMPATIBLE_VERSION;
        }
+       if (subdevice >= 0 && (mode == SND_PCM_OPEN_PLAYBACK || mode == SND_PCM_OPEN_DUPLEX)) {
+               if (ioctl(fd, SND_PCM_IOCTL_PLAYBACK_INFO, &pinfo) < 0) {
+                       err = -errno;
+                       close(fd);
+                       snd_ctl_close(ctl);
+                       return err;
+               }
+               if (pinfo.subdevice != subdevice) {
+                       close(fd);
+                       goto __again;
+               }
+       }
+       if (subdevice >= 0 && (mode == SND_PCM_OPEN_CAPTURE || mode == SND_PCM_OPEN_DUPLEX)) {
+               if (ioctl(fd, SND_PCM_IOCTL_CAPTURE_INFO, &cinfo) < 0) {
+                       err = -errno;
+                       close(fd);
+                       snd_ctl_close(ctl);
+                       return err;
+               }
+               if (cinfo.subdevice != subdevice) {
+                       close(fd);
+                       goto __again;
+               }
+       }
        pcm = (snd_pcm_t *) calloc(1, sizeof(snd_pcm_t));
        if (pcm == NULL) {
                close(fd);
@@ -69,6 +116,7 @@ int snd_pcm_open(snd_pcm_t **handle, int card, int device, int mode)
        pcm->card = card;
        pcm->device = device;
        pcm->fd = fd;
+       pcm->mode = mode;
        *handle = pcm;
        return 0;
 }