1/** 2 * \file pcm/pcm_generic.c 3 * \ingroup PCM 4 * \brief PCM Interface 5 * \author Jaroslav Kysela <perex@perex.cz> 6 * \date 2004 7 */ 8/* 9 * PCM - Common generic plugin code 10 * Copyright (c) 2004 by Jaroslav Kysela <perex@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 26 * 27 */ 28 29#include "pcm_local.h" 30#include "pcm_generic.h" 31#include <sys/ioctl.h> 32#include <limits.h> 33 34#ifndef DOC_HIDDEN 35 36int 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 err; 44} 45 46int 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 52int 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 58int 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 64int 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 70int 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 76int 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 82int 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 88int 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 94int 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 100int 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_internal(generic->slave, params); 104} 105 106int 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 112int 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 127int 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 133snd_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 139int 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 145int 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 151int 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 157int 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 163int 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 169int 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 175int 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 181int 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 187snd_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 193snd_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 199snd_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 205snd_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 211int 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 219int 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 227int 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 235snd_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 241snd_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 247snd_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 253snd_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 259snd_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 267snd_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 273int 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 */ 283int 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->tstamp_type); 297 ok = 1; 298 } 299 return 0; 300} 301 302int 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 314int 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 325snd_pcm_chmap_query_t **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm) 326{ 327 snd_pcm_generic_t *generic = pcm->private_data; 328 return snd_pcm_query_chmaps(generic->slave); 329} 330 331snd_pcm_chmap_t *snd_pcm_generic_get_chmap(snd_pcm_t *pcm) 332{ 333 snd_pcm_generic_t *generic = pcm->private_data; 334 return snd_pcm_get_chmap(generic->slave); 335} 336 337int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map) 338{ 339 snd_pcm_generic_t *generic = pcm->private_data; 340 return snd_pcm_set_chmap(generic->slave, map); 341} 342 343int snd_pcm_generic_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail ATTRIBUTE_UNUSED) 344{ 345 snd_pcm_generic_t *generic = pcm->private_data; 346 return snd_pcm_may_wait_for_avail_min(generic->slave, snd_pcm_mmap_avail(generic->slave)); 347} 348 349#endif /* DOC_HIDDEN */ 350