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