mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	Improved mmap emulation over write/read
This commit is contained in:
		
							parent
							
								
									437c96ef5f
								
							
						
					
					
						commit
						484c05ec36
					
				
					 1 changed files with 44 additions and 11 deletions
				
			
		| 
						 | 
					@ -45,6 +45,8 @@ typedef struct {
 | 
				
			||||||
	int card, device, subdevice;
 | 
						int card, device, subdevice;
 | 
				
			||||||
	volatile struct sndrv_pcm_mmap_status *mmap_status;
 | 
						volatile struct sndrv_pcm_mmap_status *mmap_status;
 | 
				
			||||||
	struct sndrv_pcm_mmap_control *mmap_control;
 | 
						struct sndrv_pcm_mmap_control *mmap_control;
 | 
				
			||||||
 | 
						int shadow_appl_ptr: 1, avail_update_flag: 1;
 | 
				
			||||||
 | 
						snd_pcm_uframes_t appl_ptr;
 | 
				
			||||||
	int shmid;
 | 
						int shmid;
 | 
				
			||||||
} snd_pcm_hw_t;
 | 
					} snd_pcm_hw_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,6 +54,11 @@ typedef struct {
 | 
				
			||||||
#define SNDRV_FILE_PCM_STREAM_CAPTURE		"/dev/snd/pcmC%iD%ic"
 | 
					#define SNDRV_FILE_PCM_STREAM_CAPTURE		"/dev/snd/pcmC%iD%ic"
 | 
				
			||||||
#define SNDRV_PCM_VERSION_MAX			SNDRV_PROTOCOL_VERSION(2, 0, 0)
 | 
					#define SNDRV_PCM_VERSION_MAX			SNDRV_PROTOCOL_VERSION(2, 0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* update appl_ptr with driver */
 | 
				
			||||||
 | 
					#define UPDATE_SHADOW_PTR(hw) \
 | 
				
			||||||
 | 
						do { if (hw->shadow_appl_ptr && !hw->avail_update_flag) \
 | 
				
			||||||
 | 
						       hw->appl_ptr = hw->mmap_control->appl_ptr; } while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int snd_pcm_hw_nonblock(snd_pcm_t *pcm, int nonblock)
 | 
					static int snd_pcm_hw_nonblock(snd_pcm_t *pcm, int nonblock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	long flags;
 | 
						long flags;
 | 
				
			||||||
| 
						 | 
					@ -134,6 +141,16 @@ static int snd_pcm_hw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
 | 
				
			||||||
		SYSERR("SNDRV_PCM_IOCTL_HW_PARAMS failed");
 | 
							SYSERR("SNDRV_PCM_IOCTL_HW_PARAMS failed");
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
 | 
				
			||||||
 | 
							if (!(params->info & SNDRV_PCM_INFO_MMAP)) {
 | 
				
			||||||
 | 
								hw->shadow_appl_ptr = 1;
 | 
				
			||||||
 | 
								hw->appl_ptr = 0;
 | 
				
			||||||
 | 
								pcm->appl_ptr = &hw->appl_ptr;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								hw->shadow_appl_ptr = 0;
 | 
				
			||||||
 | 
								pcm->appl_ptr = &hw->mmap_control->appl_ptr;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -358,6 +375,7 @@ static snd_pcm_sframes_t snd_pcm_hw_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_
 | 
				
			||||||
	result = ioctl(fd, SNDRV_PCM_IOCTL_READI_FRAMES, &xferi);
 | 
						result = ioctl(fd, SNDRV_PCM_IOCTL_READI_FRAMES, &xferi);
 | 
				
			||||||
	if (result < 0)
 | 
						if (result < 0)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
 | 
						UPDATE_SHADOW_PTR(hw);
 | 
				
			||||||
	return xferi.result;
 | 
						return xferi.result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -372,6 +390,7 @@ static snd_pcm_sframes_t snd_pcm_hw_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_u
 | 
				
			||||||
	result = ioctl(fd, SNDRV_PCM_IOCTL_READN_FRAMES, &xfern);
 | 
						result = ioctl(fd, SNDRV_PCM_IOCTL_READN_FRAMES, &xfern);
 | 
				
			||||||
	if (result < 0)
 | 
						if (result < 0)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
 | 
						UPDATE_SHADOW_PTR(hw);
 | 
				
			||||||
	return xfern.result;
 | 
						return xfern.result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -467,28 +486,42 @@ static int snd_pcm_hw_close(snd_pcm_t *pcm)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm,
 | 
					static int snd_pcm_hw_mmap_commit(snd_pcm_t *pcm,
 | 
				
			||||||
				  snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
 | 
									  snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
 | 
				
			||||||
				  snd_pcm_uframes_t size)
 | 
									  snd_pcm_uframes_t size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!(pcm->info & SND_PCM_INFO_MMAP) && 
 | 
						if (!(pcm->info & SND_PCM_INFO_MMAP)) {
 | 
				
			||||||
	    pcm->stream == SND_PCM_STREAM_PLAYBACK)
 | 
							if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
 | 
				
			||||||
		return snd_pcm_write_mmap(pcm, size);
 | 
							    	snd_pcm_sframes_t res;
 | 
				
			||||||
 | 
							    	do {
 | 
				
			||||||
 | 
									res = snd_pcm_write_mmap(pcm, size);
 | 
				
			||||||
 | 
									if (res < 0)
 | 
				
			||||||
 | 
										return res;
 | 
				
			||||||
 | 
									size -= res;
 | 
				
			||||||
 | 
								} while (size > 0);
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								snd_pcm_hw_t *hw = pcm->private_data;
 | 
				
			||||||
 | 
								assert(hw->shadow_appl_ptr);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	snd_pcm_mmap_appl_forward(pcm, size);
 | 
						snd_pcm_mmap_appl_forward(pcm, size);
 | 
				
			||||||
	return size;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm)
 | 
					static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	snd_pcm_uframes_t avail;
 | 
						snd_pcm_uframes_t avail;
 | 
				
			||||||
	snd_pcm_sframes_t err;
 | 
					 | 
				
			||||||
	if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
 | 
						if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
 | 
				
			||||||
		avail = snd_pcm_mmap_playback_avail(pcm);
 | 
							avail = snd_pcm_mmap_playback_avail(pcm);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		avail = snd_pcm_mmap_capture_avail(pcm);
 | 
							avail = snd_pcm_mmap_capture_avail(pcm);
 | 
				
			||||||
		if (avail > 0 && 
 | 
							if (avail > 0 && !(pcm->info & SND_PCM_INFO_MMAP)) {
 | 
				
			||||||
		    !(pcm->info & SND_PCM_INFO_MMAP)) {
 | 
								snd_pcm_sframes_t err;
 | 
				
			||||||
 | 
								snd_pcm_hw_t *hw = pcm->private_data;
 | 
				
			||||||
 | 
								hw->avail_update_flag = 1;
 | 
				
			||||||
			err = snd_pcm_read_mmap(pcm, avail);
 | 
								err = snd_pcm_read_mmap(pcm, avail);
 | 
				
			||||||
 | 
								hw->avail_update_flag = 0;
 | 
				
			||||||
			if (err < 0)
 | 
								if (err < 0)
 | 
				
			||||||
				return err;
 | 
									return err;
 | 
				
			||||||
			assert((snd_pcm_uframes_t)err == avail);
 | 
								assert((snd_pcm_uframes_t)err == avail);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue