diff options
author | Jaroslav Kysela <perex@perex.cz> | 2002-01-12 10:52:42 +0000 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2002-01-12 10:52:42 +0000 |
commit | 8c1887d7aff5221e9a4abd2baa14f6467c585263 (patch) | |
tree | 6afd47d6e472446b1fe752edbaec87749f39ff2d | |
parent | b36ad628f704c60d378a96642d38dff88f78b64b (diff) |
Moved some prototypes from src/pcm/pcm_plugin.h to include/pcm_plugin.h.
Merged src/pcm/atomic.h to include/iatomic.h.
Added initial description of hw and hooks plugins.
-rw-r--r-- | doc/doxygen.cfg | 22 | ||||
-rw-r--r-- | doc/index.doxygen | 1 | ||||
-rw-r--r-- | include/Makefile.am | 6 | ||||
-rw-r--r-- | include/iatomic.h | 74 | ||||
-rw-r--r-- | include/local.h | 1 | ||||
-rw-r--r-- | include/pcm_plugin.h | 112 | ||||
-rw-r--r-- | src/conf.c | 2 | ||||
-rw-r--r-- | src/pcm/Makefile.am | 2 | ||||
-rw-r--r-- | src/pcm/atomic.c | 2 | ||||
-rw-r--r-- | src/pcm/atomic.h | 85 | ||||
-rw-r--r-- | src/pcm/pcm_hooks.c | 120 | ||||
-rw-r--r-- | src/pcm/pcm_hw.c | 71 | ||||
-rw-r--r-- | src/pcm/pcm_local.h | 13 | ||||
-rw-r--r-- | src/pcm/pcm_plug.c | 4 | ||||
-rw-r--r-- | src/pcm/pcm_plugin.c | 19 | ||||
-rw-r--r-- | src/pcm/pcm_plugin.h | 23 | ||||
-rw-r--r-- | src/pcm/pcm_rate.c | 4 | ||||
-rw-r--r-- | src/pcm/pcm_route.c | 40 |
18 files changed, 442 insertions, 159 deletions
diff --git a/doc/doxygen.cfg b/doc/doxygen.cfg index 5bc0c55b..8a520908 100644 --- a/doc/doxygen.cfg +++ b/doc/doxygen.cfg @@ -25,7 +25,27 @@ INPUT = index.doxygen \ ../include/seq_midi_event.h \ ../include/conv.h \ ../include/instr.h \ - ../src + ../src/error.c \ + ../src/dlmisc.c \ + ../src/async.c \ + ../src/input.c \ + ../src/output.c \ + ../src/conf.c \ + ../src/confmisc.c \ + ../src/control \ + ../src/mixer \ + ../src/pcm/pcm.c \ + ../src/pcm/pcm_mmap.c \ + ../src/pcm/pcm_plugin.c \ + ../src/pcm/pcm_hw.c \ + ../src/pcm/pcm_hooks.c \ + ../src/pcm/pcm_meter.c \ + ../src/pcm/pcm_misc.c \ + ../src/rawmidi \ + ../src/timer \ + ../src/hwdep \ + ../src/seq \ + ../src/instr EXCLUDE = ../src/control/control_local.h \ ../src/pcm/atomic.h \ ../src/pcm/interval.h \ diff --git a/doc/index.doxygen b/doc/index.doxygen index 183cca5c..1c445d14 100644 --- a/doc/index.doxygen +++ b/doc/index.doxygen @@ -31,6 +31,7 @@ may be placed in the library code instead of the kernel driver.</P> <UL> <LI>Page \ref pcm explains the design of PCM (digital audio) API + <LI>Page \ref pcm_plugins explains the design of PCM (digital audio) plugins </UL> <H2>Configuration</H2> diff --git a/include/Makefile.am b/include/Makefile.am index 0a41c075..9d847f56 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -3,12 +3,12 @@ alsaincludedir = ${includedir}/alsa alsainclude_HEADERS = asoundlib.h asoundef.h \ version.h global.h input.h output.h error.h \ - conf.h pcm.h rawmidi.h timer.h \ + conf.h pcm.h pcm_plugin.h rawmidi.h timer.h \ hwdep.h control.h mixer.h \ seq_event.h seq.h seqmid.h seq_midi_event.h \ - conv.h instr.h + conv.h instr.h iatomic.h -noinst_HEADERS = sys.h search.h list.h aserver.h local.h config.h iatomic.h +noinst_HEADERS = sys.h search.h list.h aserver.h local.h config.h EXTRA_CLEAN = stamp-vh diff --git a/include/iatomic.h b/include/iatomic.h index 6f697a64..6d7f546c 100644 --- a/include/iatomic.h +++ b/include/iatomic.h @@ -1,5 +1,5 @@ -#ifndef __ALSA_IATOMIC__ -#define __ALSA_IATOMIC__ +#ifndef __ALSA_IATOMIC_H +#define __ALSA_IATOMIC_H #ifdef __i386__ @@ -1059,4 +1059,72 @@ typedef struct { volatile int counter; } atomic_t; #endif /* IATOMIC_DEFINED */ -#endif /* __ALSA_IATOMIC__ */ +/* + * Atomic read/write + * Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org> + */ + +/* Max number of times we must spin on a spinlock calling sched_yield(). + After MAX_SPIN_COUNT iterations, we put the calling thread to sleep. */ + +#ifndef MAX_SPIN_COUNT +#define MAX_SPIN_COUNT 50 +#endif + +/* Duration of sleep (in nanoseconds) when we can't acquire a spinlock + after MAX_SPIN_COUNT iterations of sched_yield(). + This MUST BE > 2ms. + (Otherwise the kernel does busy-waiting for realtime threads, + giving other threads no chance to run.) */ + +#ifndef SPIN_SLEEP_DURATION +#define SPIN_SLEEP_DURATION 2000001 +#endif + +typedef struct { + unsigned int begin, end; +} snd_atomic_write_t; + +typedef struct { + volatile const snd_atomic_write_t *write; + unsigned int end; +} snd_atomic_read_t; + +void snd_atomic_read_wait(snd_atomic_read_t *t); + +static inline void snd_atomic_write_init(snd_atomic_write_t *w) +{ + w->begin = 0; + w->end = 0; +} + +static inline void snd_atomic_write_begin(snd_atomic_write_t *w) +{ + w->begin++; + wmb(); +} + +static inline void snd_atomic_write_end(snd_atomic_write_t *w) +{ + wmb(); + w->end++; +} + +static inline void snd_atomic_read_init(snd_atomic_read_t *r, snd_atomic_write_t *w) +{ + r->write = w; +} + +static inline void snd_atomic_read_begin(snd_atomic_read_t *r) +{ + r->end = r->write->end; + rmb(); +} + +static inline int snd_atomic_read_ok(snd_atomic_read_t *r) +{ + rmb(); + return r->end == r->write->begin; +} + +#endif /* __ALSA_IATOMIC_H */ diff --git a/include/local.h b/include/local.h index 4f43edc1..5151780b 100644 --- a/include/local.h +++ b/include/local.h @@ -93,6 +93,7 @@ typedef struct sndrv_seq_event snd_seq_event_t; #include "error.h" #include "conf.h" #include "pcm.h" +#include "pcm_plugin.h" #include "rawmidi.h" #include "timer.h" #include "hwdep.h" diff --git a/include/pcm_plugin.h b/include/pcm_plugin.h new file mode 100644 index 00000000..db4f1630 --- /dev/null +++ b/include/pcm_plugin.h @@ -0,0 +1,112 @@ +/** + * \file <alsa/pcm_plugin.h> + * \brief Common PCM plugin code + * \author Abramo Bagnara <abramo@alsa-project.org> + * \author Jaroslav Kysela <perex@suse.cz> + * \date 2000-2001 + * + * Application interface library for the ALSA driver. + * See the \ref pcm_plugins page for more details. + * + * \warning Using of contents of this header file might be dangerous + * in the sense of compatibility reasons. The contents might be + * freely changed in future. + * + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __ALSA_PCM_PLUGIN_H + +/** + * \defgroup PCM_Plugins PCM Plugins + * \ingroup PCM + * See the \ref pcm_plugins page for more details. + * \{ + */ + +#define SND_PCM_PLUGIN_RATE_MIN 4000 /**< minimal rate for the rate plugin */ +#define SND_PCM_PLUGIN_RATE_MAX 192000 /**< maximal rate for the rate plugin */ + +#define SND_PCM_PLUGIN_ROUTE_FLOAT 1 /**< use floats for route plugin */ +#define SND_PCM_PLUGIN_ROUTE_RESOLUTION 16 /**< integer resolution for route plugin */ + +#if SND_PCM_PLUGIN_ROUTE_FLOAT +/** route ttable entry type */ +typedef float snd_pcm_route_ttable_entry_t; +#define SND_PCM_PLUGIN_ROUTE_HALF 0.5 /**< half value */ +#define SND_PCM_PLUGIN_ROUTE_FULL 1.0 /**< full value */ +#else +/** route ttable entry type */ +typedef int snd_pcm_route_ttable_entry_t; +#define SND_PCM_PLUGIN_ROUTE_HALF (SND_PCM_PLUGIN_ROUTE_RESOLUTION / 2) /**< half value */ +#define SND_PCM_PLUGIN_ROUTE_FULL SND_PCM_PLUGIN_ROUTE_RESOLUTION /**< full value */ +#endif + +/* + * Hardware plugin + */ +int snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name, + int card, int device, int subdevice, + snd_pcm_stream_t stream, int mode, + int mmap_emulation); +int _snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name, + snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *conf, + snd_pcm_stream_t stream, int mode); + +int snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name, + snd_pcm_t *slave, int close_slave); +int snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name, + snd_pcm_format_t sformat, snd_pcm_t *slave, + int close_slave); +int snd_pcm_lfloat_open(snd_pcm_t **pcmp, const char *name, + snd_pcm_format_t sformat, snd_pcm_t *slave, + int close_slave); +int snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name, + snd_pcm_format_t sformat, snd_pcm_t *slave, + int close_slave); +int snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name, + snd_pcm_format_t sformat, snd_pcm_t *slave, + int close_slave); +int snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name, + snd_pcm_format_t sformat, snd_pcm_t *slave, + int close_slave); +int snd_pcm_route_load_ttable(snd_config_t *tt, snd_pcm_route_ttable_entry_t *ttable, + unsigned int tt_csize, unsigned int tt_ssize, + unsigned int *tt_cused, unsigned int *tt_sused, + int schannels); +int snd_pcm_route_open(snd_pcm_t **pcmp, const char *name, + snd_pcm_format_t sformat, int schannels, + snd_pcm_route_ttable_entry_t *ttable, + unsigned int tt_ssize, + unsigned int tt_cused, unsigned int tt_sused, + snd_pcm_t *slave, int close_slave); +int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name, + snd_pcm_format_t sformat, unsigned int srate, + snd_pcm_t *slave, int close_slave); + +/* + * Hooks plugin + */ +int snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, + snd_pcm_t *slave, int close_slave); +int _snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, + snd_config_t *root, snd_config_t *conf, + snd_pcm_stream_t stream, int mode); + +/** \} */ + +#endif /* __ALSA_PCM_PLUGIN_H */ @@ -239,7 +239,7 @@ with new contents. This mode is specified with a prefix char note of exclamation (!). \code -!defaults.pcm.device 1 +defaults.pcm.!device 1 \endcode \section conf_syntax_summary Syntax summary diff --git a/src/pcm/Makefile.am b/src/pcm/Makefile.am index 24f8b1dc..551c80d1 100644 --- a/src/pcm/Makefile.am +++ b/src/pcm/Makefile.am @@ -8,7 +8,7 @@ libpcm_la_SOURCES = atomic.c mask.c interval.c \ pcm_rate.c pcm_plug.c pcm_misc.c pcm_mmap.c pcm_multi.c \ pcm_shm.c pcm_file.c pcm_null.c pcm_share.c \ pcm_meter.c pcm_hooks.c pcm_lfloat.c pcm_ladspa.c pcm_symbols.c -noinst_HEADERS = atomic.h pcm_local.h pcm_plugin.h mask.h mask_inline.h \ +noinst_HEADERS = pcm_local.h pcm_plugin.h mask.h mask_inline.h \ interval.h interval_inline.h plugin_ops.h ladspa.h alsadir = $(datadir)/alsa diff --git a/src/pcm/atomic.c b/src/pcm/atomic.c index 4896b5c8..75659457 100644 --- a/src/pcm/atomic.c +++ b/src/pcm/atomic.c @@ -21,7 +21,7 @@ #include <stdlib.h> #include <time.h> #include <sched.h> -#include "atomic.h" +#include "iatomic.h" void snd_atomic_read_wait(snd_atomic_read_t *t) { diff --git a/src/pcm/atomic.h b/src/pcm/atomic.h deleted file mode 100644 index 946bd297..00000000 --- a/src/pcm/atomic.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Atomic read/write - * Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org> - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "iatomic.h" - -/* Max number of times we must spin on a spinlock calling sched_yield(). - After MAX_SPIN_COUNT iterations, we put the calling thread to sleep. */ - -#ifndef MAX_SPIN_COUNT -#define MAX_SPIN_COUNT 50 -#endif - -/* Duration of sleep (in nanoseconds) when we can't acquire a spinlock - after MAX_SPIN_COUNT iterations of sched_yield(). - This MUST BE > 2ms. - (Otherwise the kernel does busy-waiting for realtime threads, - giving other threads no chance to run.) */ - -#ifndef SPIN_SLEEP_DURATION -#define SPIN_SLEEP_DURATION 2000001 -#endif - -typedef struct { - unsigned int begin, end; -} snd_atomic_write_t; - -typedef struct { - volatile const snd_atomic_write_t *write; - unsigned int end; -} snd_atomic_read_t; - -void snd_atomic_read_wait(snd_atomic_read_t *t); - -static inline void snd_atomic_write_init(snd_atomic_write_t *w) -{ - w->begin = 0; - w->end = 0; -} - -static inline void snd_atomic_write_begin(snd_atomic_write_t *w) -{ - w->begin++; - wmb(); -} - -static inline void snd_atomic_write_end(snd_atomic_write_t *w) -{ - wmb(); - w->end++; -} - -static inline void snd_atomic_read_init(snd_atomic_read_t *r, snd_atomic_write_t *w) -{ - r->write = w; -} - -static inline void snd_atomic_read_begin(snd_atomic_read_t *r) -{ - r->end = r->write->end; - rmb(); -} - -static inline int snd_atomic_read_ok(snd_atomic_read_t *r) -{ - rmb(); - return r->end == r->write->begin; -} - diff --git a/src/pcm/pcm_hooks.c b/src/pcm/pcm_hooks.c index 4c9bf65f..a1d1dd2f 100644 --- a/src/pcm/pcm_hooks.c +++ b/src/pcm/pcm_hooks.c @@ -1,3 +1,11 @@ +/** + * \file pcm/pcm_hooks.c + * \ingroup PCM_Hook + * \brief PCM Hook Interface + * \author Abramo Bagnara <abramo@alsa-project.org> + * \author Jaroslav Kysela <perex@suse.cz> + * \date 2000-2001 + */ /* * PCM - Hook functions * Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org> @@ -40,6 +48,7 @@ typedef struct { int close_slave; struct list_head hooks[SND_PCM_HOOK_TYPE_LAST + 1]; } snd_pcm_hooks_t; +#endif static int snd_pcm_hooks_close(snd_pcm_t *pcm) { @@ -265,7 +274,7 @@ static void snd_pcm_hooks_dump(snd_pcm_t *pcm, snd_output_t *out) snd_pcm_dump(h->slave, out); } -snd_pcm_ops_t snd_pcm_hooks_ops = { +static snd_pcm_ops_t snd_pcm_hooks_ops = { close: snd_pcm_hooks_close, info: snd_pcm_hooks_info, hw_refine: snd_pcm_hooks_hw_refine, @@ -280,7 +289,7 @@ snd_pcm_ops_t snd_pcm_hooks_ops = { munmap: snd_pcm_hooks_munmap, }; -snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = { +static snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = { status: snd_pcm_hooks_status, state: snd_pcm_hooks_state, delay: snd_pcm_hooks_delay, @@ -300,6 +309,17 @@ snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = { mmap_commit: snd_pcm_hooks_mmap_commit, }; +/** + * \brief Creates a new hooks PCM + * \param pcmp Returns created PCM handle + * \param name Name of PCM + * \param slave Slave PCM + * \param close_slave If set, slave PCM handle is closed when hooks PCM is closed + * \retval zero on success otherwise a negative error code + * \warning Using of this function might be dangerous in the sense + * of compatibility reasons. The prototype might be freely + * changed in future. + */ int snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int close_slave) { snd_pcm_t *pcm; @@ -331,6 +351,81 @@ int snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int return 0; } +/*! \page pcm_plugins + +\section pcm_plugins_hooks Plugin: hooks + +\code +# Hook arguments definition +hook_args.NAME { + ... # Arbitrary arguments +} + +# PCM hook type +pcm_hook_type.NAME { + [lib STR] # Library file (default libasound.so) + [install STR] # Install function (default _snd_pcm_hook_NAME_install) +} + +# PCM hook definition +pcm_hook.NAME { + type STR # PCM Hook type (see pcm_hook_type) + [args STR] # Arguments for install function (see hook_args) + # or + [args { }] # Arguments for install function +} + +# PCM hook plugin +pcm.NAME { + type hooks # PCM with hooks + slave STR # Slave name + # or + slave { # Slave definition + pcm STR # Slave PCM name + # or + pcm { } # Slave PCM definition + } + hooks { + ID STR # Hook name (see pcm_hook) + # or + ID { } # Hook definition (see pcm_hook) + } +} +\endcode + +Example: + +\code + hooks.0 { + type ctl_elems + hook_args [ + { + name "Wave Surround Playback Volume" + preserve true + lock true + value [ 0 0 ] + } + { + name "EMU10K1 PCM Send Volume" + index { @func private_pcm_subdevice } + lock true + value [ 0 0 0 0 0 0 255 0 0 0 0 255 ] + } + ] + } +\endcode + +\subsection pcm_plugins_hooks_funcref Function reference + +<UL> + <LI>The function ctl_elems - _snd_pcm_hook_ctl_elems_install() - installs + CTL settings described by given configuration. + <LI>snd_pcm_hooks_open() + <LI>_snd_pcm_hooks_open() +</UL> + +*/ + static int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *root, snd_config_t *conf) { int err; @@ -444,6 +539,19 @@ static int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *root, snd_config_ return 0; } +/** + * \brief Creates a new hooks PCM + * \param pcmp Returns created PCM handle + * \param name Name of PCM + * \param root Root configuration node + * \param conf Configuration node with hooks PCM description + * \param stream PCM Stream + * \param mode PCM Mode + * \retval zero on success otherwise a negative error code + * \warning Using of this function might be dangerous in the sense + * of compatibility reasons. The prototype might be freely + * changed in future. + */ int _snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, snd_config_t *root, snd_config_t *conf, snd_pcm_stream_t stream, int mode) @@ -514,8 +622,8 @@ int _snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, *pcmp = rpcm; return 0; } +#ifndef DOC_HIDDEN SND_DLSYM_BUILD_VERSION(_snd_pcm_hooks_open, SND_PCM_DLSYM_VERSION); - #endif /** @@ -623,6 +731,12 @@ static int snd_pcm_hook_ctl_elems_close(snd_pcm_hook_t *hook) return err; } +/** + * \brief Install CTL settings using hardware associated with PCM handle + * \param pcm PCM handle + * \param conf Configuration node with CTL settings + * \return zero on success otherwise a negative error code + */ int _snd_pcm_hook_ctl_elems_install(snd_pcm_t *pcm, snd_config_t *conf) { int err; diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index e2953122..13c32457 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -1,3 +1,11 @@ +/** + * \file pcm/pcm_hw.c + * \ingroup PCM_Plugins + * \brief PCM HW Interface + * \author Abramo Bagnara <abramo@alsa-project.org> + * \author Jaroslav Kysela <perex@suse.cz> + * \date 2000-2001 + */ /* * PCM - Hardware * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org> @@ -36,6 +44,8 @@ const char *_snd_module_pcm_hw = ""; #endif +#ifndef DOC_HIDDEN + #ifndef F_SETSIG #define F_SETSIG 10 #endif @@ -62,6 +72,8 @@ typedef struct { do { if (hw->shadow_appl_ptr && !hw->avail_update_flag) \ hw->appl_ptr = hw->mmap_control->appl_ptr; } while (0) +#endif /* DOC_HIDDEN */ + static int snd_pcm_hw_nonblock(snd_pcm_t *pcm, int nonblock) { long flags; @@ -643,7 +655,7 @@ static void snd_pcm_hw_dump(snd_pcm_t *pcm, snd_output_t *out) } } -snd_pcm_ops_t snd_pcm_hw_ops = { +static snd_pcm_ops_t snd_pcm_hw_ops = { close: snd_pcm_hw_close, info: snd_pcm_hw_info, hw_refine: snd_pcm_hw_hw_refine, @@ -658,7 +670,7 @@ snd_pcm_ops_t snd_pcm_hw_ops = { munmap: snd_pcm_hw_munmap, }; -snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = { +static snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = { status: snd_pcm_hw_status, state: snd_pcm_hw_state, delay: snd_pcm_hw_delay, @@ -678,6 +690,20 @@ snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = { mmap_commit: snd_pcm_hw_mmap_commit, }; +/** + * \brief Creates a new hw PCM + * \param pcmp Returns created PCM handle + * \param name Name of PCM + * \param card Number of card + * \param device Number of device + * \param subdevice Number of subdevice + * \param stream PCM Stream + * \param mode PCM Mode + * \retval zero on success otherwise a negative error code + * \warning Using of this function might be dangerous in the sense + * of compatibility reasons. The prototype might be freely + * changed in future. + */ int snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name, int card, int device, int subdevice, snd_pcm_stream_t stream, int mode, @@ -795,6 +821,45 @@ int snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name, return ret; } +/*! \page pcm_plugins + +\section pcm_plugins_hw Plugin: hw + +This plugin communicates directly with the ALSA kernel driver. It is a raw +communication without any conversions. The emulation of mmap access can be +optionally enabled, but expect a worse latency in the case. + +\code +pcm.name { + type hw # Kernel PCM + card INT/STR # Card name (string) or number (integer) + [device INT] # Device number (default 0) + [subdevice INT] # Subdevice number (default -1: first available) + [mmap_emulation BOOL] # Enable mmap emulation for ro/wo devices +} +\endcode + +\subsection pcm_plugins_hw_funcref Function reference + +<UL> + <LI>snd_pcm_hw_open() + <LI>_snd_pcm_hw_open() +</UL> + +*/ + +/** + * \brief Creates a new hw PCM + * \param pcmp Returns created PCM handle + * \param name Name of PCM + * \param root Root configuration node + * \param conf Configuration node with hw PCM description + * \param stream PCM Stream + * \param mode PCM Mode + * \warning Using of this function might be dangerous in the sense + * of compatibility reasons. The prototype might be freely + * changed in future. + */ int _snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name, snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *conf, snd_pcm_stream_t stream, int mode) @@ -858,4 +923,6 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name, } return snd_pcm_hw_open(pcmp, name, card, device, subdevice, stream, mode, mmap_emulation); } +#ifndef DOC_HIDDEN SND_DLSYM_BUILD_VERSION(_snd_pcm_hw_open, SND_PCM_DLSYM_VERSION); +#endif diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index a7cb60c6..96de21b8 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -193,19 +193,6 @@ struct _snd_pcm { struct list_head async_handlers; }; -#define ROUTE_PLUGIN_FLOAT 1 -#define ROUTE_PLUGIN_RESOLUTION 16 - -#if ROUTE_PLUGIN_FLOAT -typedef float snd_pcm_route_ttable_entry_t; -#define HALF 0.5 -#define FULL 1.0 -#else -typedef int snd_pcm_route_ttable_entry_t; -#define HALF (ROUTE_PLUGIN_RESOLUTION / 2) -#define FULL ROUTE_PLUGIN_RESOLUTION -#endif - /* FIXME */ #define _snd_pcm_link_descriptor _snd_pcm_poll_descriptor #define _snd_pcm_async_descriptor _snd_pcm_poll_descriptor diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c index 19e93a63..8aaf56df 100644 --- a/src/pcm/pcm_plug.c +++ b/src/pcm/pcm_plug.c @@ -333,7 +333,7 @@ static int snd_pcm_plug_change_channels(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm n = slv->channels; } while (n-- > 0) { - snd_pcm_route_ttable_entry_t v = FULL; + snd_pcm_route_ttable_entry_t v = SND_PCM_PLUGIN_ROUTE_FULL; if (rpolicy == PLUG_ROUTE_POLICY_AVERAGE) { if (pcm->stream == SND_PCM_STREAM_PLAYBACK && clt->channels > slv->channels) { @@ -363,7 +363,7 @@ static int snd_pcm_plug_change_channels(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm n = slv->channels; } for (c = 0; (int)c < n; c++) - ttable[c * tt_ssize + c] = FULL; + ttable[c * tt_ssize + c] = SND_PCM_PLUGIN_ROUTE_FULL; break; default: SNDERR("Invalid route policy"); diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c index 23a7ae82..0353dff1 100644 --- a/src/pcm/pcm_plugin.c +++ b/src/pcm/pcm_plugin.c @@ -1,3 +1,11 @@ +/** + * \file pcm/pcm_plugin.c + * \ingroup PCM + * \brief PCM Interface + * \author Jaroslav Kysela <perex@suse.cz> + * \author Abramo Bagnara <abramo@alsa-project.org> + * \date 2000-2001 + */ /* * PCM - Common plugin code * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org> @@ -18,12 +26,21 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ +/*! + * \page pcm_plugins PCM (digital audio) plugins + * + * PCM plugins extends functionality and features of PCM devices. + * The plugins take care about various sample conversions, sample + * copying among channels and so on. + */ #include <sys/shm.h> #include <limits.h> #include "pcm_local.h" #include "pcm_plugin.h" +#ifndef DOC_HIDDEN + int snd_pcm_plugin_close(snd_pcm_t *pcm) { snd_pcm_plugin_t *plugin = pcm->private_data; @@ -481,3 +498,5 @@ snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = { mmap_commit: snd_pcm_plugin_mmap_commit, }; + +#endif diff --git a/src/pcm/pcm_plugin.h b/src/pcm/pcm_plugin.h index 0ab89883..a3297244 100644 --- a/src/pcm/pcm_plugin.h +++ b/src/pcm/pcm_plugin.h @@ -19,7 +19,7 @@ * */ -#include "atomic.h" +#include "iatomic.h" typedef snd_pcm_uframes_t (*snd_pcm_slave_xfer_areas_func_t) (snd_pcm_t *pcm, @@ -79,30 +79,9 @@ int snd_pcm_plugin_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); extern snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops; -#define RATE_MIN 4000 -#define RATE_MAX 192000 - int snd_pcm_linear_get_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format); int snd_pcm_linear_put_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format); int snd_pcm_linear_convert_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format); -int snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int close_slave); -int snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, snd_pcm_t *slave, int close_slave); -int snd_pcm_lfloat_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, snd_pcm_t *slave, int close_slave); -int snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, snd_pcm_t *slave, int close_slave); -int snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, snd_pcm_t *slave, int close_slave); -int snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, snd_pcm_t *slave, int close_slave); -int snd_pcm_route_load_ttable(snd_config_t *tt, snd_pcm_route_ttable_entry_t *ttable, - unsigned int tt_csize, unsigned int tt_ssize, - unsigned int *tt_cused, unsigned int *tt_sused, - int schannels); -int snd_pcm_route_open(snd_pcm_t **pcmp, const char *name, - snd_pcm_format_t sformat, int schannels, - snd_pcm_route_ttable_entry_t *ttable, - unsigned int tt_ssize, - unsigned int tt_cused, unsigned int tt_sused, - snd_pcm_t *slave, int close_slave); -int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, unsigned int srate, snd_pcm_t *slave, int close_slave); - void snd_pcm_linear_convert(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, diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index 2ca4ec9f..3d817bc1 100644 --- a/src/pcm/pcm_rate.c +++ b/src/pcm/pcm_rate.c @@ -229,11 +229,11 @@ static int snd_pcm_rate_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_ if (err < 0) return err; err = _snd_pcm_hw_param_set_min(params, - SND_PCM_HW_PARAM_RATE, RATE_MIN, 0); + SND_PCM_HW_PARAM_RATE, SND_PCM_PLUGIN_RATE_MIN, 0); if (err < 0) return err; err = _snd_pcm_hw_param_set_max(params, - SND_PCM_HW_PARAM_RATE, RATE_MAX, 0); + SND_PCM_HW_PARAM_RATE, SND_PCM_PLUGIN_RATE_MAX, 0); if (err < 0) return err; params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c index 19640041..37177c9d 100644 --- a/src/pcm/pcm_route.c +++ b/src/pcm/pcm_route.c @@ -30,9 +30,9 @@ const char *_snd_module_pcm_route = ""; #endif /* The best possible hack to support missing optimization in gcc 2.7.2.3 */ -#if ROUTE_PLUGIN_RESOLUTION & (ROUTE_PLUGIN_RESOLUTION - 1) != 0 -#define div(a) a /= ROUTE_PLUGIN_RESOLUTION -#elif ROUTE_PLUGIN_RESOLUTION == 16 +#if SND_PCM_PLUGIN_ROUTE_RESOLUTION & (SND_PCM_PLUGIN_ROUTE_RESOLUTION - 1) != 0 +#define div(a) a /= SND_PCM_PLUGIN_ROUTE_RESOLUTION +#elif SND_PCM_PLUGIN_ROUTE_RESOLUTION == 16 #define div(a) a >>= 4 #else #error "Add some code here" @@ -41,7 +41,7 @@ const char *_snd_module_pcm_route = ""; typedef struct { int channel; int as_int; -#if ROUTE_PLUGIN_FLOAT +#if SND_PCM_PLUGIN_ROUTE_FLOAT float as_float; #endif } snd_pcm_route_ttable_src_t; @@ -78,7 +78,7 @@ struct snd_pcm_route_ttable_dst { typedef union { int32_t as_sint32; int64_t as_sint64; -#if ROUTE_PLUGIN_FLOAT +#if SND_PCM_PLUGIN_ROUTE_FLOAT float as_float; #endif } sum_t; @@ -163,7 +163,7 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area, #undef PUT32_LABELS static void *zero_labels[3] = { &&zero_int32, &&zero_int64, -#if ROUTE_PLUGIN_FLOAT +#if SND_PCM_PLUGIN_ROUTE_FLOAT &&zero_float #endif }; @@ -171,7 +171,7 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area, static void *add_labels[3 * 2] = { &&add_int32_noatt, &&add_int32_att, &&add_int64_noatt, &&add_int64_att, -#if ROUTE_PLUGIN_FLOAT +#if SND_PCM_PLUGIN_ROUTE_FLOAT &&add_float_noatt, &&add_float_att #endif }; @@ -193,7 +193,7 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area, &&norm_int64_8_att, &&norm_int64_16_att, &&norm_int64_24_att, -#if ROUTE_PLUGIN_FLOAT +#if SND_PCM_PLUGIN_ROUTE_FLOAT &&norm_float_0, &&norm_float_8, &&norm_float_16, @@ -226,7 +226,7 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area, src_areas, src_offset, frames, ttable, params); return; - } else if (nsrcs == 1 && src_tt[0].as_int == ROUTE_PLUGIN_RESOLUTION) { + } else if (nsrcs == 1 && src_tt[0].as_int == SND_PCM_PLUGIN_ROUTE_RESOLUTION) { snd_pcm_route_convert1_one(dst_area, dst_offset, src_areas, src_offset, frames, ttable, params); @@ -253,7 +253,7 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area, zero_int64: sum.as_sint64 = 0; goto zero_end; -#if ROUTE_PLUGIN_FLOAT +#if SND_PCM_PLUGIN_ROUTE_FLOAT zero_float: sum.as_float = 0.0; goto zero_end; @@ -285,7 +285,7 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area, if (ttp->as_int) sum.as_sint64 += sample; goto after_sum; -#if ROUTE_PLUGIN_FLOAT +#if SND_PCM_PLUGIN_ROUTE_FLOAT add_float_att: sum.as_float += sample * ttp->as_float; goto after_sum; @@ -349,7 +349,7 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area, sample = sum.as_sint64; goto after_norm; -#if ROUTE_PLUGIN_FLOAT +#if SND_PCM_PLUGIN_ROUTE_FLOAT norm_float_8: sum.as_float *= 1 << 8; goto norm_float; @@ -552,7 +552,7 @@ static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) route->params.conv_idx = snd_pcm_linear_convert_index(src_format, dst_format); route->params.src_size = snd_pcm_format_width(src_format) / 8; route->params.dst_sfmt = dst_format; -#if ROUTE_PLUGIN_FLOAT +#if SND_PCM_PLUGIN_ROUTE_FLOAT route->params.sum_idx = FLOAT; #else if (snd_pcm_format_width(src_format) == 32) @@ -624,10 +624,10 @@ static void snd_pcm_route_dump(snd_pcm_t *pcm, snd_output_t *out) while (1) { snd_pcm_route_ttable_src_t *s = &d->srcs[src]; if (d->att) -#if ROUTE_PLUGIN_FLOAT +#if SND_PCM_PLUGIN_ROUTE_FLOAT snd_output_printf(out, "%d*%g", s->channel, s->as_float); #else - snd_output_printf(out, "%d*%g", s->channel, (double)s->as_int / (double)ROUTE_PLUGIN_RESOLUTION); + snd_output_printf(out, "%d*%g", s->channel, (double)s->as_int / (double)SND_PCM_PLUGIN_ROUTE_RESOLUTION); #endif else snd_output_printf(out, "%d", s->channel); @@ -693,24 +693,24 @@ static int route_load_ttable(snd_pcm_route_params_t *params, snd_pcm_stream_t st for (src_channel = 0; src_channel < sused; ++src_channel) { snd_pcm_route_ttable_entry_t v; v = ttable[src_channel * smul + dst_channel * dmul]; - assert(v >= 0 && v <= FULL); + assert(v >= 0 && v <= SND_PCM_PLUGIN_ROUTE_FULL); if (v != 0) { srcs[nsrcs].channel = src_channel; -#if ROUTE_PLUGIN_FLOAT +#if SND_PCM_PLUGIN_ROUTE_FLOAT /* Also in user space for non attenuated */ - srcs[nsrcs].as_int = (v == FULL ? ROUTE_PLUGIN_RESOLUTION : 0); + srcs[nsrcs].as_int = (v == SND_PCM_PLUGIN_ROUTE_FULL ? SND_PCM_PLUGIN_ROUTE_RESOLUTION : 0); srcs[nsrcs].as_float = v; #else srcs[nsrcs].as_int = v; #endif - if (v != FULL) + if (v != SND_PCM_PLUGIN_ROUTE_FULL) att = 1; t += v; nsrcs++; } } #if 0 - assert(t <= FULL); + assert(t <= SND_PCM_PLUGIN_ROUTE_FULL); #endif dptr->att = att; dptr->nsrcs = nsrcs; |