mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-10-29 05:40:25 -04:00 
			
		
		
		
	Added snd_timer_async() function.
More updates to pcm_dmix.c .
This commit is contained in:
		
							parent
							
								
									7c5e5f5728
								
							
						
					
					
						commit
						757785fece
					
				
					 5 changed files with 125 additions and 32 deletions
				
			
		|  | @ -48,6 +48,12 @@ | |||
| const char *_snd_module_pcm_dmix = ""; | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  * | ||||
|  */ | ||||
|   | ||||
| int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid); | ||||
| 
 | ||||
| /*
 | ||||
|  * | ||||
|  */ | ||||
|  | @ -432,24 +438,51 @@ static int client_discard(snd_pcm_dmix_t *dmix) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  ring buffer operation | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  *  synchronize shm ring buffer with hardware | ||||
|  */ | ||||
| static void snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm, snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_dmix_t *dmix = pcm->private_data; | ||||
| 	snd_pcm_uframes_t appl_ptr; | ||||
| 	 | ||||
| 	/* get the start of update area */ | ||||
| 	appl_ptr = dmix->appl_ptr - size; | ||||
| 	if (appl_ptr > pcm->boundary) | ||||
| 		appl_ptr += pcm->boundary; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  plugin implementation | ||||
|  */ | ||||
| 
 | ||||
| static int snd_pcm_dmix_nonblock(snd_pcm_t *pcm, int nonblock) | ||||
| static int snd_pcm_dmix_nonblock(snd_pcm_t *pcm, int nonblock ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* value is cached for us in pcm->mode (SND_PCM_NONBLOCK flag) */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_async(snd_pcm_t *pcm, int sig, pid_t pid) | ||||
| { | ||||
| 	snd_pcm_dmix_t *dmix = pcm->private_data; | ||||
| 	return 0; | ||||
| 	return snd_timer_async(dmix->timer, sig, pid); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_info(snd_pcm_t *pcm, snd_pcm_info_t * info) | ||||
| { | ||||
| 	snd_pcm_dmix_t *dmix = pcm->private_data; | ||||
| 	memset(info, 0, sizeof(*info)); | ||||
| 	info->stream = pcm->stream; | ||||
| 	info->card = -1; | ||||
| 	/* FIXME: fill this with something more useful: we know the hardware name */ | ||||
| 	strncpy(info->id, pcm->name, sizeof(info->id)); | ||||
| 	strncpy(info->name, pcm->name, sizeof(info->name)); | ||||
| 	strncpy(info->subname, pcm->name, sizeof(info->subname)); | ||||
| 	info->subdevices_count = 1; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -499,26 +532,25 @@ static int snd_pcm_dmix_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
| 
 | ||||
| static int snd_pcm_dmix_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | ||||
| { | ||||
| 	snd_pcm_dmix_t *dmix = pcm->private_data; | ||||
| 	// snd_pcm_dmix_t *dmix = pcm->private_data;
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_hw_free(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_dmix_t *dmix = pcm->private_data; | ||||
| 	// snd_pcm_dmix_t *dmix = pcm->private_data;
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) | ||||
| { | ||||
| 	snd_pcm_dmix_t *dmix = pcm->private_data; | ||||
| 	// snd_pcm_dmix_t *dmix = pcm->private_data;
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info) | ||||
| { | ||||
| 	snd_pcm_dmix_t *dmix = pcm->private_data; | ||||
| 	return 0; | ||||
|         return snd_pcm_channel_info_shm(pcm, info, -1); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status) | ||||
|  | @ -595,33 +627,35 @@ static int snd_pcm_dmix_resume(snd_pcm_t *pcm) | |||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_dmix_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) | ||||
| { | ||||
| 	return -ENODEV; | ||||
| 	int res = snd_pcm_mmap_writei(pcm, buffer, size); | ||||
| 	snd_pcm_dmix_sync_ptr(pcm, size); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_dmix_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) | ||||
| { | ||||
| 	return -ENODEV; | ||||
| 	int res = snd_pcm_mmap_writen(pcm, bufs, size); | ||||
| 	snd_pcm_dmix_sync_ptr(pcm, size); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_dmix_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size) | ||||
| static snd_pcm_sframes_t snd_pcm_dmix_readi(snd_pcm_t *pcm ATTRIBUTE_UNUSED, void *buffer ATTRIBUTE_UNUSED, snd_pcm_uframes_t size ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return -ENODEV; | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_dmix_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) | ||||
| static snd_pcm_sframes_t snd_pcm_dmix_readn(snd_pcm_t *pcm ATTRIBUTE_UNUSED, void **bufs ATTRIBUTE_UNUSED, snd_pcm_uframes_t size ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return -ENODEV; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_mmap(snd_pcm_t *pcm) | ||||
| static int snd_pcm_dmix_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	snd_pcm_dmix_t *dmix = pcm->private_data; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_munmap(snd_pcm_t *pcm) | ||||
| static int snd_pcm_dmix_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	snd_pcm_dmix_t *dmix = pcm->private_data; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -651,13 +685,14 @@ static snd_pcm_sframes_t snd_pcm_dmix_mmap_commit(snd_pcm_t *pcm, | |||
| 						  snd_pcm_uframes_t offset ATTRIBUTE_UNUSED, | ||||
| 						  snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_dmix_t *hw = pcm->private_data; | ||||
| 	return 0; | ||||
| 	snd_pcm_mmap_appl_forward(pcm, size); | ||||
| 	snd_pcm_dmix_sync_ptr(pcm, size); | ||||
| 	return size; | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm) | ||||
| static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	snd_pcm_dmix_t *hw = pcm->private_data; | ||||
| 	//snd_pcm_dmix_t *dmix = pcm->private_data;
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -65,7 +65,7 @@ static int snd_pcm_null_async(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int sig ATTRIBUTE | |||
| 	return -ENOSYS; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_null_info(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_info_t * info) | ||||
| static int snd_pcm_null_info(snd_pcm_t *pcm, snd_pcm_info_t * info) | ||||
| { | ||||
| 	memset(info, 0, sizeof(*info)); | ||||
| 	info->stream = pcm->stream; | ||||
|  | @ -79,7 +79,6 @@ static int snd_pcm_null_info(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_info_t * i | |||
| 
 | ||||
| static int snd_pcm_null_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info) | ||||
| { | ||||
| 	snd_pcm_null_t *null = pcm->private_data; | ||||
| 	return snd_pcm_channel_info_shm(pcm, info, -1); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -73,6 +73,7 @@ This example shows opening a timer device and reading of timer events. | |||
| #include <string.h> | ||||
| #include <fcntl.h> | ||||
| #include <dlfcn.h> | ||||
| #include <signal.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include "timer_local.h" | ||||
| 
 | ||||
|  | @ -350,6 +351,27 @@ int snd_timer_nonblock(snd_timer_t *timer, int nonblock) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #ifndef DOC_HIDDEN | ||||
| /**
 | ||||
|  * \brief set async mode | ||||
|  * \param timer timer handle | ||||
|  * \param sig Signal to raise: < 0 disable, 0 default (SIGIO) | ||||
|  * \param pid Process ID to signal: 0 current | ||||
|  * \return 0 on success otherwise a negative error code | ||||
|  * | ||||
|  * A signal is raised every period. | ||||
|  */ | ||||
| int snd_timer(snd_timer_t *timer, int sig, pid_t pid) | ||||
| { | ||||
| 	assert(timer); | ||||
|         if (sig == 0) | ||||
|                 sig = SIGIO; | ||||
| 	if (pid == 0) | ||||
| 		pid = getpid(); | ||||
| 	return timer->ops->async(timer, sig, pid); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief get size of the snd_timer_info_t structure in bytes | ||||
|  * \return size of the snd_timer_info_t structure in bytes | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ | |||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <string.h> | ||||
| #define __USE_GNU | ||||
| #include <fcntl.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include "timer_local.h" | ||||
|  | @ -61,6 +62,38 @@ static int snd_timer_hw_nonblock(snd_timer_t *timer, int nonblock) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_timer_hw_async(snd_timer_t *timer, int sig, pid_t pid) | ||||
| { | ||||
| 	long flags; | ||||
| 	int fd; | ||||
| 
 | ||||
| 	assert(timer); | ||||
| 	fd = timer->poll_fd; | ||||
| 	if ((flags = fcntl(fd, F_GETFL)) < 0) { | ||||
| 		SYSERR("F_GETFL failed"); | ||||
| 		return -errno; | ||||
| 	} | ||||
| 	if (sig >= 0) | ||||
| 		flags |= O_ASYNC; | ||||
| 	else | ||||
| 		flags &= ~O_ASYNC; | ||||
| 	if (fcntl(fd, F_SETFL, flags) < 0) { | ||||
| 		SYSERR("F_SETFL for O_ASYNC failed"); | ||||
| 		return -errno; | ||||
| 	} | ||||
| 	if (sig < 0) | ||||
| 		return 0; | ||||
| 	if (fcntl(fd, F_SETSIG, (long)sig) < 0) { | ||||
| 		SYSERR("F_SETSIG failed"); | ||||
| 		return -errno; | ||||
| 	} | ||||
| 	if (fcntl(fd, F_SETOWN, (long)pid) < 0) { | ||||
| 		SYSERR("F_SETOWN failed"); | ||||
| 		return -errno; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_timer_hw_info(snd_timer_t *handle, snd_timer_info_t * info) | ||||
| { | ||||
| 	snd_timer_t *tmr; | ||||
|  | @ -148,15 +181,16 @@ static ssize_t snd_timer_hw_read(snd_timer_t *handle, void *buffer, size_t size) | |||
| } | ||||
| 
 | ||||
| static snd_timer_ops_t snd_timer_hw_ops = { | ||||
| 	close: snd_timer_hw_close, | ||||
| 	nonblock: snd_timer_hw_nonblock, | ||||
| 	info: snd_timer_hw_info, | ||||
| 	params: snd_timer_hw_params, | ||||
| 	status: snd_timer_hw_status, | ||||
| 	rt_start: snd_timer_hw_start, | ||||
| 	rt_stop: snd_timer_hw_stop, | ||||
| 	rt_continue: snd_timer_hw_continue, | ||||
| 	read: snd_timer_hw_read, | ||||
| 	.close = snd_timer_hw_close, | ||||
| 	.nonblock = snd_timer_hw_nonblock, | ||||
| 	.async = snd_timer_hw_async, | ||||
| 	.info = snd_timer_hw_info, | ||||
| 	.params = snd_timer_hw_params, | ||||
| 	.status = snd_timer_hw_status, | ||||
| 	.rt_start = snd_timer_hw_start, | ||||
| 	.rt_stop = snd_timer_hw_stop, | ||||
| 	.rt_continue = snd_timer_hw_continue, | ||||
| 	.read = snd_timer_hw_read, | ||||
| }; | ||||
| 
 | ||||
| int snd_timer_hw_open(snd_timer_t **handle, const char *name, int dev_class, int dev_sclass, int card, int device, int subdevice, int mode) | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ | |||
| typedef struct { | ||||
| 	int (*close)(snd_timer_t *timer); | ||||
| 	int (*nonblock)(snd_timer_t *timer, int nonblock); | ||||
| 	int (*async)(snd_timer_t *timer, int sig, pid_t pid); | ||||
| 	int (*info)(snd_timer_t *timer, snd_timer_info_t *info); | ||||
| 	int (*params)(snd_timer_t *timer, snd_timer_params_t *params); | ||||
| 	int (*status)(snd_timer_t *timer, snd_timer_status_t *status); | ||||
|  | @ -62,3 +63,5 @@ struct _snd_timer_query { | |||
| }; | ||||
| 
 | ||||
| int snd_timer_query_hw_open(snd_timer_query_t **handle, const char *name, int mode); | ||||
| 
 | ||||
| int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jaroslav Kysela
						Jaroslav Kysela