~ubuntu-branches/ubuntu/warty/alsa-lib/warty

« back to all changes in this revision

Viewing changes to src/pcm/pcm_linear.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-09-23 19:38:45 UTC
  • Revision ID: james.westby@ubuntu.com-20040923193845-71lrqesgxij0yzn7
Tags: upstream-1.0.5
ImportĀ upstreamĀ versionĀ 1.0.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * \file pcm/pcm_linear.c
 
3
 * \ingroup PCM_Plugins
 
4
 * \brief PCM Linear Conversion Plugin Interface
 
5
 * \author Abramo Bagnara <abramo@alsa-project.org>
 
6
 * \date 2000-2001
 
7
 */
 
8
/*
 
9
 *  PCM - Linear conversion
 
10
 *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
 
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 <byteswap.h>
 
30
#include "pcm_local.h"
 
31
#include "pcm_plugin.h"
 
32
 
 
33
#ifndef PIC
 
34
/* entry for static linking */
 
35
const char *_snd_module_pcm_linear = "";
 
36
#endif
 
37
 
 
38
#ifndef DOC_HIDDEN
 
39
typedef struct {
 
40
        /* This field need to be the first */
 
41
        snd_pcm_plugin_t plug;
 
42
        unsigned int use_getput;
 
43
        unsigned int conv_idx;
 
44
        unsigned int get_idx, put_idx;
 
45
        snd_pcm_format_t sformat;
 
46
} snd_pcm_linear_t;
 
47
#endif
 
48
 
 
49
#ifndef DOC_HIDDEN
 
50
 
 
51
int snd_pcm_linear_convert_index(snd_pcm_format_t src_format,
 
52
                                 snd_pcm_format_t dst_format)
 
53
{
 
54
        int src_endian, dst_endian, sign, src_width, dst_width;
 
55
 
 
56
        sign = (snd_pcm_format_signed(src_format) !=
 
57
                snd_pcm_format_signed(dst_format));
 
58
#ifdef SND_LITTLE_ENDIAN
 
59
        src_endian = snd_pcm_format_big_endian(src_format);
 
60
        dst_endian = snd_pcm_format_big_endian(dst_format);
 
61
#else
 
62
        src_endian = snd_pcm_format_little_endian(src_format);
 
63
        dst_endian = snd_pcm_format_little_endian(dst_format);
 
64
#endif
 
65
 
 
66
        if (src_endian < 0)
 
67
                src_endian = 0;
 
68
        if (dst_endian < 0)
 
69
                dst_endian = 0;
 
70
 
 
71
        src_width = snd_pcm_format_width(src_format) / 8 - 1;
 
72
        dst_width = snd_pcm_format_width(dst_format) / 8 - 1;
 
73
 
 
74
        return src_width * 32 + src_endian * 16 + sign * 8 + dst_width * 2 + dst_endian;
 
75
}
 
76
 
 
77
int snd_pcm_linear_get_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format)
 
78
{
 
79
        int sign, width, pwidth, endian;
 
80
        sign = (snd_pcm_format_signed(src_format) != 
 
81
                snd_pcm_format_signed(dst_format));
 
82
#ifdef SND_LITTLE_ENDIAN
 
83
        endian = snd_pcm_format_big_endian(src_format);
 
84
#else
 
85
        endian = snd_pcm_format_little_endian(src_format);
 
86
#endif
 
87
        if (endian < 0)
 
88
                endian = 0;
 
89
        pwidth = snd_pcm_format_physical_width(src_format);
 
90
        width = snd_pcm_format_width(src_format);
 
91
        if (pwidth == 24) {
 
92
                switch (width) {
 
93
                case 24:
 
94
                        width = 0; break;
 
95
                case 20:
 
96
                        width = 1; break;
 
97
                case 18:
 
98
                default:
 
99
                        width = 2; break;
 
100
                }
 
101
                return width * 4 + endian * 2 + sign + 16;
 
102
        } else {
 
103
                width = width / 8 - 1;
 
104
                return width * 4 + endian * 2 + sign;
 
105
        }
 
106
}
 
107
 
 
108
int snd_pcm_linear_get32_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format)
 
109
{
 
110
        return snd_pcm_linear_get_index(src_format, dst_format);
 
111
}
 
112
 
 
113
int snd_pcm_linear_put_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format)
 
114
{
 
115
        int sign, width, endian;
 
116
        sign = (snd_pcm_format_signed(src_format) != 
 
117
                snd_pcm_format_signed(dst_format));
 
118
        width = snd_pcm_format_width(dst_format) / 8 - 1;
 
119
#ifdef SND_LITTLE_ENDIAN
 
120
        endian = snd_pcm_format_big_endian(dst_format);
 
121
#else
 
122
        endian = snd_pcm_format_little_endian(dst_format);
 
123
#endif
 
124
        if (endian < 0)
 
125
                endian = 0;
 
126
        return width * 4 + endian * 2 + sign;
 
127
}
 
128
 
 
129
int snd_pcm_linear_put32_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format)
 
130
{
 
131
        int sign, width, pwidth, endian;
 
132
        sign = (snd_pcm_format_signed(src_format) != 
 
133
                snd_pcm_format_signed(dst_format));
 
134
#ifdef SND_LITTLE_ENDIAN
 
135
        endian = snd_pcm_format_big_endian(dst_format);
 
136
#else
 
137
        endian = snd_pcm_format_little_endian(dst_format);
 
138
#endif
 
139
        if (endian < 0)
 
140
                endian = 0;
 
141
        pwidth = snd_pcm_format_physical_width(dst_format);
 
142
        width = snd_pcm_format_width(dst_format);
 
143
        if (pwidth == 24) {
 
144
                switch (width) {
 
145
                case 24:
 
146
                        width = 0; break;
 
147
                case 20:
 
148
                        width = 1; break;
 
149
                case 18:
 
150
                default:
 
151
                        width = 2; break;
 
152
                }
 
153
                return width * 4 + endian * 2 + sign + 16;
 
154
        } else {
 
155
                width = width / 8 - 1;
 
156
                return width * 4 + endian * 2 + sign;
 
157
        }
 
158
}
 
159
 
 
160
void snd_pcm_linear_convert(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset,
 
161
                            const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset,
 
162
                            unsigned int channels, snd_pcm_uframes_t frames,
 
163
                            unsigned int convidx)
 
164
{
 
165
#define CONV_LABELS
 
166
#include "plugin_ops.h"
 
167
#undef CONV_LABELS
 
168
        void *conv = conv_labels[convidx];
 
169
        unsigned int channel;
 
170
        for (channel = 0; channel < channels; ++channel) {
 
171
                const char *src;
 
172
                char *dst;
 
173
                int src_step, dst_step;
 
174
                snd_pcm_uframes_t frames1;
 
175
                const snd_pcm_channel_area_t *src_area = &src_areas[channel];
 
176
                const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
 
177
                src = snd_pcm_channel_area_addr(src_area, src_offset);
 
178
                dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
 
179
                src_step = snd_pcm_channel_area_step(src_area);
 
180
                dst_step = snd_pcm_channel_area_step(dst_area);
 
181
                frames1 = frames;
 
182
                while (frames1-- > 0) {
 
183
                        goto *conv;
 
184
#define CONV_END after
 
185
#include "plugin_ops.h"
 
186
#undef CONV_END
 
187
                after:
 
188
                        src += src_step;
 
189
                        dst += dst_step;
 
190
                }
 
191
        }
 
192
}
 
193
 
 
194
void snd_pcm_linear_getput(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset,
 
195
                           const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset,
 
196
                           unsigned int channels, snd_pcm_uframes_t frames,
 
197
                           unsigned int get_idx, unsigned int put_idx)
 
198
{
 
199
#define CONV24_LABELS
 
200
#include "plugin_ops.h"
 
201
#undef CONV24_LABELS
 
202
        void *get = get32_labels[get_idx];
 
203
        void *put = put32_labels[put_idx];
 
204
        unsigned int channel;
 
205
        u_int32_t sample = 0;
 
206
        for (channel = 0; channel < channels; ++channel) {
 
207
                const char *src;
 
208
                char *dst;
 
209
                int src_step, dst_step;
 
210
                snd_pcm_uframes_t frames1;
 
211
                const snd_pcm_channel_area_t *src_area = &src_areas[channel];
 
212
                const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
 
213
                src = snd_pcm_channel_area_addr(src_area, src_offset);
 
214
                dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
 
215
                src_step = snd_pcm_channel_area_step(src_area);
 
216
                dst_step = snd_pcm_channel_area_step(dst_area);
 
217
                frames1 = frames;
 
218
                while (frames1-- > 0) {
 
219
                        goto *get;
 
220
#define CONV24_END after
 
221
#include "plugin_ops.h"
 
222
#undef CONV24_END
 
223
                after:
 
224
                        src += src_step;
 
225
                        dst += dst_step;
 
226
                }
 
227
        }
 
228
}
 
229
 
 
230
#endif /* DOC_HIDDEN */
 
231
 
 
232
static int snd_pcm_linear_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
 
233
{
 
234
        int err;
 
235
        snd_pcm_access_mask_t access_mask = { SND_PCM_ACCBIT_SHM };
 
236
        snd_pcm_format_mask_t format_mask = { SND_PCM_FMTBIT_LINEAR };
 
237
        err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_ACCESS,
 
238
                                         &access_mask);
 
239
        if (err < 0)
 
240
                return err;
 
241
        err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_FORMAT,
 
242
                                         &format_mask);
 
243
        if (err < 0)
 
244
                return err;
 
245
        err = _snd_pcm_hw_params_set_subformat(params, SND_PCM_SUBFORMAT_STD);
 
246
        if (err < 0)
 
247
                return err;
 
248
        params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
 
249
        return 0;
 
250
}
 
251
 
 
252
static int snd_pcm_linear_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *sparams)
 
253
{
 
254
        snd_pcm_linear_t *linear = pcm->private_data;
 
255
        snd_pcm_access_mask_t saccess_mask = { SND_PCM_ACCBIT_MMAP };
 
256
        _snd_pcm_hw_params_any(sparams);
 
257
        _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
 
258
                                   &saccess_mask);
 
259
        _snd_pcm_hw_params_set_format(sparams, linear->sformat);
 
260
        _snd_pcm_hw_params_set_subformat(sparams, SND_PCM_SUBFORMAT_STD);
 
261
        return 0;
 
262
}
 
263
 
 
264
static int snd_pcm_linear_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
 
265
                                            snd_pcm_hw_params_t *sparams)
 
266
{
 
267
        int err;
 
268
        unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
 
269
                              SND_PCM_HW_PARBIT_RATE |
 
270
                              SND_PCM_HW_PARBIT_PERIOD_SIZE |
 
271
                              SND_PCM_HW_PARBIT_BUFFER_SIZE |
 
272
                              SND_PCM_HW_PARBIT_PERIODS |
 
273
                              SND_PCM_HW_PARBIT_PERIOD_TIME |
 
274
                              SND_PCM_HW_PARBIT_BUFFER_TIME |
 
275
                              SND_PCM_HW_PARBIT_TICK_TIME);
 
276
        err = _snd_pcm_hw_params_refine(sparams, links, params);
 
277
        if (err < 0)
 
278
                return err;
 
279
        return 0;
 
280
}
 
281
        
 
282
static int snd_pcm_linear_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
 
283
                                            snd_pcm_hw_params_t *sparams)
 
284
{
 
285
        int err;
 
286
        unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
 
287
                              SND_PCM_HW_PARBIT_RATE |
 
288
                              SND_PCM_HW_PARBIT_PERIOD_SIZE |
 
289
                              SND_PCM_HW_PARBIT_BUFFER_SIZE |
 
290
                              SND_PCM_HW_PARBIT_PERIODS |
 
291
                              SND_PCM_HW_PARBIT_PERIOD_TIME |
 
292
                              SND_PCM_HW_PARBIT_BUFFER_TIME |
 
293
                              SND_PCM_HW_PARBIT_TICK_TIME);
 
294
        err = _snd_pcm_hw_params_refine(params, links, sparams);
 
295
        if (err < 0)
 
296
                return err;
 
297
        return 0;
 
298
}
 
299
 
 
300
static int snd_pcm_linear_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
 
301
{
 
302
        return snd_pcm_hw_refine_slave(pcm, params,
 
303
                                       snd_pcm_linear_hw_refine_cprepare,
 
304
                                       snd_pcm_linear_hw_refine_cchange,
 
305
                                       snd_pcm_linear_hw_refine_sprepare,
 
306
                                       snd_pcm_linear_hw_refine_schange,
 
307
                                       snd_pcm_plugin_hw_refine_slave);
 
308
}
 
309
 
 
310
static int snd_pcm_linear_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
 
311
{
 
312
        snd_pcm_linear_t *linear = pcm->private_data;
 
313
        snd_pcm_format_t format;
 
314
        int err = snd_pcm_hw_params_slave(pcm, params,
 
315
                                          snd_pcm_linear_hw_refine_cchange,
 
316
                                          snd_pcm_linear_hw_refine_sprepare,
 
317
                                          snd_pcm_linear_hw_refine_schange,
 
318
                                          snd_pcm_plugin_hw_params_slave);
 
319
        if (err < 0)
 
320
                return err;
 
321
        err = INTERNAL(snd_pcm_hw_params_get_format)(params, &format);
 
322
        if (err < 0)
 
323
                return err;
 
324
        linear->use_getput = (snd_pcm_format_physical_width(format) == 24 ||
 
325
                              snd_pcm_format_physical_width(linear->sformat) == 24);
 
326
        if (linear->use_getput) {
 
327
                if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
 
328
                        linear->get_idx = snd_pcm_linear_get32_index(format, SND_PCM_FORMAT_S32);
 
329
                        linear->put_idx = snd_pcm_linear_put32_index(SND_PCM_FORMAT_S32, linear->sformat);
 
330
                } else {
 
331
                        linear->get_idx = snd_pcm_linear_get32_index(linear->sformat, SND_PCM_FORMAT_S32);
 
332
                        linear->put_idx = snd_pcm_linear_put32_index(SND_PCM_FORMAT_S32, format);
 
333
                }
 
334
        } else {
 
335
                if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
 
336
                        linear->conv_idx = snd_pcm_linear_convert_index(format,
 
337
                                                                        linear->sformat);
 
338
                else
 
339
                        linear->conv_idx = snd_pcm_linear_convert_index(linear->sformat,
 
340
                                                                        format);
 
341
        }
 
342
        return 0;
 
343
}
 
344
 
 
345
static snd_pcm_uframes_t
 
346
snd_pcm_linear_write_areas(snd_pcm_t *pcm,
 
347
                           const snd_pcm_channel_area_t *areas,
 
348
                           snd_pcm_uframes_t offset,
 
349
                           snd_pcm_uframes_t size,
 
350
                           const snd_pcm_channel_area_t *slave_areas,
 
351
                           snd_pcm_uframes_t slave_offset,
 
352
                           snd_pcm_uframes_t *slave_sizep)
 
353
{
 
354
        snd_pcm_linear_t *linear = pcm->private_data;
 
355
        if (size > *slave_sizep)
 
356
                size = *slave_sizep;
 
357
        if (linear->use_getput)
 
358
                snd_pcm_linear_getput(slave_areas, slave_offset,
 
359
                                      areas, offset, 
 
360
                                      pcm->channels, size,
 
361
                                      linear->get_idx, linear->put_idx);
 
362
        else
 
363
                snd_pcm_linear_convert(slave_areas, slave_offset,
 
364
                                       areas, offset, 
 
365
                                       pcm->channels, size, linear->conv_idx);
 
366
        *slave_sizep = size;
 
367
        return size;
 
368
}
 
369
 
 
370
static snd_pcm_uframes_t
 
371
snd_pcm_linear_read_areas(snd_pcm_t *pcm,
 
372
                          const snd_pcm_channel_area_t *areas,
 
373
                          snd_pcm_uframes_t offset,
 
374
                          snd_pcm_uframes_t size,
 
375
                          const snd_pcm_channel_area_t *slave_areas,
 
376
                          snd_pcm_uframes_t slave_offset,
 
377
                          snd_pcm_uframes_t *slave_sizep)
 
378
{
 
379
        snd_pcm_linear_t *linear = pcm->private_data;
 
380
        if (size > *slave_sizep)
 
381
                size = *slave_sizep;
 
382
        if (linear->use_getput)
 
383
                snd_pcm_linear_getput(areas, offset, 
 
384
                                      slave_areas, slave_offset,
 
385
                                      pcm->channels, size,
 
386
                                      linear->get_idx, linear->put_idx);
 
387
        else
 
388
                snd_pcm_linear_convert(areas, offset, 
 
389
                                       slave_areas, slave_offset,
 
390
                                       pcm->channels, size, linear->conv_idx);
 
391
        *slave_sizep = size;
 
392
        return size;
 
393
}
 
394
 
 
395
static void snd_pcm_linear_dump(snd_pcm_t *pcm, snd_output_t *out)
 
396
{
 
397
        snd_pcm_linear_t *linear = pcm->private_data;
 
398
        snd_output_printf(out, "Linear conversion PCM (%s)\n", 
 
399
                snd_pcm_format_name(linear->sformat));
 
400
        if (pcm->setup) {
 
401
                snd_output_printf(out, "Its setup is:\n");
 
402
                snd_pcm_dump_setup(pcm, out);
 
403
        }
 
404
        snd_output_printf(out, "Slave: ");
 
405
        snd_pcm_dump(linear->plug.slave, out);
 
406
}
 
407
 
 
408
static snd_pcm_ops_t snd_pcm_linear_ops = {
 
409
        .close = snd_pcm_plugin_close,
 
410
        .info = snd_pcm_plugin_info,
 
411
        .hw_refine = snd_pcm_linear_hw_refine,
 
412
        .hw_params = snd_pcm_linear_hw_params,
 
413
        .hw_free = snd_pcm_plugin_hw_free,
 
414
        .sw_params = snd_pcm_plugin_sw_params,
 
415
        .channel_info = snd_pcm_plugin_channel_info,
 
416
        .dump = snd_pcm_linear_dump,
 
417
        .nonblock = snd_pcm_plugin_nonblock,
 
418
        .async = snd_pcm_plugin_async,
 
419
        .poll_revents = snd_pcm_plugin_poll_revents,
 
420
        .mmap = snd_pcm_plugin_mmap,
 
421
        .munmap = snd_pcm_plugin_munmap,
 
422
};
 
423
 
 
424
 
 
425
/**
 
426
 * \brief Creates a new linear conversion PCM
 
427
 * \param pcmp Returns created PCM handle
 
428
 * \param name Name of PCM
 
429
 * \param sformat Slave (destination) format
 
430
 * \param slave Slave PCM handle
 
431
 * \param close_slave When set, the slave PCM handle is closed with copy PCM
 
432
 * \retval zero on success otherwise a negative error code
 
433
 * \warning Using of this function might be dangerous in the sense
 
434
 *          of compatibility reasons. The prototype might be freely
 
435
 *          changed in future.
 
436
 */
 
437
int snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, snd_pcm_t *slave, int close_slave)
 
438
{
 
439
        snd_pcm_t *pcm;
 
440
        snd_pcm_linear_t *linear;
 
441
        int err;
 
442
        assert(pcmp && slave);
 
443
        if (snd_pcm_format_linear(sformat) != 1)
 
444
                return -EINVAL;
 
445
        linear = calloc(1, sizeof(snd_pcm_linear_t));
 
446
        if (!linear) {
 
447
                return -ENOMEM;
 
448
        }
 
449
        snd_pcm_plugin_init(&linear->plug);
 
450
        linear->sformat = sformat;
 
451
        linear->plug.read = snd_pcm_linear_read_areas;
 
452
        linear->plug.write = snd_pcm_linear_write_areas;
 
453
        linear->plug.undo_read = snd_pcm_plugin_undo_read_generic;
 
454
        linear->plug.undo_write = snd_pcm_plugin_undo_write_generic;
 
455
        linear->plug.slave = slave;
 
456
        linear->plug.close_slave = close_slave;
 
457
 
 
458
        err = snd_pcm_new(&pcm, SND_PCM_TYPE_LINEAR, name, slave->stream, slave->mode);
 
459
        if (err < 0) {
 
460
                free(linear);
 
461
                return err;
 
462
        }
 
463
        pcm->ops = &snd_pcm_linear_ops;
 
464
        pcm->fast_ops = &snd_pcm_plugin_fast_ops;
 
465
        pcm->private_data = linear;
 
466
        pcm->poll_fd = slave->poll_fd;
 
467
        pcm->poll_events = slave->poll_events;
 
468
        snd_pcm_set_hw_ptr(pcm, &linear->plug.hw_ptr, -1, 0);
 
469
        snd_pcm_set_appl_ptr(pcm, &linear->plug.appl_ptr, -1, 0);
 
470
        *pcmp = pcm;
 
471
 
 
472
        return 0;
 
473
}
 
474
 
 
475
/*! \page pcm_plugins
 
476
 
 
477
\section pcm_plugins_linear Plugin: linear
 
478
 
 
479
This plugin converts linear samples from master linear conversion PCM to given
 
480
slave PCM. The channel count, format and rate must match for both of them.
 
481
 
 
482
\code
 
483
pcm.name {
 
484
        type linear             # Linear conversion PCM
 
485
        slave STR               # Slave name
 
486
        # or
 
487
        slave {                 # Slave definition
 
488
                pcm STR         # Slave PCM name
 
489
                # or
 
490
                pcm { }         # Slave PCM definition
 
491
                format STR      # Slave format
 
492
        }
 
493
}
 
494
\endcode
 
495
 
 
496
\subsection pcm_plugins_linear_funcref Function reference
 
497
 
 
498
<UL>
 
499
  <LI>snd_pcm_linear_open()
 
500
  <LI>_snd_pcm_linear_open()
 
501
</UL>
 
502
 
 
503
*/
 
504
 
 
505
/**
 
506
 * \brief Creates a new linear conversion PCM
 
507
 * \param pcmp Returns created PCM handle
 
508
 * \param name Name of PCM
 
509
 * \param root Root configuration node
 
510
 * \param conf Configuration node with copy PCM description
 
511
 * \param stream Stream type
 
512
 * \param mode Stream mode
 
513
 * \retval zero on success otherwise a negative error code
 
514
 * \warning Using of this function might be dangerous in the sense
 
515
 *          of compatibility reasons. The prototype might be freely
 
516
 *          changed in future.
 
517
 */
 
518
int _snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name,
 
519
                         snd_config_t *root, snd_config_t *conf, 
 
520
                         snd_pcm_stream_t stream, int mode)
 
521
{
 
522
        snd_config_iterator_t i, next;
 
523
        int err;
 
524
        snd_pcm_t *spcm;
 
525
        snd_config_t *slave = NULL, *sconf;
 
526
        snd_pcm_format_t sformat;
 
527
        snd_config_for_each(i, next, conf) {
 
528
                snd_config_t *n = snd_config_iterator_entry(i);
 
529
                const char *id;
 
530
                if (snd_config_get_id(n, &id) < 0)
 
531
                        continue;
 
532
                if (snd_pcm_conf_generic_id(id))
 
533
                        continue;
 
534
                if (strcmp(id, "slave") == 0) {
 
535
                        slave = n;
 
536
                        continue;
 
537
                }
 
538
                SNDERR("Unknown field %s", id);
 
539
                return -EINVAL;
 
540
        }
 
541
        if (!slave) {
 
542
                SNDERR("slave is not defined");
 
543
                return -EINVAL;
 
544
        }
 
545
        err = snd_pcm_slave_conf(root, slave, &sconf, 1,
 
546
                                 SND_PCM_HW_PARAM_FORMAT, SCONF_MANDATORY, &sformat);
 
547
        if (err < 0)
 
548
                return err;
 
549
        if (snd_pcm_format_linear(sformat) != 1) {
 
550
                snd_config_delete(sconf);
 
551
                SNDERR("slave format is not linear");
 
552
                return -EINVAL;
 
553
        }
 
554
        err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
 
555
        snd_config_delete(sconf);
 
556
        if (err < 0)
 
557
                return err;
 
558
        err = snd_pcm_linear_open(pcmp, name, sformat, spcm, 1);
 
559
        if (err < 0)
 
560
                snd_pcm_close(spcm);
 
561
        return err;
 
562
}
 
563
#ifndef DOC_HIDDEN
 
564
SND_DLSYM_BUILD_VERSION(_snd_pcm_linear_open, SND_PCM_DLSYM_VERSION);
 
565
#endif