summaryrefslogtreecommitdiff
path: root/src/pcm
diff options
context:
space:
mode:
Diffstat (limited to 'src/pcm')
-rw-r--r--src/pcm/Makefile.in5
-rw-r--r--src/pcm/pcm.c253
-rw-r--r--src/pcm/pcm_adpcm.c6
-rw-r--r--src/pcm/pcm_alaw.c2
-rw-r--r--src/pcm/pcm_copy.c2
-rw-r--r--src/pcm/pcm_direct.c6
-rw-r--r--src/pcm/pcm_dmix.c20
-rw-r--r--src/pcm/pcm_dmix_i386.h4
-rw-r--r--src/pcm/pcm_dmix_x86_64.h2
-rw-r--r--src/pcm/pcm_dshare.c30
-rw-r--r--src/pcm/pcm_dsnoop.c23
-rw-r--r--src/pcm/pcm_extplug.c6
-rw-r--r--src/pcm/pcm_file.c216
-rw-r--r--src/pcm/pcm_generic.c13
-rw-r--r--src/pcm/pcm_generic.h6
-rw-r--r--src/pcm/pcm_hooks.c6
-rw-r--r--src/pcm/pcm_hw.c210
-rw-r--r--src/pcm/pcm_iec958.c4
-rw-r--r--src/pcm/pcm_ioplug.c22
-rw-r--r--src/pcm/pcm_ladspa.c2
-rw-r--r--src/pcm/pcm_lfloat.c2
-rw-r--r--src/pcm/pcm_linear.c2
-rw-r--r--src/pcm/pcm_local.h19
-rw-r--r--src/pcm/pcm_meter.c10
-rw-r--r--src/pcm/pcm_misc.c13
-rw-r--r--src/pcm/pcm_mmap.c9
-rw-r--r--src/pcm/pcm_mmap_emul.c35
-rw-r--r--src/pcm/pcm_mulaw.c2
-rw-r--r--src/pcm/pcm_multi.c4
-rw-r--r--src/pcm/pcm_null.c7
-rw-r--r--src/pcm/pcm_params.c24
-rw-r--r--src/pcm/pcm_plug.c98
-rw-r--r--src/pcm/pcm_plugin.c31
-rw-r--r--src/pcm/pcm_plugin.h2
-rw-r--r--src/pcm/pcm_rate.c8
-rw-r--r--src/pcm/pcm_rate_linear.c2
-rw-r--r--src/pcm/pcm_route.c8
-rw-r--r--src/pcm/pcm_share.c29
-rw-r--r--src/pcm/pcm_shm.c16
-rw-r--r--src/pcm/pcm_softvol.c107
-rw-r--r--src/pcm/pcm_symbols_list.c9
-rw-r--r--src/pcm/plugin_ops.h22
-rw-r--r--src/pcm/scopes/Makefile.in5
43 files changed, 1046 insertions, 256 deletions
diff --git a/src/pcm/Makefile.in b/src/pcm/Makefile.in
index 55b4a47..db0320d 100644
--- a/src/pcm/Makefile.in
+++ b/src/pcm/Makefile.in
@@ -36,7 +36,6 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-target_triplet = @target@
@BUILD_PCM_PLUGIN_TRUE@am__append_1 = pcm_generic.c pcm_plugin.c
@BUILD_PCM_PLUGIN_COPY_TRUE@am__append_2 = pcm_copy.c
@BUILD_PCM_PLUGIN_LINEAR_TRUE@am__append_3 = pcm_linear.c
@@ -358,11 +357,7 @@ psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
-target = @target@
target_alias = @target_alias@
-target_cpu = @target_cpu@
-target_os = @target_os@
-target_vendor = @target_vendor@
SUBDIRS =
DIST_SUBDIRS = scopes
EXTRA_LTLIBRARIES = libpcm.la
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index efabf5c..2016dd4 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -394,6 +394,7 @@ call.
\subsection pcm_status_fast Obtaining stream state fast and update r/w pointer
+<p>
The function #snd_pcm_avail_update() updates the current
available count of samples for writing (playback) or filled samples for
reading (capture). This call is mandatory for updating actual r/w pointer.
@@ -401,15 +402,12 @@ Using standalone, it is a light method to obtain current stream position,
because it does not require the user <-> kernel context switch, but the value
is less accurate, because ring buffer pointers are updated in kernel drivers
only when an interrupt occurs. If you want to get accurate stream state,
-use functions #snd_pcm_hwsync() or #snd_pcm_delay().
-Note that both of these functions do not update the current r/w pointer
-for applications, so the function #snd_pcm_avail_update() must
-be called afterwards before any read/write begin+commit operations.
+use functions #snd_pcm_avail(), #snd_pcm_delay() or #snd_pcm_avail_delay().
+</p>
<p>
-The function #snd_pcm_hwsync() reads the current hardware pointer
-in the ring buffer from hardware. Note that this function does not update the current
-r/w pointer for applications, so the function #snd_pcm_avail_update()
-must be called afterwards before any read/write/begin+commit operations.
+The function #snd_pcm_avail() reads the current hardware pointer
+in the ring buffer from hardware and calls #snd_pcm_avail_update() then.
+</p>
<p>
The function #snd_pcm_delay() returns the delay in samples.
For playback, it means count of samples in the ring buffer before
@@ -419,6 +417,11 @@ only when the stream is in the running or draining (playback only) state.
Note that this function does not update the current r/w pointer for applications,
so the function #snd_pcm_avail_update() must be called afterwards
before any read/write begin+commit operations.
+</p>
+<p>
+The function #snd_pcm_avail_delay() combines #snd_pcm_avail() and
+#snd_pcm_delay() and returns both values in sync.
+</p>
\section pcm_action Managing the stream state
@@ -627,7 +630,6 @@ playback devices.
#include <stdarg.h>
#include <signal.h>
#include <sys/poll.h>
-#include <sys/shm.h>
#include <sys/mman.h>
#include <limits.h>
#include "pcm_local.h"
@@ -879,6 +881,7 @@ int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
pcm->tstamp_mode = params->tstamp_mode;
pcm->period_step = params->period_step;
pcm->avail_min = params->avail_min;
+ pcm->period_event = params->period_event;
pcm->start_threshold = params->start_threshold;
pcm->stop_threshold = params->stop_threshold;
pcm->silence_threshold = params->silence_threshold;
@@ -914,7 +917,7 @@ snd_pcm_state_t snd_pcm_state(snd_pcm_t *pcm)
}
/**
- * \brief Synchronize stream position with hardware
+ * \brief (DEPRECATED) Synchronize stream position with hardware
* \param pcm PCM handle
* \return 0 on success otherwise a negative error code
*
@@ -931,6 +934,9 @@ int snd_pcm_hwsync(snd_pcm_t *pcm)
}
return pcm->fast_ops->hwsync(pcm->fast_op_arg);
}
+#ifndef DOC_HIDDEN
+link_warning(snd_pcm_hwsync, "Warning: snd_pcm_hwsync() is deprecated, consider to use snd_pcm_avail()");
+#endif
/**
* \brief Obtain delay for a running PCM handle
@@ -938,11 +944,23 @@ int snd_pcm_hwsync(snd_pcm_t *pcm)
* \param delayp Returned delay in frames
* \return 0 on success otherwise a negative error code
*
- * Delay is distance between current application frame position and
- * sound frame position.
- * It's positive and less than buffer size in normal situation,
- * negative on playback underrun and greater than buffer size on
- * capture overrun.
+ * For playback the delay is defined as the time that a frame that is written
+ * to the PCM stream shortly after this call will take to be actually
+ * audible. It is as such the overall latency from the write call to the final
+ * DAC.
+ *
+ * For capture the delay is defined as the time that a frame that was
+ * digitized by the audio device takes until it can be read from the PCM
+ * stream shortly after this call returns. It is as such the overall latency
+ * from the initial ADC to the read call.
+ *
+ * Please note that hence in case of a playback underrun this value will not
+ * necessarily got down to 0.
+ *
+ * If the application is interested in the fill level of the playback buffer
+ * of the device, it should use #snd_pcm_avail*() functions. The
+ * value returned by that call is not directly related to the delay, since the
+ * latter might include some additional, fixed latencies the former does not.
*
* Note this function does not update the actual r/w pointer
* for applications. The function #snd_pcm_avail_update()
@@ -1112,6 +1130,25 @@ int snd_pcm_pause(snd_pcm_t *pcm, int enable)
}
/**
+ * \brief Get safe count of frames which can be rewinded
+ * \param pcm PCM handle
+ * \return a positive number of frames or negative error code
+ *
+ * Note: The snd_pcm_rewind() can accept bigger value than returned
+ * by this function. But it is not guaranteed that output stream
+ * will be consistent with bigger value.
+ */
+snd_pcm_sframes_t snd_pcm_rewindable(snd_pcm_t *pcm)
+{
+ assert(pcm);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
+ return pcm->fast_ops->rewindable(pcm->fast_op_arg);
+}
+
+/**
* \brief Move application frame position backward
* \param pcm PCM handle
* \param frames wanted displacement in frames
@@ -1131,6 +1168,25 @@ snd_pcm_sframes_t snd_pcm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
}
/**
+ * \brief Get safe count of frames which can be forwarded
+ * \param pcm PCM handle
+ * \return a positive number of frames or negative error code
+ *
+ * Note: The snd_pcm_forward() can accept bigger value than returned
+ * by this function. But it is not guaranteed that output stream
+ * will be consistent with bigger value.
+ */
+snd_pcm_sframes_t snd_pcm_forwardable(snd_pcm_t *pcm)
+{
+ assert(pcm);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
+ return pcm->fast_ops->forwardable(pcm->fast_op_arg);
+}
+
+/**
* \brief Move application frame position forward
* \param pcm PCM handle
* \param frames wanted skip in frames
@@ -1222,7 +1278,7 @@ snd_pcm_sframes_t snd_pcm_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t
* \brief Read interleaved frames from a PCM
* \param pcm PCM handle
* \param buffer frames containing buffer
- * \param size frames to be written
+ * \param size frames to be read
* \return a positive number of frames actually read otherwise a
* negative error code
* \retval -EBADFD PCM is not in the right state (#SND_PCM_STATE_PREPARED or #SND_PCM_STATE_RUNNING)
@@ -1254,7 +1310,7 @@ snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t
* \brief Read non interleaved frames to a PCM
* \param pcm PCM handle
* \param bufs frames containing buffers (one for each channel)
- * \param size frames to be written
+ * \param size frames to be read
* \return a positive number of frames actually read otherwise a
* negative error code
* \retval -EBADFD PCM is not in the right state (#SND_PCM_STATE_PREPARED or #SND_PCM_STATE_RUNNING)
@@ -1415,12 +1471,12 @@ int snd_pcm_poll_descriptors_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsign
#define SUBFORMATD(v, d) [SND_PCM_SUBFORMAT_##v] = d
-static const char *snd_pcm_stream_names[] = {
+static const char *const snd_pcm_stream_names[] = {
STREAM(PLAYBACK),
STREAM(CAPTURE),
};
-static const char *snd_pcm_state_names[] = {
+static const char *const snd_pcm_state_names[] = {
STATE(OPEN),
STATE(SETUP),
STATE(PREPARED),
@@ -1432,7 +1488,7 @@ static const char *snd_pcm_state_names[] = {
STATE(DISCONNECTED),
};
-static const char *snd_pcm_access_names[] = {
+static const char *const snd_pcm_access_names[] = {
ACCESS(MMAP_INTERLEAVED),
ACCESS(MMAP_NONINTERLEAVED),
ACCESS(MMAP_COMPLEX),
@@ -1440,7 +1496,7 @@ static const char *snd_pcm_access_names[] = {
ACCESS(RW_NONINTERLEAVED),
};
-static const char *snd_pcm_format_names[] = {
+static const char *const snd_pcm_format_names[] = {
FORMAT(S8),
FORMAT(U8),
FORMAT(S16_LE),
@@ -1481,7 +1537,7 @@ static const char *snd_pcm_format_names[] = {
FORMAT(U18_3BE),
};
-static const char *snd_pcm_format_aliases[SND_PCM_FORMAT_LAST+1] = {
+static const char *const snd_pcm_format_aliases[SND_PCM_FORMAT_LAST+1] = {
FORMAT(S16),
FORMAT(U16),
FORMAT(S24),
@@ -1493,7 +1549,7 @@ static const char *snd_pcm_format_aliases[SND_PCM_FORMAT_LAST+1] = {
FORMAT(IEC958_SUBFRAME),
};
-static const char *snd_pcm_format_descriptions[] = {
+static const char *const snd_pcm_format_descriptions[] = {
FORMATD(S8, "Signed 8 bit"),
FORMATD(U8, "Unsigned 8 bit"),
FORMATD(S16_LE, "Signed 16 bit Little Endian"),
@@ -1534,7 +1590,7 @@ static const char *snd_pcm_format_descriptions[] = {
FORMATD(U18_3BE, "Unsigned 18 bit Big Endian in 3bytes"),
};
-static const char *snd_pcm_type_names[] = {
+static const char *const snd_pcm_type_names[] = {
PCMTYPE(HW),
PCMTYPE(HOOKS),
PCMTYPE(MULTI),
@@ -1566,25 +1622,25 @@ static const char *snd_pcm_type_names[] = {
PCMTYPE(EXTPLUG),
};
-static const char *snd_pcm_subformat_names[] = {
+static const char *const snd_pcm_subformat_names[] = {
SUBFORMAT(STD),
};
-static const char *snd_pcm_subformat_descriptions[] = {
+static const char *const snd_pcm_subformat_descriptions[] = {
SUBFORMATD(STD, "Standard"),
};
-static const char *snd_pcm_start_mode_names[] = {
+static const char *const snd_pcm_start_mode_names[] = {
START(EXPLICIT),
START(DATA),
};
-static const char *snd_pcm_xrun_mode_names[] = {
+static const char *const snd_pcm_xrun_mode_names[] = {
XRUN(NONE),
XRUN(STOP),
};
-static const char *snd_pcm_tstamp_mode_names[] = {
+static const char *const snd_pcm_tstamp_mode_names[] = {
TSTAMP(NONE),
TSTAMP(ENABLE),
};
@@ -1809,6 +1865,7 @@ int snd_pcm_dump_sw_setup(snd_pcm_t *pcm, snd_output_t *out)
snd_output_printf(out, " tstamp_mode : %s\n", snd_pcm_tstamp_mode_name(pcm->tstamp_mode));
snd_output_printf(out, " period_step : %d\n", pcm->period_step);
snd_output_printf(out, " avail_min : %ld\n", pcm->avail_min);
+ snd_output_printf(out, " period_event : %i\n", pcm->period_event);
snd_output_printf(out, " start_threshold : %ld\n", pcm->start_threshold);
snd_output_printf(out, " stop_threshold : %ld\n", pcm->stop_threshold);
snd_output_printf(out, " silence_threshold: %ld\n", pcm->silence_threshold);
@@ -1977,7 +2034,7 @@ snd_pcm_t *snd_async_handler_get_pcm(snd_async_handler_t *handler)
return handler->u.pcm;
}
-static char *build_in_pcms[] = {
+static const char *const build_in_pcms[] = {
"adpcm", "alaw", "copy", "dmix", "file", "hooks", "hw", "ladspa", "lfloat",
"linear", "meter", "mulaw", "multi", "null", "empty", "plug", "rate", "route", "share",
"shm", "dsnoop", "dshare", "asym", "iec958", "softvol", "mmap_emul",
@@ -2071,7 +2128,7 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
sprintf(buf, "_snd_pcm_%s_open", str);
}
if (!lib) {
- char **build_in = build_in_pcms;
+ const char *const *build_in = build_in_pcms;
while (*build_in) {
if (!strcmp(*build_in, str))
break;
@@ -2345,7 +2402,7 @@ int snd_pcm_wait_nocheck(snd_pcm_t *pcm, int timeout)
#endif
/**
- * \brief Return number of frames ready to be read/written
+ * \brief Return number of frames ready to be read (capture) / written (playback)
* \param pcm PCM handle
* \return a positive number of frames ready otherwise a negative
* error code
@@ -2353,8 +2410,17 @@ int snd_pcm_wait_nocheck(snd_pcm_t *pcm, int timeout)
* On capture does all the actions needed to transport to application
* level all the ready frames across underlying layers.
*
- * Using of this function is useless for the standard read/write
- * operations. Use it only for mmap access. See to #snd_pcm_delay.
+ * The position is not synced with hardware (driver) position in the sound
+ * ring buffer in this function. This function is a light version of
+ * #snd_pcm_avail() .
+ *
+ * Using this function is ideal after poll() or select() when audio
+ * file descriptor made the event and when application expects just period
+ * timing.
+ *
+ * Also this function might be called after #snd_pcm_delay() or
+ * #snd_pcm_hwsync() functions to move private ring buffer pointers
+ * in alsa-lib (the internal plugin chain).
*/
snd_pcm_sframes_t snd_pcm_avail_update(snd_pcm_t *pcm)
{
@@ -2362,6 +2428,63 @@ snd_pcm_sframes_t snd_pcm_avail_update(snd_pcm_t *pcm)
}
/**
+ * \brief Return number of frames ready to be read (capture) / written (playback)
+ * \param pcm PCM handle
+ * \return a positive number of frames ready otherwise a negative
+ * error code
+ *
+ * On capture does all the actions needed to transport to application
+ * level all the ready frames across underlying layers.
+ *
+ * The position is synced with hardware (driver) position in the sound
+ * ring buffer in this functions.
+ */
+snd_pcm_sframes_t snd_pcm_avail(snd_pcm_t *pcm)
+{
+ int err;
+
+ assert(pcm);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
+ err = pcm->fast_ops->hwsync(pcm->fast_op_arg);
+ if (err < 0)
+ return err;
+ return pcm->fast_ops->avail_update(pcm->fast_op_arg);
+}
+
+/**
+ * \brief Combine snd_pcm_avail and snd_pcm_delay functions
+ * \param pcm PCM handle
+ * \param avail Number of available frames in the ring buffer
+ * \param delay Total I/O latency in frames
+ * \return zero on success otherwise a negative error code
+ *
+ * The avail and delay values retuned are in sync.
+ */
+int snd_pcm_avail_delay(snd_pcm_t *pcm,
+ snd_pcm_sframes_t *availp,
+ snd_pcm_sframes_t *delayp)
+{
+ snd_pcm_sframes_t sf;
+
+ assert(pcm && availp && delayp);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
+ sf = pcm->fast_ops->delay(pcm->fast_op_arg, delayp);
+ if (sf < 0)
+ return (int)sf;
+ sf = pcm->fast_ops->avail_update(pcm->fast_op_arg);
+ if (sf < 0)
+ return (int)sf;
+ *availp = sf;
+ return 0;
+}
+
+/**
* \brief Silence an area
* \param dst_area area specification
* \param dst_offset offset in frames inside area
@@ -2812,6 +2935,27 @@ int snd_pcm_hw_params_is_block_transfer(const snd_pcm_hw_params_t *params)
}
/**
+ * \brief Check, if timestamps are monotonic for given configuration
+ * \param params Configuration space
+ * \return Boolean value
+ * \retval 0 Device doesn't do monotomic timestamps
+ * \retval 1 Device does monotonic timestamps
+ *
+ * It is not allowed to call this function when given configuration is not exactly one.
+ * Usually, #snd_pcm_hw_params() function chooses one configuration
+ * from the configuration space.
+ */
+int snd_pcm_hw_params_is_monotonic(const snd_pcm_hw_params_t *params)
+{
+ assert(params);
+ if (CHECK_SANITY(params->info == ~0U)) {
+ SNDMSG("invalid PCM info field");
+ return 0; /* FIXME: should be a negative error? */
+ }
+ return !!(params->info & SND_PCM_INFO_MONOTONIC);
+}
+
+/**
* \brief Check, if hardware supports overrange detection
* \param params Configuration space
* \return Boolean value
@@ -5305,6 +5449,7 @@ int snd_pcm_sw_params_current(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
params->period_step = pcm->period_step;
params->sleep_min = 0;
params->avail_min = pcm->avail_min;
+ params->period_event = pcm->period_event;
params->xfer_align = 1;
params->start_threshold = pcm->start_threshold;
params->stop_threshold = pcm->stop_threshold;
@@ -5600,6 +5745,34 @@ int snd_pcm_sw_params_get_avail_min(const snd_pcm_sw_params_t *params, snd_pcm_u
return 0;
}
+/**
+ * \brief Set period event inside a software configuration container
+ * \param pcm PCM handle
+ * \param params Software configuration container
+ * \param val 0 = disable period event, 1 = enable period event
+ * \return 0 otherwise a negative error code
+ *
+ * An poll (select) wakeup event is raised if enabled.
+ */
+int snd_pcm_sw_params_set_period_event(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, int val)
+{
+ assert(pcm && params);
+ params->period_event = val;
+ return 0;
+}
+
+/**
+ * \brief Get period event from a software configuration container
+ * \param params Software configuration container
+ * \param val returned period event state
+ * \return 0 otherwise a negative error code
+ */
+int snd_pcm_sw_params_get_period_event(const snd_pcm_sw_params_t *params, int *val)
+{
+ assert(params && val);
+ *val = params->period_event;
+ return 0;
+}
/**
* \brief (DEPRECATED) Set xfer align inside a software configuration container
@@ -5882,6 +6055,10 @@ snd_pcm_state_t snd_pcm_status_get_state(const snd_pcm_status_t *obj)
* \brief Get trigger timestamp from a PCM status container
* \param obj #snd_pcm_status_t pointer
* \param ptr Pointer to returned timestamp
+ *
+ * Trigger means a PCM state transition (from stopped to running or
+ * versa vice). It applies also to pause and suspend. In other words,
+ * timestamp contains time when stream started or when it was stopped.
*/
void snd_pcm_status_get_trigger_tstamp(const snd_pcm_status_t *obj, snd_timestamp_t *ptr)
{
@@ -5894,6 +6071,10 @@ void snd_pcm_status_get_trigger_tstamp(const snd_pcm_status_t *obj, snd_timestam
* \brief Get trigger hi-res timestamp from a PCM status container
* \param obj #snd_pcm_status_t pointer
* \param ptr Pointer to returned timestamp
+ *
+ * Trigger means a PCM state transition (from stopped to running or
+ * versa vice). It applies also to pause and suspend. In other words,
+ * timestamp contains time when stream started or when it was stopped.
*/
#ifndef DOXYGEN
void INTERNAL(snd_pcm_status_get_trigger_htstamp)(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr)
@@ -6508,7 +6689,7 @@ link_warning(_snd_pcm_mmap_hw_ptr, "Warning: _snd_pcm_mmap_hw_ptr() is deprecate
link_warning(_snd_pcm_boundary, "Warning: _snd_pcm_boundary() is deprecated, consider to use snd_pcm_sw_params_current()");
#endif
-static const char *names[SND_PCM_HW_PARAM_LAST_INTERVAL + 1] = {
+static const char *const names[SND_PCM_HW_PARAM_LAST_INTERVAL + 1] = {
[SND_PCM_HW_PARAM_FORMAT] = "format",
[SND_PCM_HW_PARAM_CHANNELS] = "channels",
[SND_PCM_HW_PARAM_RATE] = "rate",
@@ -6654,7 +6835,7 @@ int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf,
int snd_pcm_conf_generic_id(const char *id)
{
- static const char *ids[] = { "comment", "type", "hint" };
+ static const char ids[3][8] = { "comment", "type", "hint" };
unsigned int k;
for (k = 0; k < sizeof(ids) / sizeof(ids[0]); ++k) {
if (strcmp(id, ids[k]) == 0)
diff --git a/src/pcm/pcm_adpcm.c b/src/pcm/pcm_adpcm.c
index 4f9c46b..b68007f 100644
--- a/src/pcm/pcm_adpcm.c
+++ b/src/pcm/pcm_adpcm.c
@@ -89,10 +89,10 @@ typedef struct {
#endif
/* First table lookup for Ima-ADPCM quantizer */
-static char IndexAdjust[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
+static const char IndexAdjust[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
/* Second table lookup for Ima-ADPCM quantizer */
-static short StepSize[89] = {
+static const short StepSize[89] = {
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
@@ -518,7 +518,7 @@ static void snd_pcm_adpcm_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(adpcm->plug.gen.slave, out);
}
-static snd_pcm_ops_t snd_pcm_adpcm_ops = {
+static const snd_pcm_ops_t snd_pcm_adpcm_ops = {
.close = snd_pcm_generic_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_adpcm_hw_refine,
diff --git a/src/pcm/pcm_alaw.c b/src/pcm/pcm_alaw.c
index 3814241..09ad481 100644
--- a/src/pcm/pcm_alaw.c
+++ b/src/pcm/pcm_alaw.c
@@ -391,7 +391,7 @@ static void snd_pcm_alaw_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(alaw->plug.gen.slave, out);
}
-static snd_pcm_ops_t snd_pcm_alaw_ops = {
+static const snd_pcm_ops_t snd_pcm_alaw_ops = {
.close = snd_pcm_generic_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_alaw_hw_refine,
diff --git a/src/pcm/pcm_copy.c b/src/pcm/pcm_copy.c
index 9d3eb38..072bb12 100644
--- a/src/pcm/pcm_copy.c
+++ b/src/pcm/pcm_copy.c
@@ -152,7 +152,7 @@ static void snd_pcm_copy_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(copy->plug.gen.slave, out);
}
-static snd_pcm_ops_t snd_pcm_copy_ops = {
+static const snd_pcm_ops_t snd_pcm_copy_ops = {
.close = snd_pcm_generic_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_copy_hw_refine,
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
index a884b12..82cc126 100644
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -654,7 +654,7 @@ static int hw_param_interval_refine_minmax(snd_pcm_hw_params_t *params,
int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
{
snd_pcm_direct_t *dshare = pcm->private_data;
- static snd_mask_t access = { .bits = {
+ static const snd_mask_t access = { .bits = {
(1<<SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) |
(1<<SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED) |
(1<<SNDRV_PCM_ACCESS_RW_INTERLEAVED) |
@@ -1107,7 +1107,7 @@ int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix)
snd_pcm_info_get_subdevice(info) * 2 + capture);
ret = snd_timer_open(&dmix->timer, name, SND_TIMER_OPEN_NONBLOCK | SND_TIMER_OPEN_TREAD);
if (ret < 0) {
- dmix->tread = 1;
+ dmix->tread = 0;
ret = snd_timer_open(&dmix->timer, name, SND_TIMER_OPEN_NONBLOCK);
if (ret < 0) {
SNDERR("unable to open timer '%s'", name);
@@ -1293,7 +1293,7 @@ int snd_pcm_direct_check_interleave(snd_pcm_direct_t *dmix, snd_pcm_t *pcm)
const snd_pcm_channel_area_t *dst_areas;
const snd_pcm_channel_area_t *src_areas;
- bits = snd_pcm_format_physical_width(dmix->type);
+ bits = snd_pcm_format_physical_width(pcm->format);
if ((bits % 8) != 0)
interleaved = 0;
channels = dmix->channels;
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
index 4d21e9b..5b967e8 100644
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -311,9 +311,9 @@ static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
if (size >= pcm->boundary / 2)
size = pcm->boundary - size;
- /* the slave_app_ptr can be far behing the slave_hw_ptr */
+ /* the slave_app_ptr can be far behind the slave_hw_ptr */
/* reduce mixing and errors here - just skip not catched writes */
- if (dmix->slave_hw_ptr < dmix->slave_appl_ptr)
+ if (dmix->slave_hw_ptr <= dmix->slave_appl_ptr)
slave_size = dmix->slave_appl_ptr - dmix->slave_hw_ptr;
else
slave_size = dmix->slave_appl_ptr + (dmix->slave_boundary - dmix->slave_hw_ptr);
@@ -649,6 +649,11 @@ static int snd_pcm_dmix_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTRIB
return -EIO;
}
+static snd_pcm_sframes_t snd_pcm_dmix_rewindable(snd_pcm_t *pcm)
+{
+ return snd_pcm_mmap_hw_avail(pcm);
+}
+
static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_direct_t *dmix = pcm->private_data;
@@ -723,6 +728,11 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
return result + frames;
}
+static snd_pcm_sframes_t snd_pcm_dmix_forwardable(snd_pcm_t *pcm)
+{
+ return snd_pcm_mmap_avail(pcm);
+}
+
static snd_pcm_sframes_t snd_pcm_dmix_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_sframes_t avail;
@@ -859,7 +869,7 @@ static void snd_pcm_dmix_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(dmix->spcm, out);
}
-static snd_pcm_ops_t snd_pcm_dmix_ops = {
+static const snd_pcm_ops_t snd_pcm_dmix_ops = {
.close = snd_pcm_dmix_close,
.info = snd_pcm_direct_info,
.hw_refine = snd_pcm_direct_hw_refine,
@@ -874,7 +884,7 @@ static snd_pcm_ops_t snd_pcm_dmix_ops = {
.munmap = snd_pcm_direct_munmap,
};
-static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
+static const snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
.status = snd_pcm_dmix_status,
.state = snd_pcm_dmix_state,
.hwsync = snd_pcm_dmix_hwsync,
@@ -885,7 +895,9 @@ static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
.drop = snd_pcm_dmix_drop,
.drain = snd_pcm_dmix_drain,
.pause = snd_pcm_dmix_pause,
+ .rewindable = snd_pcm_dmix_rewindable,
.rewind = snd_pcm_dmix_rewind,
+ .forwardable = snd_pcm_dmix_forwardable,
.forward = snd_pcm_dmix_forward,
.resume = snd_pcm_direct_resume,
.link = NULL,
diff --git a/src/pcm/pcm_dmix_i386.h b/src/pcm/pcm_dmix_i386.h
index 1ae037a..9ea155d 100644
--- a/src/pcm/pcm_dmix_i386.h
+++ b/src/pcm/pcm_dmix_i386.h
@@ -400,7 +400,7 @@ static void MIX_AREAS_24(unsigned int size,
"\tmovzwl (%%esi), %%ecx\n"
"\tmovl (%%ebx), %%edx\n"
"\tsall $16, %%eax\n"
- "\t" LOCK_PREFIX "btsl $0, (%%edi)\n"
+ "\t" LOCK_PREFIX "btsw $0, (%%edi)\n"
"\tleal (%%ecx,%%eax,1), %%ecx\n"
"\tjc 2f\n"
"\t" XSUB " %%edx, %%ecx\n"
@@ -505,7 +505,7 @@ static void MIX_AREAS_24_CMOV(unsigned int size,
"\tmovzwl (%%esi), %%ecx\n"
"\tmovl (%%ebx), %%edx\n"
"\tsall $16, %%eax\n"
- "\t" LOCK_PREFIX "btsl $0, (%%edi)\n"
+ "\t" LOCK_PREFIX "btsw $0, (%%edi)\n"
"\tleal (%%ecx,%%eax,1), %%ecx\n"
"\tjc 2f\n"
"\t" XSUB " %%edx, %%ecx\n"
diff --git a/src/pcm/pcm_dmix_x86_64.h b/src/pcm/pcm_dmix_x86_64.h
index 4562734..b4d0a41 100644
--- a/src/pcm/pcm_dmix_x86_64.h
+++ b/src/pcm/pcm_dmix_x86_64.h
@@ -287,7 +287,7 @@ static void MIX_AREAS_24(unsigned int size,
"\tmovswl (%%rsi), %%ecx\n"
"\tmovl (%%rbx), %%edx\n"
"\tsall $16, %%eax\n"
- "\t" LOCK_PREFIX "btsl $0, (%%rdi)\n"
+ "\t" LOCK_PREFIX "btsw $0, (%%rdi)\n"
"\t.byte 0x67, 0x8d, 0x0c, 0x01\n"
"\tjc 2f\n"
"\t" XSUB " %%edx, %%ecx\n"
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
index 8d40354..c91fa3b 100644
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -410,15 +410,27 @@ static int snd_pcm_dshare_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTR
return -EIO;
}
-static snd_pcm_sframes_t snd_pcm_dshare_rewind(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_uframes_t frames ATTRIBUTE_UNUSED)
+static snd_pcm_sframes_t snd_pcm_dshare_rewindable(snd_pcm_t *pcm)
{
-#if 0
- /* FIXME: substract samples from the mix ring buffer, too? */
+ return snd_pcm_mmap_playback_hw_avail(pcm);
+}
+
+static snd_pcm_sframes_t snd_pcm_dshare_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
+{
+ snd_pcm_sframes_t avail;
+
+ avail = snd_pcm_mmap_playback_hw_avail(pcm);
+ if (avail < 0)
+ return 0;
+ if (frames > (snd_pcm_uframes_t)avail)
+ frames = avail;
snd_pcm_mmap_appl_backward(pcm, frames);
return frames;
-#else
- return -EIO;
-#endif
+}
+
+static snd_pcm_sframes_t snd_pcm_dshare_forwardable(snd_pcm_t *pcm)
+{
+ return snd_pcm_mmap_playback_avail(pcm);
}
static snd_pcm_sframes_t snd_pcm_dshare_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
@@ -548,7 +560,7 @@ static void snd_pcm_dshare_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(dshare->spcm, out);
}
-static snd_pcm_ops_t snd_pcm_dshare_ops = {
+static const snd_pcm_ops_t snd_pcm_dshare_ops = {
.close = snd_pcm_dshare_close,
.info = snd_pcm_direct_info,
.hw_refine = snd_pcm_direct_hw_refine,
@@ -563,7 +575,7 @@ static snd_pcm_ops_t snd_pcm_dshare_ops = {
.munmap = snd_pcm_direct_munmap,
};
-static snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = {
+static const snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = {
.status = snd_pcm_dshare_status,
.state = snd_pcm_dshare_state,
.hwsync = snd_pcm_dshare_hwsync,
@@ -574,7 +586,9 @@ static snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = {
.drop = snd_pcm_dshare_drop,
.drain = snd_pcm_dshare_drain,
.pause = snd_pcm_dshare_pause,
+ .rewindable = snd_pcm_dshare_rewindable,
.rewind = snd_pcm_dshare_rewind,
+ .forwardable = snd_pcm_dshare_forwardable,
.forward = snd_pcm_dshare_forward,
.resume = snd_pcm_direct_resume,
.link = NULL,
diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
index e9ea81b..9d42c12 100644
--- a/src/pcm/pcm_dsnoop.c
+++ b/src/pcm/pcm_dsnoop.c
@@ -313,12 +313,29 @@ static int snd_pcm_dsnoop_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTR
return -EIO;
}
+static snd_pcm_sframes_t snd_pcm_dsnoop_rewindable(snd_pcm_t *pcm)
+{
+ return snd_pcm_mmap_capture_avail(pcm);
+}
+
static snd_pcm_sframes_t snd_pcm_dsnoop_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
+ snd_pcm_sframes_t avail;
+
+ avail = snd_pcm_mmap_capture_avail(pcm);
+ if (avail < 0)
+ return 0;
+ if (frames > (snd_pcm_uframes_t)avail)
+ frames = avail;
snd_pcm_mmap_appl_backward(pcm, frames);
return frames;
}
+static snd_pcm_sframes_t snd_pcm_dsnoop_forwardable(snd_pcm_t *pcm)
+{
+ return snd_pcm_mmap_capture_hw_avail(pcm);
+}
+
static snd_pcm_sframes_t snd_pcm_dsnoop_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_sframes_t avail;
@@ -438,7 +455,7 @@ static void snd_pcm_dsnoop_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(dsnoop->spcm, out);
}
-static snd_pcm_ops_t snd_pcm_dsnoop_ops = {
+static const snd_pcm_ops_t snd_pcm_dsnoop_ops = {
.close = snd_pcm_dsnoop_close,
.info = snd_pcm_direct_info,
.hw_refine = snd_pcm_direct_hw_refine,
@@ -453,7 +470,7 @@ static snd_pcm_ops_t snd_pcm_dsnoop_ops = {
.munmap = snd_pcm_direct_munmap,
};
-static snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = {
+static const snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = {
.status = snd_pcm_dsnoop_status,
.state = snd_pcm_dsnoop_state,
.hwsync = snd_pcm_dsnoop_hwsync,
@@ -464,7 +481,9 @@ static snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = {
.drop = snd_pcm_dsnoop_drop,
.drain = snd_pcm_dsnoop_drain,
.pause = snd_pcm_dsnoop_pause,
+ .rewindable = snd_pcm_dsnoop_rewindable,
.rewind = snd_pcm_dsnoop_rewind,
+ .forwardable = snd_pcm_dsnoop_forwardable,
.forward = snd_pcm_dsnoop_forward,
.resume = snd_pcm_direct_resume,
.link = NULL,
diff --git a/src/pcm/pcm_extplug.c b/src/pcm/pcm_extplug.c
index 5651014..a34706f 100644
--- a/src/pcm/pcm_extplug.c
+++ b/src/pcm/pcm_extplug.c
@@ -45,14 +45,14 @@ typedef struct snd_pcm_extplug_priv {
struct snd_ext_parm sparams[SND_PCM_EXTPLUG_HW_PARAMS];
} extplug_priv_t;
-static int hw_params_type[SND_PCM_EXTPLUG_HW_PARAMS] = {
+static const int hw_params_type[SND_PCM_EXTPLUG_HW_PARAMS] = {
[SND_PCM_EXTPLUG_HW_FORMAT] = SND_PCM_HW_PARAM_FORMAT,
[SND_PCM_EXTPLUG_HW_CHANNELS] = SND_PCM_HW_PARAM_CHANNELS
};
#define is_mask_type(i) (hw_params_type[i] < SND_PCM_HW_PARAM_FIRST_INTERVAL)
-static unsigned int excl_parbits[SND_PCM_EXTPLUG_HW_PARAMS] = {
+static const unsigned int excl_parbits[SND_PCM_EXTPLUG_HW_PARAMS] = {
[SND_PCM_EXTPLUG_HW_FORMAT] = (SND_PCM_HW_PARBIT_FORMAT|
SND_PCM_HW_PARBIT_SUBFORMAT |
SND_PCM_HW_PARBIT_SAMPLE_BITS),
@@ -425,7 +425,7 @@ static int snd_pcm_extplug_close(snd_pcm_t *pcm)
return 0;
}
-static snd_pcm_ops_t snd_pcm_extplug_ops = {
+static const snd_pcm_ops_t snd_pcm_extplug_ops = {
.close = snd_pcm_extplug_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_extplug_hw_refine,
diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c
index 4b8eaa5..82823a0 100644
--- a/src/pcm/pcm_file.c
+++ b/src/pcm/pcm_file.c
@@ -26,6 +26,7 @@
*
*/
+#include <endian.h>
#include <byteswap.h>
#include <ctype.h>
#include "pcm_local.h"
@@ -39,9 +40,20 @@ const char *_snd_module_pcm_file = "";
#ifndef DOC_HIDDEN
typedef enum _snd_pcm_file_format {
- SND_PCM_FILE_FORMAT_RAW
+ SND_PCM_FILE_FORMAT_RAW,
+ SND_PCM_FILE_FORMAT_WAV
} snd_pcm_file_format_t;
+/* WAV format chunk */
+struct wav_fmt {
+ short fmt;
+ short chan;
+ int rate;
+ int bps;
+ short bwidth;
+ short bits;
+};
+
typedef struct {
snd_pcm_generic_t gen;
char *fname;
@@ -60,14 +72,97 @@ typedef struct {
char *rbuf;
snd_pcm_channel_area_t *wbuf_areas;
size_t buffer_bytes;
+ struct wav_fmt wav_header;
+ size_t filelen;
} snd_pcm_file_t;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define TO_LE32(x) (x)
+#define TO_LE16(x) (x)
+#else
+#define TO_LE32(x) bswap_32(x)
+#define TO_LE16(x) bswap_16(x)
+#endif
+
+static void setup_wav_header(snd_pcm_t *pcm, struct wav_fmt *fmt)
+{
+ fmt->fmt = TO_LE16(0x01);
+ fmt->chan = TO_LE16(pcm->channels);
+ fmt->rate = TO_LE32(pcm->rate);
+ fmt->bwidth = pcm->frame_bits / 8;
+ fmt->bps = fmt->bwidth * pcm->rate;
+ fmt->bits = snd_pcm_format_width(pcm->format);
+ fmt->bps = TO_LE32(fmt->bps);
+ fmt->bwidth = TO_LE16(fmt->bwidth);
+ fmt->bits = TO_LE16(fmt->bits);
+}
+
+static int write_wav_header(snd_pcm_t *pcm)
+{
+ snd_pcm_file_t *file = pcm->private_data;
+ static const char header[] = {
+ 'R', 'I', 'F', 'F',
+ 0x24, 0, 0, 0,
+ 'W', 'A', 'V', 'E',
+ 'f', 'm', 't', ' ',
+ 0x10, 0, 0, 0,
+ };
+ static const char header2[] = {
+ 'd', 'a', 't', 'a',
+ 0, 0, 0, 0
+ };
+
+ setup_wav_header(pcm, &file->wav_header);
+
+ if (write(file->fd, header, sizeof(header)) != sizeof(header) ||
+ write(file->fd, &file->wav_header, sizeof(file->wav_header)) !=
+ sizeof(file->wav_header) ||
+ write(file->fd, header2, sizeof(header2)) != sizeof(header2)) {
+ int err = errno;
+ SYSERR("Write error.\n");
+ return -err;
+ }
+ return 0;
+}
+
+/* fix up the length fields in WAV header */
+static void fixup_wav_header(snd_pcm_t *pcm)
+{
+ snd_pcm_file_t *file = pcm->private_data;
+ int len, ret;
+
+ /* RIFF length */
+ if (lseek(file->fd, 4, SEEK_SET) == 4) {
+ len = (file->filelen + 0x24) > 0x7fffffff ?
+ 0x7fffffff : (int)(file->filelen + 0x24);
+ len = TO_LE32(len);
+ ret = write(file->fd, &len, 4);
+ if (ret < 0)
+ return;
+ }
+ /* data length */
+ if (lseek(file->fd, 0x28, SEEK_SET) == 0x28) {
+ len = file->filelen > 0x7fffffff ?
+ 0x7fffffff : (int)file->filelen;
+ len = TO_LE32(len);
+ ret = write(file->fd, &len, 4);
+ if (ret < 0)
+ return;
+ }
+}
#endif /* DOC_HIDDEN */
static void snd_pcm_file_write_bytes(snd_pcm_t *pcm, size_t bytes)
{
snd_pcm_file_t *file = pcm->private_data;
assert(bytes <= file->wbuf_used_bytes);
+
+ if (file->format == SND_PCM_FILE_FORMAT_WAV &&
+ !file->wav_header.fmt) {
+ if (write_wav_header(pcm) < 0)
+ return;
+ }
+
while (bytes > 0) {
snd_pcm_sframes_t err;
size_t n = bytes;
@@ -84,6 +179,7 @@ static void snd_pcm_file_write_bytes(snd_pcm_t *pcm, size_t bytes)
file->file_ptr_bytes += err;
if (file->file_ptr_bytes == file->wbuf_size_bytes)
file->file_ptr_bytes = 0;
+ file->filelen += err;
if ((snd_pcm_uframes_t)err != n)
break;
}
@@ -122,6 +218,8 @@ static int snd_pcm_file_close(snd_pcm_t *pcm)
{
snd_pcm_file_t *file = pcm->private_data;
if (file->fname) {
+ if (file->wav_header.fmt)
+ fixup_wav_header(pcm);
free((void *)file->fname);
close(file->fd);
}
@@ -167,6 +265,16 @@ static int snd_pcm_file_drain(snd_pcm_t *pcm)
return err;
}
+static snd_pcm_sframes_t snd_pcm_file_rewindable(snd_pcm_t *pcm)
+{
+ snd_pcm_file_t *file = pcm->private_data;
+ snd_pcm_sframes_t res = snd_pcm_rewindable(pcm);
+ snd_pcm_sframes_t n = snd_pcm_bytes_to_frames(pcm, file->wbuf_used_bytes);
+ if (res > n)
+ res = n;
+ return res;
+}
+
static snd_pcm_sframes_t snd_pcm_file_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_file_t *file = pcm->private_data;
@@ -185,6 +293,16 @@ static snd_pcm_sframes_t snd_pcm_file_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
return err;
}
+static snd_pcm_sframes_t snd_pcm_file_forwardable(snd_pcm_t *pcm)
+{
+ snd_pcm_file_t *file = pcm->private_data;
+ snd_pcm_sframes_t res = snd_pcm_forwardable(pcm);
+ snd_pcm_sframes_t n = snd_pcm_bytes_to_frames(pcm, file->wbuf_size_bytes - file->wbuf_used_bytes);
+ if (res > n)
+ res = n;
+ return res;
+}
+
static snd_pcm_sframes_t snd_pcm_file_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_file_t *file = pcm->private_data;
@@ -231,21 +349,19 @@ static snd_pcm_sframes_t snd_pcm_file_readi(snd_pcm_t *pcm, void *buffer, snd_pc
{
snd_pcm_file_t *file = pcm->private_data;
snd_pcm_channel_area_t areas[pcm->channels];
- snd_pcm_sframes_t n /* , bytesn */;
+ snd_pcm_sframes_t n;
+ n = snd_pcm_readi(file->gen.slave, buffer, size);
+ if (n <= 0)
+ return n;
if (file->ifd >= 0) {
- n = /* bytesn = */ read(file->ifd, buffer, size * pcm->frame_bits / 8);
- if (n > 0)
- n = n * 8 / pcm->frame_bits;
- /* SNDERR("DEBUG: channels = %d, sample_bits = %d, frame_bits = %d, bytes = %d, frames = %d",
- pcm->channels, pcm->sample_bits, pcm->frame_bits, bytesn, n); */
- } else {
- n = snd_pcm_readi(file->gen.slave, buffer, size);
- if (n > 0) {
- snd_pcm_areas_from_buf(pcm, areas, buffer);
- snd_pcm_file_add_frames(pcm, areas, 0, n);
- }
+ n = read(file->ifd, buffer, n * pcm->frame_bits / 8);
+ if (n < 0)
+ return n;
+ return n * 8 / pcm->frame_bits;
}
+ snd_pcm_areas_from_buf(pcm, areas, buffer);
+ snd_pcm_file_add_frames(pcm, areas, 0, n);
return n;
}
@@ -344,7 +460,7 @@ static void snd_pcm_file_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(file->gen.slave, out);
}
-static snd_pcm_ops_t snd_pcm_file_ops = {
+static const snd_pcm_ops_t snd_pcm_file_ops = {
.close = snd_pcm_file_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_generic_hw_refine,
@@ -359,7 +475,7 @@ static snd_pcm_ops_t snd_pcm_file_ops = {
.munmap = snd_pcm_generic_munmap,
};
-static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
+static const snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
.status = snd_pcm_generic_status,
.state = snd_pcm_generic_state,
.hwsync = snd_pcm_generic_hwsync,
@@ -370,7 +486,9 @@ static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
.drop = snd_pcm_file_drop,
.drain = snd_pcm_file_drain,
.pause = snd_pcm_generic_pause,
+ .rewindable = snd_pcm_file_rewindable,
.rewind = snd_pcm_file_rewind,
+ .forwardable = snd_pcm_file_forwardable,
.forward = snd_pcm_file_forward,
.resume = snd_pcm_generic_resume,
.link = snd_pcm_generic_link,
@@ -396,7 +514,8 @@ static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
* \param ifname Input filename (or NULL if file descriptor ifd is available)
* \param ifd Input file descriptor (if (ifd < 0) && (ifname == NULL), no input
* redirection will be performed)
- * \param fmt File format ("raw" is supported only)
+ * \param trunc Truncate the file if it already exists
+ * \param fmt File format ("raw" or "wav" are available)
* \param perm File permission
* \param slave Slave PCM handle
* \param close_slave When set, the slave PCM handle is closed with copy PCM
@@ -406,27 +525,52 @@ static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
* changed in future.
*/
int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
- const char *fname, int fd, const char *ifname, int ifd,
+ const char *fname, int fd, const char *ifname, int ifd,
+ int trunc,
const char *fmt, int perm, snd_pcm_t *slave, int close_slave)
{
snd_pcm_t *pcm;
snd_pcm_file_t *file;
snd_pcm_file_format_t format;
struct timespec timespec;
+ char *tmpname = NULL;
int err;
assert(pcmp);
if (fmt == NULL ||
strcmp(fmt, "raw") == 0)
format = SND_PCM_FILE_FORMAT_RAW;
+ else if (!strcmp(fmt, "wav"))
+ format = SND_PCM_FILE_FORMAT_WAV;
else {
SNDERR("file format %s is unknown", fmt);
return -EINVAL;
}
if (fname) {
- fd = open(fname, O_WRONLY|O_CREAT, perm);
+ if (trunc)
+ fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, perm);
+ else {
+ fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, perm);
+ if (fd < 0) {
+ int idx, len;
+ len = strlen(fname) + 6;
+ tmpname = malloc(len);
+ if (!tmpname)
+ return -ENOMEM;
+ for (idx = 1; idx < 10000; idx++) {
+ snprintf(tmpname, len,
+ "%s.%04d", fname, idx);
+ fd = open(tmpname, O_WRONLY|O_CREAT|O_EXCL, perm);
+ if (fd >= 0) {
+ fname = tmpname;
+ break;
+ }
+ }
+ }
+ }
if (fd < 0) {
SYSERR("open %s for writing failed", fname);
+ free(tmpname);
return -errno;
}
}
@@ -434,6 +578,7 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
if (!file) {
if (fname)
close(fd);
+ free(tmpname);
return -ENOMEM;
}
@@ -443,6 +588,8 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
SYSERR("open %s for reading failed", ifname);
if (fname)
close(fd);
+ free(file);
+ free(tmpname);
return -errno;
}
}
@@ -461,6 +608,7 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
if (err < 0) {
free(file->fname);
free(file);
+ free(tmpname);
return err;
}
pcm->ops = &snd_pcm_file_ops;
@@ -469,7 +617,7 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
pcm->poll_fd = slave->poll_fd;
pcm->poll_events = slave->poll_events;
pcm->mmap_shadow = 1;
-#ifdef HAVE_CLOCK_GETTIME
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
pcm->monotonic = clock_gettime(CLOCK_MONOTONIC, &timespec) == 0;
#else
pcm->monotonic = 0;
@@ -478,6 +626,7 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
snd_pcm_link_appl_ptr(pcm, slave);
*pcmp = pcm;
+ free(tmpname);
return 0;
}
@@ -501,10 +650,10 @@ pcm.name {
file STR # Output filename
or
file INT # Output file descriptor number
- infile STR # Input filename
+ infile STR # Input filename - only raw format
or
infile INT # Input file descriptor number
- [format STR] # File format (only "raw" at the moment)
+ [format STR] # File format ("raw" or "wav")
[perm INT] # Output file permission (octal, def. 0600)
}
\endcode
@@ -541,7 +690,7 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
snd_config_t *slave = NULL, *sconf;
const char *fname = NULL, *ifname = NULL;
const char *format = NULL;
- long fd = -1, ifd = -1;
+ long fd = -1, ifd = -1, trunc = 1;
long perm = 0600;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
@@ -596,9 +745,27 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
}
continue;
}
+ if (strcmp(id, "truncate") == 0) {
+ err = snd_config_get_bool(n);
+ if (err < 0)
+ return -EINVAL;
+ trunc = err;
+ continue;
+ }
SNDERR("Unknown field %s", id);
return -EINVAL;
}
+ if (!format) {
+ snd_config_t *n;
+ /* read defaults */
+ if (snd_config_search(root, "defaults.pcm.file_format", &n) >= 0) {
+ err = snd_config_get_string(n, &format);
+ if (err < 0) {
+ SNDERR("Invalid file format");
+ return -EINVAL;
+ }
+ }
+ }
if (!slave) {
SNDERR("slave is not defined");
return -EINVAL;
@@ -606,7 +773,7 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
err = snd_pcm_slave_conf(root, slave, &sconf, 0);
if (err < 0)
return err;
- if (!fname && fd < 0) {
+ if (!fname && fd < 0 && !ifname) {
snd_config_delete(sconf);
SNDERR("file is not defined");
return -EINVAL;
@@ -615,7 +782,8 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
snd_config_delete(sconf);
if (err < 0)
return err;
- err = snd_pcm_file_open(pcmp, name, fname, fd, ifname, ifd, format, perm, spcm, 1);
+ err = snd_pcm_file_open(pcmp, name, fname, fd, ifname, ifd,
+ trunc, format, perm, spcm, 1);
if (err < 0)
snd_pcm_close(spcm);
return err;
diff --git a/src/pcm/pcm_generic.c b/src/pcm/pcm_generic.c
index 85b8d4f..d26aead 100644
--- a/src/pcm/pcm_generic.c
+++ b/src/pcm/pcm_generic.c
@@ -26,7 +26,6 @@
*
*/
-#include <sys/shm.h>
#include <sys/ioctl.h>
#include <limits.h>
#include "pcm_local.h"
@@ -185,12 +184,24 @@ int snd_pcm_generic_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
return snd_pcm_delay(generic->slave, delayp);
}
+snd_pcm_sframes_t snd_pcm_generic_forwardable(snd_pcm_t *pcm)
+{
+ snd_pcm_generic_t *generic = pcm->private_data;
+ return snd_pcm_forwardable(generic->slave);
+}
+
snd_pcm_sframes_t snd_pcm_generic_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_generic_t *generic = pcm->private_data;
return INTERNAL(snd_pcm_forward)(generic->slave, frames);
}
+snd_pcm_sframes_t snd_pcm_generic_rewindable(snd_pcm_t *pcm)
+{
+ snd_pcm_generic_t *generic = pcm->private_data;
+ return snd_pcm_rewindable(generic->slave);
+}
+
snd_pcm_sframes_t snd_pcm_generic_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_generic_t *generic = pcm->private_data;
diff --git a/src/pcm/pcm_generic.h b/src/pcm/pcm_generic.h
index 9874c1b..430b8cf 100644
--- a/src/pcm/pcm_generic.h
+++ b/src/pcm/pcm_generic.h
@@ -73,8 +73,12 @@ typedef struct {
snd1_pcm_generic_resume
#define snd_pcm_generic_delay \
snd1_pcm_generic_delay
+#define snd_pcm_generic_forwardable \
+ snd1_pcm_generic_forwardable
#define snd_pcm_generic_forward \
snd1_pcm_generic_forward
+#define snd_pcm_generic_rewindable \
+ snd1_pcm_generic_rewindable
#define snd_pcm_generic_rewind \
snd1_pcm_generic_rewind
#define snd_pcm_generic_link \
@@ -124,7 +128,9 @@ int snd_pcm_generic_drain(snd_pcm_t *pcm);
int snd_pcm_generic_pause(snd_pcm_t *pcm, int enable);
int snd_pcm_generic_resume(snd_pcm_t *pcm);
int snd_pcm_generic_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
+snd_pcm_sframes_t snd_pcm_generic_forwardable(snd_pcm_t *pcm);
snd_pcm_sframes_t snd_pcm_generic_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
+snd_pcm_sframes_t snd_pcm_generic_rewindable(snd_pcm_t *pcm);
snd_pcm_sframes_t snd_pcm_generic_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
int snd_pcm_generic_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
int snd_pcm_generic_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master);
diff --git a/src/pcm/pcm_hooks.c b/src/pcm/pcm_hooks.c
index 5f9b662..826685f 100644
--- a/src/pcm/pcm_hooks.c
+++ b/src/pcm/pcm_hooks.c
@@ -121,7 +121,7 @@ static void snd_pcm_hooks_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(h->gen.slave, out);
}
-static snd_pcm_ops_t snd_pcm_hooks_ops = {
+static const snd_pcm_ops_t snd_pcm_hooks_ops = {
.close = snd_pcm_hooks_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_generic_hw_refine,
@@ -136,7 +136,7 @@ static snd_pcm_ops_t snd_pcm_hooks_ops = {
.munmap = snd_pcm_generic_munmap,
};
-static snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
+static const snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
.status = snd_pcm_generic_status,
.state = snd_pcm_generic_state,
.hwsync = snd_pcm_generic_hwsync,
@@ -147,7 +147,9 @@ static snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
.drop = snd_pcm_generic_drop,
.drain = snd_pcm_generic_drain,
.pause = snd_pcm_generic_pause,
+ .rewindable = snd_pcm_generic_rewindable,
.rewind = snd_pcm_generic_rewind,
+ .forwardable = snd_pcm_generic_forwardable,
.forward = snd_pcm_generic_forward,
.resume = snd_pcm_generic_resume,
.link = snd_pcm_generic_link,
diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c
index 8495f71..95bb2ac 100644
--- a/src/pcm/pcm_hw.c
+++ b/src/pcm/pcm_hw.c
@@ -36,9 +36,9 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
-#include <sys/shm.h>
#include "pcm_local.h"
#include "../control/control_local.h"
+#include "../timer/timer_local.h"
//#define DEBUG_RW /* use to debug readi/writei/readn/writen */
//#define DEBUG_MMAP /* debug mmap_commit */
@@ -79,6 +79,8 @@ struct sndrv_pcm_hw_params_old {
static int use_old_hw_params_ioctl(int fd, unsigned int cmd, snd_pcm_hw_params_t *params);
static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm);
+static const snd_pcm_fast_ops_t snd_pcm_hw_fast_ops;
+static const snd_pcm_fast_ops_t snd_pcm_hw_fast_ops_timer;
/*
*
@@ -94,6 +96,10 @@ typedef struct {
struct sndrv_pcm_sync_ptr *sync_ptr;
snd_pcm_uframes_t hw_ptr;
snd_pcm_uframes_t appl_ptr;
+ int period_event;
+ snd_timer_t *period_timer;
+ struct pollfd period_timer_pfd;
+ int period_timer_need_poll;
/* restricted parameters */
snd_pcm_format_t format;
int rate;
@@ -139,6 +145,54 @@ static inline int sync_ptr(snd_pcm_hw_t *hw, unsigned int flags)
return hw->sync_ptr ? sync_ptr1(hw, flags) : 0;
}
+static int snd_pcm_hw_clear_timer_queue(snd_pcm_hw_t *hw)
+{
+ if (hw->period_timer_need_poll) {
+ while (poll(&hw->period_timer_pfd, 1, 0) > 0) {
+ snd_timer_tread_t rbuf[4];
+ snd_timer_read(hw->period_timer, rbuf, sizeof(rbuf));
+ }
+ } else {
+ snd_timer_tread_t rbuf[4];
+ snd_timer_read(hw->period_timer, rbuf, sizeof(rbuf));
+ }
+ return 0;
+}
+
+static int snd_pcm_hw_poll_descriptors_count(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
+{
+ return 2;
+}
+
+static int snd_pcm_hw_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space)
+{
+ snd_pcm_hw_t *hw = pcm->private_data;
+
+ if (space < 2)
+ return -ENOMEM;
+ pfds[0].fd = hw->fd;
+ pfds[0].events = pcm->poll_events | POLLERR | POLLNVAL;
+ pfds[1].fd = hw->period_timer_pfd.fd;
+ pfds[1].events = POLLIN | POLLERR | POLLNVAL;
+ return 2;
+}
+
+static int snd_pcm_hw_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned nfds, unsigned short *revents)
+{
+ snd_pcm_hw_t *hw = pcm->private_data;
+ unsigned int events;
+
+ if (nfds != 2 || pfds[0].fd != hw->fd || pfds[1].fd != hw->period_timer_pfd.fd)
+ return -EINVAL;
+ events = pfds[0].revents;
+ if (pfds[1].revents & POLLIN) {
+ snd_pcm_hw_clear_timer_queue(hw);
+ events |= pcm->poll_events & ~(POLLERR|POLLNVAL);
+ }
+ *revents = events;
+ return 0;
+}
+
static int snd_pcm_hw_nonblock(snd_pcm_t *pcm, int nonblock)
{
long flags;
@@ -245,6 +299,11 @@ static int snd_pcm_hw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
// SYSMSG("SNDRV_PCM_IOCTL_HW_REFINE failed");
return err;
}
+
+ if (params->info != ~0U) {
+ params->info &= ~0xf0000000;
+ params->info |= (pcm->monotonic ? SND_PCM_INFO_MONOTONIC : 0);
+ }
return 0;
}
@@ -288,16 +347,94 @@ static int snd_pcm_hw_hw_free(snd_pcm_t *pcm)
return 0;
}
+static void snd_pcm_hw_close_timer(snd_pcm_hw_t *hw)
+{
+ if (hw->period_timer) {
+ snd_timer_close(hw->period_timer);
+ hw->period_timer = NULL;
+ }
+}
+
+static int snd_pcm_hw_change_timer(snd_pcm_t *pcm, int enable)
+{
+ snd_pcm_hw_t *hw = pcm->private_data;
+ snd_timer_params_t *params;
+ unsigned int suspend, resume;
+ int err;
+
+ if (enable) {
+ snd_timer_params_alloca(&params);
+ err = snd_timer_hw_open(&hw->period_timer, "hw-pcm-period-event", SND_TIMER_CLASS_PCM, SND_TIMER_SCLASS_NONE, hw->card, hw->device, hw->subdevice, SND_TIMER_OPEN_NONBLOCK | SND_TIMER_OPEN_TREAD);
+ if (err < 0) {
+ err = snd_timer_hw_open(&hw->period_timer, "hw-pcm-period-event", SND_TIMER_CLASS_PCM, SND_TIMER_SCLASS_NONE, hw->card, hw->device, hw->subdevice, SND_TIMER_OPEN_NONBLOCK);
+ return err;
+ }
+ if (snd_timer_poll_descriptors_count(hw->period_timer) != 1) {
+ snd_pcm_hw_close_timer(hw);
+ return -EINVAL;
+ }
+ hw->period_timer_pfd.events = POLLIN;
+ hw->period_timer_pfd.revents = 0;
+ snd_timer_poll_descriptors(hw->period_timer, &hw->period_timer_pfd, 1);
+ hw->period_timer_need_poll = 0;
+ suspend = 1<<SND_TIMER_EVENT_MSUSPEND;
+ resume = 1<<SND_TIMER_EVENT_MRESUME;
+ /*
+ * hacks for older kernel drivers
+ */
+ {
+ int ver = 0;
+ ioctl(hw->period_timer_pfd.fd, SNDRV_TIMER_IOCTL_PVERSION, &ver);
+ /* In older versions, check via poll before read() is needed
+ * because of the confliction between TIMER_START and
+ * FIONBIO ioctls.
+ */
+ if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 4))
+ hw->period_timer_need_poll = 1;
+ /*
+ * In older versions, timer uses pause events instead
+ * suspend/resume events.
+ */
+ if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 5)) {
+ suspend = 1<<SND_TIMER_EVENT_MPAUSE;
+ resume = 1<<SND_TIMER_EVENT_MCONTINUE;
+ }
+ }
+ snd_timer_params_set_auto_start(params, 1);
+ snd_timer_params_set_ticks(params, 1);
+ snd_timer_params_set_filter(params, (1<<SND_TIMER_EVENT_TICK) |
+ suspend | resume);
+ err = snd_timer_params(hw->period_timer, params);
+ if (err < 0) {
+ snd_pcm_hw_close_timer(hw);
+ return err;
+ }
+ err = snd_timer_start(hw->period_timer);
+ if (err < 0) {
+ snd_pcm_hw_close_timer(hw);
+ return err;
+ }
+ pcm->fast_ops = &snd_pcm_hw_fast_ops_timer;
+ } else {
+ snd_pcm_hw_close_timer(hw);
+ pcm->fast_ops = &snd_pcm_hw_fast_ops;
+ }
+ return 0;
+}
+
static int snd_pcm_hw_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
{
snd_pcm_hw_t *hw = pcm->private_data;
int fd = hw->fd, err;
+ int old_period_event = params->period_event;
+ params->period_event = 0;
if ((snd_pcm_tstamp_t) params->tstamp_mode == pcm->tstamp_mode &&
params->period_step == pcm->period_step &&
params->start_threshold == pcm->start_threshold &&
params->stop_threshold == pcm->stop_threshold &&
params->silence_threshold == pcm->silence_threshold &&
- params->silence_size == pcm->silence_size) {
+ params->silence_size == pcm->silence_size &&
+ old_period_event == hw->period_event) {
hw->mmap_control->avail_min = params->avail_min;
return sync_ptr(hw, 0);
}
@@ -306,7 +443,14 @@ static int snd_pcm_hw_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
SYSMSG("SNDRV_PCM_IOCTL_SW_PARAMS failed");
return err;
}
+ params->period_event = old_period_event;
hw->mmap_control->avail_min = params->avail_min;
+ if (hw->period_event != old_period_event) {
+ err = snd_pcm_hw_change_timer(pcm, old_period_event);
+ if (err < 0)
+ return err;
+ hw->period_event = old_period_event;
+ }
return 0;
}
@@ -475,6 +619,7 @@ static int snd_pcm_hw_drop(snd_pcm_t *pcm)
err = -errno;
SYSMSG("SNDRV_PCM_IOCTL_DROP failed");
return err;
+ } else {
}
return 0;
}
@@ -503,6 +648,11 @@ static int snd_pcm_hw_pause(snd_pcm_t *pcm, int enable)
return 0;
}
+static snd_pcm_sframes_t snd_pcm_hw_rewindable(snd_pcm_t *pcm)
+{
+ return snd_pcm_mmap_hw_avail(pcm);
+}
+
static snd_pcm_sframes_t snd_pcm_hw_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_hw_t *hw = pcm->private_data;
@@ -518,6 +668,11 @@ static snd_pcm_sframes_t snd_pcm_hw_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t fra
return frames;
}
+static snd_pcm_sframes_t snd_pcm_hw_forwardable(snd_pcm_t *pcm)
+{
+ return snd_pcm_mmap_avail(pcm);
+}
+
static snd_pcm_sframes_t snd_pcm_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_hw_t *hw = pcm->private_data;
@@ -884,7 +1039,7 @@ static void snd_pcm_hw_dump(snd_pcm_t *pcm, snd_output_t *out)
}
}
-static snd_pcm_ops_t snd_pcm_hw_ops = {
+static const 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,
@@ -899,7 +1054,7 @@ static snd_pcm_ops_t snd_pcm_hw_ops = {
.munmap = snd_pcm_hw_munmap,
};
-static snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
+static const snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
.status = snd_pcm_hw_status,
.state = snd_pcm_hw_state,
.hwsync = snd_pcm_hw_hwsync,
@@ -910,7 +1065,9 @@ static snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
.drop = snd_pcm_hw_drop,
.drain = snd_pcm_hw_drain,
.pause = snd_pcm_hw_pause,
+ .rewindable = snd_pcm_hw_rewindable,
.rewind = snd_pcm_hw_rewind,
+ .forwardable = snd_pcm_hw_forwardable,
.forward = snd_pcm_hw_forward,
.resume = snd_pcm_hw_resume,
.link = snd_pcm_hw_link,
@@ -928,6 +1085,37 @@ static snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
.poll_revents = NULL,
};
+static const snd_pcm_fast_ops_t snd_pcm_hw_fast_ops_timer = {
+ .status = snd_pcm_hw_status,
+ .state = snd_pcm_hw_state,
+ .hwsync = snd_pcm_hw_hwsync,
+ .delay = snd_pcm_hw_delay,
+ .prepare = snd_pcm_hw_prepare,
+ .reset = snd_pcm_hw_reset,
+ .start = snd_pcm_hw_start,
+ .drop = snd_pcm_hw_drop,
+ .drain = snd_pcm_hw_drain,
+ .pause = snd_pcm_hw_pause,
+ .rewindable = snd_pcm_hw_rewindable,
+ .rewind = snd_pcm_hw_rewind,
+ .forwardable = snd_pcm_hw_forwardable,
+ .forward = snd_pcm_hw_forward,
+ .resume = snd_pcm_hw_resume,
+ .link = snd_pcm_hw_link,
+ .link_slaves = snd_pcm_hw_link_slaves,
+ .unlink = snd_pcm_hw_unlink,
+ .writei = snd_pcm_hw_writei,
+ .writen = snd_pcm_hw_writen,
+ .readi = snd_pcm_hw_readi,
+ .readn = snd_pcm_hw_readn,
+ .avail_update = snd_pcm_hw_avail_update,
+ .mmap_commit = snd_pcm_hw_mmap_commit,
+ .htimestamp = snd_pcm_hw_htimestamp,
+ .poll_descriptors = snd_pcm_hw_poll_descriptors,
+ .poll_descriptors_count = snd_pcm_hw_poll_descriptors_count,
+ .poll_revents = snd_pcm_hw_poll_revents,
+};
+
/**
* \brief Creates a new hw PCM
* \param pcmp Returns created PCM handle
@@ -994,7 +1182,7 @@ int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name,
if (SNDRV_PROTOCOL_INCOMPATIBLE(ver, SNDRV_PCM_VERSION_MAX))
return -SND_ERROR_INCOMPATIBLE_VERSION;
-#ifdef HAVE_CLOCK_GETTIME
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
if (SNDRV_PROTOCOL_VERSION(2, 0, 9) <= ver) {
struct timespec timespec;
if (clock_gettime(CLOCK_MONOTONIC, &timespec) == 0) {
@@ -1006,9 +1194,9 @@ int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name,
}
monotonic = 1;
}
- }
+ } else
#endif
- else if (SNDRV_PROTOCOL_VERSION(2, 0, 5) <= ver) {
+ if (SNDRV_PROTOCOL_VERSION(2, 0, 5) <= ver) {
int on = 1;
if (ioctl(fd, SNDRV_PCM_IOCTL_TSTAMP, &on) < 0) {
ret = -errno;
@@ -1318,7 +1506,13 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name,
/* revert to blocking mode for read/write access */
snd_pcm_hw_nonblock(*pcmp, 0);
(*pcmp)->mode = mode;
- }
+ } else
+ /* make sure the SND_PCM_NO_xxx flags don't get lost on the
+ * way */
+ (*pcmp)->mode |= mode & (SND_PCM_NO_AUTO_RESAMPLE|
+ SND_PCM_NO_AUTO_CHANNELS|
+ SND_PCM_NO_AUTO_FORMAT|
+ SND_PCM_NO_SOFTVOL);
hw = (*pcmp)->private_data;
if (format != SND_PCM_FORMAT_UNKNOWN)
diff --git a/src/pcm/pcm_iec958.c b/src/pcm/pcm_iec958.c
index f0990d2..3d70ed0 100644
--- a/src/pcm/pcm_iec958.c
+++ b/src/pcm/pcm_iec958.c
@@ -416,7 +416,7 @@ static void snd_pcm_iec958_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(iec->plug.gen.slave, out);
}
-static snd_pcm_ops_t snd_pcm_iec958_ops = {
+static const snd_pcm_ops_t snd_pcm_iec958_ops = {
.close = snd_pcm_generic_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_iec958_hw_refine,
@@ -453,7 +453,7 @@ int snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo
snd_pcm_t *pcm;
snd_pcm_iec958_t *iec;
int err;
- static unsigned char default_status_bits[] = {
+ static const unsigned char default_status_bits[] = {
IEC958_AES0_CON_EMPHASIS_NONE,
IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
0,
diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c
index 2a8ce54..e43d354 100644
--- a/src/pcm/pcm_ioplug.c
+++ b/src/pcm/pcm_ioplug.c
@@ -146,7 +146,7 @@ static int snd_pcm_ioplug_prepare(snd_pcm_t *pcm)
return 0;
}
-static int hw_params_type[SND_PCM_IOPLUG_HW_PARAMS] = {
+static const int hw_params_type[SND_PCM_IOPLUG_HW_PARAMS] = {
[SND_PCM_IOPLUG_HW_ACCESS] = SND_PCM_HW_PARAM_ACCESS,
[SND_PCM_IOPLUG_HW_FORMAT] = SND_PCM_HW_PARAM_FORMAT,
[SND_PCM_IOPLUG_HW_CHANNELS] = SND_PCM_HW_PARAM_CHANNELS,
@@ -483,8 +483,8 @@ static int snd_pcm_ioplug_drain(snd_pcm_t *pcm)
static int snd_pcm_ioplug_pause(snd_pcm_t *pcm, int enable)
{
ioplug_priv_t *io = pcm->private_data;
- static snd_pcm_state_t states[2] = {
- SND_PCM_STATE_PAUSED, SND_PCM_STATE_RUNNING
+ static const snd_pcm_state_t states[2] = {
+ SND_PCM_STATE_RUNNING, SND_PCM_STATE_PAUSED
};
int prev, err;
@@ -501,12 +501,22 @@ static int snd_pcm_ioplug_pause(snd_pcm_t *pcm, int enable)
return 0;
}
+static snd_pcm_sframes_t snd_pcm_ioplug_rewindable(snd_pcm_t *pcm)
+{
+ return snd_pcm_mmap_hw_avail(pcm);
+}
+
static snd_pcm_sframes_t snd_pcm_ioplug_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_mmap_appl_backward(pcm, frames);
return frames;
}
+static snd_pcm_sframes_t snd_pcm_ioplug_forwardable(snd_pcm_t *pcm)
+{
+ return snd_pcm_mmap_avail(pcm);
+}
+
static snd_pcm_sframes_t snd_pcm_ioplug_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_mmap_appl_forward(pcm, frames);
@@ -737,7 +747,7 @@ static int snd_pcm_ioplug_close(snd_pcm_t *pcm)
return 0;
}
-static snd_pcm_ops_t snd_pcm_ioplug_ops = {
+static const snd_pcm_ops_t snd_pcm_ioplug_ops = {
.close = snd_pcm_ioplug_close,
.nonblock = snd_pcm_ioplug_nonblock,
.async = snd_pcm_ioplug_async,
@@ -752,7 +762,7 @@ static snd_pcm_ops_t snd_pcm_ioplug_ops = {
.munmap = snd_pcm_ioplug_munmap,
};
-static snd_pcm_fast_ops_t snd_pcm_ioplug_fast_ops = {
+static const snd_pcm_fast_ops_t snd_pcm_ioplug_fast_ops = {
.status = snd_pcm_ioplug_status,
.prepare = snd_pcm_ioplug_prepare,
.reset = snd_pcm_ioplug_reset,
@@ -767,7 +777,9 @@ static snd_pcm_fast_ops_t snd_pcm_ioplug_fast_ops = {
.link = NULL,
.link_slaves = NULL,
.unlink = NULL,
+ .rewindable = snd_pcm_ioplug_rewindable,
.rewind = snd_pcm_ioplug_rewind,
+ .forwardable = snd_pcm_ioplug_forwardable,
.forward = snd_pcm_ioplug_forward,
.writei = snd_pcm_ioplug_writei,
.writen = snd_pcm_ioplug_writen,
diff --git a/src/pcm/pcm_ladspa.c b/src/pcm/pcm_ladspa.c
index 97bb901..5161820 100644
--- a/src/pcm/pcm_ladspa.c
+++ b/src/pcm/pcm_ladspa.c
@@ -1061,7 +1061,7 @@ static void snd_pcm_ladspa_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(ladspa->plug.gen.slave, out);
}
-static snd_pcm_ops_t snd_pcm_ladspa_ops = {
+static const snd_pcm_ops_t snd_pcm_ladspa_ops = {
.close = snd_pcm_ladspa_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_ladspa_hw_refine,
diff --git a/src/pcm/pcm_lfloat.c b/src/pcm/pcm_lfloat.c
index 883fce9..62eb398 100644
--- a/src/pcm/pcm_lfloat.c
+++ b/src/pcm/pcm_lfloat.c
@@ -350,7 +350,7 @@ static void snd_pcm_lfloat_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(lfloat->plug.gen.slave, out);
}
-static snd_pcm_ops_t snd_pcm_lfloat_ops = {
+static const snd_pcm_ops_t snd_pcm_lfloat_ops = {
.close = snd_pcm_generic_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_lfloat_hw_refine,
diff --git a/src/pcm/pcm_linear.c b/src/pcm/pcm_linear.c
index e3aeac1..12e2e7f 100644
--- a/src/pcm/pcm_linear.c
+++ b/src/pcm/pcm_linear.c
@@ -407,7 +407,7 @@ static void snd_pcm_linear_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(linear->plug.gen.slave, out);
}
-static snd_pcm_ops_t snd_pcm_linear_ops = {
+static const snd_pcm_ops_t snd_pcm_linear_ops = {
.close = snd_pcm_generic_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_linear_hw_refine,
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
index 8d4ae40..9aa81e1 100644
--- a/src/pcm/pcm_local.h
+++ b/src/pcm/pcm_local.h
@@ -95,6 +95,8 @@ typedef enum sndrv_pcm_hw_param snd_pcm_hw_param_t;
#define SND_PCM_HW_PARAMS_NORESAMPLE SNDRV_PCM_HW_PARAMS_NORESAMPLE
#define SND_PCM_HW_PARAMS_EXPORT_BUFFER SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER
+#define SND_PCM_INFO_MONOTONIC 0x80000000
+
typedef struct _snd_pcm_rbptr {
snd_pcm_t *master;
volatile snd_pcm_uframes_t *ptr;
@@ -155,7 +157,9 @@ typedef struct {
int (*link)(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
int (*link_slaves)(snd_pcm_t *pcm, snd_pcm_t *master);
int (*unlink)(snd_pcm_t *pcm);
+ snd_pcm_sframes_t (*rewindable)(snd_pcm_t *pcm);
snd_pcm_sframes_t (*rewind)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
+ snd_pcm_sframes_t (*forwardable)(snd_pcm_t *pcm);
snd_pcm_sframes_t (*forward)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
snd_pcm_sframes_t (*writei)(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
snd_pcm_sframes_t (*writen)(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
@@ -191,8 +195,9 @@ struct _snd_pcm {
snd_pcm_tstamp_t tstamp_mode; /* timestamp mode */
unsigned int period_step;
snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */
- snd_pcm_uframes_t start_threshold;
- snd_pcm_uframes_t stop_threshold;
+ int period_event;
+ snd_pcm_uframes_t start_threshold;
+ snd_pcm_uframes_t stop_threshold;
snd_pcm_uframes_t silence_threshold; /* Silence filling happens when
noise is nearest than this */
snd_pcm_uframes_t silence_size; /* Silence filling size */
@@ -218,8 +223,8 @@ struct _snd_pcm {
snd_pcm_channel_info_t *mmap_channels;
snd_pcm_channel_area_t *running_areas;
snd_pcm_channel_area_t *stopped_areas;
- snd_pcm_ops_t *ops;
- snd_pcm_fast_ops_t *fast_ops;
+ const snd_pcm_ops_t *ops;
+ const snd_pcm_fast_ops_t *fast_ops;
snd_pcm_t *op_arg;
snd_pcm_t *fast_op_arg;
void *private_data;
@@ -857,6 +862,8 @@ snd_pcm_open_slave(snd_pcm_t **pcmp, snd_config_t *root,
int snd_pcm_conf_generic_id(const char *id);
int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, int fd, int mmap_emulation, int sync_ptr_ioctl);
+int __snd_pcm_mmap_emul_open(snd_pcm_t **pcmp, const char *name,
+ snd_pcm_t *slave, int close_slave);
int snd_pcm_wait_nocheck(snd_pcm_t *pcm, int timeout);
@@ -944,13 +951,17 @@ typedef union snd_tmp_double {
/* get the current timestamp */
static inline void gettimestamp(snd_htimestamp_t *tstamp, int monotonic)
{
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
if (monotonic) {
clock_gettime(CLOCK_MONOTONIC, tstamp);
} else {
+#endif
struct timeval tv;
gettimeofday(&tv, 0);
tstamp->tv_sec = tv.tv_sec;
tstamp->tv_nsec = tv.tv_usec * 1000L;
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
}
+#endif
}
diff --git a/src/pcm/pcm_meter.c b/src/pcm/pcm_meter.c
index 079de1e..0357921 100644
--- a/src/pcm/pcm_meter.c
+++ b/src/pcm/pcm_meter.c
@@ -501,7 +501,7 @@ static void snd_pcm_meter_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(meter->gen.slave, out);
}
-static snd_pcm_ops_t snd_pcm_meter_ops = {
+static const snd_pcm_ops_t snd_pcm_meter_ops = {
.close = snd_pcm_meter_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_meter_hw_refine,
@@ -516,7 +516,7 @@ static snd_pcm_ops_t snd_pcm_meter_ops = {
.munmap = snd_pcm_generic_munmap,
};
-static snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
+static const snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
.status = snd_pcm_generic_status,
.state = snd_pcm_generic_state,
.hwsync = snd_pcm_generic_hwsync,
@@ -527,7 +527,9 @@ static snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
.drop = snd_pcm_generic_drop,
.drain = snd_pcm_generic_drain,
.pause = snd_pcm_generic_pause,
+ .rewindable = snd_pcm_generic_rewindable,
.rewind = snd_pcm_meter_rewind,
+ .forwardable = snd_pcm_generic_forwardable,
.forward = snd_pcm_meter_forward,
.resume = snd_pcm_generic_resume,
.writei = snd_pcm_mmap_writei,
@@ -601,7 +603,7 @@ static int snd_pcm_meter_add_scope_conf(snd_pcm_t *pcm, const char *name,
snd_config_iterator_t i, next;
const char *id;
const char *lib = NULL, *open_name = NULL, *str = NULL;
- snd_config_t *c, *type_conf;
+ snd_config_t *c, *type_conf = NULL;
int (*open_func)(snd_pcm_t *, const char *,
snd_config_t *, snd_config_t *) = NULL;
snd_pcm_meter_t *meter = pcm->private_data;
@@ -1141,7 +1143,7 @@ static void s16_reset(snd_pcm_scope_t *scope)
s16->old = meter->now;
}
-snd_pcm_scope_ops_t s16_ops = {
+static const snd_pcm_scope_ops_t s16_ops = {
.enable = s16_enable,
.disable = s16_disable,
.close = s16_close,
diff --git a/src/pcm/pcm_misc.c b/src/pcm/pcm_misc.c
index ef6c417..d52160c 100644
--- a/src/pcm/pcm_misc.c
+++ b/src/pcm/pcm_misc.c
@@ -26,15 +26,6 @@
#include <byteswap.h>
#include "pcm_local.h"
-/* Bionic does not provide bswap_64() */
-#ifndef bswap_64
-#undef __ASM_ARM_BYTEORDER_H
-#include <asm/byteorder.h>
-#include <linux/byteorder/swab.h>
-
-#define bswap_64 __swab64
-#endif
-
/**
* \brief Return sign info for a PCM sample linear format
@@ -632,7 +623,7 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
return 0;
}
-static int linear_formats[4][2][2] = {
+static const int linear_formats[4][2][2] = {
{ { SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8 },
{ SNDRV_PCM_FORMAT_U8, SNDRV_PCM_FORMAT_U8 } },
{ { SNDRV_PCM_FORMAT_S16_LE, SNDRV_PCM_FORMAT_S16_BE },
@@ -643,7 +634,7 @@ static int linear_formats[4][2][2] = {
{ SNDRV_PCM_FORMAT_U32_LE, SNDRV_PCM_FORMAT_U32_BE } }
};
-static int linear24_formats[3][2][2] = {
+static const int linear24_formats[3][2][2] = {
{ { SNDRV_PCM_FORMAT_S24_3LE, SNDRV_PCM_FORMAT_S24_3BE },
{ SNDRV_PCM_FORMAT_U24_3LE, SNDRV_PCM_FORMAT_U24_3BE } },
{ { SNDRV_PCM_FORMAT_S20_3LE, SNDRV_PCM_FORMAT_S20_3BE },
diff --git a/src/pcm/pcm_mmap.c b/src/pcm/pcm_mmap.c
index 9771b6d..4b7a353 100644
--- a/src/pcm/pcm_mmap.c
+++ b/src/pcm/pcm_mmap.c
@@ -23,13 +23,14 @@
#include <string.h>
#include <sys/poll.h>
#include <sys/mman.h>
+#ifndef ANDROID
#include <sys/shm.h>
-#include <unistd.h>
+#endif
#include "pcm_local.h"
size_t page_size(void)
{
- int s = getpagesize();
+ long s = sysconf(_SC_PAGE_SIZE);
assert(s > 0);
return s;
}
@@ -372,6 +373,7 @@ int snd_pcm_mmap(snd_pcm_t *pcm)
}
i->addr = ptr;
break;
+#ifndef ANDROID
case SND_PCM_AREA_SHM:
if (i->u.shm.shmid < 0) {
int id;
@@ -417,6 +419,7 @@ int snd_pcm_mmap(snd_pcm_t *pcm)
}
i->addr = ptr;
break;
+#endif
case SND_PCM_AREA_LOCAL:
ptr = malloc(size);
if (ptr == NULL) {
@@ -497,6 +500,7 @@ int snd_pcm_munmap(snd_pcm_t *pcm)
}
errno = 0;
break;
+#ifndef ANDROID
case SND_PCM_AREA_SHM:
if (i->u.shm.area) {
snd_shm_area_destroy(i->u.shm.area);
@@ -514,6 +518,7 @@ int snd_pcm_munmap(snd_pcm_t *pcm)
}
}
break;
+#endif
case SND_PCM_AREA_LOCAL:
free(i->addr);
break;
diff --git a/src/pcm/pcm_mmap_emul.c b/src/pcm/pcm_mmap_emul.c
index a00ddb1..0dc1973 100644
--- a/src/pcm/pcm_mmap_emul.c
+++ b/src/pcm/pcm_mmap_emul.c
@@ -62,11 +62,9 @@ static int snd_pcm_mmap_emul_hw_refine(snd_pcm_t *pcm,
snd_mask_none(&mask);
err = snd_pcm_hw_refine(map->gen.slave, params);
if (err < 0) {
- /* try to use RW_* */
snd_pcm_hw_params_t new = *params;
- if (!(params->rmask & (1<<SND_PCM_HW_PARAM_ACCESS)))
- return err;
+ /* try to use RW_* */
if (snd_pcm_access_mask_test(&oldmask,
SND_PCM_ACCESS_MMAP_INTERLEAVED) &&
!snd_pcm_access_mask_test(&oldmask,
@@ -156,7 +154,7 @@ static int snd_pcm_mmap_emul_hw_params(snd_pcm_t *pcm,
snd_pcm_hw_params_t old = *params;
snd_pcm_access_t access;
snd_pcm_access_mask_t oldmask;
- const snd_mask_t *pmask;
+ snd_pcm_access_mask_t *pmask;
int err;
err = _snd_pcm_hw_params(map->gen.slave, params);
@@ -166,21 +164,20 @@ static int snd_pcm_mmap_emul_hw_params(snd_pcm_t *pcm,
}
*params = old;
- pmask = snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_ACCESS);
- oldmask = *(snd_pcm_access_mask_t *)pmask;
+ pmask = (snd_pcm_access_mask_t *)snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_ACCESS);
+ oldmask = *pmask;
if (INTERNAL(snd_pcm_hw_params_get_access)(params, &access) < 0)
goto _err;
switch (access) {
case SND_PCM_ACCESS_MMAP_INTERLEAVED:
- snd_pcm_access_mask_reset((snd_pcm_access_mask_t *)pmask,
+ snd_pcm_access_mask_reset(pmask,
SND_PCM_ACCESS_MMAP_INTERLEAVED);
- snd_pcm_access_mask_set((snd_pcm_access_mask_t *)pmask,
- SND_PCM_ACCESS_RW_INTERLEAVED);
+ snd_pcm_access_mask_set(pmask, SND_PCM_ACCESS_RW_INTERLEAVED);
break;
case SND_PCM_ACCESS_MMAP_NONINTERLEAVED:
- snd_pcm_access_mask_reset((snd_pcm_access_mask_t *)pmask,
+ snd_pcm_access_mask_reset(pmask,
SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
- snd_pcm_access_mask_set((snd_pcm_access_mask_t *)pmask,
+ snd_pcm_access_mask_set(pmask,
SND_PCM_ACCESS_RW_NONINTERLEAVED);
break;
default:
@@ -191,7 +188,7 @@ static int snd_pcm_mmap_emul_hw_params(snd_pcm_t *pcm,
goto _err;
/* need to back the access type to relieve apps */
- *(snd_pcm_access_mask_t *)pmask = oldmask;
+ *pmask = oldmask;
/* OK, we do fake */
map->mmap_emul = 1;
@@ -332,7 +329,7 @@ static void snd_pcm_mmap_emul_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(map->gen.slave, out);
}
-static snd_pcm_ops_t snd_pcm_mmap_emul_ops = {
+static const snd_pcm_ops_t snd_pcm_mmap_emul_ops = {
.close = snd_pcm_generic_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_mmap_emul_hw_refine,
@@ -347,7 +344,7 @@ static snd_pcm_ops_t snd_pcm_mmap_emul_ops = {
.munmap = snd_pcm_generic_munmap,
};
-static snd_pcm_fast_ops_t snd_pcm_mmap_emul_fast_ops = {
+static const snd_pcm_fast_ops_t snd_pcm_mmap_emul_fast_ops = {
.status = snd_pcm_generic_status,
.state = snd_pcm_generic_state,
.hwsync = snd_pcm_generic_hwsync,
@@ -358,7 +355,9 @@ static snd_pcm_fast_ops_t snd_pcm_mmap_emul_fast_ops = {
.drop = snd_pcm_generic_drop,
.drain = snd_pcm_generic_drain,
.pause = snd_pcm_generic_pause,
+ .rewindable = snd_pcm_generic_rewindable,
.rewind = snd_pcm_mmap_emul_rewind,
+ .forwardable = snd_pcm_generic_forwardable,
.forward = snd_pcm_mmap_emul_forward,
.resume = snd_pcm_generic_resume,
.link = snd_pcm_generic_link,
@@ -376,8 +375,9 @@ static snd_pcm_fast_ops_t snd_pcm_mmap_emul_fast_ops = {
.poll_revents = snd_pcm_generic_poll_revents,
};
-static int snd_pcm_mmap_emul_open(snd_pcm_t **pcmp, const char *name,
- snd_pcm_t *slave, int close_slave)
+#ifndef DOC_HIDDEN
+int __snd_pcm_mmap_emul_open(snd_pcm_t **pcmp, const char *name,
+ snd_pcm_t *slave, int close_slave)
{
snd_pcm_t *pcm;
mmap_emul_t *map;
@@ -407,6 +407,7 @@ static int snd_pcm_mmap_emul_open(snd_pcm_t **pcmp, const char *name,
return 0;
}
+#endif
/*! \page pcm_plugins
@@ -474,7 +475,7 @@ int _snd_pcm_mmap_emul_open(snd_pcm_t **pcmp, const char *name,
snd_config_delete(sconf);
if (err < 0)
return err;
- err = snd_pcm_mmap_emul_open(pcmp, name, spcm, 1);
+ err = __snd_pcm_mmap_emul_open(pcmp, name, spcm, 1);
if (err < 0)
snd_pcm_close(spcm);
return err;
diff --git a/src/pcm/pcm_mulaw.c b/src/pcm/pcm_mulaw.c
index d696c96..22e7d96 100644
--- a/src/pcm/pcm_mulaw.c
+++ b/src/pcm/pcm_mulaw.c
@@ -406,7 +406,7 @@ static void snd_pcm_mulaw_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(mulaw->plug.gen.slave, out);
}
-static snd_pcm_ops_t snd_pcm_mulaw_ops = {
+static const snd_pcm_ops_t snd_pcm_mulaw_ops = {
.close = snd_pcm_generic_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_mulaw_hw_refine,
diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c
index 9b8583c..68f2d68 100644
--- a/src/pcm/pcm_multi.c
+++ b/src/pcm/pcm_multi.c
@@ -762,7 +762,7 @@ static void snd_pcm_multi_dump(snd_pcm_t *pcm, snd_output_t *out)
}
}
-static snd_pcm_ops_t snd_pcm_multi_ops = {
+static const snd_pcm_ops_t snd_pcm_multi_ops = {
.close = snd_pcm_multi_close,
.info = snd_pcm_multi_info,
.hw_refine = snd_pcm_multi_hw_refine,
@@ -777,7 +777,7 @@ static snd_pcm_ops_t snd_pcm_multi_ops = {
.munmap = snd_pcm_multi_munmap,
};
-static snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
+static const snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
.status = snd_pcm_multi_status,
.state = snd_pcm_multi_state,
.hwsync = snd_pcm_multi_hwsync,
diff --git a/src/pcm/pcm_null.c b/src/pcm/pcm_null.c
index 60ee9b6..2f2a42f 100644
--- a/src/pcm/pcm_null.c
+++ b/src/pcm/pcm_null.c
@@ -28,7 +28,6 @@
#include <byteswap.h>
#include <limits.h>
-#include <sys/shm.h>
#include "pcm_local.h"
#include "pcm_plugin.h"
@@ -139,6 +138,7 @@ static int snd_pcm_null_start(snd_pcm_t *pcm)
static int snd_pcm_null_drop(snd_pcm_t *pcm)
{
snd_pcm_null_t *null = pcm->private_data;
+ assert(null->state != SND_PCM_STATE_OPEN);
null->state = SND_PCM_STATE_SETUP;
return 0;
}
@@ -146,6 +146,7 @@ static int snd_pcm_null_drop(snd_pcm_t *pcm)
static int snd_pcm_null_drain(snd_pcm_t *pcm)
{
snd_pcm_null_t *null = pcm->private_data;
+ assert(null->state != SND_PCM_STATE_OPEN);
null->state = SND_PCM_STATE_SETUP;
return 0;
}
@@ -275,7 +276,7 @@ static void snd_pcm_null_dump(snd_pcm_t *pcm, snd_output_t *out)
}
}
-static snd_pcm_ops_t snd_pcm_null_ops = {
+static const snd_pcm_ops_t snd_pcm_null_ops = {
.close = snd_pcm_null_close,
.info = snd_pcm_null_info,
.hw_refine = snd_pcm_null_hw_refine,
@@ -290,7 +291,7 @@ static snd_pcm_ops_t snd_pcm_null_ops = {
.munmap = snd_pcm_generic_munmap,
};
-static snd_pcm_fast_ops_t snd_pcm_null_fast_ops = {
+static const snd_pcm_fast_ops_t snd_pcm_null_fast_ops = {
.status = snd_pcm_null_status,
.state = snd_pcm_null_state,
.hwsync = snd_pcm_null_hwsync,
diff --git a/src/pcm/pcm_params.c b/src/pcm/pcm_params.c
index 3462599..80b3fd2 100644
--- a/src/pcm/pcm_params.c
+++ b/src/pcm/pcm_params.c
@@ -1232,7 +1232,7 @@ void snd_pcm_hw_param_dump(const snd_pcm_hw_params_t *params,
#define HW_PARAM(v) [SND_PCM_HW_PARAM_##v] = #v
-const char *snd_pcm_hw_param_names[] = {
+static const char *const snd_pcm_hw_param_names[] = {
HW_PARAM(ACCESS),
HW_PARAM(FORMAT),
HW_PARAM(SUBFORMAT),
@@ -1660,7 +1660,7 @@ int snd_pcm_hw_params_try_explain_failure(snd_pcm_t *pcm,
typedef struct _snd_pcm_hw_rule snd_pcm_hw_rule_t;
typedef int (*snd_pcm_hw_rule_func_t)(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule);
+ const snd_pcm_hw_rule_t *rule);
struct _snd_pcm_hw_rule {
int var;
@@ -1670,7 +1670,7 @@ struct _snd_pcm_hw_rule {
};
static int snd_pcm_hw_rule_mul(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+ const snd_pcm_hw_rule_t *rule)
{
snd_interval_t t;
snd_interval_mul(hw_param_interval_c(params, rule->deps[0]),
@@ -1679,7 +1679,7 @@ static int snd_pcm_hw_rule_mul(snd_pcm_hw_params_t *params,
}
static int snd_pcm_hw_rule_div(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+ const snd_pcm_hw_rule_t *rule)
{
snd_interval_t t;
snd_interval_div(hw_param_interval_c(params, rule->deps[0]),
@@ -1688,7 +1688,7 @@ static int snd_pcm_hw_rule_div(snd_pcm_hw_params_t *params,
}
static int snd_pcm_hw_rule_muldivk(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+ const snd_pcm_hw_rule_t *rule)
{
snd_interval_t t;
snd_interval_muldivk(hw_param_interval_c(params, rule->deps[0]),
@@ -1698,7 +1698,7 @@ static int snd_pcm_hw_rule_muldivk(snd_pcm_hw_params_t *params,
}
static int snd_pcm_hw_rule_mulkdiv(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+ const snd_pcm_hw_rule_t *rule)
{
snd_interval_t t;
snd_interval_mulkdiv(hw_param_interval_c(params, rule->deps[0]),
@@ -1708,7 +1708,7 @@ static int snd_pcm_hw_rule_mulkdiv(snd_pcm_hw_params_t *params,
}
static int snd_pcm_hw_rule_format(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+ const snd_pcm_hw_rule_t *rule)
{
int changed = 0;
snd_pcm_format_t k;
@@ -1733,7 +1733,7 @@ static int snd_pcm_hw_rule_format(snd_pcm_hw_params_t *params,
static int snd_pcm_hw_rule_sample_bits(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+ const snd_pcm_hw_rule_t *rule)
{
unsigned int min, max;
snd_pcm_format_t k;
@@ -1767,7 +1767,7 @@ static int snd_pcm_hw_rule_sample_bits(snd_pcm_hw_params_t *params,
return changed;
}
-static snd_pcm_hw_rule_t refine_rules[] = {
+static const snd_pcm_hw_rule_t refine_rules[] = {
{
.var = SND_PCM_HW_PARAM_FORMAT,
.func = snd_pcm_hw_rule_format,
@@ -1911,7 +1911,7 @@ static snd_pcm_hw_rule_t refine_rules[] = {
#define RULES (sizeof(refine_rules) / sizeof(refine_rules[0]))
-static snd_mask_t refine_masks[SND_PCM_HW_PARAM_LAST_MASK - SND_PCM_HW_PARAM_FIRST_MASK + 1] = {
+static const snd_mask_t refine_masks[SND_PCM_HW_PARAM_LAST_MASK - SND_PCM_HW_PARAM_FIRST_MASK + 1] = {
[SND_PCM_HW_PARAM_ACCESS - SND_PCM_HW_PARAM_FIRST_MASK] = {
.bits = { 0x1f },
},
@@ -1923,7 +1923,7 @@ static snd_mask_t refine_masks[SND_PCM_HW_PARAM_LAST_MASK - SND_PCM_HW_PARAM_FIR
},
};
-static snd_interval_t refine_intervals[SND_PCM_HW_PARAM_LAST_INTERVAL - SND_PCM_HW_PARAM_FIRST_INTERVAL + 1] = {
+static const snd_interval_t refine_intervals[SND_PCM_HW_PARAM_LAST_INTERVAL - SND_PCM_HW_PARAM_FIRST_INTERVAL + 1] = {
[SND_PCM_HW_PARAM_SAMPLE_BITS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
.min = 1, .max = UINT_MAX,
.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
@@ -2022,7 +2022,7 @@ int snd_pcm_hw_refine_soft(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t
do {
again = 0;
for (k = 0; k < RULES; k++) {
- snd_pcm_hw_rule_t *r = &refine_rules[k];
+ const snd_pcm_hw_rule_t *r = &refine_rules[k];
unsigned int d;
int doit = 0;
for (d = 0; r->deps[d] >= 0; d++) {
diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c
index 561e163..abd3d43 100644
--- a/src/pcm/pcm_plug.c
+++ b/src/pcm/pcm_plug.c
@@ -87,7 +87,7 @@ static int snd_pcm_plug_info(snd_pcm_t *pcm, snd_pcm_info_t *info)
return 0;
}
-static snd_pcm_format_t linear_preferred_formats[] = {
+static const snd_pcm_format_t linear_preferred_formats[] = {
#ifdef SND_LITTLE_ENDIAN
SND_PCM_FORMAT_S16_LE,
SND_PCM_FORMAT_U16_LE,
@@ -176,7 +176,7 @@ static snd_pcm_format_t linear_preferred_formats[] = {
#endif
#ifdef BUILD_PCM_NONLINEAR
-static snd_pcm_format_t nonlinear_preferred_formats[] = {
+static const snd_pcm_format_t nonlinear_preferred_formats[] = {
#ifdef BUILD_PCM_PLUGIN_MULAW
SND_PCM_FORMAT_MU_LAW,
#endif
@@ -190,7 +190,7 @@ static snd_pcm_format_t nonlinear_preferred_formats[] = {
#endif
#ifdef BUILD_PCM_PLUGIN_LFLOAT
-static snd_pcm_format_t float_preferred_formats[] = {
+static const snd_pcm_format_t float_preferred_formats[] = {
#ifdef SND_LITTLE_ENDIAN
SND_PCM_FORMAT_FLOAT_LE,
SND_PCM_FORMAT_FLOAT64_LE,
@@ -205,7 +205,7 @@ static snd_pcm_format_t float_preferred_formats[] = {
};
#endif
-static char linear_format_widths[32] = {
+static const char linear_format_widths[32] = {
0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 1,
0, 1, 0, 1, 0, 0, 0, 1,
@@ -581,12 +581,44 @@ static int snd_pcm_plug_change_access(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm_p
return 1;
}
+#ifdef BUILD_PCM_PLUGIN_MMAP_EMUL
+static int snd_pcm_plug_change_mmap(snd_pcm_t *pcm, snd_pcm_t **new,
+ snd_pcm_plug_params_t *clt,
+ snd_pcm_plug_params_t *slv)
+{
+ snd_pcm_plug_t *plug = pcm->private_data;
+ int err;
+
+ if (clt->access == slv->access)
+ return 0;
+
+ switch (slv->access) {
+ case SND_PCM_ACCESS_MMAP_INTERLEAVED:
+ case SND_PCM_ACCESS_MMAP_NONINTERLEAVED:
+ case SND_PCM_ACCESS_MMAP_COMPLEX:
+ return 0;
+ default:
+ break;
+ }
+
+ err = __snd_pcm_mmap_emul_open(new, NULL, plug->gen.slave,
+ plug->gen.slave != plug->req_slave);
+ if (err < 0)
+ return err;
+ slv->access = clt->access;
+ return 1;
+}
+#endif
+
static int snd_pcm_plug_insert_plugins(snd_pcm_t *pcm,
snd_pcm_plug_params_t *client,
snd_pcm_plug_params_t *slave)
{
snd_pcm_plug_t *plug = pcm->private_data;
- static int (*funcs[])(snd_pcm_t *_pcm, snd_pcm_t **new, snd_pcm_plug_params_t *s, snd_pcm_plug_params_t *d) = {
+ static int (*const funcs[])(snd_pcm_t *_pcm, snd_pcm_t **new, snd_pcm_plug_params_t *s, snd_pcm_plug_params_t *d) = {
+#ifdef BUILD_PCM_PLUGIN_MMAP_EMUL
+ snd_pcm_plug_change_mmap,
+#endif
snd_pcm_plug_change_format,
#ifdef BUILD_PCM_PLUGIN_ROUTE
snd_pcm_plug_change_channels,
@@ -693,6 +725,43 @@ static int snd_pcm_plug_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *
return 0;
}
+static int check_access_change(snd_pcm_hw_params_t *cparams,
+ snd_pcm_hw_params_t *sparams)
+{
+ snd_pcm_access_mask_t *smask;
+#ifdef BUILD_PCM_PLUGIN_MMAP_EMUL
+ const snd_pcm_access_mask_t *cmask;
+ snd_pcm_access_mask_t mask;
+#endif
+
+ smask = (snd_pcm_access_mask_t *)
+ snd_pcm_hw_param_get_mask(sparams,
+ SND_PCM_HW_PARAM_ACCESS);
+ if (snd_pcm_access_mask_test(smask, SND_PCM_ACCESS_MMAP_INTERLEAVED) ||
+ snd_pcm_access_mask_test(smask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED) ||
+ snd_pcm_access_mask_test(smask, SND_PCM_ACCESS_MMAP_COMPLEX))
+ return 0; /* OK, we have mmap support */
+#ifdef BUILD_PCM_PLUGIN_MMAP_EMUL
+ /* no mmap support - we need mmap emulation */
+ cmask = (const snd_pcm_access_mask_t *)
+ snd_pcm_hw_param_get_mask(cparams,
+ SND_PCM_HW_PARAM_ACCESS);
+ snd_mask_none(&mask);
+ if (snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_RW_INTERLEAVED) ||
+ snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_MMAP_INTERLEAVED))
+ snd_pcm_access_mask_set(&mask,
+ SND_PCM_ACCESS_RW_INTERLEAVED);
+ if (snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_RW_NONINTERLEAVED) ||
+ snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED))
+ snd_pcm_access_mask_set(&mask,
+ SND_PCM_ACCESS_RW_NONINTERLEAVED);
+ *smask = mask;
+ return 0;
+#else
+ return -EINVAL;
+#endif
+}
+
static int snd_pcm_plug_hw_refine_schange(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
snd_pcm_hw_params_t *sparams)
{
@@ -764,18 +833,15 @@ static int snd_pcm_plug_hw_refine_schange(snd_pcm_t *pcm, snd_pcm_hw_params_t *p
return -EINVAL;
}
- if (snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_FORMAT, sparams) ||
- snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_CHANNELS, sparams) ||
- snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_RATE, sparams) ||
- snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_ACCESS, sparams)) {
- snd_pcm_access_mask_t access_mask = { SND_PCM_ACCBIT_MMAP };
- _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
- &access_mask);
- if (snd_pcm_access_mask_empty(snd_pcm_hw_param_get_mask(sparams, SND_PCM_HW_PARAM_ACCESS))) {
- SNDERR("Unable to find an usable access for '%s'", pcm->name);
- return -EINVAL;
+ if (snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_ACCESS, sparams)) {
+ err = check_access_change(params, sparams);
+ if (err < 0) {
+ SNDERR("Unable to find an usable access for '%s'",
+ pcm->name);
+ return err;
}
}
+
if ((links & SND_PCM_HW_PARBIT_RATE) ||
snd_pcm_hw_param_always_eq(params, SND_PCM_HW_PARAM_RATE, sparams))
links |= (SND_PCM_HW_PARBIT_PERIOD_SIZE |
@@ -985,7 +1051,7 @@ static void snd_pcm_plug_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(plug->gen.slave, out);
}
-static snd_pcm_ops_t snd_pcm_plug_ops = {
+static const snd_pcm_ops_t snd_pcm_plug_ops = {
.close = snd_pcm_plug_close,
.info = snd_pcm_plug_info,
.hw_refine = snd_pcm_plug_hw_refine,
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index d5fc5d7..a751deb 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -82,7 +82,6 @@ pcm.rate44100Hz {
*/
-#include <sys/shm.h>
#include <limits.h>
#include "pcm_local.h"
#include "pcm_plugin.h"
@@ -192,18 +191,22 @@ static int snd_pcm_plugin_reset(snd_pcm_t *pcm)
return 0;
}
+static snd_pcm_sframes_t snd_pcm_plugin_rewindable(snd_pcm_t *pcm)
+{
+ return snd_pcm_mmap_hw_avail(pcm);
+}
+
static snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_plugin_t *plugin = pcm->private_data;
snd_pcm_sframes_t n = snd_pcm_mmap_hw_avail(pcm);
snd_pcm_sframes_t sframes;
- if ((snd_pcm_uframes_t)n > frames)
+ if ((snd_pcm_uframes_t)n < frames)
frames = n;
if (frames == 0)
return 0;
- /* FIXME: rate plugin */
if (plugin->slave_frames)
sframes = plugin->slave_frames(pcm, (snd_pcm_sframes_t) frames);
else
@@ -218,28 +221,32 @@ static snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
frames = plugin->client_frames(pcm, sframes);
snd_pcm_mmap_appl_backward(pcm, (snd_pcm_uframes_t) frames);
snd_atomic_write_end(&plugin->watom);
- return n;
+ return (snd_pcm_sframes_t) frames;
+}
+
+static snd_pcm_sframes_t snd_pcm_plugin_forwardable(snd_pcm_t *pcm)
+{
+ return snd_pcm_mmap_avail(pcm);
}
static snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_plugin_t *plugin = pcm->private_data;
snd_pcm_sframes_t n = snd_pcm_mmap_avail(pcm);
- snd_pcm_uframes_t sframes;
+ snd_pcm_sframes_t sframes;
- if ((snd_pcm_uframes_t)n > frames)
+ if ((snd_pcm_uframes_t)n < frames)
frames = n;
if (frames == 0)
return 0;
- /* FIXME: rate plugin */
if (plugin->slave_frames)
sframes = plugin->slave_frames(pcm, (snd_pcm_sframes_t) frames);
else
sframes = frames;
snd_atomic_write_begin(&plugin->watom);
- sframes = INTERNAL(snd_pcm_forward)(plugin->gen.slave, (snd_pcm_uframes_t) sframes);
- if ((snd_pcm_sframes_t) sframes < 0) {
+ sframes = INTERNAL(snd_pcm_forward)(plugin->gen.slave, sframes);
+ if (sframes < 0) {
snd_atomic_write_end(&plugin->watom);
return sframes;
}
@@ -247,7 +254,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_
frames = plugin->client_frames(pcm, sframes);
snd_pcm_mmap_appl_forward(pcm, (snd_pcm_uframes_t) frames);
snd_atomic_write_end(&plugin->watom);
- return n;
+ return (snd_pcm_sframes_t) frames;
}
static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
@@ -552,7 +559,7 @@ static int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
return 0;
}
-snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
+const snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
.status = snd_pcm_plugin_status,
.state = snd_pcm_generic_state,
.hwsync = snd_pcm_generic_hwsync,
@@ -563,7 +570,9 @@ snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
.drop = snd_pcm_generic_drop,
.drain = snd_pcm_generic_drain,
.pause = snd_pcm_generic_pause,
+ .rewindable = snd_pcm_plugin_rewindable,
.rewind = snd_pcm_plugin_rewind,
+ .forwardable = snd_pcm_plugin_forwardable,
.forward = snd_pcm_plugin_forward,
.resume = snd_pcm_generic_resume,
.link = snd_pcm_generic_link,
diff --git a/src/pcm/pcm_plugin.h b/src/pcm/pcm_plugin.h
index b427e13..dfcf6de 100644
--- a/src/pcm/pcm_plugin.h
+++ b/src/pcm/pcm_plugin.h
@@ -63,7 +63,7 @@ typedef struct {
void snd_pcm_plugin_init(snd_pcm_plugin_t *plugin);
-extern snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops;
+extern const snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops;
snd_pcm_sframes_t snd_pcm_plugin_undo_read_generic
(snd_pcm_t *pcm,
diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
index 9cf090a..a97a5de 100644
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -1195,7 +1195,7 @@ static int snd_pcm_rate_close(snd_pcm_t *pcm)
return snd_pcm_generic_close(pcm);
}
-static snd_pcm_fast_ops_t snd_pcm_rate_fast_ops = {
+static const snd_pcm_fast_ops_t snd_pcm_rate_fast_ops = {
.status = snd_pcm_rate_status,
.state = snd_pcm_rate_state,
.hwsync = snd_pcm_rate_hwsync,
@@ -1221,7 +1221,7 @@ static snd_pcm_fast_ops_t snd_pcm_rate_fast_ops = {
.poll_revents = snd_pcm_rate_poll_revents,
};
-static snd_pcm_ops_t snd_pcm_rate_ops = {
+static const snd_pcm_ops_t snd_pcm_rate_ops = {
.close = snd_pcm_rate_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_rate_hw_refine,
@@ -1256,7 +1256,7 @@ static int is_builtin_plugin(const char *type)
return strcmp(type, "linear") == 0;
}
-static const char *default_rate_plugins[] = {
+static const char *const default_rate_plugins[] = {
"speexrate", "linear", NULL
};
@@ -1340,7 +1340,7 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
#ifdef PIC
err = -ENOENT;
if (!converter) {
- const char **types;
+ const char *const *types;
for (types = default_rate_plugins; *types; types++) {
err = rate_open_func(rate, *types);
if (!err) {
diff --git a/src/pcm/pcm_rate_linear.c b/src/pcm/pcm_rate_linear.c
index a19fecb..20e119b 100644
--- a/src/pcm/pcm_rate_linear.c
+++ b/src/pcm/pcm_rate_linear.c
@@ -405,7 +405,7 @@ static void linear_close(void *obj)
free(obj);
}
-static snd_pcm_rate_ops_t linear_ops = {
+static const snd_pcm_rate_ops_t linear_ops = {
.close = linear_close,
.init = linear_init,
.free = linear_free,
diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c
index 6991fb1..4da623f 100644
--- a/src/pcm/pcm_route.c
+++ b/src/pcm/pcm_route.c
@@ -236,14 +236,14 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
#include "plugin_ops.h"
#undef GETS_LABELS
#undef PUT32_LABELS
- static void *zero_labels[3] = {
+ static void *const zero_labels[3] = {
&&zero_int32, &&zero_int64,
#if SND_PCM_PLUGIN_ROUTE_FLOAT
&&zero_float
#endif
};
/* sum_type att */
- static void *add_labels[3 * 2] = {
+ static void *const add_labels[3 * 2] = {
&&add_int32_noatt, &&add_int32_att,
&&add_int64_noatt, &&add_int64_att,
#if SND_PCM_PLUGIN_ROUTE_FLOAT
@@ -251,7 +251,7 @@ static void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
#endif
};
/* sum_type att shift */
- static void *norm_labels[3 * 2 * 4] = {
+ static void *const norm_labels[3 * 2 * 4] = {
0,
&&norm_int32_8_noatt,
&&norm_int32_16_noatt,
@@ -747,7 +747,7 @@ static void snd_pcm_route_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(route->plug.gen.slave, out);
}
-static snd_pcm_ops_t snd_pcm_route_ops = {
+static const snd_pcm_ops_t snd_pcm_route_ops = {
.close = snd_pcm_route_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_route_hw_refine,
diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c
index a01e759..3f8a0ac 100644
--- a/src/pcm/pcm_share.c
+++ b/src/pcm/pcm_share.c
@@ -35,7 +35,6 @@
#include <math.h>
#include <sys/socket.h>
#include <sys/poll.h>
-#include <sys/shm.h>
#include <pthread.h>
#include "pcm_local.h"
@@ -1039,6 +1038,17 @@ static snd_pcm_sframes_t _snd_pcm_share_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
return n;
}
+static snd_pcm_sframes_t snd_pcm_share_rewindable(snd_pcm_t *pcm)
+{
+ snd_pcm_share_t *share = pcm->private_data;
+ snd_pcm_share_slave_t *slave = share->slave;
+ snd_pcm_sframes_t ret;
+ Pthread_mutex_lock(&slave->mutex);
+ ret = snd_pcm_rewindable(slave->pcm);
+ Pthread_mutex_unlock(&slave->mutex);
+ return ret;
+}
+
static snd_pcm_sframes_t snd_pcm_share_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_share_t *share = pcm->private_data;
@@ -1085,6 +1095,17 @@ static snd_pcm_sframes_t _snd_pcm_share_forward(snd_pcm_t *pcm, snd_pcm_uframes_
return n;
}
+static snd_pcm_sframes_t snd_pcm_share_forwardable(snd_pcm_t *pcm)
+{
+ snd_pcm_share_t *share = pcm->private_data;
+ snd_pcm_share_slave_t *slave = share->slave;
+ snd_pcm_sframes_t ret;
+ Pthread_mutex_lock(&slave->mutex);
+ ret = snd_pcm_forwardable(slave->pcm);
+ Pthread_mutex_unlock(&slave->mutex);
+ return ret;
+}
+
static snd_pcm_sframes_t snd_pcm_share_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_share_t *share = pcm->private_data;
@@ -1286,7 +1307,7 @@ static void snd_pcm_share_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_dump(slave->pcm, out);
}
-static snd_pcm_ops_t snd_pcm_share_ops = {
+static const snd_pcm_ops_t snd_pcm_share_ops = {
.close = snd_pcm_share_close,
.info = snd_pcm_share_info,
.hw_refine = snd_pcm_share_hw_refine,
@@ -1301,7 +1322,7 @@ static snd_pcm_ops_t snd_pcm_share_ops = {
.munmap = snd_pcm_share_munmap,
};
-static snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
+static const snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
.status = snd_pcm_share_status,
.state = snd_pcm_share_state,
.hwsync = snd_pcm_share_hwsync,
@@ -1316,7 +1337,9 @@ static snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
.writen = snd_pcm_mmap_writen,
.readi = snd_pcm_mmap_readi,
.readn = snd_pcm_mmap_readn,
+ .rewindable = snd_pcm_share_rewindable,
.rewind = snd_pcm_share_rewind,
+ .forwardable = snd_pcm_share_forwardable,
.forward = snd_pcm_share_forward,
.resume = snd_pcm_share_resume,
.avail_update = snd_pcm_share_avail_update,
diff --git a/src/pcm/pcm_shm.c b/src/pcm/pcm_shm.c
index 29f9d23..69d0524 100644
--- a/src/pcm/pcm_shm.c
+++ b/src/pcm/pcm_shm.c
@@ -508,6 +508,11 @@ static int snd_pcm_shm_pause(snd_pcm_t *pcm, int enable)
return snd_pcm_shm_action(pcm);
}
+static snd_pcm_sframes_t snd_pcm_shm_rewindable(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
+{
+ return 0; /* FIX ME */
+}
+
static snd_pcm_sframes_t snd_pcm_shm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_shm_t *shm = pcm->private_data;
@@ -517,6 +522,11 @@ static snd_pcm_sframes_t snd_pcm_shm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t fr
return snd_pcm_shm_action(pcm);
}
+static snd_pcm_sframes_t snd_pcm_shm_forwardable(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
+{
+ return 0; /* FIX ME */
+}
+
static snd_pcm_sframes_t snd_pcm_shm_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_shm_t *shm = pcm->private_data;
@@ -581,7 +591,7 @@ static void snd_pcm_shm_dump(snd_pcm_t *pcm, snd_output_t *out)
}
}
-static snd_pcm_ops_t snd_pcm_shm_ops = {
+static const snd_pcm_ops_t snd_pcm_shm_ops = {
.close = snd_pcm_shm_close,
.info = snd_pcm_shm_info,
.hw_refine = snd_pcm_shm_hw_refine,
@@ -596,7 +606,7 @@ static snd_pcm_ops_t snd_pcm_shm_ops = {
.munmap = snd_pcm_shm_munmap,
};
-static snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = {
+static const snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = {
.status = snd_pcm_shm_status,
.state = snd_pcm_shm_state,
.hwsync = snd_pcm_shm_hwsync,
@@ -607,7 +617,9 @@ static snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = {
.drop = snd_pcm_shm_drop,
.drain = snd_pcm_shm_drain,
.pause = snd_pcm_shm_pause,
+ .rewindable = snd_pcm_shm_rewindable,
.rewind = snd_pcm_shm_rewind,
+ .forwardable = snd_pcm_shm_forwardable,
.forward = snd_pcm_shm_forward,
.resume = snd_pcm_shm_resume,
.writei = snd_pcm_mmap_writei,
diff --git a/src/pcm/pcm_softvol.c b/src/pcm/pcm_softvol.c
index 7af7f40..637e5cb 100644
--- a/src/pcm/pcm_softvol.c
+++ b/src/pcm/pcm_softvol.c
@@ -61,7 +61,7 @@ typedef struct {
#define ZERO_DB 0.0
#define MAX_DB_UPPER_LIMIT 50
-static unsigned int preset_dB_value[PRESET_RESOLUTION] = {
+static const unsigned int preset_dB_value[PRESET_RESOLUTION] = {
0x00b8, 0x00bd, 0x00c1, 0x00c5, 0x00ca, 0x00cf, 0x00d4, 0x00d9,
0x00de, 0x00e3, 0x00e8, 0x00ed, 0x00f3, 0x00f9, 0x00fe, 0x0104,
0x010a, 0x0111, 0x0117, 0x011e, 0x0124, 0x012b, 0x0132, 0x0139,
@@ -275,9 +275,15 @@ static void softvol_convert_stereo_vol(snd_pcm_softvol_t *svol,
return;
}
- vol[0] = svol->dB_value[svol->cur_vol[0]];
- vol[1] = svol->dB_value[svol->cur_vol[1]];
- vol_c = svol->dB_value[(svol->cur_vol[0] + svol->cur_vol[1]) / 2];
+ if (svol->max_val == 1) {
+ vol[0] = svol->cur_vol[0] ? 0xffff : 0;
+ vol[1] = svol->cur_vol[1] ? 0xffff : 0;
+ vol_c = vol[0] | vol[1];
+ } else {
+ vol[0] = svol->dB_value[svol->cur_vol[0]];
+ vol[1] = svol->dB_value[svol->cur_vol[1]];
+ vol_c = svol->dB_value[(svol->cur_vol[0] + svol->cur_vol[1]) / 2];
+ }
switch (svol->sformat) {
case SND_PCM_FORMAT_S16_LE:
case SND_PCM_FORMAT_S16_BE:
@@ -325,7 +331,10 @@ static void softvol_convert_mono_vol(snd_pcm_softvol_t *svol,
return;
}
- vol_scale = svol->dB_value[svol->cur_vol[0]];
+ if (svol->max_val == 1)
+ vol_scale = svol->cur_vol[0] ? 0xffff : 0;
+ else
+ vol_scale = svol->dB_value[svol->cur_vol[0]];
switch (svol->sformat) {
case SND_PCM_FORMAT_S16_LE:
case SND_PCM_FORMAT_S16_BE:
@@ -436,6 +445,38 @@ static int snd_pcm_softvol_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_
return 0;
}
+/*
+ * refine the access mask
+ */
+static int check_access_mask(snd_pcm_hw_params_t *src,
+ snd_pcm_hw_params_t *dst)
+{
+ const snd_pcm_access_mask_t *mask;
+ snd_pcm_access_mask_t smask;
+
+ mask = snd_pcm_hw_param_get_mask(src, SND_PCM_HW_PARAM_ACCESS);
+ snd_mask_none(&smask);
+ if (snd_pcm_access_mask_test(mask, SND_PCM_ACCESS_RW_INTERLEAVED) ||
+ snd_pcm_access_mask_test(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED)) {
+ snd_pcm_access_mask_set(&smask,
+ SND_PCM_ACCESS_RW_INTERLEAVED);
+ snd_pcm_access_mask_set(&smask,
+ SND_PCM_ACCESS_MMAP_INTERLEAVED);
+ }
+ if (snd_pcm_access_mask_test(mask, SND_PCM_ACCESS_RW_NONINTERLEAVED) ||
+ snd_pcm_access_mask_test(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) {
+ snd_pcm_access_mask_set(&smask,
+ SND_PCM_ACCESS_RW_NONINTERLEAVED);
+ snd_pcm_access_mask_set(&smask,
+ SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
+ }
+ if (snd_pcm_access_mask_test(mask, SND_PCM_ACCESS_MMAP_COMPLEX))
+ snd_pcm_access_mask_set(&smask,
+ SND_PCM_ACCESS_MMAP_COMPLEX);
+
+ return _snd_pcm_hw_param_set_mask(dst, SND_PCM_HW_PARAM_ACCESS, &smask);
+}
+
static int snd_pcm_softvol_hw_refine_schange(snd_pcm_t *pcm,
snd_pcm_hw_params_t *params,
snd_pcm_hw_params_t *sparams)
@@ -457,6 +498,11 @@ static int snd_pcm_softvol_hw_refine_schange(snd_pcm_t *pcm,
err = _snd_pcm_hw_params_refine(sparams, links, params);
if (err < 0)
return err;
+
+ err = check_access_mask(params, sparams);
+ if (err < 0)
+ return err;
+
return 0;
}
@@ -481,6 +527,11 @@ static int snd_pcm_softvol_hw_refine_cchange(snd_pcm_t *pcm,
err = _snd_pcm_hw_params_refine(params, links, sparams);
if (err < 0)
return err;
+
+ err = check_access_mask(sparams, params);
+ if (err < 0)
+ return err;
+
return 0;
}
@@ -569,9 +620,13 @@ static void snd_pcm_softvol_dump(snd_pcm_t *pcm, snd_output_t *out)
snd_pcm_softvol_t *svol = pcm->private_data;
snd_output_printf(out, "Soft volume PCM\n");
snd_output_printf(out, "Control: %s\n", svol->elem.id.name);
- snd_output_printf(out, "min_dB: %g\n", svol->min_dB);
- snd_output_printf(out, "max_dB: %g\n", svol->max_dB);
- snd_output_printf(out, "resolution: %d\n", svol->max_val + 1);
+ if (svol->max_val == 1)
+ snd_output_printf(out, "boolean\n");
+ else {
+ snd_output_printf(out, "min_dB: %g\n", svol->min_dB);
+ snd_output_printf(out, "max_dB: %g\n", svol->max_dB);
+ snd_output_printf(out, "resolution: %d\n", svol->max_val + 1);
+ }
if (pcm->setup) {
snd_output_printf(out, "Its setup is:\n");
snd_pcm_dump_setup(pcm, out);
@@ -596,13 +651,21 @@ static int add_user_ctl(snd_pcm_softvol_t *svol, snd_ctl_elem_info_t *cinfo, int
int i;
unsigned int def_val;
- err = snd_ctl_elem_add_integer(svol->ctl, &cinfo->id, count, 0, svol->max_val, 0);
+ if (svol->max_val == 1)
+ err = snd_ctl_elem_add_boolean(svol->ctl, &cinfo->id, count);
+ else
+ err = snd_ctl_elem_add_integer(svol->ctl, &cinfo->id, count,
+ 0, svol->max_val, 0);
if (err < 0)
return err;
- add_tlv_info(svol, cinfo);
- /* set zero dB value as default, or max_val if
- there is no 0 dB setting */
- def_val = svol->zero_dB_val ? svol->zero_dB_val : svol->max_val;
+ if (svol->max_val == 1)
+ def_val = 1;
+ else {
+ add_tlv_info(svol, cinfo);
+ /* set zero dB value as default, or max_val if
+ there is no 0 dB setting */
+ def_val = svol->zero_dB_val ? svol->zero_dB_val : svol->max_val;
+ }
for (i = 0; i < count; i++)
svol->elem.value.integer.value[i] = def_val;
return snd_ctl_elem_write(svol->ctl, &svol->elem);
@@ -647,7 +710,7 @@ static int softvol_load_control(snd_pcm_t *pcm, snd_pcm_softvol_t *svol,
svol->max_val = resolution - 1;
svol->min_dB = min_dB;
svol->max_dB = max_dB;
- if (svol->max_dB == ZERO_DB)
+ if (svol->max_val == 1 || svol->max_dB == ZERO_DB)
svol->zero_dB_val = svol->max_val;
else if (svol->max_dB < 0)
svol->zero_dB_val = 0; /* there is no 0 dB setting */
@@ -671,7 +734,8 @@ static int softvol_load_control(snd_pcm_t *pcm, snd_pcm_softvol_t *svol,
/* hardware control exists */
return 1; /* notify */
- } else if (cinfo->type != SND_CTL_ELEM_TYPE_INTEGER ||
+ } else if ((cinfo->type != SND_CTL_ELEM_TYPE_INTEGER &&
+ cinfo->type != SND_CTL_ELEM_TYPE_BOOLEAN) ||
cinfo->count != (unsigned int)cchannels ||
cinfo->value.integer.min != 0 ||
cinfo->value.integer.max != resolution - 1) {
@@ -684,7 +748,7 @@ static int softvol_load_control(snd_pcm_t *pcm, snd_pcm_softvol_t *svol,
SNDERR("Cannot add a control");
return err;
}
- } else {
+ } else if (svol->max_val > 1) {
/* check TLV availability */
unsigned int tlv[4];
err = snd_ctl_elem_tlv_read(svol->ctl, &cinfo->id, tlv, sizeof(tlv));
@@ -693,8 +757,12 @@ static int softvol_load_control(snd_pcm_t *pcm, snd_pcm_softvol_t *svol,
}
}
+ if (svol->max_val == 1)
+ return 0;
+
+ /* set up dB table */
if (min_dB == PRESET_MIN_DB && max_dB == ZERO_DB && resolution == PRESET_RESOLUTION)
- svol->dB_value = preset_dB_value;
+ svol->dB_value = (unsigned int*)preset_dB_value;
else {
#ifndef HAVE_SOFT_FLOAT
svol->dB_value = calloc(resolution, sizeof(unsigned int));
@@ -719,7 +787,7 @@ static int softvol_load_control(snd_pcm_t *pcm, snd_pcm_softvol_t *svol,
return 0;
}
-static snd_pcm_ops_t snd_pcm_softvol_ops = {
+static const snd_pcm_ops_t snd_pcm_softvol_ops = {
.close = snd_pcm_softvol_close,
.info = snd_pcm_generic_info,
.hw_refine = snd_pcm_softvol_hw_refine,
@@ -863,6 +931,7 @@ pcm.name {
[min_dB REAL] # minimal dB value (default: -51.0)
[max_dB REAL] # maximal dB value (default: 0.0)
[resolution INT] # resolution (default: 256)
+ # resolution = 2 means a mute switch
}
\endcode
@@ -965,7 +1034,7 @@ int _snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name,
MAX_DB_UPPER_LIMIT);
return -EINVAL;
}
- if (resolution < 0 || resolution > 1024) {
+ if (resolution <= 1 || resolution > 1024) {
SNDERR("Invalid resolution value %d", resolution);
return -EINVAL;
}
diff --git a/src/pcm/pcm_symbols_list.c b/src/pcm/pcm_symbols_list.c
deleted file mode 100644
index 12221fd..0000000
--- a/src/pcm/pcm_symbols_list.c
+++ /dev/null
@@ -1,9 +0,0 @@
-&_snd_module_pcm_copy,
-&_snd_module_pcm_linear,
-&_snd_module_pcm_plug,
-&_snd_module_pcm_null,
-&_snd_module_pcm_empty,
-&_snd_module_pcm_hooks,
-&_snd_module_pcm_asym,
-&_snd_module_pcm_extplug,
-&_snd_module_pcm_ioplug,
diff --git a/src/pcm/plugin_ops.h b/src/pcm/plugin_ops.h
index 10b963c..04220d6 100644
--- a/src/pcm/plugin_ops.h
+++ b/src/pcm/plugin_ops.h
@@ -108,7 +108,7 @@ copy_64: as_s64(dst) = as_s64c(src); goto COPY_END;
#ifdef CONV_LABELS
/* src_wid src_endswap sign_toggle dst_wid dst_endswap */
-static void *conv_labels[4 * 2 * 2 * 4 * 2] = {
+static void *const conv_labels[4 * 2 * 2 * 4 * 2] = {
&&conv_xxx1_xxx1, /* 8h -> 8h */
&&conv_xxx1_xxx1, /* 8h -> 8s */
&&conv_xxx1_xx10, /* 8h -> 16h */
@@ -341,7 +341,7 @@ conv_1234_123C: as_u32(dst) = as_u32c(src) ^ 0x80; goto CONV_END;
#ifdef GET16_LABELS
/* src_wid src_endswap sign_toggle */
-static void *get16_labels[4 * 2 * 2 + 4 * 3] = {
+static void *const get16_labels[4 * 2 * 2 + 4 * 3] = {
&&get16_1_10, /* 8h -> 16h */
&&get16_1_90, /* 8h ^> 16h */
&&get16_1_10, /* 8s -> 16h */
@@ -407,7 +407,7 @@ get16_123_B2_18: sample = (_get_triple_s(src) >> 2) ^ 0x8000; goto GET16_END;
#ifdef PUT16_LABELS
/* dst_wid dst_endswap sign_toggle */
-static void *put16_labels[4 * 2 * 2] = {
+static void *const put16_labels[4 * 2 * 2] = {
&&put16_12_1, /* 16h -> 8h */
&&put16_12_9, /* 16h ^> 8h */
&&put16_12_1, /* 16h -> 8s */
@@ -453,7 +453,7 @@ put16_12_0029: as_u32(dst) = (u_int32_t)bswap_16(sample) ^ 0x80; goto PUT16_END;
#ifdef GET32_LABELS
/* src_wid src_endswap sign_toggle */
-static void *get32_labels[4 * 2 * 2 + 4 * 3] = {
+static void *const get32_labels[4 * 2 * 2 + 4 * 3] = {
&&get32_1_1000, /* 8h -> 32h */
&&get32_1_9000, /* 8h ^> 32h */
&&get32_1_1000, /* 8s -> 32h */
@@ -528,7 +528,7 @@ __conv24_get: goto *put;
#ifdef PUT32_LABELS
/* dst_wid dst_endswap sign_toggle */
-static void *put32_labels[4 * 2 * 2 + 4 * 3] = {
+static void *const put32_labels[4 * 2 * 2 + 4 * 3] = {
&&put32_1234_1, /* 32h -> 8h */
&&put32_1234_9, /* 32h ^> 8h */
&&put32_1234_1, /* 32h -> 8s */
@@ -604,7 +604,7 @@ put32_1234_329_18: _put_triple_s(dst, (sample ^ 0x80000000) >> 14); goto PUT32_E
#ifdef GETU_LABELS
/* width endswap sign_toggle */
-static void *getu_labels[4 * 2 * 2] = {
+static void *const getu_labels[4 * 2 * 2] = {
&&getu_1_1, /* 8h -> 8h */
&&getu_1_9, /* 8h ^> 8h */
&&getu_1_1, /* 8s -> 8h */
@@ -645,7 +645,7 @@ getu_1234_C321: sample = bswap_32(as_u32c(src) ^ 0x80); goto GETU_END;
#ifdef GETS_LABELS
/* width endswap sign_toggle */
-static void *gets_labels[4 * 2 * 2] = {
+static void *const gets_labels[4 * 2 * 2] = {
&&gets_1_1, /* 8h -> 8h */
&&gets_1_9, /* 8h ^> 8h */
&&gets_1_1, /* 8s -> 8h */
@@ -686,7 +686,7 @@ gets_1234_C321: sample = (int32_t)bswap_32(as_s32c(src) ^ 0x80); goto GETS_END;
#ifdef PUT_LABELS
/* width endswap sign_toggle */
-static void *put_labels[4 * 2 * 2] = {
+static void *const put_labels[4 * 2 * 2] = {
&&put_1_1, /* 8h -> 8h */
&&put_1_9, /* 8h ^> 8h */
&&put_1_1, /* 8h -> 8s */
@@ -726,7 +726,7 @@ put_1234_4329: as_u32(dst) = bswap_32(sample) ^ 0x80; goto PUT_END;
#ifdef PUT32F_LABELS
/* type (0 = float, 1 = float64), endswap */
-static void *put32float_labels[2 * 2] = {
+static void *const put32float_labels[2 * 2] = {
&&put32f_1234_1234F, /* 32h -> (float)h */
&&put32f_1234_4321F, /* 32h -> (float)s */
&&put32f_1234_1234D, /* 32h -> (float64)h */
@@ -745,7 +745,7 @@ put32f_1234_4321D: tmp_double.d = (double_t)((int32_t)sample) / (double_t)0x8000
#ifdef GET32F_LABELS
/* type (0 = float, 1 = float64), endswap */
-static void *get32float_labels[2 * 2] = {
+static void *const get32float_labels[2 * 2] = {
&&get32f_1234F_1234, /* (float)h -> 32h */
&&get32f_4321F_1234, /* (float)s -> 32h */
&&get32f_1234D_1234, /* (float64)h -> 32h */
@@ -924,7 +924,7 @@ static inline void _norms(const void *src, void *dst,
}
/* src_wid dst_sign dst_wid dst_end */
-static void *norms_labels[4 * 2 * 4 * 2] = {
+static void *const norms_labels[4 * 2 * 4 * 2] = {
&&norms_8_u8, /* s8 -> u8 */
&&norms_8_u8, /* s8 -> u8 */
&&norms_8_u16h, /* s8 -> u16h */
diff --git a/src/pcm/scopes/Makefile.in b/src/pcm/scopes/Makefile.in
index a7d1b5a..b0fd144 100644
--- a/src/pcm/scopes/Makefile.in
+++ b/src/pcm/scopes/Makefile.in
@@ -35,7 +35,6 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-target_triplet = @target@
subdir = src/pcm/scopes
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -275,11 +274,7 @@ psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
-target = @target@
target_alias = @target_alias@
-target_cpu = @target_cpu@
-target_os = @target_os@
-target_vendor = @target_vendor@
AM_CFLAGS = -g -O2 -W -Wall
pkglib_LTLIBRARIES = scope-level.la
scope_level_la_SOURCES = level.c