mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-10-29 05:40:25 -04:00 
			
		
		
		
	improved stream linking and plugin code cleanups
- added link/unlink/link_fd fast_ops callbacks - moved code from snd_pcm_link to pcm_hw.c - moved "empty" routines pointing to slave to pcm_generic.c - introduced snd_pcm_generic_t
This commit is contained in:
		
							parent
							
								
									9501520606
								
							
						
					
					
						commit
						836987aa99
					
				
					 25 changed files with 767 additions and 957 deletions
				
			
		|  | @ -5,7 +5,7 @@ EXTRA_LTLIBRARIES = libpcm.la | |||
| 
 | ||||
| libpcm_la_SOURCES = atomic.c mask.c interval.c \ | ||||
| 		    pcm.c pcm_params.c pcm_simple.c \ | ||||
| 		    pcm_hw.c pcm_plugin.c pcm_copy.c pcm_linear.c \ | ||||
| 		    pcm_hw.c pcm_generic.c pcm_plugin.c pcm_copy.c pcm_linear.c \ | ||||
| 		    pcm_route.c pcm_mulaw.c pcm_alaw.c pcm_adpcm.c \ | ||||
| 		    pcm_rate.c pcm_plug.c pcm_misc.c pcm_mmap.c pcm_multi.c \ | ||||
| 	            pcm_shm.c pcm_file.c pcm_null.c pcm_share.c \ | ||||
|  |  | |||
|  | @ -1239,15 +1239,11 @@ snd_pcm_sframes_t snd_pcm_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t s | |||
|  */  | ||||
| int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2) | ||||
| { | ||||
| 	int fd1 = _snd_pcm_link_descriptor(pcm1); | ||||
| 	int fd2 = _snd_pcm_link_descriptor(pcm2); | ||||
| 	if (fd1 < 0 || fd2 < 0) | ||||
| 	assert(pcm1); | ||||
| 	assert(pcm2); | ||||
| 	if (pcm1->fast_ops->link) | ||||
| 		return pcm1->fast_ops->link(pcm1, pcm2); | ||||
| 	return -ENOSYS; | ||||
| 	if (ioctl(fd1, SNDRV_PCM_IOCTL_LINK, fd2) < 0) { | ||||
| 		SYSMSG("SNDRV_PCM_IOCTL_LINK failed"); | ||||
| 		return -errno; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -1257,13 +1253,10 @@ int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2) | |||
|  */ | ||||
| int snd_pcm_unlink(snd_pcm_t *pcm) | ||||
| { | ||||
| 	int fd; | ||||
| 	fd = _snd_pcm_link_descriptor(pcm); | ||||
| 	if (ioctl(fd, SNDRV_PCM_IOCTL_UNLINK) < 0) { | ||||
| 		SYSMSG("SNDRV_PCM_IOCTL_UNLINK failed"); | ||||
| 		return -errno; | ||||
| 	} | ||||
| 	return 0; | ||||
| 	assert(pcm); | ||||
| 	if (pcm->fast_ops->unlink) | ||||
| 		return pcm->fast_ops->unlink(pcm); | ||||
| 	return -ENOSYS; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -6147,6 +6140,14 @@ snd_pcm_sframes_t snd_pcm_mmap_commit(snd_pcm_t *pcm, | |||
| 
 | ||||
| #ifndef DOC_HIDDEN | ||||
| 
 | ||||
| int _snd_pcm_link_descriptor(snd_pcm_t *pcm) | ||||
| { | ||||
| 	assert(pcm); | ||||
| 	if (pcm->fast_ops->link_fd) | ||||
| 		return pcm->fast_ops->link_fd(pcm); | ||||
| 	return -ENOSYS; | ||||
| } | ||||
| 
 | ||||
| int _snd_pcm_poll_descriptor(snd_pcm_t *pcm) | ||||
| { | ||||
| 	assert(pcm); | ||||
|  |  | |||
|  | @ -401,7 +401,7 @@ static int snd_pcm_adpcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
| 				       snd_pcm_adpcm_hw_refine_cchange, | ||||
| 				       snd_pcm_adpcm_hw_refine_sprepare, | ||||
| 				       snd_pcm_adpcm_hw_refine_schange, | ||||
| 				       snd_pcm_plugin_hw_refine_slave); | ||||
| 				       snd_pcm_generic_hw_refine); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_adpcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | ||||
|  | @ -412,7 +412,7 @@ static int snd_pcm_adpcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | |||
| 					  snd_pcm_adpcm_hw_refine_cchange, | ||||
| 					  snd_pcm_adpcm_hw_refine_sprepare, | ||||
| 					  snd_pcm_adpcm_hw_refine_schange, | ||||
| 					  snd_pcm_plugin_hw_params_slave); | ||||
| 					  snd_pcm_generic_hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 
 | ||||
|  | @ -438,7 +438,7 @@ static int snd_pcm_adpcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | |||
| 		} | ||||
| 	} | ||||
| 	assert(!adpcm->states); | ||||
| 	adpcm->states = malloc(adpcm->plug.slave->channels * sizeof(*adpcm->states)); | ||||
| 	adpcm->states = malloc(adpcm->plug.gen.slave->channels * sizeof(*adpcm->states)); | ||||
| 	if (adpcm->states == NULL) | ||||
| 		return -ENOMEM; | ||||
| 	return 0; | ||||
|  | @ -451,7 +451,7 @@ static int snd_pcm_adpcm_hw_free(snd_pcm_t *pcm) | |||
| 		free(adpcm->states); | ||||
| 		adpcm->states = 0; | ||||
| 	} | ||||
| 	return snd_pcm_hw_free(adpcm->plug.slave); | ||||
| 	return snd_pcm_hw_free(adpcm->plug.gen.slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_adpcm_init(snd_pcm_t *pcm) | ||||
|  | @ -515,23 +515,23 @@ static void snd_pcm_adpcm_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 		snd_pcm_dump_setup(pcm, out); | ||||
| 	} | ||||
| 	snd_output_printf(out, "Slave: "); | ||||
| 	snd_pcm_dump(adpcm->plug.slave, out); | ||||
| 	snd_pcm_dump(adpcm->plug.gen.slave, out); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_adpcm_ops = { | ||||
| 	.close = snd_pcm_plugin_close, | ||||
| 	.info = snd_pcm_plugin_info, | ||||
| 	.close = snd_pcm_generic_close, | ||||
| 	.info = snd_pcm_generic_info, | ||||
| 	.hw_refine = snd_pcm_adpcm_hw_refine, | ||||
| 	.hw_params = snd_pcm_adpcm_hw_params, | ||||
| 	.hw_free = snd_pcm_adpcm_hw_free, | ||||
| 	.sw_params = snd_pcm_plugin_sw_params, | ||||
| 	.channel_info = snd_pcm_plugin_channel_info, | ||||
| 	.sw_params = snd_pcm_generic_sw_params, | ||||
| 	.channel_info = snd_pcm_generic_channel_info, | ||||
| 	.dump = snd_pcm_adpcm_dump, | ||||
| 	.nonblock = snd_pcm_plugin_nonblock, | ||||
| 	.async = snd_pcm_plugin_async, | ||||
| 	.poll_revents = snd_pcm_plugin_poll_revents, | ||||
| 	.mmap = snd_pcm_plugin_mmap, | ||||
| 	.munmap = snd_pcm_plugin_munmap, | ||||
| 	.nonblock = snd_pcm_generic_nonblock, | ||||
| 	.async = snd_pcm_generic_async, | ||||
| 	.poll_revents = snd_pcm_generic_poll_revents, | ||||
| 	.mmap = snd_pcm_generic_mmap, | ||||
| 	.munmap = snd_pcm_generic_munmap, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -564,8 +564,8 @@ int snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfor | |||
| 	adpcm->plug.read = snd_pcm_adpcm_read_areas; | ||||
| 	adpcm->plug.write = snd_pcm_adpcm_write_areas; | ||||
| 	adpcm->plug.init = snd_pcm_adpcm_init; | ||||
| 	adpcm->plug.slave = slave; | ||||
| 	adpcm->plug.close_slave = close_slave; | ||||
| 	adpcm->plug.gen.slave = slave; | ||||
| 	adpcm->plug.gen.close_slave = close_slave; | ||||
| 
 | ||||
| 	err = snd_pcm_new(&pcm, SND_PCM_TYPE_ADPCM, name, slave->stream, slave->mode); | ||||
| 	if (err < 0) { | ||||
|  |  | |||
|  | @ -297,7 +297,7 @@ static int snd_pcm_alaw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
| 				       snd_pcm_alaw_hw_refine_cchange, | ||||
| 				       snd_pcm_alaw_hw_refine_sprepare, | ||||
| 				       snd_pcm_alaw_hw_refine_schange, | ||||
| 				       snd_pcm_plugin_hw_refine_slave); | ||||
| 				       snd_pcm_generic_hw_refine); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_alaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | ||||
|  | @ -308,7 +308,7 @@ static int snd_pcm_alaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | |||
| 					  snd_pcm_alaw_hw_refine_cchange, | ||||
| 					  snd_pcm_alaw_hw_refine_sprepare, | ||||
| 					  snd_pcm_alaw_hw_refine_schange, | ||||
| 					  snd_pcm_plugin_hw_params_slave); | ||||
| 					  snd_pcm_generic_hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 
 | ||||
|  | @ -386,23 +386,23 @@ static void snd_pcm_alaw_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 		snd_pcm_dump_setup(pcm, out); | ||||
| 	} | ||||
| 	snd_output_printf(out, "Slave: "); | ||||
| 	snd_pcm_dump(alaw->plug.slave, out); | ||||
| 	snd_pcm_dump(alaw->plug.gen.slave, out); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_alaw_ops = { | ||||
| 	.close = snd_pcm_plugin_close, | ||||
| 	.info = snd_pcm_plugin_info, | ||||
| 	.close = snd_pcm_generic_close, | ||||
| 	.info = snd_pcm_generic_info, | ||||
| 	.hw_refine = snd_pcm_alaw_hw_refine, | ||||
| 	.hw_params = snd_pcm_alaw_hw_params, | ||||
| 	.hw_free = snd_pcm_plugin_hw_free, | ||||
| 	.sw_params = snd_pcm_plugin_sw_params, | ||||
| 	.channel_info = snd_pcm_plugin_channel_info, | ||||
| 	.hw_free = snd_pcm_generic_hw_free, | ||||
| 	.sw_params = snd_pcm_generic_sw_params, | ||||
| 	.channel_info = snd_pcm_generic_channel_info, | ||||
| 	.dump = snd_pcm_alaw_dump, | ||||
| 	.nonblock = snd_pcm_plugin_nonblock, | ||||
| 	.async = snd_pcm_plugin_async, | ||||
| 	.poll_revents = snd_pcm_plugin_poll_revents, | ||||
| 	.mmap = snd_pcm_plugin_mmap, | ||||
| 	.munmap = snd_pcm_plugin_munmap, | ||||
| 	.nonblock = snd_pcm_generic_nonblock, | ||||
| 	.async = snd_pcm_generic_async, | ||||
| 	.poll_revents = snd_pcm_generic_poll_revents, | ||||
| 	.mmap = snd_pcm_generic_mmap, | ||||
| 	.munmap = snd_pcm_generic_munmap, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -436,8 +436,8 @@ int snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sform | |||
| 	alaw->plug.write = snd_pcm_alaw_write_areas; | ||||
| 	alaw->plug.undo_read = snd_pcm_plugin_undo_read_generic; | ||||
| 	alaw->plug.undo_write = snd_pcm_plugin_undo_write_generic; | ||||
| 	alaw->plug.slave = slave; | ||||
| 	alaw->plug.close_slave = close_slave; | ||||
| 	alaw->plug.gen.slave = slave; | ||||
| 	alaw->plug.gen.close_slave = close_slave; | ||||
| 
 | ||||
| 	err = snd_pcm_new(&pcm, SND_PCM_TYPE_ALAW, name, slave->stream, slave->mode); | ||||
| 	if (err < 0) { | ||||
|  |  | |||
|  | @ -92,7 +92,7 @@ static int snd_pcm_copy_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
| 				       snd_pcm_copy_hw_refine_cchange, | ||||
| 				       snd_pcm_copy_hw_refine_sprepare, | ||||
| 				       snd_pcm_copy_hw_refine_schange, | ||||
| 				       snd_pcm_plugin_hw_refine_slave); | ||||
| 				       snd_pcm_generic_hw_refine); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_copy_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
|  | @ -101,7 +101,7 @@ static int snd_pcm_copy_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
| 				       snd_pcm_copy_hw_refine_cchange, | ||||
| 				       snd_pcm_copy_hw_refine_sprepare, | ||||
| 				       snd_pcm_copy_hw_refine_schange, | ||||
| 				       snd_pcm_plugin_hw_params_slave); | ||||
| 				       snd_pcm_generic_hw_params); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_uframes_t | ||||
|  | @ -149,23 +149,23 @@ static void snd_pcm_copy_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 		snd_pcm_dump_setup(pcm, out); | ||||
| 	} | ||||
| 	snd_output_printf(out, "Slave: "); | ||||
| 	snd_pcm_dump(copy->plug.slave, out); | ||||
| 	snd_pcm_dump(copy->plug.gen.slave, out); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_copy_ops = { | ||||
| 	.close = snd_pcm_plugin_close, | ||||
| 	.info = snd_pcm_plugin_info, | ||||
| 	.close = snd_pcm_generic_close, | ||||
| 	.info = snd_pcm_generic_info, | ||||
| 	.hw_refine = snd_pcm_copy_hw_refine, | ||||
| 	.hw_params = snd_pcm_copy_hw_params, | ||||
| 	.hw_free = snd_pcm_plugin_hw_free, | ||||
| 	.sw_params = snd_pcm_plugin_sw_params, | ||||
| 	.channel_info = snd_pcm_plugin_channel_info, | ||||
| 	.hw_free = snd_pcm_generic_hw_free, | ||||
| 	.sw_params = snd_pcm_generic_sw_params, | ||||
| 	.channel_info = snd_pcm_generic_channel_info, | ||||
| 	.dump = snd_pcm_copy_dump, | ||||
| 	.nonblock = snd_pcm_plugin_nonblock, | ||||
| 	.async = snd_pcm_plugin_async, | ||||
| 	.poll_revents = snd_pcm_plugin_poll_revents, | ||||
| 	.mmap = snd_pcm_plugin_mmap, | ||||
| 	.munmap = snd_pcm_plugin_munmap, | ||||
| 	.nonblock = snd_pcm_generic_nonblock, | ||||
| 	.async = snd_pcm_generic_async, | ||||
| 	.poll_revents = snd_pcm_generic_poll_revents, | ||||
| 	.mmap = snd_pcm_generic_mmap, | ||||
| 	.munmap = snd_pcm_generic_munmap, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -194,8 +194,8 @@ int snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int | |||
| 	copy->plug.write = snd_pcm_copy_write_areas; | ||||
| 	copy->plug.undo_read = snd_pcm_plugin_undo_read_generic; | ||||
| 	copy->plug.undo_write = snd_pcm_plugin_undo_write_generic; | ||||
| 	copy->plug.slave = slave; | ||||
| 	copy->plug.close_slave = close_slave; | ||||
| 	copy->plug.gen.slave = slave; | ||||
| 	copy->plug.gen.close_slave = close_slave; | ||||
| 
 | ||||
| 	err = snd_pcm_new(&pcm, SND_PCM_TYPE_COPY, name, slave->stream, slave->mode); | ||||
| 	if (err < 0) { | ||||
|  |  | |||
|  | @ -767,6 +767,9 @@ static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = { | |||
| 	.forward = snd_pcm_dmix_forward, | ||||
| 	.resume = snd_pcm_dmix_resume, | ||||
| 	.poll_ask = NULL, | ||||
| 	.link_fd = NULL, | ||||
| 	.link = NULL, | ||||
| 	.unlink = NULL, | ||||
| 	.writei = snd_pcm_mmap_writei, | ||||
| 	.writen = snd_pcm_mmap_writen, | ||||
| 	.readi = snd_pcm_dmix_readi, | ||||
|  |  | |||
|  | @ -496,6 +496,9 @@ static snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = { | |||
| 	.forward = snd_pcm_dshare_forward, | ||||
| 	.resume = snd_pcm_dshare_resume, | ||||
| 	.poll_ask = NULL, | ||||
| 	.link_fd = NULL, | ||||
| 	.link = NULL, | ||||
| 	.unlink = NULL, | ||||
| 	.writei = snd_pcm_mmap_writei, | ||||
| 	.writen = snd_pcm_mmap_writen, | ||||
| 	.readi = snd_pcm_dshare_readi, | ||||
|  |  | |||
|  | @ -464,6 +464,9 @@ static snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = { | |||
| 	.forward = snd_pcm_dsnoop_forward, | ||||
| 	.resume = snd_pcm_dsnoop_resume, | ||||
| 	.poll_ask = NULL, | ||||
| 	.link_fd = NULL, | ||||
| 	.link = NULL, | ||||
| 	.unlink = NULL, | ||||
| 	.writei = snd_pcm_dsnoop_writei, | ||||
| 	.writen = snd_pcm_dsnoop_writen, | ||||
| 	.readi = snd_pcm_mmap_readi, | ||||
|  |  | |||
|  | @ -42,8 +42,7 @@ typedef enum _snd_pcm_file_format { | |||
| } snd_pcm_file_format_t; | ||||
| 
 | ||||
| typedef struct { | ||||
| 	snd_pcm_t *slave; | ||||
| 	int close_slave; | ||||
| 	snd_pcm_generic_t gen; | ||||
| 	char *fname; | ||||
| 	int fd; | ||||
| 	int format; | ||||
|  | @ -115,81 +114,17 @@ static void snd_pcm_file_add_frames(snd_pcm_t *pcm, | |||
| static int snd_pcm_file_close(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	int err = 0; | ||||
| 	if (file->close_slave) | ||||
| 		err = snd_pcm_close(file->slave); | ||||
| 	if (file->fname) { | ||||
| 		free((void *)file->fname); | ||||
| 		close(file->fd); | ||||
| 	} | ||||
| 	free(file); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_nonblock(snd_pcm_t *pcm, int nonblock) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_nonblock(file->slave, nonblock); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_async(snd_pcm_t *pcm, int sig, pid_t pid) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_async(file->slave, sig, pid); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_poll_descriptors_revents(file->slave, pfds, nfds, revents); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_info(snd_pcm_t *pcm, snd_pcm_info_t * info) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_info(file->slave, info); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_channel_info(file->slave, info); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_status(snd_pcm_t *pcm, snd_pcm_status_t * status) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_status(file->slave, status); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_state_t snd_pcm_file_state(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_state(file->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_hwsync(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_hwsync(file->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_delay(file->slave, delayp); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_prepare(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_prepare(file->slave); | ||||
| 	return snd_pcm_generic_close(pcm); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_reset(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	int err = snd_pcm_reset(file->slave); | ||||
| 	int err = snd_pcm_reset(file->gen.slave); | ||||
| 	if (err >= 0) { | ||||
| 		/* FIXME: Questionable here */ | ||||
| 		snd_pcm_file_write_bytes(pcm, file->wbuf_used_bytes); | ||||
|  | @ -198,16 +133,10 @@ static int snd_pcm_file_reset(snd_pcm_t *pcm) | |||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_start(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_start(file->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_drop(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	int err = snd_pcm_drop(file->slave); | ||||
| 	int err = snd_pcm_drop(file->gen.slave); | ||||
| 	if (err >= 0) { | ||||
| 		/* FIXME: Questionable here */ | ||||
| 		snd_pcm_file_write_bytes(pcm, file->wbuf_used_bytes); | ||||
|  | @ -219,7 +148,7 @@ static int snd_pcm_file_drop(snd_pcm_t *pcm) | |||
| static int snd_pcm_file_drain(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	int err = snd_pcm_drain(file->slave); | ||||
| 	int err = snd_pcm_drain(file->gen.slave); | ||||
| 	if (err >= 0) { | ||||
| 		snd_pcm_file_write_bytes(pcm, file->wbuf_used_bytes); | ||||
| 		assert(file->wbuf_used_bytes == 0); | ||||
|  | @ -227,12 +156,6 @@ static int snd_pcm_file_drain(snd_pcm_t *pcm) | |||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_pause(snd_pcm_t *pcm, int enable) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_pause(file->slave, enable); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_file_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
|  | @ -242,7 +165,7 @@ static snd_pcm_sframes_t snd_pcm_file_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f | |||
| 	n = snd_pcm_frames_to_bytes(pcm, frames); | ||||
| 	if (n > file->wbuf_used_bytes) | ||||
| 		frames = snd_pcm_bytes_to_frames(pcm, file->wbuf_used_bytes); | ||||
| 	err = snd_pcm_rewind(file->slave, frames); | ||||
| 	err = snd_pcm_rewind(file->gen.slave, frames); | ||||
| 	if (err > 0) { | ||||
| 		n = snd_pcm_frames_to_bytes(pcm, err); | ||||
| 		file->wbuf_used_bytes -= n; | ||||
|  | @ -259,7 +182,7 @@ static snd_pcm_sframes_t snd_pcm_file_forward(snd_pcm_t *pcm, snd_pcm_uframes_t | |||
| 	n = snd_pcm_frames_to_bytes(pcm, frames); | ||||
| 	if (file->wbuf_used_bytes + n > file->wbuf_size_bytes) | ||||
| 		frames = snd_pcm_bytes_to_frames(pcm, file->wbuf_size_bytes - file->wbuf_used_bytes); | ||||
| 	err = INTERNAL(snd_pcm_forward)(file->slave, frames); | ||||
| 	err = INTERNAL(snd_pcm_forward)(file->gen.slave, frames); | ||||
| 	if (err > 0) { | ||||
| 		snd_pcm_uframes_t n = snd_pcm_frames_to_bytes(pcm, err); | ||||
| 		file->wbuf_used_bytes += n; | ||||
|  | @ -267,25 +190,11 @@ static snd_pcm_sframes_t snd_pcm_file_forward(snd_pcm_t *pcm, snd_pcm_uframes_t | |||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_resume(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_resume(file->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_poll_ask(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	if (file->slave->fast_ops->poll_ask) | ||||
| 		return file->slave->fast_ops->poll_ask(file->slave->fast_op_arg); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_file_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	snd_pcm_channel_area_t areas[pcm->channels]; | ||||
| 	snd_pcm_sframes_t n = snd_pcm_writei(file->slave, buffer, size); | ||||
| 	snd_pcm_sframes_t n = snd_pcm_writei(file->gen.slave, buffer, size); | ||||
| 	if (n > 0) { | ||||
| 		snd_pcm_areas_from_buf(pcm, areas, (void*) buffer); | ||||
| 		snd_pcm_file_add_frames(pcm, areas, 0, n); | ||||
|  | @ -297,7 +206,7 @@ static snd_pcm_sframes_t snd_pcm_file_writen(snd_pcm_t *pcm, void **bufs, snd_pc | |||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	snd_pcm_channel_area_t areas[pcm->channels]; | ||||
| 	snd_pcm_sframes_t n = snd_pcm_writen(file->slave, bufs, size); | ||||
| 	snd_pcm_sframes_t n = snd_pcm_writen(file->gen.slave, bufs, size); | ||||
| 	if (n > 0) { | ||||
| 		snd_pcm_areas_from_bufs(pcm, areas, bufs); | ||||
| 		snd_pcm_file_add_frames(pcm, areas, 0, n); | ||||
|  | @ -309,7 +218,7 @@ static snd_pcm_sframes_t snd_pcm_file_readi(snd_pcm_t *pcm, void *buffer, snd_pc | |||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	snd_pcm_channel_area_t areas[pcm->channels]; | ||||
| 	snd_pcm_sframes_t n = snd_pcm_readi(file->slave, buffer, size); | ||||
| 	snd_pcm_sframes_t n = snd_pcm_readi(file->gen.slave, buffer, size); | ||||
| 	if (n > 0) { | ||||
| 		snd_pcm_areas_from_buf(pcm, areas, buffer); | ||||
| 		snd_pcm_file_add_frames(pcm, areas, 0, n); | ||||
|  | @ -321,7 +230,7 @@ static snd_pcm_sframes_t snd_pcm_file_readn(snd_pcm_t *pcm, void **bufs, snd_pcm | |||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	snd_pcm_channel_area_t areas[pcm->channels]; | ||||
| 	snd_pcm_sframes_t n = snd_pcm_writen(file->slave, bufs, size); | ||||
| 	snd_pcm_sframes_t n = snd_pcm_writen(file->gen.slave, bufs, size); | ||||
| 	if (n > 0) { | ||||
| 		snd_pcm_areas_from_bufs(pcm, areas, bufs); | ||||
| 		snd_pcm_file_add_frames(pcm, areas, 0, n); | ||||
|  | @ -339,26 +248,14 @@ static snd_pcm_sframes_t snd_pcm_file_mmap_commit(snd_pcm_t *pcm, | |||
| 	const snd_pcm_channel_area_t *areas; | ||||
| 	snd_pcm_sframes_t result; | ||||
| 
 | ||||
| 	snd_pcm_mmap_begin(file->slave, &areas, &ofs, &siz); | ||||
| 	snd_pcm_mmap_begin(file->gen.slave, &areas, &ofs, &siz); | ||||
| 	assert(ofs == offset && siz == size); | ||||
| 	result = snd_pcm_mmap_commit(file->slave, ofs, siz); | ||||
| 	result = snd_pcm_mmap_commit(file->gen.slave, ofs, siz); | ||||
| 	if (result > 0) | ||||
| 		snd_pcm_file_add_frames(pcm, areas, ofs, result); | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_file_avail_update(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_avail_update(file->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_hw_refine(file->slave, params); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_hw_free(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
|  | @ -369,14 +266,14 @@ static int snd_pcm_file_hw_free(snd_pcm_t *pcm) | |||
| 		file->wbuf = 0; | ||||
| 		file->wbuf_areas = 0; | ||||
| 	} | ||||
| 	return snd_pcm_hw_free(file->slave); | ||||
| 	return snd_pcm_hw_free(file->gen.slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	unsigned int channel; | ||||
| 	snd_pcm_t *slave = file->slave; | ||||
| 	snd_pcm_t *slave = file->gen.slave; | ||||
| 	int err = _snd_pcm_hw_params(slave, params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
|  | @ -404,16 +301,10 @@ static int snd_pcm_file_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return snd_pcm_sw_params(file->slave, params); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	snd_pcm_t *slave = file->slave; | ||||
| 	snd_pcm_t *slave = file->gen.slave; | ||||
| 	pcm->running_areas = slave->running_areas; | ||||
| 	pcm->stopped_areas = slave->stopped_areas; | ||||
| 	pcm->mmap_channels = slave->mmap_channels; | ||||
|  | @ -442,45 +333,48 @@ static void snd_pcm_file_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 		snd_pcm_dump_setup(pcm, out); | ||||
| 	} | ||||
| 	snd_output_printf(out, "Slave: "); | ||||
| 	snd_pcm_dump(file->slave, out); | ||||
| 	snd_pcm_dump(file->gen.slave, out); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_file_ops = { | ||||
| 	.close = snd_pcm_file_close, | ||||
| 	.info = snd_pcm_file_info, | ||||
| 	.hw_refine = snd_pcm_file_hw_refine, | ||||
| 	.hw_params = snd_pcm_file_hw_params, | ||||
| 	.info = snd_pcm_generic_info, | ||||
| 	.hw_refine = snd_pcm_generic_hw_refine, | ||||
| 	.hw_params = snd_pcm_generic_hw_params, | ||||
| 	.hw_free = snd_pcm_file_hw_free, | ||||
| 	.sw_params = snd_pcm_file_sw_params, | ||||
| 	.channel_info = snd_pcm_file_channel_info, | ||||
| 	.sw_params = snd_pcm_generic_sw_params, | ||||
| 	.channel_info = snd_pcm_generic_channel_info, | ||||
| 	.dump = snd_pcm_file_dump, | ||||
| 	.nonblock = snd_pcm_file_nonblock, | ||||
| 	.async = snd_pcm_file_async, | ||||
| 	.poll_revents = snd_pcm_file_poll_revents, | ||||
| 	.nonblock = snd_pcm_generic_nonblock, | ||||
| 	.async = snd_pcm_generic_async, | ||||
| 	.poll_revents = snd_pcm_generic_poll_revents, | ||||
| 	.mmap = snd_pcm_file_mmap, | ||||
| 	.munmap = snd_pcm_file_munmap, | ||||
| }; | ||||
| 
 | ||||
| static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = { | ||||
| 	.status = snd_pcm_file_status, | ||||
| 	.state = snd_pcm_file_state, | ||||
| 	.hwsync = snd_pcm_file_hwsync, | ||||
| 	.delay = snd_pcm_file_delay, | ||||
| 	.prepare = snd_pcm_file_prepare, | ||||
| 	.status = snd_pcm_generic_status, | ||||
| 	.state = snd_pcm_generic_state, | ||||
| 	.hwsync = snd_pcm_generic_hwsync, | ||||
| 	.delay = snd_pcm_generic_delay, | ||||
| 	.prepare = snd_pcm_generic_prepare, | ||||
| 	.reset = snd_pcm_file_reset, | ||||
| 	.start = snd_pcm_file_start, | ||||
| 	.start = snd_pcm_generic_start, | ||||
| 	.drop = snd_pcm_file_drop, | ||||
| 	.drain = snd_pcm_file_drain, | ||||
| 	.pause = snd_pcm_file_pause, | ||||
| 	.pause = snd_pcm_generic_pause, | ||||
| 	.rewind = snd_pcm_file_rewind, | ||||
| 	.forward = snd_pcm_file_forward, | ||||
| 	.resume = snd_pcm_file_resume, | ||||
| 	.poll_ask = snd_pcm_file_poll_ask, | ||||
| 	.resume = snd_pcm_generic_resume, | ||||
| 	.poll_ask = snd_pcm_generic_poll_ask, | ||||
| 	.link_fd = snd_pcm_generic_link_fd, | ||||
| 	.link = snd_pcm_generic_link, | ||||
| 	.unlink = snd_pcm_generic_unlink, | ||||
| 	.writei = snd_pcm_file_writei, | ||||
| 	.writen = snd_pcm_file_writen, | ||||
| 	.readi = snd_pcm_file_readi, | ||||
| 	.readn = snd_pcm_file_readn, | ||||
| 	.avail_update = snd_pcm_file_avail_update, | ||||
| 	.avail_update = snd_pcm_generic_avail_update, | ||||
| 	.mmap_commit = snd_pcm_file_mmap_commit, | ||||
| }; | ||||
| 
 | ||||
|  | @ -532,8 +426,8 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name, | |||
| 		file->fname = strdup(fname); | ||||
| 	file->fd = fd; | ||||
| 	file->format = format; | ||||
| 	file->slave = slave; | ||||
| 	file->close_slave = close_slave; | ||||
| 	file->gen.slave = slave; | ||||
| 	file->gen.close_slave = close_slave; | ||||
| 
 | ||||
| 	err = snd_pcm_new(&pcm, SND_PCM_TYPE_FILE, name, slave->stream, slave->mode); | ||||
| 	if (err < 0) { | ||||
|  |  | |||
							
								
								
									
										257
									
								
								src/pcm/pcm_generic.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								src/pcm/pcm_generic.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,257 @@ | |||
| /**
 | ||||
|  * \file pcm/pcm_generic.c | ||||
|  * \ingroup PCM | ||||
|  * \brief PCM Interface | ||||
|  * \author Jaroslav Kysela <perex@suse.cz> | ||||
|  * \date 2004 | ||||
|  */ | ||||
| /*
 | ||||
|  *  PCM - Common generic plugin code | ||||
|  *  Copyright (c) 2004 by Jaroslav Kysela <perex@suse.cz>  | ||||
|  * | ||||
|  * | ||||
|  *   This library is free software; you can redistribute it and/or modify | ||||
|  *   it under the terms of the GNU Lesser General Public License as | ||||
|  *   published by the Free Software Foundation; either version 2.1 of | ||||
|  *   the License, or (at your option) any later version. | ||||
|  * | ||||
|  *   This program is distributed in the hope that it will be useful, | ||||
|  *   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *   GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  *   You should have received a copy of the GNU Lesser General Public | ||||
|  *   License along with this library; if not, write to the Free Software | ||||
|  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include <sys/shm.h> | ||||
| #include <limits.h> | ||||
| #include "pcm_local.h" | ||||
| #include "pcm_generic.h" | ||||
| 
 | ||||
| #ifndef DOC_HIDDEN | ||||
| 
 | ||||
| int snd_pcm_generic_close(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	int err = 0; | ||||
| 	if (generic->close_slave) | ||||
| 		err = snd_pcm_close(generic->slave); | ||||
| 	free(generic); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_nonblock(snd_pcm_t *pcm, int nonblock) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_nonblock(generic->slave, nonblock); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_async(snd_pcm_t *pcm, int sig, pid_t pid) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_async(generic->slave, sig, pid); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_poll_descriptors_revents(generic->slave, pfds, nfds, revents); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_info(snd_pcm_t *pcm, snd_pcm_info_t * info) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_info(generic->slave, info); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_hw_free(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_hw_free(generic->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_sw_params(generic->slave, params); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_hw_refine(generic->slave, params); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return _snd_pcm_hw_params(generic->slave, params); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_prepare(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_prepare(generic->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info) | ||||
| { | ||||
| 	return snd_pcm_channel_info_shm(pcm, info, -1); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_status(snd_pcm_t *pcm, snd_pcm_status_t * status) | ||||
| {  | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_status(generic->slave, status); | ||||
| } | ||||
| 
 | ||||
| snd_pcm_state_t snd_pcm_generic_state(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_state(generic->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_hwsync(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_hwsync(generic->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_reset(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_reset(generic->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_start(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_start(generic->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_drop(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_drop(generic->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_drain(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_drain(generic->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_pause(snd_pcm_t *pcm, int enable) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_pause(generic->slave, enable); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_resume(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_resume(generic->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_delay(generic->slave, delayp); | ||||
| } | ||||
| 
 | ||||
| snd_pcm_sframes_t snd_pcm_generic_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return INTERNAL(snd_pcm_forward)(generic->slave, frames); | ||||
| } | ||||
| 
 | ||||
| snd_pcm_sframes_t snd_pcm_generic_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_rewind(generic->slave, frames); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_poll_ask(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	if (generic->slave->fast_ops->poll_ask) | ||||
| 		return generic->slave->fast_ops->poll_ask(generic->slave->fast_op_arg); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_link_fd(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	if (generic->slave->fast_ops->link_fd) | ||||
| 		return generic->slave->fast_ops->link_fd(generic->slave->fast_op_arg); | ||||
| 	return -ENOSYS; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm1->private_data; | ||||
| 	if (generic->slave->fast_ops->link) | ||||
| 		return generic->slave->fast_ops->link(generic->slave->fast_op_arg, pcm2); | ||||
| 	return -ENOSYS; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_unlink(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	if (generic->slave->fast_ops->unlink) | ||||
| 		return generic->slave->fast_ops->unlink(generic->slave->fast_op_arg); | ||||
| 	return -ENOSYS; | ||||
| } | ||||
| 
 | ||||
| snd_pcm_sframes_t snd_pcm_generic_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_writei(generic->slave, buffer, size); | ||||
| } | ||||
| 
 | ||||
| snd_pcm_sframes_t snd_pcm_generic_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_writen(generic->slave, bufs, size); | ||||
| } | ||||
| 
 | ||||
| snd_pcm_sframes_t snd_pcm_generic_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_readi(generic->slave, buffer, size); | ||||
| } | ||||
| 
 | ||||
| snd_pcm_sframes_t snd_pcm_generic_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_readn(generic->slave, bufs, size); | ||||
| } | ||||
| 
 | ||||
| snd_pcm_sframes_t snd_pcm_generic_mmap_commit(snd_pcm_t *pcm,  | ||||
| 					      snd_pcm_uframes_t offset, | ||||
| 					      snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_mmap_commit(generic->slave, offset, size); | ||||
| } | ||||
| 
 | ||||
| snd_pcm_sframes_t snd_pcm_generic_avail_update(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_generic_t *generic = pcm->private_data; | ||||
| 	return snd_pcm_avail_update(generic->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_generic_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #endif /* DOC_HIDDEN */ | ||||
							
								
								
									
										63
									
								
								src/pcm/pcm_generic.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/pcm/pcm_generic.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,63 @@ | |||
| /*
 | ||||
|  *  PCM - Common generic plugin code | ||||
|  *  Copyright (c) 2004 by Jaroslav Kysela <perex@suse.cz> | ||||
|  * | ||||
|  * | ||||
|  *   This library is free software; you can redistribute it and/or modify | ||||
|  *   it under the terms of the GNU Lesser General Public License as | ||||
|  *   published by the Free Software Foundation; either version 2.1 of | ||||
|  *   the License, or (at your option) any later version. | ||||
|  * | ||||
|  *   This program is distributed in the hope that it will be useful, | ||||
|  *   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *   GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  *   You should have received a copy of the GNU Lesser General Public | ||||
|  *   License along with this library; if not, write to the Free Software | ||||
|  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA | ||||
|  * | ||||
|  */ | ||||
|    | ||||
| typedef struct { | ||||
| 	snd_pcm_t *slave; | ||||
| 	int close_slave; | ||||
| } snd_pcm_generic_t;	 | ||||
| 
 | ||||
| int snd_pcm_generic_close(snd_pcm_t *pcm); | ||||
| int snd_pcm_generic_nonblock(snd_pcm_t *pcm, int nonblock); | ||||
| int snd_pcm_generic_async(snd_pcm_t *pcm, int sig, pid_t pid); | ||||
| int snd_pcm_generic_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents); | ||||
| int snd_pcm_generic_info(snd_pcm_t *pcm, snd_pcm_info_t * info); | ||||
| int snd_pcm_generic_hw_free(snd_pcm_t *pcm); | ||||
| int snd_pcm_generic_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params); | ||||
| int snd_pcm_generic_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); | ||||
| int snd_pcm_generic_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); | ||||
| int snd_pcm_generic_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info); | ||||
| int snd_pcm_generic_status(snd_pcm_t *pcm, snd_pcm_status_t * status); | ||||
| snd_pcm_state_t snd_pcm_generic_state(snd_pcm_t *pcm); | ||||
| int snd_pcm_generic_prepare(snd_pcm_t *pcm); | ||||
| int snd_pcm_generic_hwsync(snd_pcm_t *pcm); | ||||
| int snd_pcm_generic_reset(snd_pcm_t *pcm); | ||||
| int snd_pcm_generic_start(snd_pcm_t *pcm); | ||||
| int snd_pcm_generic_drop(snd_pcm_t *pcm); | ||||
| int snd_pcm_generic_drain(snd_pcm_t *pcm); | ||||
| int snd_pcm_generic_pause(snd_pcm_t *pcm, int enable); | ||||
| int snd_pcm_generic_resume(snd_pcm_t *pcm); | ||||
| int snd_pcm_generic_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp); | ||||
| snd_pcm_sframes_t snd_pcm_generic_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames); | ||||
| snd_pcm_sframes_t snd_pcm_generic_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames); | ||||
| int snd_pcm_generic_poll_ask(snd_pcm_t *pcm); | ||||
| int snd_pcm_generic_link_fd(snd_pcm_t *pcm);  | ||||
| int snd_pcm_generic_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2); | ||||
| int snd_pcm_generic_unlink(snd_pcm_t *pcm); | ||||
| snd_pcm_sframes_t snd_pcm_generic_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size); | ||||
| snd_pcm_sframes_t snd_pcm_generic_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size); | ||||
| snd_pcm_sframes_t snd_pcm_generic_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size); | ||||
| snd_pcm_sframes_t snd_pcm_generic_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size); | ||||
| snd_pcm_sframes_t snd_pcm_generic_mmap_commit(snd_pcm_t *pcm, | ||||
| 					      snd_pcm_uframes_t offset, | ||||
| 					      snd_pcm_uframes_t size); | ||||
| snd_pcm_sframes_t snd_pcm_generic_avail_update(snd_pcm_t *pcm); | ||||
| int snd_pcm_generic_mmap(snd_pcm_t *pcm); | ||||
| int snd_pcm_generic_munmap(snd_pcm_t *pcm); | ||||
|  | @ -29,6 +29,7 @@ | |||
|    | ||||
| #include <dlfcn.h> | ||||
| #include "pcm_local.h" | ||||
| #include "pcm_generic.h" | ||||
| 
 | ||||
| #ifndef PIC | ||||
| /* entry for static linking */ | ||||
|  | @ -44,8 +45,7 @@ struct _snd_pcm_hook { | |||
| }; | ||||
| 
 | ||||
| typedef struct { | ||||
| 	snd_pcm_t *slave; | ||||
| 	int close_slave; | ||||
| 	snd_pcm_generic_t gen; | ||||
| 	struct list_head hooks[SND_PCM_HOOK_TYPE_LAST + 1]; | ||||
| } snd_pcm_hooks_t; | ||||
| #endif | ||||
|  | @ -56,11 +56,7 @@ static int snd_pcm_hooks_close(snd_pcm_t *pcm) | |||
| 	struct list_head *pos, *next; | ||||
| 	unsigned int k; | ||||
| 	int err; | ||||
| 	if (h->close_slave) { | ||||
| 		err = snd_pcm_close(h->slave); | ||||
| 		if (err < 0) | ||||
| 			return err; | ||||
| 	} | ||||
| 
 | ||||
| 	list_for_each_safe(pos, next, &h->hooks[SND_PCM_HOOK_TYPE_CLOSE]) { | ||||
| 		snd_pcm_hook_t *hook = list_entry(pos, snd_pcm_hook_t, list); | ||||
| 		err = hook->func(hook); | ||||
|  | @ -76,169 +72,14 @@ static int snd_pcm_hooks_close(snd_pcm_t *pcm) | |||
| 			snd_pcm_hook_remove(hook); | ||||
| 		} | ||||
| 	} | ||||
| 	free(h); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_nonblock(snd_pcm_t *pcm, int nonblock) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_nonblock(h->slave, nonblock); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_async(snd_pcm_t *pcm, int sig, pid_t pid) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_async(h->slave, sig, pid); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_info(snd_pcm_t *pcm, snd_pcm_info_t *info) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_info(h->slave, info); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_channel_info(h->slave, info); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_status(snd_pcm_t *pcm, snd_pcm_status_t * status) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_status(h->slave, status); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_state_t snd_pcm_hooks_state(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_state(h->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_hwsync(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_hwsync(h->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_delay(h->slave, delayp); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_prepare(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_prepare(h->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_reset(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_reset(h->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_start(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_start(h->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_drop(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_drop(h->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_drain(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_drain(h->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_pause(snd_pcm_t *pcm, int enable) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_pause(h->slave, enable); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_hooks_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_rewind(h->slave, frames); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_hooks_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return INTERNAL(snd_pcm_forward)(h->slave, frames); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_resume(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_resume(h->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_poll_ask(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	if (h->slave->fast_ops->poll_ask) | ||||
| 		return h->slave->fast_ops->poll_ask(h->slave->fast_op_arg); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_hooks_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_writei(h->slave, buffer, size); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_hooks_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_writen(h->slave, bufs, size); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_hooks_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_readi(h->slave, buffer, size); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_hooks_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_readn(h->slave, bufs, size); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_hooks_mmap_commit(snd_pcm_t *pcm, | ||||
| 						   snd_pcm_uframes_t offset, | ||||
| 						   snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_mmap_commit(h->slave, offset, size); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_hooks_avail_update(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_avail_update(h->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_hw_refine(h->slave, params); | ||||
| 	return snd_pcm_generic_close(pcm); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	struct list_head *pos, *next; | ||||
| 	int err = snd_pcm_hw_params(h->slave, params); | ||||
| 	int err = snd_pcm_hw_params(h->gen.slave, params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	list_for_each_safe(pos, next, &h->hooks[SND_PCM_HOOK_TYPE_HW_PARAMS]) { | ||||
|  | @ -254,7 +95,7 @@ static int snd_pcm_hooks_hw_free(snd_pcm_t *pcm) | |||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	struct list_head *pos, *next; | ||||
| 	int err = snd_pcm_hw_free(h->slave); | ||||
| 	int err = snd_pcm_hw_free(h->gen.slave); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	list_for_each_safe(pos, next, &h->hooks[SND_PCM_HOOK_TYPE_HW_FREE]) { | ||||
|  | @ -266,22 +107,6 @@ static int snd_pcm_hooks_hw_free(snd_pcm_t *pcm) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return snd_pcm_sw_params(h->slave, params); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void snd_pcm_hooks_dump(snd_pcm_t *pcm, snd_output_t *out) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
|  | @ -291,45 +116,48 @@ static void snd_pcm_hooks_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 		snd_pcm_dump_setup(pcm, out); | ||||
| 	} | ||||
| 	snd_output_printf(out, "Slave: "); | ||||
| 	snd_pcm_dump(h->slave, out); | ||||
| 	snd_pcm_dump(h->gen.slave, out); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_hooks_ops = { | ||||
| 	.close = snd_pcm_hooks_close, | ||||
| 	.info = snd_pcm_hooks_info, | ||||
| 	.hw_refine = snd_pcm_hooks_hw_refine, | ||||
| 	.info = snd_pcm_generic_info, | ||||
| 	.hw_refine = snd_pcm_generic_hw_refine, | ||||
| 	.hw_params = snd_pcm_hooks_hw_params, | ||||
| 	.hw_free = snd_pcm_hooks_hw_free, | ||||
| 	.sw_params = snd_pcm_hooks_sw_params, | ||||
| 	.channel_info = snd_pcm_hooks_channel_info, | ||||
| 	.sw_params = snd_pcm_generic_sw_params, | ||||
| 	.channel_info = snd_pcm_generic_channel_info, | ||||
| 	.dump = snd_pcm_hooks_dump, | ||||
| 	.nonblock = snd_pcm_hooks_nonblock, | ||||
| 	.async = snd_pcm_hooks_async, | ||||
| 	.mmap = snd_pcm_hooks_mmap, | ||||
| 	.munmap = snd_pcm_hooks_munmap, | ||||
| 	.nonblock = snd_pcm_generic_nonblock, | ||||
| 	.async = snd_pcm_generic_async, | ||||
| 	.mmap = snd_pcm_generic_mmap, | ||||
| 	.munmap = snd_pcm_generic_munmap, | ||||
| }; | ||||
| 
 | ||||
| static snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = { | ||||
| 	.status = snd_pcm_hooks_status, | ||||
| 	.state = snd_pcm_hooks_state, | ||||
| 	.hwsync = snd_pcm_hooks_hwsync, | ||||
| 	.delay = snd_pcm_hooks_delay, | ||||
| 	.prepare = snd_pcm_hooks_prepare, | ||||
| 	.reset = snd_pcm_hooks_reset, | ||||
| 	.start = snd_pcm_hooks_start, | ||||
| 	.drop = snd_pcm_hooks_drop, | ||||
| 	.drain = snd_pcm_hooks_drain, | ||||
| 	.pause = snd_pcm_hooks_pause, | ||||
| 	.rewind = snd_pcm_hooks_rewind, | ||||
| 	.forward = snd_pcm_hooks_forward, | ||||
| 	.resume = snd_pcm_hooks_resume, | ||||
| 	.poll_ask = snd_pcm_hooks_poll_ask, | ||||
| 	.writei = snd_pcm_hooks_writei, | ||||
| 	.writen = snd_pcm_hooks_writen, | ||||
| 	.readi = snd_pcm_hooks_readi, | ||||
| 	.readn = snd_pcm_hooks_readn, | ||||
| 	.avail_update = snd_pcm_hooks_avail_update, | ||||
| 	.mmap_commit = snd_pcm_hooks_mmap_commit, | ||||
| 	.status = snd_pcm_generic_status, | ||||
| 	.state = snd_pcm_generic_state, | ||||
| 	.hwsync = snd_pcm_generic_hwsync, | ||||
| 	.delay = snd_pcm_generic_delay, | ||||
| 	.prepare = snd_pcm_generic_prepare, | ||||
| 	.reset = snd_pcm_generic_reset, | ||||
| 	.start = snd_pcm_generic_start, | ||||
| 	.drop = snd_pcm_generic_drop, | ||||
| 	.drain = snd_pcm_generic_drain, | ||||
| 	.pause = snd_pcm_generic_pause, | ||||
| 	.rewind = snd_pcm_generic_rewind, | ||||
| 	.forward = snd_pcm_generic_forward, | ||||
| 	.resume = snd_pcm_generic_resume, | ||||
| 	.poll_ask = snd_pcm_generic_poll_ask, | ||||
| 	.link_fd = snd_pcm_generic_link_fd, | ||||
| 	.link = snd_pcm_generic_link, | ||||
| 	.unlink = snd_pcm_generic_unlink, | ||||
| 	.writei = snd_pcm_generic_writei, | ||||
| 	.writen = snd_pcm_generic_writen, | ||||
| 	.readi = snd_pcm_generic_readi, | ||||
| 	.readn = snd_pcm_generic_readn, | ||||
| 	.avail_update = snd_pcm_generic_avail_update, | ||||
| 	.mmap_commit = snd_pcm_generic_mmap_commit, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -353,8 +181,8 @@ int snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int | |||
| 	h = calloc(1, sizeof(snd_pcm_hooks_t)); | ||||
| 	if (!h) | ||||
| 		return -ENOMEM; | ||||
| 	h->slave = slave; | ||||
| 	h->close_slave = close_slave; | ||||
| 	h->gen.slave = slave; | ||||
| 	h->gen.close_slave = close_slave; | ||||
| 	for (k = 0; k <= SND_PCM_HOOK_TYPE_LAST; ++k) { | ||||
| 		INIT_LIST_HEAD(&h->hooks[k]); | ||||
| 	} | ||||
|  |  | |||
|  | @ -656,6 +656,38 @@ static int snd_pcm_hw_resume(snd_pcm_t *pcm) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hw_link_fd(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_hw_t *hw = pcm->private_data; | ||||
| 
 | ||||
| 	return hw->fd; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hw_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2) | ||||
| { | ||||
| 	snd_pcm_hw_t *hw = pcm1->private_data; | ||||
| 	int fd2 = _snd_pcm_link_descriptor(pcm2); | ||||
| 
 | ||||
| 	if (fd2 < 0) | ||||
| 		return -ENOSYS; | ||||
| 	if (ioctl(hw->fd, SNDRV_PCM_IOCTL_LINK, fd2) < 0) { | ||||
| 		SYSMSG("SNDRV_PCM_IOCTL_LINK failed"); | ||||
| 		return -errno; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hw_unlink(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_hw_t *hw = pcm->private_data; | ||||
| 
 | ||||
| 	if (ioctl(hw->fd, SNDRV_PCM_IOCTL_UNLINK) < 0) { | ||||
| 		SYSMSG("SNDRV_PCM_IOCTL_UNLINK failed"); | ||||
| 		return -errno; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_hw_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) | ||||
| { | ||||
| 	int err; | ||||
|  | @ -970,6 +1002,9 @@ static snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = { | |||
| 	.forward = snd_pcm_hw_forward, | ||||
| 	.resume = snd_pcm_hw_resume, | ||||
| 	.poll_ask = NULL, | ||||
| 	.link_fd = snd_pcm_hw_link_fd, | ||||
| 	.link = snd_pcm_hw_link, | ||||
| 	.unlink = snd_pcm_hw_unlink, | ||||
| 	.writei = snd_pcm_hw_writei, | ||||
| 	.writen = snd_pcm_hw_writen, | ||||
| 	.readi = snd_pcm_hw_readi, | ||||
|  |  | |||
|  | @ -305,7 +305,7 @@ static int snd_pcm_iec958_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
| 				       snd_pcm_iec958_hw_refine_cchange, | ||||
| 				       snd_pcm_iec958_hw_refine_sprepare, | ||||
| 				       snd_pcm_iec958_hw_refine_schange, | ||||
| 				       snd_pcm_plugin_hw_refine_slave); | ||||
| 				       snd_pcm_generic_hw_refine); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_iec958_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | ||||
|  | @ -316,7 +316,7 @@ static int snd_pcm_iec958_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params | |||
| 					  snd_pcm_iec958_hw_refine_cchange, | ||||
| 					  snd_pcm_iec958_hw_refine_sprepare, | ||||
| 					  snd_pcm_iec958_hw_refine_schange, | ||||
| 					  snd_pcm_plugin_hw_params_slave); | ||||
| 					  snd_pcm_generic_hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 
 | ||||
|  | @ -409,23 +409,23 @@ static void snd_pcm_iec958_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 		snd_pcm_dump_setup(pcm, out); | ||||
| 	} | ||||
| 	snd_output_printf(out, "Slave: "); | ||||
| 	snd_pcm_dump(iec->plug.slave, out); | ||||
| 	snd_pcm_dump(iec->plug.gen.slave, out); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_iec958_ops = { | ||||
| 	.close = snd_pcm_plugin_close, | ||||
| 	.info = snd_pcm_plugin_info, | ||||
| 	.close = snd_pcm_generic_close, | ||||
| 	.info = snd_pcm_generic_info, | ||||
| 	.hw_refine = snd_pcm_iec958_hw_refine, | ||||
| 	.hw_params = snd_pcm_iec958_hw_params, | ||||
| 	.hw_free = snd_pcm_plugin_hw_free, | ||||
| 	.sw_params = snd_pcm_plugin_sw_params, | ||||
| 	.channel_info = snd_pcm_plugin_channel_info, | ||||
| 	.hw_free = snd_pcm_generic_hw_free, | ||||
| 	.sw_params = snd_pcm_generic_sw_params, | ||||
| 	.channel_info = snd_pcm_generic_channel_info, | ||||
| 	.dump = snd_pcm_iec958_dump, | ||||
| 	.nonblock = snd_pcm_plugin_nonblock, | ||||
| 	.async = snd_pcm_plugin_async, | ||||
| 	.poll_revents = snd_pcm_plugin_poll_revents, | ||||
| 	.mmap = snd_pcm_plugin_mmap, | ||||
| 	.munmap = snd_pcm_plugin_munmap, | ||||
| 	.nonblock = snd_pcm_generic_nonblock, | ||||
| 	.async = snd_pcm_generic_async, | ||||
| 	.poll_revents = snd_pcm_generic_poll_revents, | ||||
| 	.mmap = snd_pcm_generic_mmap, | ||||
| 	.munmap = snd_pcm_generic_munmap, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -471,8 +471,8 @@ int snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo | |||
| 	iec->plug.init = snd_pcm_iec958_init; | ||||
| 	iec->plug.undo_read = snd_pcm_plugin_undo_read_generic; | ||||
| 	iec->plug.undo_write = snd_pcm_plugin_undo_write_generic; | ||||
| 	iec->plug.slave = slave; | ||||
| 	iec->plug.close_slave = close_slave; | ||||
| 	iec->plug.gen.slave = slave; | ||||
| 	iec->plug.gen.close_slave = close_slave; | ||||
| 
 | ||||
| 	if (status_bits) | ||||
| 		memcpy(iec->status, status_bits, sizeof(iec->status)); | ||||
|  |  | |||
|  | @ -175,7 +175,7 @@ static int snd_pcm_ladspa_close(snd_pcm_t *pcm) | |||
| 	snd_pcm_ladspa_t *ladspa = pcm->private_data; | ||||
| 
 | ||||
| 	snd_pcm_ladspa_free(ladspa); | ||||
| 	return snd_pcm_plugin_close(pcm); | ||||
| 	return snd_pcm_generic_close(pcm); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_ladspa_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params) | ||||
|  | @ -252,7 +252,7 @@ static int snd_pcm_ladspa_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
| 				       snd_pcm_ladspa_hw_refine_cchange, | ||||
| 				       snd_pcm_ladspa_hw_refine_sprepare, | ||||
| 				       snd_pcm_ladspa_hw_refine_schange, | ||||
| 				       snd_pcm_plugin_hw_refine_slave); | ||||
| 				       snd_pcm_generic_hw_refine); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_ladspa_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | ||||
|  | @ -262,7 +262,7 @@ static int snd_pcm_ladspa_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params | |||
| 					  snd_pcm_ladspa_hw_refine_cchange, | ||||
| 					  snd_pcm_ladspa_hw_refine_sprepare, | ||||
| 					  snd_pcm_ladspa_hw_refine_schange, | ||||
| 					  snd_pcm_plugin_hw_params_slave); | ||||
| 					  snd_pcm_generic_hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	return 0; | ||||
|  | @ -554,7 +554,7 @@ static int snd_pcm_ladspa_hw_free(snd_pcm_t *pcm) | |||
| 	snd_pcm_ladspa_t *ladspa = pcm->private_data; | ||||
| 
 | ||||
| 	snd_pcm_ladspa_free_instances(pcm, ladspa, 1); | ||||
| 	return snd_pcm_plugin_hw_free(pcm); | ||||
| 	return snd_pcm_generic_hw_free(pcm); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_uframes_t | ||||
|  | @ -693,23 +693,23 @@ static void snd_pcm_ladspa_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 		snd_pcm_dump_setup(pcm, out); | ||||
| 	} | ||||
| 	snd_output_printf(out, "Slave: "); | ||||
| 	snd_pcm_dump(ladspa->plug.slave, out); | ||||
| 	snd_pcm_dump(ladspa->plug.gen.slave, out); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_ladspa_ops = { | ||||
| 	.close = snd_pcm_ladspa_close, | ||||
| 	.info = snd_pcm_plugin_info, | ||||
| 	.info = snd_pcm_generic_info, | ||||
| 	.hw_refine = snd_pcm_ladspa_hw_refine, | ||||
| 	.hw_params = snd_pcm_ladspa_hw_params, | ||||
| 	.hw_free = snd_pcm_ladspa_hw_free, | ||||
| 	.sw_params = snd_pcm_plugin_sw_params, | ||||
| 	.channel_info = snd_pcm_plugin_channel_info, | ||||
| 	.sw_params = snd_pcm_generic_sw_params, | ||||
| 	.channel_info = snd_pcm_generic_channel_info, | ||||
| 	.dump = snd_pcm_ladspa_dump, | ||||
| 	.nonblock = snd_pcm_plugin_nonblock, | ||||
| 	.async = snd_pcm_plugin_async, | ||||
| 	.poll_revents = snd_pcm_plugin_poll_revents, | ||||
| 	.mmap = snd_pcm_plugin_mmap, | ||||
| 	.munmap = snd_pcm_plugin_munmap, | ||||
| 	.nonblock = snd_pcm_generic_nonblock, | ||||
| 	.async = snd_pcm_generic_async, | ||||
| 	.poll_revents = snd_pcm_generic_poll_revents, | ||||
| 	.mmap = snd_pcm_generic_mmap, | ||||
| 	.munmap = snd_pcm_generic_munmap, | ||||
| }; | ||||
| 
 | ||||
| static int snd_pcm_ladspa_check_file(snd_pcm_ladspa_plugin_t * const plugin, | ||||
|  | @ -1149,8 +1149,8 @@ int snd_pcm_ladspa_open(snd_pcm_t **pcmp, const char *name, | |||
| 	ladspa->plug.write = snd_pcm_ladspa_write_areas; | ||||
| 	ladspa->plug.undo_read = snd_pcm_plugin_undo_read_generic; | ||||
| 	ladspa->plug.undo_write = snd_pcm_plugin_undo_write_generic; | ||||
| 	ladspa->plug.slave = slave; | ||||
| 	ladspa->plug.close_slave = close_slave; | ||||
| 	ladspa->plug.gen.slave = slave; | ||||
| 	ladspa->plug.gen.close_slave = close_slave; | ||||
| 
 | ||||
| 	INIT_LIST_HEAD(&ladspa->pplugins); | ||||
| 	INIT_LIST_HEAD(&ladspa->cplugins); | ||||
|  |  | |||
|  | @ -261,19 +261,19 @@ static int snd_pcm_lfloat_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
| 				       snd_pcm_lfloat_hw_refine_cchange, | ||||
| 				       snd_pcm_lfloat_hw_refine_sprepare, | ||||
| 				       snd_pcm_lfloat_hw_refine_schange, | ||||
| 				       snd_pcm_plugin_hw_refine_slave); | ||||
| 				       snd_pcm_generic_hw_refine); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_lfloat_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_lfloat_t *lfloat = pcm->private_data; | ||||
| 	snd_pcm_t *slave = lfloat->plug.slave; | ||||
| 	snd_pcm_t *slave = lfloat->plug.gen.slave; | ||||
| 	snd_pcm_format_t src_format, dst_format; | ||||
| 	int err = snd_pcm_hw_params_slave(pcm, params, | ||||
| 					  snd_pcm_lfloat_hw_refine_cchange, | ||||
| 					  snd_pcm_lfloat_hw_refine_sprepare, | ||||
| 					  snd_pcm_lfloat_hw_refine_schange, | ||||
| 					  snd_pcm_plugin_hw_params_slave); | ||||
| 					  snd_pcm_generic_hw_refine); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { | ||||
|  | @ -345,23 +345,23 @@ static void snd_pcm_lfloat_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 		snd_pcm_dump_setup(pcm, out); | ||||
| 	} | ||||
| 	snd_output_printf(out, "Slave: "); | ||||
| 	snd_pcm_dump(lfloat->plug.slave, out); | ||||
| 	snd_pcm_dump(lfloat->plug.gen.slave, out); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_lfloat_ops = { | ||||
| 	.close = snd_pcm_plugin_close, | ||||
| 	.info = snd_pcm_plugin_info, | ||||
| 	.close = snd_pcm_generic_close, | ||||
| 	.info = snd_pcm_generic_info, | ||||
| 	.hw_refine = snd_pcm_lfloat_hw_refine, | ||||
| 	.hw_params = snd_pcm_lfloat_hw_params, | ||||
| 	.hw_free = snd_pcm_plugin_hw_free, | ||||
| 	.sw_params = snd_pcm_plugin_sw_params, | ||||
| 	.channel_info = snd_pcm_plugin_channel_info, | ||||
| 	.hw_free = snd_pcm_generic_hw_free, | ||||
| 	.sw_params = snd_pcm_generic_sw_params, | ||||
| 	.channel_info = snd_pcm_generic_channel_info, | ||||
| 	.dump = snd_pcm_lfloat_dump, | ||||
| 	.nonblock = snd_pcm_plugin_nonblock, | ||||
| 	.async = snd_pcm_plugin_async, | ||||
| 	.poll_revents = snd_pcm_plugin_poll_revents, | ||||
| 	.mmap = snd_pcm_plugin_mmap, | ||||
| 	.munmap = snd_pcm_plugin_munmap, | ||||
| 	.nonblock = snd_pcm_generic_nonblock, | ||||
| 	.async = snd_pcm_generic_async, | ||||
| 	.poll_revents = snd_pcm_generic_poll_revents, | ||||
| 	.mmap = snd_pcm_generic_mmap, | ||||
| 	.munmap = snd_pcm_generic_munmap, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -395,8 +395,8 @@ int snd_pcm_lfloat_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo | |||
| 	lfloat->plug.write = snd_pcm_lfloat_write_areas; | ||||
| 	lfloat->plug.undo_read = snd_pcm_plugin_undo_read_generic; | ||||
| 	lfloat->plug.undo_write = snd_pcm_plugin_undo_write_generic; | ||||
| 	lfloat->plug.slave = slave; | ||||
| 	lfloat->plug.close_slave = close_slave; | ||||
| 	lfloat->plug.gen.slave = slave; | ||||
| 	lfloat->plug.gen.close_slave = close_slave; | ||||
| 
 | ||||
| 	err = snd_pcm_new(&pcm, SND_PCM_TYPE_LINEAR_FLOAT, name, slave->stream, slave->mode); | ||||
| 	if (err < 0) { | ||||
|  |  | |||
|  | @ -304,7 +304,7 @@ static int snd_pcm_linear_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
| 				       snd_pcm_linear_hw_refine_cchange, | ||||
| 				       snd_pcm_linear_hw_refine_sprepare, | ||||
| 				       snd_pcm_linear_hw_refine_schange, | ||||
| 				       snd_pcm_plugin_hw_refine_slave); | ||||
| 				       snd_pcm_generic_hw_refine); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_linear_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
|  | @ -315,7 +315,7 @@ static int snd_pcm_linear_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
| 					  snd_pcm_linear_hw_refine_cchange, | ||||
| 					  snd_pcm_linear_hw_refine_sprepare, | ||||
| 					  snd_pcm_linear_hw_refine_schange, | ||||
| 					  snd_pcm_plugin_hw_params_slave); | ||||
| 					  snd_pcm_generic_hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = INTERNAL(snd_pcm_hw_params_get_format)(params, &format); | ||||
|  | @ -402,23 +402,23 @@ static void snd_pcm_linear_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 		snd_pcm_dump_setup(pcm, out); | ||||
| 	} | ||||
| 	snd_output_printf(out, "Slave: "); | ||||
| 	snd_pcm_dump(linear->plug.slave, out); | ||||
| 	snd_pcm_dump(linear->plug.gen.slave, out); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_linear_ops = { | ||||
| 	.close = snd_pcm_plugin_close, | ||||
| 	.info = snd_pcm_plugin_info, | ||||
| 	.close = snd_pcm_generic_close, | ||||
| 	.info = snd_pcm_generic_info, | ||||
| 	.hw_refine = snd_pcm_linear_hw_refine, | ||||
| 	.hw_params = snd_pcm_linear_hw_params, | ||||
| 	.hw_free = snd_pcm_plugin_hw_free, | ||||
| 	.sw_params = snd_pcm_plugin_sw_params, | ||||
| 	.channel_info = snd_pcm_plugin_channel_info, | ||||
| 	.hw_free = snd_pcm_generic_hw_free, | ||||
| 	.sw_params = snd_pcm_generic_sw_params, | ||||
| 	.channel_info = snd_pcm_generic_channel_info, | ||||
| 	.dump = snd_pcm_linear_dump, | ||||
| 	.nonblock = snd_pcm_plugin_nonblock, | ||||
| 	.async = snd_pcm_plugin_async, | ||||
| 	.poll_revents = snd_pcm_plugin_poll_revents, | ||||
| 	.mmap = snd_pcm_plugin_mmap, | ||||
| 	.munmap = snd_pcm_plugin_munmap, | ||||
| 	.nonblock = snd_pcm_generic_nonblock, | ||||
| 	.async = snd_pcm_generic_async, | ||||
| 	.poll_revents = snd_pcm_generic_poll_revents, | ||||
| 	.mmap = snd_pcm_generic_mmap, | ||||
| 	.munmap = snd_pcm_generic_munmap, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -452,8 +452,8 @@ int snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo | |||
| 	linear->plug.write = snd_pcm_linear_write_areas; | ||||
| 	linear->plug.undo_read = snd_pcm_plugin_undo_read_generic; | ||||
| 	linear->plug.undo_write = snd_pcm_plugin_undo_write_generic; | ||||
| 	linear->plug.slave = slave; | ||||
| 	linear->plug.close_slave = close_slave; | ||||
| 	linear->plug.gen.slave = slave; | ||||
| 	linear->plug.gen.close_slave = close_slave; | ||||
| 
 | ||||
| 	err = snd_pcm_new(&pcm, SND_PCM_TYPE_LINEAR, name, slave->stream, slave->mode); | ||||
| 	if (err < 0) { | ||||
|  |  | |||
|  | @ -152,6 +152,9 @@ typedef struct { | |||
| 	int (*delay)(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp); | ||||
| 	int (*resume)(snd_pcm_t *pcm); | ||||
| 	int (*poll_ask)(snd_pcm_t *pcm); | ||||
| 	int (*link_fd)(snd_pcm_t *pcm); | ||||
| 	int (*link)(snd_pcm_t *pcm1, snd_pcm_t *pcm2); | ||||
| 	int (*unlink)(snd_pcm_t *pcm); | ||||
| 	snd_pcm_sframes_t (*rewind)(snd_pcm_t *pcm, snd_pcm_uframes_t frames); | ||||
| 	snd_pcm_sframes_t (*forward)(snd_pcm_t *pcm, snd_pcm_uframes_t frames); | ||||
| 	snd_pcm_sframes_t (*writei)(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size); | ||||
|  | @ -218,10 +221,6 @@ struct _snd_pcm { | |||
| 	struct list_head async_handlers; | ||||
| }; | ||||
| 
 | ||||
| /* FIXME */ | ||||
| #define _snd_pcm_link_descriptor _snd_pcm_poll_descriptor | ||||
| #define _snd_pcm_async_descriptor _snd_pcm_poll_descriptor | ||||
| 
 | ||||
| int snd_pcm_new(snd_pcm_t **pcmp, snd_pcm_type_t type, const char *name, | ||||
| 		snd_pcm_stream_t stream, int mode); | ||||
| int snd_pcm_free(snd_pcm_t *pcm); | ||||
|  | @ -266,6 +265,8 @@ snd_pcm_sframes_t snd_pcm_write_mmap(snd_pcm_t *pcm, snd_pcm_uframes_t size); | |||
| int snd_pcm_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info); | ||||
| int snd_pcm_channel_info_shm(snd_pcm_t *pcm, snd_pcm_channel_info_t *info, int shmid); | ||||
| int _snd_pcm_poll_descriptor(snd_pcm_t *pcm); | ||||
| int _snd_pcm_link_descriptor(snd_pcm_t *pcm); | ||||
| #define _snd_pcm_async_descriptor _snd_pcm_poll_descriptor /* FIXME */ | ||||
| 
 | ||||
| /* handle special error cases */ | ||||
| static inline int snd_pcm_check_error(snd_pcm_t *pcm, int err) | ||||
|  | @ -820,4 +821,3 @@ typedef union snd_tmp_double { | |||
| 	double d; | ||||
| 	int64_t l; | ||||
| } snd_tmp_double_t; | ||||
| 
 | ||||
|  |  | |||
|  | @ -312,7 +312,7 @@ static int snd_pcm_mulaw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
| 				       snd_pcm_mulaw_hw_refine_cchange, | ||||
| 				       snd_pcm_mulaw_hw_refine_sprepare, | ||||
| 				       snd_pcm_mulaw_hw_refine_schange, | ||||
| 				       snd_pcm_plugin_hw_refine_slave); | ||||
| 				       snd_pcm_generic_hw_refine); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_mulaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | ||||
|  | @ -323,7 +323,7 @@ static int snd_pcm_mulaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | |||
| 					  snd_pcm_mulaw_hw_refine_cchange, | ||||
| 					  snd_pcm_mulaw_hw_refine_sprepare, | ||||
| 					  snd_pcm_mulaw_hw_refine_schange, | ||||
| 					  snd_pcm_plugin_hw_params_slave); | ||||
| 					  snd_pcm_generic_hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 
 | ||||
|  | @ -401,23 +401,23 @@ static void snd_pcm_mulaw_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 		snd_pcm_dump_setup(pcm, out); | ||||
| 	} | ||||
| 	snd_output_printf(out, "Slave: "); | ||||
| 	snd_pcm_dump(mulaw->plug.slave, out); | ||||
| 	snd_pcm_dump(mulaw->plug.gen.slave, out); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_mulaw_ops = { | ||||
| 	.close = snd_pcm_plugin_close, | ||||
| 	.info = snd_pcm_plugin_info, | ||||
| 	.close = snd_pcm_generic_close, | ||||
| 	.info = snd_pcm_generic_info, | ||||
| 	.hw_refine = snd_pcm_mulaw_hw_refine, | ||||
| 	.hw_params = snd_pcm_mulaw_hw_params, | ||||
| 	.hw_free = snd_pcm_plugin_hw_free, | ||||
| 	.sw_params = snd_pcm_plugin_sw_params, | ||||
| 	.channel_info = snd_pcm_plugin_channel_info, | ||||
| 	.hw_free = snd_pcm_generic_hw_free, | ||||
| 	.sw_params = snd_pcm_generic_sw_params, | ||||
| 	.channel_info = snd_pcm_generic_channel_info, | ||||
| 	.dump = snd_pcm_mulaw_dump, | ||||
| 	.nonblock = snd_pcm_plugin_nonblock, | ||||
| 	.async = snd_pcm_plugin_async, | ||||
| 	.poll_revents = snd_pcm_plugin_poll_revents, | ||||
| 	.mmap = snd_pcm_plugin_mmap, | ||||
| 	.munmap = snd_pcm_plugin_munmap, | ||||
| 	.nonblock = snd_pcm_generic_nonblock, | ||||
| 	.async = snd_pcm_generic_async, | ||||
| 	.poll_revents = snd_pcm_generic_poll_revents, | ||||
| 	.mmap = snd_pcm_generic_mmap, | ||||
| 	.munmap = snd_pcm_generic_munmap, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -451,8 +451,8 @@ int snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfor | |||
| 	mulaw->plug.write = snd_pcm_mulaw_write_areas; | ||||
| 	mulaw->plug.undo_read = snd_pcm_plugin_undo_read_generic; | ||||
| 	mulaw->plug.undo_write = snd_pcm_plugin_undo_write_generic; | ||||
| 	mulaw->plug.slave = slave; | ||||
| 	mulaw->plug.close_slave = close_slave; | ||||
| 	mulaw->plug.gen.slave = slave; | ||||
| 	mulaw->plug.gen.close_slave = close_slave; | ||||
| 
 | ||||
| 	err = snd_pcm_new(&pcm, SND_PCM_TYPE_MULAW, name, slave->stream, slave->mode); | ||||
| 	if (err < 0) { | ||||
|  |  | |||
|  | @ -45,9 +45,8 @@ enum snd_pcm_plug_route_policy { | |||
| }; | ||||
| 
 | ||||
| typedef struct { | ||||
| 	snd_pcm_generic_t gen; | ||||
| 	snd_pcm_t *req_slave; | ||||
| 	int close_slave; | ||||
| 	snd_pcm_t *slave; | ||||
| 	snd_pcm_format_t sformat; | ||||
| 	int schannels; | ||||
| 	int srate; | ||||
|  | @ -65,11 +64,11 @@ static int snd_pcm_plug_close(snd_pcm_t *pcm) | |||
| 	int err, result = 0; | ||||
| 	if (plug->ttable) | ||||
| 		free(plug->ttable); | ||||
| 	if (plug->slave != plug->req_slave) { | ||||
| 	if (plug->gen.slave != plug->req_slave) { | ||||
| 		SNDERR("plug slaves mismatch"); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 	if (plug->close_slave) { | ||||
| 	if (plug->gen.close_slave) { | ||||
| 		snd_pcm_unlink_hw_ptr(pcm, plug->req_slave); | ||||
| 		snd_pcm_unlink_appl_ptr(pcm, plug->req_slave); | ||||
| 		err = snd_pcm_close(plug->req_slave); | ||||
|  | @ -80,24 +79,6 @@ static int snd_pcm_plug_close(snd_pcm_t *pcm) | |||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_plug_nonblock(snd_pcm_t *pcm, int nonblock) | ||||
| { | ||||
| 	snd_pcm_plug_t *plug = pcm->private_data; | ||||
| 	return snd_pcm_nonblock(plug->slave, nonblock); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_plug_async(snd_pcm_t *pcm, int sig, pid_t pid) | ||||
| { | ||||
| 	snd_pcm_plug_t *plug = pcm->private_data; | ||||
| 	return snd_pcm_async(plug->slave, sig, pid); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_plug_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) | ||||
| { | ||||
| 	snd_pcm_plug_t *plug = pcm->private_data; | ||||
| 	return snd_pcm_poll_descriptors_revents(plug->slave, pfds, nfds, revents); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_plug_info(snd_pcm_t *pcm, snd_pcm_info_t *info) | ||||
| { | ||||
| 	snd_pcm_plug_t *plug = pcm->private_data; | ||||
|  | @ -320,11 +301,11 @@ static void snd_pcm_plug_clear(snd_pcm_t *pcm) | |||
| 	snd_pcm_plug_t *plug = pcm->private_data; | ||||
| 	snd_pcm_t *slave = plug->req_slave; | ||||
| 	/* Clear old plugins */ | ||||
| 	if (plug->slave != slave) { | ||||
| 		snd_pcm_unlink_hw_ptr(pcm, plug->slave); | ||||
| 		snd_pcm_unlink_appl_ptr(pcm, plug->slave); | ||||
| 		snd_pcm_close(plug->slave); | ||||
| 		plug->slave = slave; | ||||
| 	if (plug->gen.slave != slave) { | ||||
| 		snd_pcm_unlink_hw_ptr(pcm, plug->gen.slave); | ||||
| 		snd_pcm_unlink_appl_ptr(pcm, plug->gen.slave); | ||||
| 		snd_pcm_close(plug->gen.slave); | ||||
| 		plug->gen.slave = slave; | ||||
| 		pcm->fast_ops = slave->fast_ops; | ||||
| 		pcm->fast_op_arg = slave->fast_op_arg; | ||||
| 	} | ||||
|  | @ -344,7 +325,7 @@ static int snd_pcm_plug_change_rate(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm_plu | |||
| 	assert(snd_pcm_format_linear(slv->format)); | ||||
| 	if (clt->rate == slv->rate) | ||||
| 		return 0; | ||||
| 	err = snd_pcm_rate_open(new, NULL, slv->format, slv->rate, plug->slave, plug->slave != plug->req_slave); | ||||
| 	err = snd_pcm_rate_open(new, NULL, slv->format, slv->rate, plug->gen.slave, plug->gen.slave != plug->req_slave); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	slv->access = clt->access; | ||||
|  | @ -445,7 +426,7 @@ static int snd_pcm_plug_change_channels(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm | |||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	err = snd_pcm_route_open(new, NULL, slv->format, (int) slv->channels, ttable, tt_ssize, tt_cused, tt_sused, plug->slave, plug->slave != plug->req_slave); | ||||
| 	err = snd_pcm_route_open(new, NULL, slv->format, (int) slv->channels, ttable, tt_ssize, tt_cused, tt_sused, plug->gen.slave, plug->gen.slave != plug->req_slave); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	slv->channels = clt->channels; | ||||
|  | @ -525,7 +506,7 @@ static int snd_pcm_plug_change_format(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm_p | |||
| 		else | ||||
| 			cfmt = SND_PCM_FORMAT_S16; | ||||
| 	} | ||||
| 	err = f(new, NULL, slv->format, plug->slave, plug->slave != plug->req_slave); | ||||
| 	err = f(new, NULL, slv->format, plug->gen.slave, plug->gen.slave != plug->req_slave); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	slv->format = cfmt; | ||||
|  | @ -539,7 +520,7 @@ static int snd_pcm_plug_change_access(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm_p | |||
| 	int err; | ||||
| 	if (clt->access == slv->access) | ||||
| 		return 0; | ||||
| 	err = snd_pcm_copy_open(new, NULL, plug->slave, plug->slave != plug->req_slave); | ||||
| 	err = snd_pcm_copy_open(new, NULL, plug->gen.slave, plug->gen.slave != plug->req_slave); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	slv->access = clt->access; | ||||
|  | @ -575,7 +556,7 @@ static int snd_pcm_plug_insert_plugins(snd_pcm_t *pcm, | |||
| 			return err; | ||||
| 		} | ||||
| 		if (err) { | ||||
| 			plug->slave = new; | ||||
| 			plug->gen.slave = new; | ||||
| 			pcm->fast_ops = new->fast_ops; | ||||
| 			pcm->fast_op_arg = new->fast_op_arg; | ||||
| 		} | ||||
|  | @ -593,7 +574,7 @@ static int snd_pcm_plug_insert_plugins(snd_pcm_t *pcm, | |||
| 		} | ||||
| 		assert(err); | ||||
| 		assert(plug->ttable_ok); | ||||
| 		plug->slave = new; | ||||
| 		plug->gen.slave = new; | ||||
| 		pcm->fast_ops = new->fast_ops; | ||||
| 		pcm->fast_op_arg = new->fast_op_arg; | ||||
| 	} | ||||
|  | @ -908,7 +889,7 @@ static int snd_pcm_plug_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
| 		if (err < 0) | ||||
| 			return err; | ||||
| 	} | ||||
| 	slave = plug->slave; | ||||
| 	slave = plug->gen.slave; | ||||
| 	err = _snd_pcm_hw_params(slave, params); | ||||
| 	if (err < 0) { | ||||
| 		snd_pcm_plug_clear(pcm); | ||||
|  | @ -924,30 +905,18 @@ static int snd_pcm_plug_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
| static int snd_pcm_plug_hw_free(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_plug_t *plug = pcm->private_data; | ||||
| 	snd_pcm_t *slave = plug->slave; | ||||
| 	snd_pcm_t *slave = plug->gen.slave; | ||||
| 	int err = snd_pcm_hw_free(slave); | ||||
| 	snd_pcm_plug_clear(pcm); | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_plug_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) | ||||
| { | ||||
| 	snd_pcm_plug_t *plug = pcm->private_data; | ||||
| 	return snd_pcm_sw_params(plug->slave, params); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_plug_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info) | ||||
| { | ||||
| 	snd_pcm_plug_t *plug = pcm->private_data; | ||||
| 	return snd_pcm_channel_info(plug->slave, info); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_plug_mmap(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_plug_t *plug = pcm->private_data; | ||||
| 	pcm->mmap_channels = plug->slave->mmap_channels; | ||||
| 	pcm->running_areas = plug->slave->running_areas; | ||||
| 	pcm->stopped_areas = plug->slave->stopped_areas; | ||||
| 	pcm->mmap_channels = plug->gen.slave->mmap_channels; | ||||
| 	pcm->running_areas = plug->gen.slave->running_areas; | ||||
| 	pcm->stopped_areas = plug->gen.slave->stopped_areas; | ||||
| 	pcm->mmap_shadow = 1; | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -966,7 +935,7 @@ static void snd_pcm_plug_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| { | ||||
| 	snd_pcm_plug_t *plug = pcm->private_data; | ||||
| 	snd_output_printf(out, "Plug PCM: "); | ||||
| 	snd_pcm_dump(plug->slave, out); | ||||
| 	snd_pcm_dump(plug->gen.slave, out); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_plug_ops = { | ||||
|  | @ -975,12 +944,12 @@ static snd_pcm_ops_t snd_pcm_plug_ops = { | |||
| 	.hw_refine = snd_pcm_plug_hw_refine, | ||||
| 	.hw_params = snd_pcm_plug_hw_params, | ||||
| 	.hw_free = snd_pcm_plug_hw_free, | ||||
| 	.sw_params = snd_pcm_plug_sw_params, | ||||
| 	.channel_info = snd_pcm_plug_channel_info, | ||||
| 	.sw_params = snd_pcm_generic_sw_params, | ||||
| 	.channel_info = snd_pcm_generic_channel_info, | ||||
| 	.dump = snd_pcm_plug_dump, | ||||
| 	.nonblock = snd_pcm_plug_nonblock, | ||||
| 	.async = snd_pcm_plug_async, | ||||
| 	.poll_revents = snd_pcm_plug_poll_revents, | ||||
| 	.nonblock = snd_pcm_generic_nonblock, | ||||
| 	.async = snd_pcm_generic_async, | ||||
| 	.poll_revents = snd_pcm_generic_poll_revents, | ||||
| 	.mmap = snd_pcm_plug_mmap, | ||||
| 	.munmap = snd_pcm_plug_munmap, | ||||
| }; | ||||
|  | @ -1017,8 +986,8 @@ int snd_pcm_plug_open(snd_pcm_t **pcmp, | |||
| 	plug->sformat = sformat; | ||||
| 	plug->schannels = schannels; | ||||
| 	plug->srate = srate; | ||||
| 	plug->slave = plug->req_slave = slave; | ||||
| 	plug->close_slave = close_slave; | ||||
| 	plug->gen.slave = plug->req_slave = slave; | ||||
| 	plug->gen.close_slave = close_slave; | ||||
| 	plug->route_policy = route_policy; | ||||
| 	plug->ttable = ttable; | ||||
| 	plug->tt_ssize = tt_ssize; | ||||
|  |  | |||
|  | @ -137,74 +137,11 @@ void snd_pcm_plugin_init(snd_pcm_plugin_t *plugin) | |||
| 	snd_atomic_write_init(&plugin->watom); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_close(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	int err = 0; | ||||
| 	if (plugin->close_slave) | ||||
| 		err = snd_pcm_close(plugin->slave); | ||||
| 	free(plugin); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_nonblock(snd_pcm_t *pcm, int nonblock) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return snd_pcm_nonblock(plugin->slave, nonblock); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_async(snd_pcm_t *pcm, int sig, pid_t pid) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return snd_pcm_async(plugin->slave, sig, pid); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return snd_pcm_poll_descriptors_revents(plugin->slave, pfds, nfds, revents); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_info(snd_pcm_t *pcm, snd_pcm_info_t * info) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return snd_pcm_info(plugin->slave, info); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_hw_free(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return snd_pcm_hw_free(plugin->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return snd_pcm_sw_params(plugin->slave, params); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info) | ||||
| { | ||||
| 	return snd_pcm_channel_info_shm(pcm, info, -1); | ||||
| } | ||||
| 
 | ||||
| snd_pcm_state_t snd_pcm_plugin_state(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return snd_pcm_state(plugin->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_hwsync(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return snd_pcm_hwsync(plugin->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	snd_pcm_sframes_t sd; | ||||
| 	int err = snd_pcm_delay(plugin->slave, &sd); | ||||
| 	int err = snd_pcm_delay(plugin->gen.slave, &sd); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	if (plugin->client_frames) | ||||
|  | @ -218,7 +155,7 @@ int snd_pcm_plugin_prepare(snd_pcm_t *pcm) | |||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	int err; | ||||
| 	snd_atomic_write_begin(&plugin->watom); | ||||
| 	err = snd_pcm_prepare(plugin->slave); | ||||
| 	err = snd_pcm_prepare(plugin->gen.slave); | ||||
| 	if (err < 0) { | ||||
| 		snd_atomic_write_end(&plugin->watom); | ||||
| 		return err; | ||||
|  | @ -239,7 +176,7 @@ static int snd_pcm_plugin_reset(snd_pcm_t *pcm) | |||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	int err; | ||||
| 	snd_atomic_write_begin(&plugin->watom); | ||||
| 	err = snd_pcm_reset(plugin->slave); | ||||
| 	err = snd_pcm_reset(plugin->gen.slave); | ||||
| 	if (err < 0) { | ||||
| 		snd_atomic_write_end(&plugin->watom); | ||||
| 		return err; | ||||
|  | @ -255,30 +192,6 @@ static int snd_pcm_plugin_reset(snd_pcm_t *pcm) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_start(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return snd_pcm_start(plugin->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_drop(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return snd_pcm_drop(plugin->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_drain(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return snd_pcm_drain(plugin->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_pause(snd_pcm_t *pcm, int enable) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return snd_pcm_pause(plugin->slave, enable); | ||||
| } | ||||
| 
 | ||||
| snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
|  | @ -296,7 +209,7 @@ snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames | |||
| 	else | ||||
| 		sframes = frames; | ||||
| 	snd_atomic_write_begin(&plugin->watom); | ||||
| 	sframes = snd_pcm_rewind(plugin->slave, sframes); | ||||
| 	sframes = snd_pcm_rewind(plugin->gen.slave, sframes); | ||||
| 	if (sframes < 0) { | ||||
| 		snd_atomic_write_end(&plugin->watom); | ||||
| 		return sframes; | ||||
|  | @ -325,7 +238,7 @@ snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frame | |||
| 	else | ||||
| 		sframes = frames; | ||||
| 	snd_atomic_write_begin(&plugin->watom); | ||||
| 	sframes = INTERNAL(snd_pcm_forward)(plugin->slave, (snd_pcm_uframes_t) sframes); | ||||
| 	sframes = INTERNAL(snd_pcm_forward)(plugin->gen.slave, (snd_pcm_uframes_t) sframes); | ||||
| 	if ((snd_pcm_sframes_t) sframes < 0) { | ||||
| 		snd_atomic_write_end(&plugin->watom); | ||||
| 		return sframes; | ||||
|  | @ -337,27 +250,13 @@ snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frame | |||
| 	return n; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_resume(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return snd_pcm_resume(plugin->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_poll_ask(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	if (plugin->slave->fast_ops->poll_ask) | ||||
| 		return plugin->slave->fast_ops->poll_ask(plugin->slave->fast_op_arg); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm, | ||||
| 						    const snd_pcm_channel_area_t *areas, | ||||
| 						    snd_pcm_uframes_t offset, | ||||
| 						    snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	snd_pcm_t *slave = plugin->slave; | ||||
| 	snd_pcm_t *slave = plugin->gen.slave; | ||||
| 	snd_pcm_uframes_t xfer = 0; | ||||
| 	snd_pcm_sframes_t result; | ||||
| 	int err; | ||||
|  | @ -404,7 +303,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm, | |||
| 						   snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	snd_pcm_t *slave = plugin->slave; | ||||
| 	snd_pcm_t *slave = plugin->gen.slave; | ||||
| 	snd_pcm_uframes_t xfer = 0; | ||||
| 	snd_pcm_sframes_t result; | ||||
| 	 | ||||
|  | @ -483,7 +382,7 @@ snd_pcm_sframes_t snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm, | |||
| 					     snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	snd_pcm_t *slave = plugin->slave; | ||||
| 	snd_pcm_t *slave = plugin->gen.slave; | ||||
| 	const snd_pcm_channel_area_t *areas; | ||||
| 	snd_pcm_uframes_t appl_offset; | ||||
| 	snd_pcm_sframes_t slave_size; | ||||
|  | @ -549,7 +448,7 @@ snd_pcm_sframes_t snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm, | |||
| snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	snd_pcm_t *slave = plugin->slave; | ||||
| 	snd_pcm_t *slave = plugin->gen.slave; | ||||
| 	snd_pcm_sframes_t slave_size; | ||||
| 
 | ||||
| 	slave_size = snd_pcm_avail_update(slave); | ||||
|  | @ -617,16 +516,6 @@ snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
|  | @ -635,7 +524,7 @@ int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status) | |||
| 	snd_atomic_read_init(&ratom, &plugin->watom); | ||||
|  _again: | ||||
| 	snd_atomic_read_begin(&ratom); | ||||
| 	err = snd_pcm_status(plugin->slave, status); | ||||
| 	err = snd_pcm_status(plugin->gen.slave, status); | ||||
| 	if (err < 0) { | ||||
| 		snd_atomic_read_ok(&ratom); | ||||
| 		return err; | ||||
|  | @ -655,33 +544,24 @@ int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return snd_pcm_hw_refine(plugin->slave, params); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return _snd_pcm_hw_params(plugin->slave, params); | ||||
| } | ||||
| 
 | ||||
| snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = { | ||||
| 	.status = snd_pcm_plugin_status, | ||||
| 	.state = snd_pcm_plugin_state, | ||||
| 	.hwsync = snd_pcm_plugin_hwsync, | ||||
| 	.status = snd_pcm_generic_status, | ||||
| 	.state = snd_pcm_generic_state, | ||||
| 	.hwsync = snd_pcm_generic_hwsync, | ||||
| 	.delay = snd_pcm_plugin_delay, | ||||
| 	.prepare = snd_pcm_plugin_prepare, | ||||
| 	.reset = snd_pcm_plugin_reset, | ||||
| 	.start = snd_pcm_plugin_start, | ||||
| 	.drop = snd_pcm_plugin_drop, | ||||
| 	.drain = snd_pcm_plugin_drain, | ||||
| 	.pause = snd_pcm_plugin_pause, | ||||
| 	.start = snd_pcm_generic_start, | ||||
| 	.drop = snd_pcm_generic_drop, | ||||
| 	.drain = snd_pcm_generic_drain, | ||||
| 	.pause = snd_pcm_generic_pause, | ||||
| 	.rewind = snd_pcm_plugin_rewind, | ||||
| 	.forward = snd_pcm_plugin_forward, | ||||
| 	.resume = snd_pcm_plugin_resume, | ||||
| 	.poll_ask = snd_pcm_plugin_poll_ask, | ||||
| 	.resume = snd_pcm_generic_resume, | ||||
| 	.poll_ask = snd_pcm_generic_poll_ask, | ||||
| 	.link_fd = snd_pcm_generic_link_fd, | ||||
| 	.link = snd_pcm_generic_link, | ||||
| 	.unlink = snd_pcm_generic_unlink, | ||||
| 	.writei = snd_pcm_plugin_writei, | ||||
| 	.writen = snd_pcm_plugin_writen, | ||||
| 	.readi = snd_pcm_plugin_readi, | ||||
|  | @ -690,5 +570,4 @@ snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = { | |||
| 	.mmap_commit = snd_pcm_plugin_mmap_commit, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ | |||
|  */ | ||||
|    | ||||
| #include "iatomic.h" | ||||
| #include "pcm_generic.h" | ||||
| 
 | ||||
| typedef snd_pcm_uframes_t (*snd_pcm_slave_xfer_areas_func_t) | ||||
|      (snd_pcm_t *pcm,  | ||||
|  | @ -38,8 +39,7 @@ typedef snd_pcm_sframes_t (*snd_pcm_slave_xfer_areas_undo_func_t) | |||
|       snd_pcm_uframes_t slave_undo_size); | ||||
| 
 | ||||
| typedef struct { | ||||
| 	snd_pcm_t *slave; | ||||
| 	int close_slave; | ||||
| 	snd_pcm_generic_t gen; | ||||
| 	snd_pcm_slave_xfer_areas_func_t read; | ||||
| 	snd_pcm_slave_xfer_areas_func_t write; | ||||
| 	snd_pcm_slave_xfer_areas_undo_func_t undo_read; | ||||
|  | @ -52,24 +52,9 @@ typedef struct { | |||
| } snd_pcm_plugin_t;	 | ||||
| 
 | ||||
| void snd_pcm_plugin_init(snd_pcm_plugin_t *plugin); | ||||
| int snd_pcm_plugin_close(snd_pcm_t *pcm); | ||||
| int snd_pcm_plugin_card(snd_pcm_t *pcm); | ||||
| int snd_pcm_plugin_nonblock(snd_pcm_t *pcm, int nonblock); | ||||
| int snd_pcm_plugin_async(snd_pcm_t *pcm, int sig, pid_t pid); | ||||
| int snd_pcm_plugin_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents); | ||||
| int snd_pcm_plugin_info(snd_pcm_t *pcm, snd_pcm_info_t * info); | ||||
| int snd_pcm_plugin_hw_free(snd_pcm_t *pcm); | ||||
| int snd_pcm_plugin_sw_refine(snd_pcm_t *pcm, snd_pcm_sw_params_t *params); | ||||
| int snd_pcm_plugin_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params); | ||||
| int snd_pcm_plugin_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info); | ||||
| int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status); | ||||
| snd_pcm_state_t snd_pcm_plugin_state(snd_pcm_t *pcm); | ||||
| int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp); | ||||
| int snd_pcm_plugin_prepare(snd_pcm_t *pcm); | ||||
| int snd_pcm_plugin_start(snd_pcm_t *pcm); | ||||
| int snd_pcm_plugin_drop(snd_pcm_t *pcm); | ||||
| int snd_pcm_plugin_drain(snd_pcm_t *pcm); | ||||
| int snd_pcm_plugin_pause(snd_pcm_t *pcm, int enable); | ||||
| snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames); | ||||
| snd_pcm_sframes_t snd_pcm_plugin_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size); | ||||
| snd_pcm_sframes_t snd_pcm_plugin_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size); | ||||
|  | @ -77,15 +62,6 @@ snd_pcm_sframes_t snd_pcm_plugin_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_ufr | |||
| snd_pcm_sframes_t snd_pcm_plugin_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size); | ||||
| snd_pcm_sframes_t snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t size); | ||||
| snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm); | ||||
| int snd_pcm_plugin_mmap_status(snd_pcm_t *pcm); | ||||
| int snd_pcm_plugin_mmap_control(snd_pcm_t *pcm); | ||||
| int snd_pcm_plugin_mmap(snd_pcm_t *pcm); | ||||
| int snd_pcm_plugin_munmap_status(snd_pcm_t *pcm); | ||||
| int snd_pcm_plugin_munmap_control(snd_pcm_t *pcm); | ||||
| int snd_pcm_plugin_munmap(snd_pcm_t *pcm); | ||||
| int snd_pcm_plugin_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space); | ||||
| int snd_pcm_plugin_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); | ||||
| int snd_pcm_plugin_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); | ||||
| 
 | ||||
| extern snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops; | ||||
| 
 | ||||
|  |  | |||
|  | @ -66,8 +66,7 @@ typedef void (*rate_f)(const snd_pcm_channel_area_t *dst_areas, | |||
| 		       snd_pcm_rate_t *rate); | ||||
| 
 | ||||
| struct _snd_pcm_rate { | ||||
| 	snd_pcm_t *slave; | ||||
| 	int close_slave; | ||||
| 	snd_pcm_generic_t gen; | ||||
| 	snd_atomic_write_t watom; | ||||
| 	snd_pcm_uframes_t appl_ptr, hw_ptr; | ||||
| 	snd_pcm_uframes_t orig_avail_min; | ||||
|  | @ -497,18 +496,6 @@ static int snd_pcm_rate_hw_refine_cchange(snd_pcm_t *pcm, snd_pcm_hw_params_t *p | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	return snd_pcm_hw_refine(rate->slave, params); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	return _snd_pcm_hw_params(rate->slave, params); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_hw_refine(snd_pcm_t *pcm,  | ||||
| 				  snd_pcm_hw_params_t *params) | ||||
| { | ||||
|  | @ -517,13 +504,13 @@ static int snd_pcm_rate_hw_refine(snd_pcm_t *pcm, | |||
| 				       snd_pcm_rate_hw_refine_cchange, | ||||
| 				       snd_pcm_rate_hw_refine_sprepare, | ||||
| 				       snd_pcm_rate_hw_refine_schange, | ||||
| 				       snd_pcm_rate_hw_refine_slave); | ||||
| 				       snd_pcm_generic_hw_refine); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	snd_pcm_t *slave = rate->slave; | ||||
| 	snd_pcm_t *slave = rate->gen.slave; | ||||
| 	snd_pcm_format_t src_format, dst_format, pformat, sformat; | ||||
| 	unsigned int src_rate, dst_rate, channels, pwidth, swidth, chn; | ||||
| 	snd_pcm_uframes_t period_size, buffer_size; | ||||
|  | @ -531,7 +518,7 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | |||
| 					  snd_pcm_rate_hw_refine_cchange, | ||||
| 					  snd_pcm_rate_hw_refine_sprepare, | ||||
| 					  snd_pcm_rate_hw_refine_schange, | ||||
| 					  snd_pcm_rate_hw_params_slave); | ||||
| 					  snd_pcm_generic_hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 
 | ||||
|  | @ -620,13 +607,13 @@ static int snd_pcm_rate_hw_free(snd_pcm_t *pcm) | |||
| 		rate->pareas = NULL; | ||||
| 		rate->sareas = NULL; | ||||
| 	} | ||||
| 	return snd_pcm_hw_free(rate->slave); | ||||
| 	return snd_pcm_hw_free(rate->gen.slave); | ||||
| } | ||||
| 
 | ||||
| static void recalc(snd_pcm_t *pcm, snd_pcm_uframes_t *val) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	snd_pcm_t *slave = rate->slave; | ||||
| 	snd_pcm_t *slave = rate->gen.slave; | ||||
| 	unsigned long div; | ||||
| 
 | ||||
| 	if (*val == pcm->buffer_size) { | ||||
|  | @ -643,7 +630,7 @@ static void recalc(snd_pcm_t *pcm, snd_pcm_uframes_t *val) | |||
| static int snd_pcm_rate_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	snd_pcm_t *slave = rate->slave; | ||||
| 	snd_pcm_t *slave = rate->gen.slave; | ||||
| 	snd_pcm_sw_params_t *sparams; | ||||
| 	snd_pcm_uframes_t boundary1, boundary2; | ||||
| 
 | ||||
|  | @ -771,7 +758,7 @@ snd_pcm_rate_write_areas1(snd_pcm_t *pcm, | |||
| 			 snd_pcm_uframes_t slave_offset) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	rate->func(slave_areas, slave_offset, rate->slave->period_size, | ||||
| 	rate->func(slave_areas, slave_offset, rate->gen.slave->period_size, | ||||
| 		   areas, offset, pcm->period_size, | ||||
| 		   pcm->channels, rate); | ||||
| 	return 0; | ||||
|  | @ -786,7 +773,7 @@ snd_pcm_rate_read_areas1(snd_pcm_t *pcm, | |||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	rate->func(areas, offset, pcm->period_size, | ||||
| 		   slave_areas, slave_offset, rate->slave->period_size, | ||||
| 		   slave_areas, slave_offset, rate->gen.slave->period_size, | ||||
| 		   pcm->channels, rate); | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -796,7 +783,7 @@ static inline snd_pcm_sframes_t snd_pcm_rate_move_applptr(snd_pcm_t *pcm, snd_pc | |||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	snd_pcm_uframes_t orig_appl_ptr, appl_ptr = rate->appl_ptr, slave_appl_ptr; | ||||
| 	snd_pcm_sframes_t diff, ndiff; | ||||
| 	snd_pcm_t *slave = rate->slave; | ||||
| 	snd_pcm_t *slave = rate->gen.slave; | ||||
| 
 | ||||
| 	orig_appl_ptr = rate->appl_ptr; | ||||
| 	if (frames > 0) | ||||
|  | @ -804,7 +791,7 @@ static inline snd_pcm_sframes_t snd_pcm_rate_move_applptr(snd_pcm_t *pcm, snd_pc | |||
| 	else | ||||
| 		snd_pcm_mmap_appl_backward(pcm, -frames); | ||||
| 	slave_appl_ptr = | ||||
| 		(appl_ptr / pcm->period_size) * rate->slave->period_size; | ||||
| 		(appl_ptr / pcm->period_size) * rate->gen.slave->period_size; | ||||
| 	diff = slave_appl_ptr - *slave->appl.ptr; | ||||
| 	if (diff < -(snd_pcm_sframes_t)(slave->boundary / 2)) { | ||||
| 		diff = (slave->boundary - *slave->appl.ptr) + slave_appl_ptr; | ||||
|  | @ -814,16 +801,16 @@ static inline snd_pcm_sframes_t snd_pcm_rate_move_applptr(snd_pcm_t *pcm, snd_pc | |||
| 	if (diff == 0) | ||||
| 		return frames; | ||||
| 	if (diff > 0) { | ||||
| 		ndiff = snd_pcm_forward(rate->slave, diff); | ||||
| 		ndiff = snd_pcm_forward(rate->gen.slave, diff); | ||||
| 	} else { | ||||
| 		ndiff = snd_pcm_rewind(rate->slave, diff); | ||||
| 		ndiff = snd_pcm_rewind(rate->gen.slave, diff); | ||||
| 	} | ||||
| 	if (ndiff < 0) | ||||
| 		return diff; | ||||
| 	slave_appl_ptr = *slave->appl.ptr; | ||||
| 	rate->appl_ptr = | ||||
| 		(slave_appl_ptr / rate->slave->period_size) * pcm->period_size + | ||||
| 		snd_pcm_rate_client_frames(pcm, slave_appl_ptr % rate->slave->period_size) + | ||||
| 		(slave_appl_ptr / rate->gen.slave->period_size) * pcm->period_size + | ||||
| 		snd_pcm_rate_client_frames(pcm, slave_appl_ptr % rate->gen.slave->period_size) + | ||||
| 		orig_appl_ptr % pcm->period_size; | ||||
| 	diff = orig_appl_ptr - rate->appl_ptr; | ||||
| 	if (diff < -(snd_pcm_sframes_t)(slave->boundary / 2)) { | ||||
|  | @ -839,64 +826,19 @@ static inline snd_pcm_sframes_t snd_pcm_rate_move_applptr(snd_pcm_t *pcm, snd_pc | |||
| static inline void snd_pcm_rate_sync_hwptr(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	snd_pcm_uframes_t slave_hw_ptr = *rate->slave->hw.ptr; | ||||
| 	snd_pcm_uframes_t slave_hw_ptr = *rate->gen.slave->hw.ptr; | ||||
| 
 | ||||
| 	if (pcm->stream != SND_PCM_STREAM_PLAYBACK) | ||||
| 		return; | ||||
| 	rate->hw_ptr = | ||||
| 		(slave_hw_ptr / rate->slave->period_size) * pcm->period_size + | ||||
| 		snd_pcm_rate_client_frames(pcm, slave_hw_ptr % rate->slave->period_size); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_close(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	int err = 0; | ||||
| 	if (rate->close_slave) | ||||
| 		err = snd_pcm_close(rate->slave); | ||||
| 	free(rate); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_nonblock(snd_pcm_t *pcm, int nonblock) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	return snd_pcm_nonblock(rate->slave, nonblock); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_async(snd_pcm_t *pcm, int sig, pid_t pid) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	return snd_pcm_async(rate->slave, sig, pid); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	return snd_pcm_poll_descriptors_revents(rate->slave, pfds, nfds, revents); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_info(snd_pcm_t *pcm, snd_pcm_info_t * info) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	return snd_pcm_info(rate->slave, info); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info) | ||||
| { | ||||
| 	return snd_pcm_channel_info_shm(pcm, info, -1); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_state_t snd_pcm_rate_state(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	return snd_pcm_state(rate->slave); | ||||
| 		(slave_hw_ptr / rate->gen.slave->period_size) * pcm->period_size + | ||||
| 		snd_pcm_rate_client_frames(pcm, slave_hw_ptr % rate->gen.slave->period_size); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_hwsync(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	int err = snd_pcm_hwsync(rate->slave); | ||||
| 	int err = snd_pcm_hwsync(rate->gen.slave); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	snd_atomic_write_begin(&rate->watom); | ||||
|  | @ -921,7 +863,7 @@ static int snd_pcm_rate_prepare(snd_pcm_t *pcm) | |||
| 	int err; | ||||
| 
 | ||||
| 	snd_atomic_write_begin(&rate->watom); | ||||
| 	err = snd_pcm_prepare(rate->slave); | ||||
| 	err = snd_pcm_prepare(rate->gen.slave); | ||||
| 	if (err < 0) { | ||||
| 		snd_atomic_write_end(&rate->watom); | ||||
| 		return err; | ||||
|  | @ -940,7 +882,7 @@ static int snd_pcm_rate_reset(snd_pcm_t *pcm) | |||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	int err; | ||||
| 	snd_atomic_write_begin(&rate->watom); | ||||
| 	err = snd_pcm_reset(rate->slave); | ||||
| 	err = snd_pcm_reset(rate->gen.slave); | ||||
| 	if (err < 0) { | ||||
| 		snd_atomic_write_end(&rate->watom); | ||||
| 		return err; | ||||
|  | @ -954,30 +896,6 @@ static int snd_pcm_rate_reset(snd_pcm_t *pcm) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_start(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	return snd_pcm_start(rate->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_drop(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	return snd_pcm_drop(rate->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_drain(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	return snd_pcm_drain(rate->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_pause(snd_pcm_t *pcm, int enable) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	return snd_pcm_pause(rate->slave, enable); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_rate_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
|  | @ -1010,31 +928,25 @@ static snd_pcm_sframes_t snd_pcm_rate_forward(snd_pcm_t *pcm, snd_pcm_uframes_t | |||
| 	return n; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_resume(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	return snd_pcm_resume(rate->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_poll_ask(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	snd_pcm_uframes_t avail_min; | ||||
| 	int err; | ||||
| 
 | ||||
| 	if (rate->slave->fast_ops->poll_ask) { | ||||
| 		err = rate->slave->fast_ops->poll_ask(rate->slave->fast_op_arg); | ||||
| 	if (rate->gen.slave->fast_ops->poll_ask) { | ||||
| 		err = rate->gen.slave->fast_ops->poll_ask(rate->gen.slave->fast_op_arg); | ||||
| 		if (err < 0) | ||||
| 			return err; | ||||
| 	} | ||||
| 	avail_min = rate->appl_ptr % pcm->period_size; | ||||
| 	if (avail_min > 0) { | ||||
| 		recalc(pcm, &avail_min); | ||||
| 		if (avail_min < rate->slave->buffer_size && | ||||
| 		    avail_min != rate->slave->period_size) | ||||
| 		if (avail_min < rate->gen.slave->buffer_size && | ||||
| 		    avail_min != rate->gen.slave->period_size) | ||||
| 			avail_min++;	/* 1st small little rounding correction */ | ||||
| 		if (avail_min < rate->slave->buffer_size && | ||||
| 		    avail_min != rate->slave->period_size) | ||||
| 		if (avail_min < rate->gen.slave->buffer_size && | ||||
| 		    avail_min != rate->gen.slave->period_size) | ||||
| 			avail_min++;	/* 2nd small little rounding correction */ | ||||
| 		avail_min += rate->orig_avail_min; | ||||
| 	} else { | ||||
|  | @ -1043,7 +955,7 @@ static int snd_pcm_rate_poll_ask(snd_pcm_t *pcm) | |||
| 	if (rate->sw_params.avail_min == avail_min) | ||||
| 		return 0; | ||||
| 	rate->sw_params.avail_min = avail_min; | ||||
| 	return snd_pcm_sw_params(rate->slave, &rate->sw_params); | ||||
| 	return snd_pcm_sw_params(rate->gen.slave, &rate->sw_params); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_commit_next_period(snd_pcm_t *pcm, snd_pcm_uframes_t appl_offset) | ||||
|  | @ -1058,20 +970,20 @@ static int snd_pcm_rate_commit_next_period(snd_pcm_t *pcm, snd_pcm_uframes_t app | |||
| 
 | ||||
| 	areas = snd_pcm_mmap_areas(pcm); | ||||
| 	if (cont >= pcm->period_size) { | ||||
| 		result = snd_pcm_mmap_begin(rate->slave, &slave_areas, &slave_offset, &slave_frames); | ||||
| 		result = snd_pcm_mmap_begin(rate->gen.slave, &slave_areas, &slave_offset, &slave_frames); | ||||
| 		if (result < 0) | ||||
| 			return result; | ||||
| 		if (slave_frames < rate->slave->period_size) { | ||||
| 		if (slave_frames < rate->gen.slave->period_size) { | ||||
| 			snd_pcm_rate_write_areas1(pcm, areas, appl_offset, rate->sareas, 0); | ||||
| 			goto __partial; | ||||
| 		} | ||||
| 		snd_pcm_rate_write_areas1(pcm, areas, appl_offset, | ||||
| 					  slave_areas, slave_offset); | ||||
| 		result = snd_pcm_mmap_commit(rate->slave, slave_offset, rate->slave->period_size); | ||||
| 		if (result < (snd_pcm_sframes_t)rate->slave->period_size) { | ||||
| 		result = snd_pcm_mmap_commit(rate->gen.slave, slave_offset, rate->gen.slave->period_size); | ||||
| 		if (result < (snd_pcm_sframes_t)rate->gen.slave->period_size) { | ||||
| 			if (result < 0) | ||||
| 				return result; | ||||
| 			result = snd_pcm_rewind(rate->slave, result); | ||||
| 			result = snd_pcm_rewind(rate->gen.slave, result); | ||||
| 			if (result < 0) | ||||
| 				return result; | ||||
| 			return 0; | ||||
|  | @ -1089,36 +1001,36 @@ static int snd_pcm_rate_commit_next_period(snd_pcm_t *pcm, snd_pcm_uframes_t app | |||
| 		snd_pcm_rate_write_areas1(pcm, rate->pareas, 0, rate->sareas, 0); | ||||
| 
 | ||||
| 		/* ok, commit first fragment */ | ||||
| 		result = snd_pcm_mmap_begin(rate->slave, &slave_areas, &slave_offset, &slave_frames); | ||||
| 		result = snd_pcm_mmap_begin(rate->gen.slave, &slave_areas, &slave_offset, &slave_frames); | ||||
| 		if (result < 0) | ||||
| 			return result; | ||||
| 	      __partial: | ||||
| 		xfer = 0; | ||||
| 		cont = rate->slave->buffer_size - slave_offset; | ||||
| 		if (cont > rate->slave->period_size) | ||||
| 			cont = rate->slave->period_size; | ||||
| 		cont = rate->gen.slave->buffer_size - slave_offset; | ||||
| 		if (cont > rate->gen.slave->period_size) | ||||
| 			cont = rate->gen.slave->period_size; | ||||
| 		snd_pcm_areas_copy(slave_areas, slave_offset, | ||||
| 				   rate->sareas, 0, | ||||
| 				   pcm->channels, cont, | ||||
| 				   rate->slave->format); | ||||
| 		result = snd_pcm_mmap_commit(rate->slave, slave_offset, cont); | ||||
| 				   rate->gen.slave->format); | ||||
| 		result = snd_pcm_mmap_commit(rate->gen.slave, slave_offset, cont); | ||||
| 		if (result < (snd_pcm_sframes_t)cont) { | ||||
| 			if (result < 0) | ||||
| 				return result; | ||||
| 			result = snd_pcm_rewind(rate->slave, result); | ||||
| 			result = snd_pcm_rewind(rate->gen.slave, result); | ||||
| 			if (result < 0) | ||||
| 				return result; | ||||
| 			return 0; | ||||
| 		} | ||||
| 		xfer = cont; | ||||
| 
 | ||||
| 		if (xfer == rate->slave->period_size) | ||||
| 		if (xfer == rate->gen.slave->period_size) | ||||
| 			return 1; | ||||
| 		 | ||||
| 		/* commit second fragment */ | ||||
| 		cont = rate->slave->period_size - cont; | ||||
| 		cont = rate->gen.slave->period_size - cont; | ||||
| 		slave_frames = cont; | ||||
| 		result = snd_pcm_mmap_begin(rate->slave, &slave_areas, &slave_offset, &slave_frames); | ||||
| 		result = snd_pcm_mmap_begin(rate->gen.slave, &slave_areas, &slave_offset, &slave_frames); | ||||
| 		if (result < 0) | ||||
| 			return result; | ||||
| 		if (slave_offset) { | ||||
|  | @ -1128,12 +1040,12 @@ static int snd_pcm_rate_commit_next_period(snd_pcm_t *pcm, snd_pcm_uframes_t app | |||
| 		snd_pcm_areas_copy(slave_areas, slave_offset, | ||||
| 				   rate->sareas, xfer, | ||||
| 				   pcm->channels, cont, | ||||
| 				   rate->slave->format); | ||||
| 		result = snd_pcm_mmap_commit(rate->slave, slave_offset, cont); | ||||
| 				   rate->gen.slave->format); | ||||
| 		result = snd_pcm_mmap_commit(rate->gen.slave, slave_offset, cont); | ||||
| 		if (result < (snd_pcm_sframes_t)cont) { | ||||
| 			if (result < 0) | ||||
| 				return result; | ||||
| 			result = snd_pcm_rewind(rate->slave, result + xfer); | ||||
| 			result = snd_pcm_rewind(rate->gen.slave, result + xfer); | ||||
| 			if (result < 0) | ||||
| 				return result; | ||||
| 			return 0; | ||||
|  | @ -1154,54 +1066,54 @@ static int snd_pcm_rate_grab_next_period(snd_pcm_t *pcm, snd_pcm_uframes_t hw_of | |||
| 
 | ||||
| 	areas = snd_pcm_mmap_areas(pcm); | ||||
| 	if (cont >= pcm->period_size) { | ||||
| 		result = snd_pcm_mmap_begin(rate->slave, &slave_areas, &slave_offset, &slave_frames); | ||||
| 		result = snd_pcm_mmap_begin(rate->gen.slave, &slave_areas, &slave_offset, &slave_frames); | ||||
| 		if (result < 0) | ||||
| 			return result; | ||||
| 		if (slave_frames < rate->slave->period_size) | ||||
| 		if (slave_frames < rate->gen.slave->period_size) | ||||
| 			goto __partial; | ||||
| 		snd_pcm_rate_read_areas1(pcm, areas, hw_offset, | ||||
| 					 slave_areas, slave_offset); | ||||
| 		result = snd_pcm_mmap_commit(rate->slave, slave_offset, rate->slave->period_size); | ||||
| 		if (result < (snd_pcm_sframes_t)rate->slave->period_size) { | ||||
| 		result = snd_pcm_mmap_commit(rate->gen.slave, slave_offset, rate->gen.slave->period_size); | ||||
| 		if (result < (snd_pcm_sframes_t)rate->gen.slave->period_size) { | ||||
| 			if (result < 0) | ||||
| 				return result; | ||||
| 			result = snd_pcm_rewind(rate->slave, result); | ||||
| 			result = snd_pcm_rewind(rate->gen.slave, result); | ||||
| 			if (result < 0) | ||||
| 				return result; | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} else { | ||||
| 		/* ok, grab first fragment */ | ||||
| 		result = snd_pcm_mmap_begin(rate->slave, &slave_areas, &slave_offset, &slave_frames); | ||||
| 		result = snd_pcm_mmap_begin(rate->gen.slave, &slave_areas, &slave_offset, &slave_frames); | ||||
| 		if (result < 0) | ||||
| 			return result; | ||||
| 	      __partial: | ||||
| 		xfer = 0; | ||||
| 		cont = rate->slave->buffer_size - slave_offset; | ||||
| 		if (cont > rate->slave->period_size) | ||||
| 			cont = rate->slave->period_size; | ||||
| 		cont = rate->gen.slave->buffer_size - slave_offset; | ||||
| 		if (cont > rate->gen.slave->period_size) | ||||
| 			cont = rate->gen.slave->period_size; | ||||
| 		snd_pcm_areas_copy(rate->sareas, 0, | ||||
| 				   slave_areas, slave_offset, | ||||
| 				   pcm->channels, cont, | ||||
| 				   rate->slave->format); | ||||
| 		result = snd_pcm_mmap_commit(rate->slave, slave_offset, cont); | ||||
| 				   rate->gen.slave->format); | ||||
| 		result = snd_pcm_mmap_commit(rate->gen.slave, slave_offset, cont); | ||||
| 		if (result < (snd_pcm_sframes_t)cont) { | ||||
| 			if (result < 0) | ||||
| 				return result; | ||||
| 			result = snd_pcm_rewind(rate->slave, result); | ||||
| 			result = snd_pcm_rewind(rate->gen.slave, result); | ||||
| 			if (result < 0) | ||||
| 				return result; | ||||
| 			return 0; | ||||
| 		} | ||||
| 		xfer = cont; | ||||
| 
 | ||||
| 		if (xfer == rate->slave->period_size) | ||||
| 		if (xfer == rate->gen.slave->period_size) | ||||
| 			goto __transfer; | ||||
| 
 | ||||
| 		/* grab second fragment */ | ||||
| 		cont = rate->slave->period_size - cont; | ||||
| 		cont = rate->gen.slave->period_size - cont; | ||||
| 		slave_frames = cont; | ||||
| 		result = snd_pcm_mmap_begin(rate->slave, &slave_areas, &slave_offset, &slave_frames); | ||||
| 		result = snd_pcm_mmap_begin(rate->gen.slave, &slave_areas, &slave_offset, &slave_frames); | ||||
| 		if (result < 0) | ||||
| 			return result; | ||||
| 		if (slave_offset) { | ||||
|  | @ -1211,12 +1123,12 @@ static int snd_pcm_rate_grab_next_period(snd_pcm_t *pcm, snd_pcm_uframes_t hw_of | |||
| 		snd_pcm_areas_copy(rate->sareas, xfer, | ||||
| 		                   slave_areas, slave_offset, | ||||
| 				   pcm->channels, cont, | ||||
| 				   rate->slave->format); | ||||
| 		result = snd_pcm_mmap_commit(rate->slave, slave_offset, cont); | ||||
| 				   rate->gen.slave->format); | ||||
| 		result = snd_pcm_mmap_commit(rate->gen.slave, slave_offset, cont); | ||||
| 		if (result < (snd_pcm_sframes_t)cont) { | ||||
| 			if (result < 0) | ||||
| 				return result; | ||||
| 			result = snd_pcm_rewind(rate->slave, result + xfer); | ||||
| 			result = snd_pcm_rewind(rate->gen.slave, result + xfer); | ||||
| 			if (result < 0) | ||||
| 				return result; | ||||
| 			return 0; | ||||
|  | @ -1249,7 +1161,7 @@ static snd_pcm_sframes_t snd_pcm_rate_mmap_commit(snd_pcm_t *pcm, | |||
| 						  snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	snd_pcm_t *slave = rate->slave; | ||||
| 	snd_pcm_t *slave = rate->gen.slave; | ||||
| 	snd_pcm_uframes_t appl_offset, xfer; | ||||
| 	snd_pcm_sframes_t slave_size; | ||||
| 	int err; | ||||
|  | @ -1269,7 +1181,7 @@ static snd_pcm_sframes_t snd_pcm_rate_mmap_commit(snd_pcm_t *pcm, | |||
| 	appl_offset = (rate->appl_ptr - xfer) % pcm->buffer_size; | ||||
| 	xfer = pcm->period_size - xfer; | ||||
| 	if (xfer >= size) { | ||||
| 		if (xfer == size && (snd_pcm_uframes_t)slave_size >= rate->slave->period_size) { | ||||
| 		if (xfer == size && (snd_pcm_uframes_t)slave_size >= rate->gen.slave->period_size) { | ||||
| 			err = snd_pcm_rate_commit_next_period(pcm, appl_offset); | ||||
| 			if (err < 0) | ||||
| 				return err; | ||||
|  | @ -1281,7 +1193,7 @@ static snd_pcm_sframes_t snd_pcm_rate_mmap_commit(snd_pcm_t *pcm, | |||
| 		snd_atomic_write_end(&rate->watom); | ||||
| 		return size; | ||||
| 	} else { | ||||
| 		if ((snd_pcm_uframes_t)slave_size >= rate->slave->period_size) { | ||||
| 		if ((snd_pcm_uframes_t)slave_size >= rate->gen.slave->period_size) { | ||||
| 			err = snd_pcm_rate_commit_next_period(pcm, appl_offset); | ||||
| 			if (err < 0) | ||||
| 				return err; | ||||
|  | @ -1294,10 +1206,10 @@ static snd_pcm_sframes_t snd_pcm_rate_mmap_commit(snd_pcm_t *pcm, | |||
| 		appl_offset += pcm->period_size; | ||||
| 		appl_offset %= pcm->buffer_size; | ||||
| 		size -= xfer; | ||||
| 		slave_size -= rate->slave->period_size; | ||||
| 		slave_size -= rate->gen.slave->period_size; | ||||
| 	} | ||||
| 	while ((snd_pcm_uframes_t)size >= pcm->period_size && | ||||
| 	       (snd_pcm_uframes_t)slave_size >= rate->slave->period_size) { | ||||
| 	       (snd_pcm_uframes_t)slave_size >= rate->gen.slave->period_size) { | ||||
| 		err = snd_pcm_rate_commit_next_period(pcm, appl_offset); | ||||
| 		if (err == 0) | ||||
| 			return xfer; | ||||
|  | @ -1305,7 +1217,7 @@ static snd_pcm_sframes_t snd_pcm_rate_mmap_commit(snd_pcm_t *pcm, | |||
| 			return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; | ||||
| 		xfer += pcm->period_size; | ||||
| 		size -= pcm->period_size; | ||||
| 		slave_size -= rate->slave->period_size; | ||||
| 		slave_size -= rate->gen.slave->period_size; | ||||
| 		appl_offset += pcm->period_size; | ||||
| 		appl_offset %= pcm->buffer_size; | ||||
| 		snd_atomic_write_begin(&rate->watom); | ||||
|  | @ -1325,7 +1237,7 @@ static snd_pcm_sframes_t snd_pcm_rate_mmap_commit(snd_pcm_t *pcm, | |||
| static snd_pcm_sframes_t snd_pcm_rate_avail_update(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
| 	snd_pcm_t *slave = rate->slave; | ||||
| 	snd_pcm_t *slave = rate->gen.slave; | ||||
| 	snd_pcm_uframes_t slave_size; | ||||
| 
 | ||||
| 	slave_size = snd_pcm_avail_update(slave); | ||||
|  | @ -1342,7 +1254,7 @@ static snd_pcm_sframes_t snd_pcm_rate_avail_update(snd_pcm_t *pcm) | |||
| 	size = pcm->buffer_size - xfer; | ||||
| 	hw_offset = snd_pcm_mmap_hw_offset(pcm); | ||||
| 	while (size >= pcm->period_size && | ||||
| 	       slave_size >= rate->slave->period_size) { | ||||
| 	       slave_size >= rate->gen.slave->period_size) { | ||||
| 		int err = snd_pcm_rate_grab_next_period(pcm, hw_offset); | ||||
| 		if (err < 0) | ||||
| 			return err; | ||||
|  | @ -1350,7 +1262,7 @@ static snd_pcm_sframes_t snd_pcm_rate_avail_update(snd_pcm_t *pcm) | |||
| 			return (snd_pcm_sframes_t)xfer; | ||||
| 		xfer += pcm->period_size; | ||||
| 		size -= pcm->period_size; | ||||
| 		slave_size -= rate->slave->period_size; | ||||
| 		slave_size -= rate->gen.slave->period_size; | ||||
| 		hw_offset += pcm->period_size; | ||||
| 		hw_offset %= pcm->buffer_size; | ||||
| 		snd_pcm_mmap_hw_forward(pcm, pcm->period_size); | ||||
|  | @ -1359,16 +1271,6 @@ static snd_pcm_sframes_t snd_pcm_rate_avail_update(snd_pcm_t *pcm) | |||
|  } | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_rate_status(snd_pcm_t *pcm, snd_pcm_status_t * status) | ||||
| { | ||||
| 	snd_pcm_rate_t *rate = pcm->private_data; | ||||
|  | @ -1377,7 +1279,7 @@ static int snd_pcm_rate_status(snd_pcm_t *pcm, snd_pcm_status_t * status) | |||
| 	snd_atomic_read_init(&ratom, &rate->watom); | ||||
|  _again: | ||||
| 	snd_atomic_read_begin(&ratom); | ||||
| 	err = snd_pcm_status(rate->slave, status); | ||||
| 	err = snd_pcm_status(rate->gen.slave, status); | ||||
| 	if (err < 0) { | ||||
| 		snd_atomic_read_ok(&ratom); | ||||
| 		return err; | ||||
|  | @ -1415,23 +1317,23 @@ static void snd_pcm_rate_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 		snd_pcm_dump_setup(pcm, out); | ||||
| 	} | ||||
| 	snd_output_printf(out, "Slave: "); | ||||
| 	snd_pcm_dump(rate->slave, out); | ||||
| 	snd_pcm_dump(rate->gen.slave, out); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_fast_ops_t snd_pcm_rate_fast_ops = { | ||||
| 	.status = snd_pcm_rate_status, | ||||
| 	.state = snd_pcm_rate_state, | ||||
| 	.state = snd_pcm_generic_state, | ||||
| 	.hwsync = snd_pcm_rate_hwsync, | ||||
| 	.delay = snd_pcm_rate_delay, | ||||
| 	.prepare = snd_pcm_rate_prepare, | ||||
| 	.reset = snd_pcm_rate_reset, | ||||
| 	.start = snd_pcm_rate_start, | ||||
| 	.drop = snd_pcm_rate_drop, | ||||
| 	.drain = snd_pcm_rate_drain, | ||||
| 	.pause = snd_pcm_rate_pause, | ||||
| 	.start = snd_pcm_generic_start, | ||||
| 	.drop = snd_pcm_generic_drop, | ||||
| 	.drain = snd_pcm_generic_drain, | ||||
| 	.pause = snd_pcm_generic_pause, | ||||
| 	.rewind = snd_pcm_rate_rewind, | ||||
| 	.forward = snd_pcm_rate_forward, | ||||
| 	.resume = snd_pcm_rate_resume, | ||||
| 	.resume = snd_pcm_generic_resume, | ||||
| 	.poll_ask = snd_pcm_rate_poll_ask, | ||||
| 	.writei = snd_pcm_mmap_writei, | ||||
| 	.writen = snd_pcm_mmap_writen, | ||||
|  | @ -1442,19 +1344,19 @@ static snd_pcm_fast_ops_t snd_pcm_rate_fast_ops = { | |||
| }; | ||||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_rate_ops = { | ||||
| 	.close = snd_pcm_rate_close, | ||||
| 	.info = snd_pcm_rate_info, | ||||
| 	.close = snd_pcm_generic_close, | ||||
| 	.info = snd_pcm_generic_info, | ||||
| 	.hw_refine = snd_pcm_rate_hw_refine, | ||||
| 	.hw_params = snd_pcm_rate_hw_params, | ||||
| 	.hw_free = snd_pcm_rate_hw_free, | ||||
| 	.sw_params = snd_pcm_rate_sw_params, | ||||
| 	.channel_info = snd_pcm_rate_channel_info, | ||||
| 	.channel_info = snd_pcm_generic_channel_info, | ||||
| 	.dump = snd_pcm_rate_dump, | ||||
| 	.nonblock = snd_pcm_rate_nonblock, | ||||
| 	.async = snd_pcm_rate_async, | ||||
| 	.poll_revents = snd_pcm_rate_poll_revents, | ||||
| 	.mmap = snd_pcm_rate_mmap, | ||||
| 	.munmap = snd_pcm_rate_munmap, | ||||
| 	.nonblock = snd_pcm_generic_nonblock, | ||||
| 	.async = snd_pcm_generic_async, | ||||
| 	.poll_revents = snd_pcm_generic_poll_revents, | ||||
| 	.mmap = snd_pcm_generic_mmap, | ||||
| 	.munmap = snd_pcm_generic_munmap, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1484,8 +1386,8 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sform | |||
| 	if (!rate) { | ||||
| 		return -ENOMEM; | ||||
| 	} | ||||
| 	rate->slave = slave; | ||||
| 	rate->close_slave = close_slave; | ||||
| 	rate->gen.slave = slave; | ||||
| 	rate->gen.close_slave = close_slave; | ||||
| 	rate->type = RATE_TYPE_LINEAR; | ||||
| 	rate->srate = srate; | ||||
| 	rate->sformat = sformat; | ||||
|  |  | |||
|  | @ -507,10 +507,8 @@ static int snd_pcm_route_close(snd_pcm_t *pcm) | |||
| { | ||||
| 	snd_pcm_route_t *route = pcm->private_data; | ||||
| 	snd_pcm_route_params_t *params = &route->params; | ||||
| 	int err = 0; | ||||
| 	unsigned int dst_channel; | ||||
| 	if (route->plug.close_slave) | ||||
| 		err = snd_pcm_close(route->plug.slave); | ||||
| 
 | ||||
| 	if (params->dsts) { | ||||
| 		for (dst_channel = 0; dst_channel < params->ndsts; ++dst_channel) { | ||||
| 			if (params->dsts[dst_channel].srcs != NULL) | ||||
|  | @ -518,8 +516,7 @@ static int snd_pcm_route_close(snd_pcm_t *pcm) | |||
| 		} | ||||
| 		free(params->dsts); | ||||
| 	} | ||||
| 	free(route); | ||||
| 	return 0; | ||||
| 	return snd_pcm_generic_close(pcm); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_route_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params) | ||||
|  | @ -618,19 +615,19 @@ static int snd_pcm_route_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
| 				       snd_pcm_route_hw_refine_cchange, | ||||
| 				       snd_pcm_route_hw_refine_sprepare, | ||||
| 				       snd_pcm_route_hw_refine_schange, | ||||
| 				       snd_pcm_plugin_hw_refine_slave); | ||||
| 				       snd_pcm_generic_hw_refine); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | ||||
| { | ||||
| 	snd_pcm_route_t *route = pcm->private_data; | ||||
| 	snd_pcm_t *slave = route->plug.slave; | ||||
| 	snd_pcm_t *slave = route->plug.gen.slave; | ||||
| 	snd_pcm_format_t src_format, dst_format; | ||||
| 	int err = snd_pcm_hw_params_slave(pcm, params, | ||||
| 					  snd_pcm_route_hw_refine_cchange, | ||||
| 					  snd_pcm_route_hw_refine_sprepare, | ||||
| 					  snd_pcm_route_hw_refine_schange, | ||||
| 					  snd_pcm_plugin_hw_params_slave); | ||||
| 					  snd_pcm_generic_hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 
 | ||||
|  | @ -671,7 +668,7 @@ snd_pcm_route_write_areas(snd_pcm_t *pcm, | |||
| 			  snd_pcm_uframes_t *slave_sizep) | ||||
| { | ||||
| 	snd_pcm_route_t *route = pcm->private_data; | ||||
| 	snd_pcm_t *slave = route->plug.slave; | ||||
| 	snd_pcm_t *slave = route->plug.gen.slave; | ||||
| 	if (size > *slave_sizep) | ||||
| 		size = *slave_sizep; | ||||
| 	snd_pcm_route_convert(slave_areas, slave_offset, | ||||
|  | @ -693,7 +690,7 @@ snd_pcm_route_read_areas(snd_pcm_t *pcm, | |||
| 			 snd_pcm_uframes_t *slave_sizep) | ||||
| { | ||||
| 	snd_pcm_route_t *route = pcm->private_data; | ||||
| 	snd_pcm_t *slave = route->plug.slave; | ||||
| 	snd_pcm_t *slave = route->plug.gen.slave; | ||||
| 	if (size > *slave_sizep) | ||||
| 		size = *slave_sizep; | ||||
| 	snd_pcm_route_convert(areas, offset,  | ||||
|  | @ -746,23 +743,23 @@ static void snd_pcm_route_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 		snd_pcm_dump_setup(pcm, out); | ||||
| 	} | ||||
| 	snd_output_printf(out, "Slave: "); | ||||
| 	snd_pcm_dump(route->plug.slave, out); | ||||
| 	snd_pcm_dump(route->plug.gen.slave, out); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_route_ops = { | ||||
| 	.close = snd_pcm_route_close, | ||||
| 	.info = snd_pcm_plugin_info, | ||||
| 	.info = snd_pcm_generic_info, | ||||
| 	.hw_refine = snd_pcm_route_hw_refine, | ||||
| 	.hw_params = snd_pcm_route_hw_params, | ||||
| 	.hw_free = snd_pcm_plugin_hw_free, | ||||
| 	.sw_params = snd_pcm_plugin_sw_params, | ||||
| 	.channel_info = snd_pcm_plugin_channel_info, | ||||
| 	.hw_free = snd_pcm_generic_hw_free, | ||||
| 	.sw_params = snd_pcm_generic_sw_params, | ||||
| 	.channel_info = snd_pcm_generic_channel_info, | ||||
| 	.dump = snd_pcm_route_dump, | ||||
| 	.nonblock = snd_pcm_plugin_nonblock, | ||||
| 	.async = snd_pcm_plugin_async, | ||||
| 	.poll_revents = snd_pcm_plugin_poll_revents, | ||||
| 	.mmap = snd_pcm_plugin_mmap, | ||||
| 	.munmap = snd_pcm_plugin_munmap, | ||||
| 	.nonblock = snd_pcm_generic_nonblock, | ||||
| 	.async = snd_pcm_generic_async, | ||||
| 	.poll_revents = snd_pcm_generic_poll_revents, | ||||
| 	.mmap = snd_pcm_generic_mmap, | ||||
| 	.munmap = snd_pcm_generic_munmap, | ||||
| }; | ||||
| 
 | ||||
| static int route_load_ttable(snd_pcm_route_params_t *params, snd_pcm_stream_t stream, | ||||
|  | @ -876,8 +873,8 @@ int snd_pcm_route_open(snd_pcm_t **pcmp, const char *name, | |||
| 	route->plug.write = snd_pcm_route_write_areas; | ||||
| 	route->plug.undo_read = snd_pcm_plugin_undo_read_generic; | ||||
| 	route->plug.undo_write = snd_pcm_plugin_undo_write_generic; | ||||
| 	route->plug.slave = slave; | ||||
| 	route->plug.close_slave = close_slave; | ||||
| 	route->plug.gen.slave = slave; | ||||
| 	route->plug.gen.close_slave = close_slave; | ||||
| 
 | ||||
| 	err = snd_pcm_new(&pcm, SND_PCM_TYPE_ROUTE, name, slave->stream, slave->mode); | ||||
| 	if (err < 0) { | ||||
|  |  | |||
|  | @ -269,8 +269,8 @@ static void get_current_volume(snd_pcm_softvol_t *svol) | |||
| 
 | ||||
| static void softvol_free(snd_pcm_softvol_t *svol) | ||||
| { | ||||
| 	if (svol->plug.close_slave) | ||||
| 		snd_pcm_close(svol->plug.slave); | ||||
| 	if (svol->plug.gen.close_slave) | ||||
| 		snd_pcm_close(svol->plug.gen.slave); | ||||
| 	if (svol->ctl) | ||||
| 		snd_ctl_close(svol->ctl); | ||||
| 	if (svol->dB_value && svol->dB_value != preset_dB_value) | ||||
|  | @ -378,18 +378,18 @@ static int snd_pcm_softvol_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params | |||
| 				       snd_pcm_softvol_hw_refine_cchange, | ||||
| 				       snd_pcm_softvol_hw_refine_sprepare, | ||||
| 				       snd_pcm_softvol_hw_refine_schange, | ||||
| 				       snd_pcm_plugin_hw_refine_slave); | ||||
| 				       snd_pcm_generic_hw_refine); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_softvol_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | ||||
| { | ||||
| 	snd_pcm_softvol_t *svol = pcm->private_data; | ||||
| 	snd_pcm_t *slave = svol->plug.slave; | ||||
| 	snd_pcm_t *slave = svol->plug.gen.slave; | ||||
| 	int err = snd_pcm_hw_params_slave(pcm, params, | ||||
| 					  snd_pcm_softvol_hw_refine_cchange, | ||||
| 					  snd_pcm_softvol_hw_refine_sprepare, | ||||
| 					  snd_pcm_softvol_hw_refine_schange, | ||||
| 					  snd_pcm_plugin_hw_params_slave); | ||||
| 					  snd_pcm_generic_hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	if (slave->format != SND_PCM_FORMAT_S16 && | ||||
|  | @ -459,7 +459,7 @@ static void snd_pcm_softvol_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 		snd_pcm_dump_setup(pcm, out); | ||||
| 	} | ||||
| 	snd_output_printf(out, "Slave: "); | ||||
| 	snd_pcm_dump(svol->plug.slave, out); | ||||
| 	snd_pcm_dump(svol->plug.gen.slave, out); | ||||
| } | ||||
| 
 | ||||
| static int add_user_ctl(snd_pcm_softvol_t *svol, snd_ctl_elem_info_t *cinfo, int count) | ||||
|  | @ -573,18 +573,18 @@ static int softvol_load_control(snd_pcm_t *pcm, snd_pcm_softvol_t *svol, | |||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_softvol_ops = { | ||||
| 	.close = snd_pcm_softvol_close, | ||||
| 	.info = snd_pcm_plugin_info, | ||||
| 	.info = snd_pcm_generic_info, | ||||
| 	.hw_refine = snd_pcm_softvol_hw_refine, | ||||
| 	.hw_params = snd_pcm_softvol_hw_params, | ||||
| 	.hw_free = snd_pcm_plugin_hw_free, | ||||
| 	.sw_params = snd_pcm_plugin_sw_params, | ||||
| 	.channel_info = snd_pcm_plugin_channel_info, | ||||
| 	.hw_free = snd_pcm_generic_hw_free, | ||||
| 	.sw_params = snd_pcm_generic_sw_params, | ||||
| 	.channel_info = snd_pcm_generic_channel_info, | ||||
| 	.dump = snd_pcm_softvol_dump, | ||||
| 	.nonblock = snd_pcm_plugin_nonblock, | ||||
| 	.async = snd_pcm_plugin_async, | ||||
| 	.poll_revents = snd_pcm_plugin_poll_revents, | ||||
| 	.mmap = snd_pcm_plugin_mmap, | ||||
| 	.munmap = snd_pcm_plugin_munmap, | ||||
| 	.nonblock = snd_pcm_generic_nonblock, | ||||
| 	.async = snd_pcm_generic_async, | ||||
| 	.poll_revents = snd_pcm_generic_poll_revents, | ||||
| 	.mmap = snd_pcm_generic_mmap, | ||||
| 	.munmap = snd_pcm_generic_munmap, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -640,8 +640,8 @@ int snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name, | |||
| 	svol->plug.write = snd_pcm_softvol_write_areas; | ||||
| 	svol->plug.undo_read = snd_pcm_plugin_undo_read_generic; | ||||
| 	svol->plug.undo_write = snd_pcm_plugin_undo_write_generic; | ||||
| 	svol->plug.slave = slave; | ||||
| 	svol->plug.close_slave = close_slave; | ||||
| 	svol->plug.gen.slave = slave; | ||||
| 	svol->plug.gen.close_slave = close_slave; | ||||
| 
 | ||||
| 	err = snd_pcm_new(&pcm, SND_PCM_TYPE_SOFTVOL, name, slave->stream, slave->mode); | ||||
| 	if (err < 0) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jaroslav Kysela
						Jaroslav Kysela