Imported Upstream version 1.0.29
[platform/upstream/alsa-lib.git] / src / pcm / pcm_generic.c
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
37 int 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 err;
45 }
46
47 int 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
53 int 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
59 int 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
65 int 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
71 int 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
77 int 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
83 int 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
89 int 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
95 int 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
101 int 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_internal(generic->slave, params);
105 }
106
107 int 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
113 int 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
128 int 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
134 snd_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
140 int 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
146 int 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
152 int 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
158 int 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
164 int 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
170 int 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
176 int 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
182 int 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
188 snd_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
194 snd_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
200 snd_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
206 snd_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
212 int 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
220 int 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
228 int 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
236 snd_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
242 snd_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
248 snd_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
254 snd_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
260 snd_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
268 snd_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
274 int 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  */
284 int 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->tstamp_type);
298                 ok = 1;
299         }
300         return 0;
301 }
302
303 int 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
315 int 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 snd_pcm_chmap_query_t **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm)
327 {
328         snd_pcm_generic_t *generic = pcm->private_data;
329         return snd_pcm_query_chmaps(generic->slave);
330 }
331
332 snd_pcm_chmap_t *snd_pcm_generic_get_chmap(snd_pcm_t *pcm)
333 {
334         snd_pcm_generic_t *generic = pcm->private_data;
335         return snd_pcm_get_chmap(generic->slave);
336 }
337
338 int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
339 {
340         snd_pcm_generic_t *generic = pcm->private_data;
341         return snd_pcm_set_chmap(generic->slave, map);
342 }
343
344 int snd_pcm_generic_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail ATTRIBUTE_UNUSED)
345 {
346         snd_pcm_generic_t *generic = pcm->private_data;
347         return snd_pcm_may_wait_for_avail_min(generic->slave, snd_pcm_mmap_avail(generic->slave));
348 }
349
350 #endif /* DOC_HIDDEN */