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