Home | History | Annotate | Download | only in pcm
      1 /**
      2  * \file pcm/pcm_generic.c
      3  * \ingroup PCM
      4  * \brief PCM Interface
      5  * \author Jaroslav Kysela <perex (at) perex.cz>
      6  * \date 2004
      7  */
      8 /*
      9  *  PCM - Common generic plugin code
     10  *  Copyright (c) 2004 by Jaroslav Kysela <perex (at) perex.cz>
     11  *
     12  *
     13  *   This library is free software; you can redistribute it and/or modify
     14  *   it under the terms of the GNU Lesser General Public License as
     15  *   published by the Free Software Foundation; either version 2.1 of
     16  *   the License, or (at your option) any later version.
     17  *
     18  *   This program is distributed in the hope that it will be useful,
     19  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     20  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     21  *   GNU Lesser General Public License for more details.
     22  *
     23  *   You should have received a copy of the GNU Lesser General Public
     24  *   License along with this library; if not, write to the Free Software
     25  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
     26  *
     27  */
     28 
     29 #include <sys/ioctl.h>
     30 #include <limits.h>
     31 #include "pcm_local.h"
     32 #include "pcm_generic.h"
     33 
     34 #ifndef DOC_HIDDEN
     35 
     36 int snd_pcm_generic_close(snd_pcm_t *pcm)
     37 {
     38 	snd_pcm_generic_t *generic = pcm->private_data;
     39 	int err = 0;
     40 	if (generic->close_slave)
     41 		err = snd_pcm_close(generic->slave);
     42 	free(generic);
     43 	return 0;
     44 }
     45 
     46 int snd_pcm_generic_nonblock(snd_pcm_t *pcm, int nonblock)
     47 {
     48 	snd_pcm_generic_t *generic = pcm->private_data;
     49 	return snd_pcm_nonblock(generic->slave, nonblock);
     50 }
     51 
     52 int snd_pcm_generic_async(snd_pcm_t *pcm, int sig, pid_t pid)
     53 {
     54 	snd_pcm_generic_t *generic = pcm->private_data;
     55 	return snd_pcm_async(generic->slave, sig, pid);
     56 }
     57 
     58 int snd_pcm_generic_poll_descriptors_count(snd_pcm_t *pcm)
     59 {
     60 	snd_pcm_generic_t *generic = pcm->private_data;
     61 	return snd_pcm_poll_descriptors_count(generic->slave);
     62 }
     63 
     64 int snd_pcm_generic_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space)
     65 {
     66 	snd_pcm_generic_t *generic = pcm->private_data;
     67 	return snd_pcm_poll_descriptors(generic->slave, pfds, space);
     68 }
     69 
     70 int snd_pcm_generic_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
     71 {
     72 	snd_pcm_generic_t *generic = pcm->private_data;
     73 	return snd_pcm_poll_descriptors_revents(generic->slave, pfds, nfds, revents);
     74 }
     75 
     76 int snd_pcm_generic_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
     77 {
     78 	snd_pcm_generic_t *generic = pcm->private_data;
     79 	return snd_pcm_info(generic->slave, info);
     80 }
     81 
     82 int snd_pcm_generic_hw_free(snd_pcm_t *pcm)
     83 {
     84 	snd_pcm_generic_t *generic = pcm->private_data;
     85 	return snd_pcm_hw_free(generic->slave);
     86 }
     87 
     88 int snd_pcm_generic_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
     89 {
     90 	snd_pcm_generic_t *generic = pcm->private_data;
     91 	return snd_pcm_sw_params(generic->slave, params);
     92 }
     93 
     94 int snd_pcm_generic_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
     95 {
     96 	snd_pcm_generic_t *generic = pcm->private_data;
     97 	return snd_pcm_hw_refine(generic->slave, params);
     98 }
     99 
    100 int snd_pcm_generic_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
    101 {
    102 	snd_pcm_generic_t *generic = pcm->private_data;
    103 	return _snd_pcm_hw_params(generic->slave, params);
    104 }
    105 
    106 int snd_pcm_generic_prepare(snd_pcm_t *pcm)
    107 {
    108 	snd_pcm_generic_t *generic = pcm->private_data;
    109 	return snd_pcm_prepare(generic->slave);
    110 }
    111 
    112 int snd_pcm_generic_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info)
    113 {
    114 	snd_pcm_generic_t *generic = pcm->private_data;
    115 	if (pcm->mmap_shadow) {
    116 		/* No own buffer is required - the plugin won't change
    117 		 * the data on the buffer, or do safely on-the-place
    118 		 * conversion
    119 		 */
    120 		return snd_pcm_channel_info(generic->slave, info);
    121 	} else {
    122 		/* Allocate own buffer */
    123 		return snd_pcm_channel_info_shm(pcm, info, -1);
    124 	}
    125 }
    126 
    127 int snd_pcm_generic_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
    128 {
    129 	snd_pcm_generic_t *generic = pcm->private_data;
    130 	return snd_pcm_status(generic->slave, status);
    131 }
    132 
    133 snd_pcm_state_t snd_pcm_generic_state(snd_pcm_t *pcm)
    134 {
    135 	snd_pcm_generic_t *generic = pcm->private_data;
    136 	return snd_pcm_state(generic->slave);
    137 }
    138 
    139 int snd_pcm_generic_hwsync(snd_pcm_t *pcm)
    140 {
    141 	snd_pcm_generic_t *generic = pcm->private_data;
    142 	return snd_pcm_hwsync(generic->slave);
    143 }
    144 
    145 int snd_pcm_generic_reset(snd_pcm_t *pcm)
    146 {
    147 	snd_pcm_generic_t *generic = pcm->private_data;
    148 	return snd_pcm_reset(generic->slave);
    149 }
    150 
    151 int snd_pcm_generic_start(snd_pcm_t *pcm)
    152 {
    153 	snd_pcm_generic_t *generic = pcm->private_data;
    154 	return snd_pcm_start(generic->slave);
    155 }
    156 
    157 int snd_pcm_generic_drop(snd_pcm_t *pcm)
    158 {
    159 	snd_pcm_generic_t *generic = pcm->private_data;
    160 	return snd_pcm_drop(generic->slave);
    161 }
    162 
    163 int snd_pcm_generic_drain(snd_pcm_t *pcm)
    164 {
    165 	snd_pcm_generic_t *generic = pcm->private_data;
    166 	return snd_pcm_drain(generic->slave);
    167 }
    168 
    169 int snd_pcm_generic_pause(snd_pcm_t *pcm, int enable)
    170 {
    171 	snd_pcm_generic_t *generic = pcm->private_data;
    172 	return snd_pcm_pause(generic->slave, enable);
    173 }
    174 
    175 int snd_pcm_generic_resume(snd_pcm_t *pcm)
    176 {
    177 	snd_pcm_generic_t *generic = pcm->private_data;
    178 	return snd_pcm_resume(generic->slave);
    179 }
    180 
    181 int snd_pcm_generic_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
    182 {
    183 	snd_pcm_generic_t *generic = pcm->private_data;
    184 	return snd_pcm_delay(generic->slave, delayp);
    185 }
    186 
    187 snd_pcm_sframes_t snd_pcm_generic_forwardable(snd_pcm_t *pcm)
    188 {
    189 	snd_pcm_generic_t *generic = pcm->private_data;
    190 	return snd_pcm_forwardable(generic->slave);
    191 }
    192 
    193 snd_pcm_sframes_t snd_pcm_generic_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
    194 {
    195 	snd_pcm_generic_t *generic = pcm->private_data;
    196 	return INTERNAL(snd_pcm_forward)(generic->slave, frames);
    197 }
    198 
    199 snd_pcm_sframes_t snd_pcm_generic_rewindable(snd_pcm_t *pcm)
    200 {
    201 	snd_pcm_generic_t *generic = pcm->private_data;
    202 	return snd_pcm_rewindable(generic->slave);
    203 }
    204 
    205 snd_pcm_sframes_t snd_pcm_generic_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
    206 {
    207 	snd_pcm_generic_t *generic = pcm->private_data;
    208 	return snd_pcm_rewind(generic->slave, frames);
    209 }
    210 
    211 int snd_pcm_generic_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
    212 {
    213 	snd_pcm_generic_t *generic = pcm1->private_data;
    214 	if (generic->slave->fast_ops->link)
    215 		return generic->slave->fast_ops->link(generic->slave->fast_op_arg, pcm2);
    216 	return -ENOSYS;
    217 }
    218 
    219 int snd_pcm_generic_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master)
    220 {
    221 	snd_pcm_generic_t *generic = pcm->private_data;
    222 	if (generic->slave->fast_ops->link_slaves)
    223 		return generic->slave->fast_ops->link_slaves(generic->slave->fast_op_arg, master);
    224 	return -ENOSYS;
    225 }
    226 
    227 int snd_pcm_generic_unlink(snd_pcm_t *pcm)
    228 {
    229 	snd_pcm_generic_t *generic = pcm->private_data;
    230 	if (generic->slave->fast_ops->unlink)
    231 		return generic->slave->fast_ops->unlink(generic->slave->fast_op_arg);
    232 	return -ENOSYS;
    233 }
    234 
    235 snd_pcm_sframes_t snd_pcm_generic_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
    236 {
    237 	snd_pcm_generic_t *generic = pcm->private_data;
    238 	return snd_pcm_writei(generic->slave, buffer, size);
    239 }
    240 
    241 snd_pcm_sframes_t snd_pcm_generic_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
    242 {
    243 	snd_pcm_generic_t *generic = pcm->private_data;
    244 	return snd_pcm_writen(generic->slave, bufs, size);
    245 }
    246 
    247 snd_pcm_sframes_t snd_pcm_generic_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
    248 {
    249 	snd_pcm_generic_t *generic = pcm->private_data;
    250 	return snd_pcm_readi(generic->slave, buffer, size);
    251 }
    252 
    253 snd_pcm_sframes_t snd_pcm_generic_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
    254 {
    255 	snd_pcm_generic_t *generic = pcm->private_data;
    256 	return snd_pcm_readn(generic->slave, bufs, size);
    257 }
    258 
    259 snd_pcm_sframes_t snd_pcm_generic_mmap_commit(snd_pcm_t *pcm,
    260 					      snd_pcm_uframes_t offset,
    261 					      snd_pcm_uframes_t size)
    262 {
    263 	snd_pcm_generic_t *generic = pcm->private_data;
    264 	return snd_pcm_mmap_commit(generic->slave, offset, size);
    265 }
    266 
    267 snd_pcm_sframes_t snd_pcm_generic_avail_update(snd_pcm_t *pcm)
    268 {
    269 	snd_pcm_generic_t *generic = pcm->private_data;
    270 	return snd_pcm_avail_update(generic->slave);
    271 }
    272 
    273 int snd_pcm_generic_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
    274 			       snd_htimestamp_t *tstamp)
    275 {
    276 	snd_pcm_generic_t *generic = pcm->private_data;
    277 	return snd_pcm_htimestamp(generic->slave, avail, tstamp);
    278 }
    279 
    280 /* stand-alone version - similar like snd_pcm_hw_htimestamp but
    281  * taking the tstamp via gettimestamp().
    282  */
    283 int snd_pcm_generic_real_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
    284 				    snd_htimestamp_t *tstamp)
    285 {
    286 	snd_pcm_sframes_t avail1;
    287 	int ok = 0;
    288 
    289 	while (1) {
    290 		avail1 = snd_pcm_avail_update(pcm);
    291 		if (avail1 < 0)
    292 			return avail1;
    293 		if (ok && (snd_pcm_uframes_t)avail1 == *avail)
    294 			break;
    295 		*avail = avail1;
    296 		gettimestamp(tstamp, pcm->monotonic);
    297 		ok = 1;
    298 	}
    299 	return 0;
    300 }
    301 
    302 int snd_pcm_generic_mmap(snd_pcm_t *pcm)
    303 {
    304 	if (pcm->mmap_shadow) {
    305 		/* Copy the slave mmapped buffer data */
    306 		snd_pcm_generic_t *generic = pcm->private_data;
    307 		pcm->mmap_channels = generic->slave->mmap_channels;
    308 		pcm->running_areas = generic->slave->running_areas;
    309 		pcm->stopped_areas = generic->slave->stopped_areas;
    310 	}
    311 	return 0;
    312 }
    313 
    314 int snd_pcm_generic_munmap(snd_pcm_t *pcm)
    315 {
    316 	if (pcm->mmap_shadow) {
    317 		/* Clean up */
    318 		pcm->mmap_channels = NULL;
    319 		pcm->running_areas = NULL;
    320 		pcm->stopped_areas = NULL;
    321 	}
    322 	return 0;
    323 }
    324 
    325 #endif /* DOC_HIDDEN */
    326