"Fossies" - the Fresh Open Source Software Archive

Member "alsa-lib-1.1.9/src/pcm/pcm_linear.c" (10 May 2019, 16767 Bytes) of package /linux/misc/alsa-lib-1.1.9.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "pcm_linear.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.1.5_vs_1.1.6.

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