mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-10-29 05:40:25 -04:00 
			
		
		
		
	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:
		
							parent
							
								
									8a625fd63b
								
							
						
					
					
						commit
						0e561770c6
					
				
					 10 changed files with 93 additions and 9 deletions
				
			
		|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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]; | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
|  | @ -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, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jaroslav Kysela
						Jaroslav Kysela