Most of PCM API functions have snd_pcm_lock()/unlock() wraps for the
actual calls of ops, and some plugins try to unlock/relock internally
for the given PCM object. This, unfortunately, causes a problem in
some configurations and leads to the unexpected behavior or deadlock.
The main problem is that we call snd_pcm_lock() with the given PCM
object, while calling the ops with pcm->op_arg or pcm->fast_op_arg as
the slave PCM object. Meanwhile the plugin code assumes that the
passed PCM object is already locked, and calls snd_pcm_unlock().
This bug doesn't hit always because in most cases pcm->op_arg and
fast_op_arg are identical with pcm itself. But in some configurations
they have different values, so the problem surfaces.
This patch is an attempt to resolve these inconsistencies. It
replaces most of snd_pcm_lock()/unlock() calls with either pcm->op_arg
or pcm->fast_op_arg, depending on the call pattern, so that the plugin
code can safely run snd_pcm_unlock() to the given PCM object.
Fixes: 54931e5a54 ("pcm: Add thread-safety to PCM API")
Reported-by: Ben Russell <thematrixeatsyou@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
snd_pcm_set_chmap() leaks the memory returned from snd_pcm_get_chmap()
without releasing. Add the missing free() call as well as a slight
code refactoring.
Reported-by: Conrad Jones
BugLink: https://github.com/alsa-project/alsa-lib/pull/11
Fixes: d20e24e5d1 ("chmap: Always succeed setting the map to what it already is")
Signed-off-by: Takashi Iwai <tiwai@suse.de>
allow opening the device and start the audio clock without blocking
any channel
this is required if the audio clock has to be available all the time,
even when application is not streaming audio data
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
function is allowed to continue until it checks for error variable, as to
not conflict with original implementation flow
for simple functions involving only one line, return error immediately in
case callback is NULL
Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
previously errno would be returned even for cases where it may have
not been populated, for example one of the write functions failing,
or writing only partial buffer,
now progress through write operations separately and report errno when
appropriate
Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
Reviewed-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
previously, in case of failed write to output file, error is returned
from snd_pcm_writei/read APIs, user could run pcm_drain as fallback and
encounter an assert, since drain would try to write remaining file
buffer to a file
if failed to write to output file in first place, it makes sense to clear
current internal pmc_file file buffer variables
Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
Reviewed-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
EPIPE is defined as XRUN which is not entirely correct in this condition
failing to write to a file in pcm_file plugin can not be simply recovered
by a retry as user of the api might be led to believe when receiving EPIPE
use EIO instead to indicate a different kid of error that may not be
recoverable by retry
Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
Reviewed-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
snd_pcm_file_add_frames called two times by mistake, introduced in
2a800c0c4f
Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
when writing to output file fails, api user is notified and can handle
recovery
Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
Reviewed-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
previously playback could be interrupted by snd_pcm_file_add_frames:
assert(file->wbuf_used_bytes < file->wbuf_size_bytes)
in case snd_pcm_file_write_bytes fails to write full amount of bytes
to file, variable wbuf_used_bytes would not be fully decremented by
requested amount of bytes function was called with
for the assert to trigger, multiple write fails need to happen, so
that wbuf_used_bytes overflows wbuf_size_bytes,
this patch will allow application to report error code to api user
who might have an idea how to recover, before assert is triggered,
also reporting error along with the print out message might give user
a better idea of what is going on, where previously reason for
mentioned assert was not immediately clear
Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
Reviewed-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
The pointer operand to the binary `+` operator must be to a complete
object type.
Signed-off-by: Michael Forney <mforney@mforney.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
A return statement with an expression in a function returning void is
a constraint violation.
Signed-off-by: Michael Forney <mforney@mforney.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
They are equivalent, but __func__ is in C99. __FUNCTION__ exists only
for backwards compatibility with old gcc versions.
Signed-off-by: Michael Forney <mforney@mforney.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
mmap_begin callback is used to copy data from input file to mmaped
buffer
guard for corner use of api (multiple mmap_begin calls by user) is
introduced to check if next continuous buffer was already overwritten
buffer is overwritten with input file data only in case of stream capture
Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
Reviewed-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
main motivation for adding the callback is to use it to enable operation
on mmaped buffer before user access for pcm_file plugin
support for MMAP read access with masking by data from input file is not
implemented for pcm_file plugin, by adding this callback implementing
such feature can be done by rewriting next continuous portion of buffer
on each mmap_begin call
plugins like softvol use pcm_plugin interface and overwrite the buffer by
looping around it in avail_update callback, this patch hopes to simplify
the task by adding new api callback, removing the need for rewriting
pcm_file (to use pcm_plugin callbacks) and careful checking when looping
around whole mmaped buffer
Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
Reviewed-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
use previously introduced helper function, this commit unifies behavior
of readi and readn
corner case behavior of readi is changed by this commit, previously,
in case 0 bytes were red from file (EOF), frames = 0 was returned,
signaling api user as if no data was red from slave, after the patch,
amount of frames red from slave with data red from slave stored in buffer
is returned when EOF is reached
Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
Reviewed-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
add helper function to copy input file data to buffer mapped by areas,
in case of an error, do not fill the areas, allowing device read buffer
to be provided to api caller
previously unused rbuf variable is reused for this purpose
Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
Reviewed-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This change adapt the fix commit 6b058fda9d
("pcm: dmix: Add option to allow alignment of slave pointers")
for dsnoop plugin
Issue is that snd_pcm_wait() goes back to waiting because the hw_ptr
is not period aligned. Therefore snd_pcm_wait() will block for a longer
time as required.
With these rcar driver changes the exact position of the dma is returned.
During snd_pcm_start they read hw_ptr as reference, and this hw_ptr
is now not period aligned, and is a little ahead over the period while it
is read. Therefore when the avail is calculated during snd_pcm_wait(),
it is missing the avail_min by a few frames.
An additional option hw_ptr_alignment is provided to dsnoop configuration,
to allow the user to configure the slave application and hw pointer
alignment at startup
Signed-off-by: Vanitha Channaiah <vanitha.channaiah@in.bosch.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This change adapt the fix commit 6b058fda9d
("pcm: dmix: Add option to allow alignment of slave pointers")
for dshare plugin
Issue is that snd_pcm_wait() goes back to waiting because the hw_ptr
is not period aligned. Therefore snd_pcm_wait() will block for a longer
time as required.
With these rcar driver changes the exact position of the dma is returned.
During snd_pcm_start they read hw_ptr as reference, and this hw_ptr
is now not period aligned, and is a little ahead over the period while it
is read. Therefore when the avail is calculated during snd_pcm_wait(),
it is missing the avail_min by a few frames.
An additional option hw_ptr_alignment is provided to dshare configuration,
to allow the user to configure the slave application and hw pointer
alignment at startup
Signed-off-by: Vanitha Channaiah <vanitha.channaiah@in.bosch.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Move the code snd_pcm_direct_reset_slave_ptr() from pcm_dmix.c
to pcm_direct.c and its header so that the helper function can be
re-used by other direct-pcm plugins.
There is no change in the behavior or the functionality.
Signed-off-by: Vanitha Channaiah <vanitha.channaiah@in.bosch.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Unfortunately, the master_slave buffer pointers are not always in sync with
the presented avail value and the higher layers (like write_areas) got
confused. Create own hw_ptr and appl_ptr.
This commit also tries to fix the hwsync and delay implementation (iterate
through all slaves).
The multi plugin was designed only for hardware which runs really in sync.
Anyway, users are trying to use this plugin for other purposes.
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
The hw_ptr might be updated during the snd_pcm_may_wait_for_avail_min() call,
so even if it returns zero (OK), the avail must be updated again.
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
All slaves should be asked to wait otherwise the write loop might
be interrupted and zero frames might be returned.
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Some applications do not expect that get_period_size_min() could
return 0. Therefore these applications cannot use the null plugin without
this patch.
Due to there is no use case for having a period size of 0 this patch
disallows a period size of 0 when using the null plugin.
Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
In snd_pcm_dshare_sync_area() when 'slave_hw_ptr' rolls over
'slave_boundary', the wrong variable is checked ('dshare->slave_hw_ptr' vs
the local 'slave_hw_ptr'). In some cases, this results in 'slave_hw_ptr'
not rolling over correctly. 'slave_size' and 'size' are then much too
large, and the for loop blocks for several minutes copying samples.
This was likely only triggered on 32-bit systems, since the PCM boundary
is computed based on LONG_MAX and is much larger on 64-bit systems.
This same change was made to pcm_dmix in commit
6c7f60f7a9 ("Fix boundary overlap”) from
June 2005.
Signed-off-by: Brendan Shanks <brendan.shanks@teradek.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
snd_pcm_hw_sw_params() in pcm_hw.c tries to abuse the reserved bits
for passing period_Event flag. In this hackish way, we clear the
reserved bits at beginning, and restore before returning. However,
the code paths that return earlier don't restore the value, hence when
user calls this function twice, it may pass an unexpected value.
This patch fixes the failure, restoring the value always before
returning from the function.
Reported-by: Jamey Sharp <jamey@minilop.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
The recent change to support the drain via polling caused a regression
for pulse plugin; with speaker-test -c2 -twav with pulse, it leads to
either no sounds or stall.
The only sensible behavior change in the commit wrt pulse plugin is
that now it starts the stream before calling drain callback. This
supposed to be correct, but it seems hitting a pulse plugin bug.
The start before drain callback is only a matter of consistency, and
since this doesn't work for the single existing plugin using drain
callback, we don't need to stick with this behavior.
For addressing the regression, we check the presence of the drain
callback and start the stream only when it doesn't exist, i.e. only in
drain-via-poll mode.
Fixes: ce2095c41f ("pcm: ioplug: Implement proper drain behavior")
Reported-by: Diego Viola <diego.viola@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Without this patch it is not possible to link the channel and format
parameter if snd_pcm_extplug_set_param_*() or
snd_pcm_extplug_set_slave_param_*() is called. Therefore the client and
slave parameter can differ. So the extplug has to implement conversion.
To avoid this the new snd_pcm_extplug_set_param_link() function can be
called.
As a reproduction sceanrio the following extplug source code can be used:
===
static snd_pcm_sframes_t my_transfer(snd_pcm_extplug_t *e,
const snd_pcm_channel_area_t *da, snd_pcm_uframes_t dof,
const snd_pcm_channel_area_t *sa, snd_pcm_uframes_t sof,
snd_pcm_uframes_t s) {
return s;
}
static const snd_pcm_extplug_callback_t my_own_callback = {
.transfer = my_transfer
};
SND_PCM_PLUGIN_DEFINE_FUNC(my_plug) {
snd_config_iterator_t i, next;
snd_config_t *slave = NULL;
snd_pcm_extplug_t *myplug;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id;
if (snd_config_get_id(n, &id) < 0)
continue;
if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0)
continue;
if (strcmp(id, "slave") == 0) {
slave = n;
continue;
}
return -EINVAL;
}
myplug = calloc(1, sizeof(*myplug));
myplug->version = SND_PCM_EXTPLUG_VERSION;
myplug->callback = &my_own_callback;
snd_pcm_extplug_create(myplug, name, root, slave, stream, mode);
snd_pcm_extplug_set_param_minmax(myplug,
SND_PCM_EXTPLUG_HW_CHANNELS, 1, 16);
// snd_pcm_extplug_set_param_link(myplug, SND_PCM_EXTPLUG_HW_CHANNELS, 1);
*pcmp = myplug->pcm;
return 0;
}
SND_PCM_PLUGIN_SYMBOL(my_plug);
===
To use this plugin the following ALSA configuration is required:
pcm.myplug {
type my_plug
slave.pcm hw:Dummy
}
With this configuration without this patch
snd_pcm_hw_params_get_channels_max() will always return 16 channels
independent of the supported channels of the dummy device. Due to that for
example the start up of JACK would fail:
$ modprobe snd_dummy
$ jackd -d alsa -P myplug
ALSA: cannot set channel count to 16 for playback
ALSA: cannot configure playback channel
Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Configuration to reproduce:
~~~~
pcm.share_right {
type dshare
ipc_key 73
ipc_perm 0666
slave {
pcm "hw:0,0"
}
bindings {
# the seagfault happens when we don't bind channel 0
1 1
}
}
~~~~
Execute to reproduce:
~~~~
$ aplay -D plug:share_right test.wav
Playing WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
Segmentation fault
~~~~
For channels whithout binding, values are set to UINT_MAX in function
`snd_pcm_direct_parse_bindings()`:
~~~~
for (chn = 0; chn < count; chn++)
bindings[chn] = UINT_MAX; /* don't route */
~~~~
But, these values are not checked when playing, which causes the segfault.
This commit fixes the issue.
Signed-off-by: Kirill Marinushkin <kmarinushkin@birdec.tech>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
These changes are required due to the kernel
commit 07b7acb51d283d8469696c906b91f1882696a4d4
("ASoC: rsnd: update pointer more accurate")
Issue is that snd_pcm_wait() goes back to waiting because the hw_ptr
is not period aligned. Therefore snd_pcm_wait() will block for a longer
time as required.
With these rcar driver changes the exact position of the dma is returned.
During snd_pcm_start they read hw_ptr as reference, and this hw_ptr
is now not period aligned, and is a little ahead over the period while it
is read. Therefore when the avail is calculated during snd_pcm_wait(),
it is missing the avail_min by a few frames.
An additional option hw_ptr_alignment is provided to dmix configuration,
to allow the user to configure the slave application and hw pointer
alignment at startup
[ Slight indentation and parentheses removals by tiwai ]
Signed-off-by: Laxmi Devi <Laxmi.Devi@in.bosch.com>
Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Without this change an interval of (x x+1] will be interpreted as an
empty interval but the right value would be x+1.
This leads to a failing snd_pcm_hw_params() call which returns -EINVAL.
An example issue log is given in the following:
snd_pcm_hw_params failed with err -22 (Invalid argument)
ACCESS: MMAP_NONINTERLEAVED
FORMAT: S16_LE
SUBFORMAT: STD
SAMPLE_BITS: 16
FRAME_BITS: 16
CHANNELS: 1
RATE: 16000
PERIOD_TIME: (15999 16000]
PERIOD_SIZE: (255 256]
PERIOD_BYTES: (510 512]
PERIODS: [2 3)
BUFFER_TIME: 32000
BUFFER_SIZE: 512
BUFFER_BYTES: 1024
In case of (x x+1) we have to interpret it anyway as a single value of x to
compensate rounding issues.
For example the period size will result in an interval of (352 353) when
the period time is 16ms and the sample rate 22050 Hz
(16ms * 22,05 kHz = 352,8 frames). But 352 has to be chosen to allow a
buffer size of 705 (32ms * 22,05 kHz = 705,6 frames) which has to be >= 2x
period size to avoid Xruns. The buffer size will not end up with an
interval of (705 706) simular to the period size because
snd_pcm_rate_hw_refine_cchange() calls snd_interval_floor() for the buffer
size. Therefore this value will be interpreted as an integer interval
instead of a real interval further on.
This issue seems to exist since the change of 9bb985c38 ("pcm:
snd_interval_refine_first/last: exclude value only if also excluded
before")
Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
The snd_pcm_mmap_begin() call returns the amount of contiguous data,
which is less than the total available if it wraps around the buffer
boundary.
If we don't handle this split we leave stale data in the buffer that
should have been overwritten, as well as unread data in the io_plugin
that gets transferred on a subsequent call at the wrong offset.
Signed-off-by: Rob Duncan <rduncan@teslamotors.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Without these changes a negative error code returned by
snd_pcm_avail_update() will be not handled correctly.
With this patch the returned error code of snd_pcm_avail_update() will be
returned by snd_pcm_rate_avail_update().
Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This function can be called without calling snd_pcm_avail_update().
The call to snd_pcm_avail_update() can take some time.
Therefore some developers would not like to call it from a real-time
context (e.g. from JACK client context).
Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>