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