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: | ||||
| 		ctrl->result = snd_ctl_rawmidi_info(ctl, &ctrl->u.rawmidi_info); | ||||
| 		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: | ||||
| 		ctrl->result = snd_ctl_read1(ctl, &ctrl->u.read); | ||||
| 		break; | ||||
|  |  | |||
|  | @ -92,6 +92,7 @@ typedef struct { | |||
| 		snd_pcm_info_t pcm_info; | ||||
| 		int pcm_prefer_subdevice; | ||||
| 		snd_rawmidi_info_t rawmidi_info; | ||||
| 		int rawmidi_prefer_subdevice; | ||||
| 		snd_ctl_event_t read; | ||||
| 	} u; | ||||
| 	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_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_prefer_subdevice(snd_ctl_t *handle, int subdev); | ||||
| 
 | ||||
| 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; | ||||
| 
 | ||||
| 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_close(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); | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
| 	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; | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
| 	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_prefer_subdevice: snd_ctl_hw_pcm_prefer_subdevice, | ||||
| 	rawmidi_info: snd_ctl_hw_rawmidi_info, | ||||
| 	rawmidi_prefer_subdevice: snd_ctl_hw_rawmidi_prefer_subdevice, | ||||
| 	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_prefer_subdevice)(snd_ctl_t *handle, int subdev); | ||||
| 	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); | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -239,6 +239,19 @@ static int snd_ctl_shm_rawmidi_info(snd_ctl_t *ctl, snd_rawmidi_info_t * info) | |||
| 	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) | ||||
| { | ||||
| 	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_prefer_subdevice: snd_ctl_shm_pcm_prefer_subdevice, | ||||
| 	rawmidi_info: snd_ctl_shm_rawmidi_info, | ||||
| 	rawmidi_prefer_subdevice: snd_ctl_shm_rawmidi_prefer_subdevice, | ||||
| 	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: | ||||
| 		assert(0); | ||||
| 	} | ||||
| 	ret = snd_ctl_pcm_prefer_subdevice(ctl, subdevice); | ||||
| 	snd_ctl_close(ctl); | ||||
| 	if (ret < 0) | ||||
| 		return ret; | ||||
| 	sprintf(filename, filefmt, card, device); | ||||
| 
 | ||||
|       __again: | ||||
|       	if (attempt++ > 3) | ||||
|       	if (attempt++ > 3) { | ||||
| 		snd_ctl_close(ctl); | ||||
| 		return -EBUSY; | ||||
| 	} | ||||
| 	ret = snd_ctl_pcm_prefer_subdevice(ctl, subdevice); | ||||
| 	if (ret < 0) { | ||||
| 		snd_ctl_close(ctl); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	fmode = O_RDWR; | ||||
| 	if (mode & SND_PCM_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; | ||||
| 	if ((fd = open(filename, fmode)) < 0) { | ||||
| 		SYSERR("open %s failed", filename); | ||||
| 		snd_ctl_close(ctl); | ||||
| 		return -errno; | ||||
| 	} | ||||
| 	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); | ||||
| 	if (ret < 0) { | ||||
| 		snd_pcm_close(pcm); | ||||
| 		snd_ctl_close(ctl); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	ret = snd_pcm_hw_mmap_control(pcm); | ||||
| 	if (ret < 0) { | ||||
| 		snd_pcm_close(pcm); | ||||
| 		snd_ctl_close(ctl); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	return 0; | ||||
|  | @ -661,6 +667,7 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **pcmp, int card, int device, int subdev | |||
| 	if (pcm) | ||||
| 		free(pcm); | ||||
| 	close(fd); | ||||
| 	snd_ctl_close(ctl); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -38,33 +38,69 @@ struct snd_rawmidi { | |||
| 	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]; | ||||
| 	snd_ctl_t *ctl; | ||||
| 	snd_rawmidi_t *rmidi; | ||||
| 	snd_rawmidi_info_t info; | ||||
| 
 | ||||
| 	*handle = NULL; | ||||
| 	 | ||||
| 	if (card < 0 || card >= SND_CARDS) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	if ((ret = snd_ctl_hw_open(&ctl, NULL, card)) < 0) | ||||
| 		return ret; | ||||
| 	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) { | ||||
| 		snd_card_load(card); | ||||
| 		if ((fd = open(filename, mode)) < 0) | ||||
| 		if ((fd = open(filename, mode)) < 0) { | ||||
| 			snd_ctl_close(ctl); | ||||
| 			return -errno; | ||||
| 		} | ||||
| 	} | ||||
| 	if (ioctl(fd, SND_RAWMIDI_IOCTL_PVERSION, &ver) < 0) { | ||||
| 		ret = -errno; | ||||
| 		close(fd); | ||||
| 		return -errno; | ||||
| 		snd_ctl_close(ctl); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	if (SND_PROTOCOL_INCOMPATIBLE(ver, SND_RAWMIDI_VERSION_MAX)) { | ||||
| 		close(fd); | ||||
| 		snd_ctl_close(ctl); | ||||
| 		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)); | ||||
| 	if (rmidi == NULL) { | ||||
| 		close(fd); | ||||
| 		snd_ctl_close(ctl); | ||||
| 		return -ENOMEM; | ||||
| 	} | ||||
| 	rmidi->card = card; | ||||
|  | @ -75,6 +111,11 @@ int snd_rawmidi_open(snd_rawmidi_t **handle, int card, int device, int mode) | |||
| 	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 res; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jaroslav Kysela
						Jaroslav Kysela