Added functions:

snd_ctl_rawmidi_prefer_subdevice
	snd_rawmidi_open_subdevice
Fixed functions:
	snd_pcm_hw_open - fixed prefer subdevice code
This commit is contained in:
Jaroslav Kysela 2000-10-30 12:15:18 +00:00
parent 8a625fd63b
commit 0e561770c6
10 changed files with 93 additions and 9 deletions

View file

@ -627,6 +627,9 @@ int ctl_shm_cmd(client_t *client)
case SND_CTL_IOCTL_RAWMIDI_INFO: case SND_CTL_IOCTL_RAWMIDI_INFO:
ctrl->result = snd_ctl_rawmidi_info(ctl, &ctrl->u.rawmidi_info); ctrl->result = snd_ctl_rawmidi_info(ctl, &ctrl->u.rawmidi_info);
break; break;
case SND_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE:
ctrl->result = snd_ctl_rawmidi_prefer_subdevice(ctl, ctrl->u.rawmidi_prefer_subdevice);
break;
case SND_CTL_IOCTL_READ: case SND_CTL_IOCTL_READ:
ctrl->result = snd_ctl_read1(ctl, &ctrl->u.read); ctrl->result = snd_ctl_read1(ctl, &ctrl->u.read);
break; break;

View file

@ -92,6 +92,7 @@ typedef struct {
snd_pcm_info_t pcm_info; snd_pcm_info_t pcm_info;
int pcm_prefer_subdevice; int pcm_prefer_subdevice;
snd_rawmidi_info_t rawmidi_info; snd_rawmidi_info_t rawmidi_info;
int rawmidi_prefer_subdevice;
snd_ctl_event_t read; snd_ctl_event_t read;
} u; } u;
char data[0]; char data[0];

View file

@ -55,6 +55,7 @@ int snd_ctl_hwdep_info(snd_ctl_t *handle, snd_hwdep_info_t * info);
int snd_ctl_pcm_info(snd_ctl_t *handle, snd_pcm_info_t * info); int snd_ctl_pcm_info(snd_ctl_t *handle, snd_pcm_info_t * info);
int snd_ctl_pcm_prefer_subdevice(snd_ctl_t *handle, int subdev); int snd_ctl_pcm_prefer_subdevice(snd_ctl_t *handle, int subdev);
int snd_ctl_rawmidi_info(snd_ctl_t *handle, snd_rawmidi_info_t * info); int snd_ctl_rawmidi_info(snd_ctl_t *handle, snd_rawmidi_info_t * info);
int snd_ctl_rawmidi_prefer_subdevice(snd_ctl_t *handle, int subdev);
int snd_ctl_read(snd_ctl_t *handle, snd_ctl_callbacks_t * callbacks); int snd_ctl_read(snd_ctl_t *handle, snd_ctl_callbacks_t * callbacks);

View file

@ -18,6 +18,7 @@ extern "C" {
typedef struct snd_rawmidi snd_rawmidi_t; typedef struct snd_rawmidi snd_rawmidi_t;
int snd_rawmidi_open_subdevice(snd_rawmidi_t **handle, int card, int device, int subdevice, int mode);
int snd_rawmidi_open(snd_rawmidi_t **handle, int card, int device, int mode); int snd_rawmidi_open(snd_rawmidi_t **handle, int card, int device, int mode);
int snd_rawmidi_close(snd_rawmidi_t *handle); int snd_rawmidi_close(snd_rawmidi_t *handle);
int snd_rawmidi_poll_descriptor(snd_rawmidi_t *handle); int snd_rawmidi_poll_descriptor(snd_rawmidi_t *handle);

View file

@ -104,6 +104,12 @@ int snd_ctl_rawmidi_info(snd_ctl_t *ctl, snd_rawmidi_info_t * info)
return ctl->ops->rawmidi_info(ctl, info); return ctl->ops->rawmidi_info(ctl, info);
} }
int snd_ctl_rawmidi_prefer_subdevice(snd_ctl_t *ctl, int subdev)
{
assert(ctl);
return ctl->ops->rawmidi_prefer_subdevice(ctl, subdev);
}
int snd_ctl_read1(snd_ctl_t *ctl, snd_ctl_event_t *event) int snd_ctl_read1(snd_ctl_t *ctl, snd_ctl_event_t *event)
{ {
assert(ctl && event); assert(ctl && event);

View file

@ -126,6 +126,14 @@ static int snd_ctl_hw_rawmidi_info(snd_ctl_t *handle, snd_rawmidi_info_t * info)
return 0; return 0;
} }
static int snd_ctl_hw_rawmidi_prefer_subdevice(snd_ctl_t *handle, int subdev)
{
snd_ctl_hw_t *hw = handle->private;
if (ioctl(hw->fd, SND_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE, &subdev) < 0)
return -errno;
return 0;
}
static int snd_ctl_hw_read(snd_ctl_t *handle, snd_ctl_event_t *event) static int snd_ctl_hw_read(snd_ctl_t *handle, snd_ctl_event_t *event)
{ {
snd_ctl_hw_t *hw = handle->private; snd_ctl_hw_t *hw = handle->private;
@ -144,6 +152,7 @@ struct snd_ctl_ops snd_ctl_hw_ops = {
pcm_info: snd_ctl_hw_pcm_info, pcm_info: snd_ctl_hw_pcm_info,
pcm_prefer_subdevice: snd_ctl_hw_pcm_prefer_subdevice, pcm_prefer_subdevice: snd_ctl_hw_pcm_prefer_subdevice,
rawmidi_info: snd_ctl_hw_rawmidi_info, rawmidi_info: snd_ctl_hw_rawmidi_info,
rawmidi_prefer_subdevice: snd_ctl_hw_rawmidi_prefer_subdevice,
read: snd_ctl_hw_read, read: snd_ctl_hw_read,
}; };

View file

@ -35,6 +35,7 @@ struct snd_ctl_ops {
int (*pcm_info)(snd_ctl_t *handle, snd_pcm_info_t * info); int (*pcm_info)(snd_ctl_t *handle, snd_pcm_info_t * info);
int (*pcm_prefer_subdevice)(snd_ctl_t *handle, int subdev); int (*pcm_prefer_subdevice)(snd_ctl_t *handle, int subdev);
int (*rawmidi_info)(snd_ctl_t *handle, snd_rawmidi_info_t * info); int (*rawmidi_info)(snd_ctl_t *handle, snd_rawmidi_info_t * info);
int (*rawmidi_prefer_subdevice)(snd_ctl_t *handle, int subdev);
int (*read)(snd_ctl_t *handle, snd_ctl_event_t *event); int (*read)(snd_ctl_t *handle, snd_ctl_event_t *event);
}; };

View file

@ -239,6 +239,19 @@ static int snd_ctl_shm_rawmidi_info(snd_ctl_t *ctl, snd_rawmidi_info_t * info)
return err; return err;
} }
static int snd_ctl_shm_rawmidi_prefer_subdevice(snd_ctl_t *ctl, int subdev)
{
snd_ctl_shm_t *shm = ctl->private;
snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
int err;
ctrl->u.rawmidi_prefer_subdevice = subdev;
ctrl->cmd = SND_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE;
err = snd_ctl_shm_action(ctl);
if (err < 0)
return err;
return err;
}
static int snd_ctl_shm_read(snd_ctl_t *ctl, snd_ctl_event_t *event) static int snd_ctl_shm_read(snd_ctl_t *ctl, snd_ctl_event_t *event)
{ {
snd_ctl_shm_t *shm = ctl->private; snd_ctl_shm_t *shm = ctl->private;
@ -265,6 +278,7 @@ struct snd_ctl_ops snd_ctl_shm_ops = {
pcm_info: snd_ctl_shm_pcm_info, pcm_info: snd_ctl_shm_pcm_info,
pcm_prefer_subdevice: snd_ctl_shm_pcm_prefer_subdevice, pcm_prefer_subdevice: snd_ctl_shm_pcm_prefer_subdevice,
rawmidi_info: snd_ctl_shm_rawmidi_info, rawmidi_info: snd_ctl_shm_rawmidi_info,
rawmidi_prefer_subdevice: snd_ctl_shm_rawmidi_prefer_subdevice,
read: snd_ctl_shm_read, read: snd_ctl_shm_read,
}; };

View file

@ -579,15 +579,18 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **pcmp, int card, int device, int subdev
default: default:
assert(0); assert(0);
} }
ret = snd_ctl_pcm_prefer_subdevice(ctl, subdevice);
snd_ctl_close(ctl);
if (ret < 0)
return ret;
sprintf(filename, filefmt, card, device); sprintf(filename, filefmt, card, device);
__again: __again:
if (attempt++ > 3) if (attempt++ > 3) {
snd_ctl_close(ctl);
return -EBUSY; return -EBUSY;
}
ret = snd_ctl_pcm_prefer_subdevice(ctl, subdevice);
if (ret < 0) {
snd_ctl_close(ctl);
return ret;
}
fmode = O_RDWR; fmode = O_RDWR;
if (mode & SND_PCM_NONBLOCK) if (mode & SND_PCM_NONBLOCK)
fmode |= O_NONBLOCK; fmode |= O_NONBLOCK;
@ -595,6 +598,7 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **pcmp, int card, int device, int subdev
fmode |= O_ASYNC; fmode |= O_ASYNC;
if ((fd = open(filename, fmode)) < 0) { if ((fd = open(filename, fmode)) < 0) {
SYSERR("open %s failed", filename); SYSERR("open %s failed", filename);
snd_ctl_close(ctl);
return -errno; return -errno;
} }
if (ioctl(fd, SND_PCM_IOCTL_PVERSION, &ver) < 0) { if (ioctl(fd, SND_PCM_IOCTL_PVERSION, &ver) < 0) {
@ -646,11 +650,13 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **pcmp, int card, int device, int subdev
ret = snd_pcm_hw_mmap_status(pcm); ret = snd_pcm_hw_mmap_status(pcm);
if (ret < 0) { if (ret < 0) {
snd_pcm_close(pcm); snd_pcm_close(pcm);
snd_ctl_close(ctl);
return ret; return ret;
} }
ret = snd_pcm_hw_mmap_control(pcm); ret = snd_pcm_hw_mmap_control(pcm);
if (ret < 0) { if (ret < 0) {
snd_pcm_close(pcm); snd_pcm_close(pcm);
snd_ctl_close(ctl);
return ret; return ret;
} }
return 0; return 0;
@ -661,6 +667,7 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **pcmp, int card, int device, int subdev
if (pcm) if (pcm)
free(pcm); free(pcm);
close(fd); close(fd);
snd_ctl_close(ctl);
return ret; return ret;
} }

View file

@ -38,33 +38,69 @@ struct snd_rawmidi {
int mode; int mode;
}; };
int snd_rawmidi_open(snd_rawmidi_t **handle, int card, int device, int mode) int snd_rawmidi_open_subdevice(snd_rawmidi_t **handle, int card, int device, int subdevice, int mode)
{ {
int fd, ver; int fd, ver, ret;
int attempt = 0;
char filename[32]; char filename[32];
snd_ctl_t *ctl;
snd_rawmidi_t *rmidi; snd_rawmidi_t *rmidi;
snd_rawmidi_info_t info;
*handle = NULL; *handle = NULL;
if (card < 0 || card >= SND_CARDS) if (card < 0 || card >= SND_CARDS)
return -EINVAL; return -EINVAL;
if ((ret = snd_ctl_hw_open(&ctl, NULL, card)) < 0)
return ret;
sprintf(filename, SND_FILE_RAWMIDI, card, device); sprintf(filename, SND_FILE_RAWMIDI, card, device);
__again:
if (attempt++ > 3) {
snd_ctl_close(ctl);
return -EBUSY;
}
ret = snd_ctl_rawmidi_prefer_subdevice(ctl, subdevice);
if (ret < 0) {
snd_ctl_close(ctl);
return ret;
}
if ((fd = open(filename, mode)) < 0) { if ((fd = open(filename, mode)) < 0) {
snd_card_load(card); snd_card_load(card);
if ((fd = open(filename, mode)) < 0) if ((fd = open(filename, mode)) < 0) {
snd_ctl_close(ctl);
return -errno; return -errno;
} }
}
if (ioctl(fd, SND_RAWMIDI_IOCTL_PVERSION, &ver) < 0) { if (ioctl(fd, SND_RAWMIDI_IOCTL_PVERSION, &ver) < 0) {
ret = -errno;
close(fd); close(fd);
return -errno; snd_ctl_close(ctl);
return ret;
} }
if (SND_PROTOCOL_INCOMPATIBLE(ver, SND_RAWMIDI_VERSION_MAX)) { if (SND_PROTOCOL_INCOMPATIBLE(ver, SND_RAWMIDI_VERSION_MAX)) {
close(fd); close(fd);
snd_ctl_close(ctl);
return -SND_ERROR_INCOMPATIBLE_VERSION; return -SND_ERROR_INCOMPATIBLE_VERSION;
} }
if (subdevice >= 0) {
memset(&info, 0, sizeof(info));
if (ioctl(fd, SND_RAWMIDI_IOCTL_INFO, &info) < 0) {
ret = -errno;
close(fd);
snd_ctl_close(ctl);
return ret;
}
if (info.subdevice != subdevice) {
close(fd);
goto __again;
}
}
rmidi = (snd_rawmidi_t *) calloc(1, sizeof(snd_rawmidi_t)); rmidi = (snd_rawmidi_t *) calloc(1, sizeof(snd_rawmidi_t));
if (rmidi == NULL) { if (rmidi == NULL) {
close(fd); close(fd);
snd_ctl_close(ctl);
return -ENOMEM; return -ENOMEM;
} }
rmidi->card = card; rmidi->card = card;
@ -75,6 +111,11 @@ int snd_rawmidi_open(snd_rawmidi_t **handle, int card, int device, int mode)
return 0; return 0;
} }
int snd_rawmidi_open(snd_rawmidi_t **handle, int card, int device, int mode)
{
return snd_rawmidi_open_subdevice(handle, card, device, -1, mode);
}
int snd_rawmidi_close(snd_rawmidi_t *rmidi) int snd_rawmidi_close(snd_rawmidi_t *rmidi)
{ {
int res; int res;