|
Packit Service |
db8eaa |
/**
|
|
Packit Service |
db8eaa |
* \file pcm/pcm_plugin.c
|
|
Packit Service |
db8eaa |
* \ingroup PCM
|
|
Packit Service |
db8eaa |
* \brief PCM Interface
|
|
Packit Service |
db8eaa |
* \author Jaroslav Kysela <perex@perex.cz>
|
|
Packit Service |
db8eaa |
* \author Abramo Bagnara <abramo@alsa-project.org>
|
|
Packit Service |
db8eaa |
* \date 2000-2001
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
/*
|
|
Packit Service |
db8eaa |
* PCM - Common plugin code
|
|
Packit Service |
db8eaa |
* Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
|
|
Packit Service |
db8eaa |
*
|
|
Packit Service |
db8eaa |
*
|
|
Packit Service |
db8eaa |
* This library is free software; you can redistribute it and/or modify
|
|
Packit Service |
db8eaa |
* it under the terms of the GNU Lesser General Public License as
|
|
Packit Service |
db8eaa |
* published by the Free Software Foundation; either version 2.1 of
|
|
Packit Service |
db8eaa |
* the License, or (at your option) any later version.
|
|
Packit Service |
db8eaa |
*
|
|
Packit Service |
db8eaa |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
db8eaa |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
db8eaa |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
db8eaa |
* GNU Lesser General Public License for more details.
|
|
Packit Service |
db8eaa |
*
|
|
Packit Service |
db8eaa |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit Service |
db8eaa |
* License along with this library; if not, write to the Free Software
|
|
Packit Service |
db8eaa |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit Service |
db8eaa |
*
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/*!
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
\page pcm_plugins PCM (digital audio) plugins
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
PCM plugins extends functionality and features of PCM devices.
|
|
Packit Service |
db8eaa |
The plugins take care about various sample conversions, sample
|
|
Packit Service |
db8eaa |
copying among channels and so on.
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
\section pcm_plugins_slave Slave definition
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
The slave plugin can be specified directly with a string or the definition
|
|
Packit Service |
db8eaa |
can be entered inside a compound configuration node. Some restrictions can
|
|
Packit Service |
db8eaa |
be also specified (like static rate or count of channels).
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
\code
|
|
Packit Service |
db8eaa |
pcm_slave.NAME {
|
|
Packit Service |
db8eaa |
pcm STR # PCM name
|
|
Packit Service |
db8eaa |
# or
|
|
Packit Service |
db8eaa |
pcm { } # PCM definition
|
|
Packit Service |
db8eaa |
format STR # Format or "unchanged"
|
|
Packit Service |
db8eaa |
channels INT # Count of channels or "unchanged" string
|
|
Packit Service |
db8eaa |
rate INT # Rate in Hz or "unchanged" string
|
|
Packit Service |
db8eaa |
period_time INT # Period time in us or "unchanged" string
|
|
Packit Service |
db8eaa |
buffer_time INT # Buffer time in us or "unchanged" string
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
\endcode
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
Example:
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
\code
|
|
Packit Service |
db8eaa |
pcm_slave.slave_rate44100Hz {
|
|
Packit Service |
db8eaa |
pcm "hw:0,0"
|
|
Packit Service |
db8eaa |
rate 44100
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
pcm.rate44100Hz {
|
|
Packit Service |
db8eaa |
type plug
|
|
Packit Service |
db8eaa |
slave slave_rate44100Hz
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
\endcode
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
The equivalent configuration (in one compound):
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
\code
|
|
Packit Service |
db8eaa |
pcm.rate44100Hz {
|
|
Packit Service |
db8eaa |
type plug
|
|
Packit Service |
db8eaa |
slave {
|
|
Packit Service |
db8eaa |
pcm "hw:0,0"
|
|
Packit Service |
db8eaa |
rate 44100
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
\endcode
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#include <limits.h>
|
|
Packit Service |
db8eaa |
#include "pcm_local.h"
|
|
Packit Service |
db8eaa |
#include "pcm_plugin.h"
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#ifndef DOC_HIDDEN
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static snd_pcm_sframes_t
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_undo_read(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
const snd_pcm_channel_area_t *res_areas ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t res_offset ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t res_size ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t slave_undo_size ATTRIBUTE_UNUSED)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
return -EIO;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static snd_pcm_sframes_t
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_undo_write(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
const snd_pcm_channel_area_t *res_areas ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t res_offset ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t res_size ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t slave_undo_size ATTRIBUTE_UNUSED)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
return -EIO;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_undo_read_generic(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
const snd_pcm_channel_area_t *res_areas ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t res_offset ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t res_size ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t slave_undo_size)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
return slave_undo_size;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_undo_write_generic(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
const snd_pcm_channel_area_t *res_areas ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t res_offset ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t res_size ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t slave_undo_size)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
return slave_undo_size;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
void snd_pcm_plugin_init(snd_pcm_plugin_t *plugin)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
memset(plugin, 0, sizeof(snd_pcm_plugin_t));
|
|
Packit Service |
db8eaa |
plugin->undo_read = snd_pcm_plugin_undo_read;
|
|
Packit Service |
db8eaa |
plugin->undo_write = snd_pcm_plugin_undo_write;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_t *plugin = pcm->private_data;
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t sd;
|
|
Packit Service |
db8eaa |
int err = snd_pcm_delay(plugin->gen.slave, &sd);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
45dc4a |
if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
|
|
Packit Service |
45dc4a |
pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
|
|
Packit Service |
45dc4a |
pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
|
|
Packit Service |
45dc4a |
sd += snd_pcm_mmap_capture_avail(pcm);
|
|
Packit Service |
45dc4a |
}
|
|
Packit Service |
45dc4a |
|
|
Packit Service |
db8eaa |
*delayp = sd;
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static int snd_pcm_plugin_prepare(snd_pcm_t *pcm)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_t *plugin = pcm->private_data;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
err = snd_pcm_prepare(plugin->gen.slave);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
*pcm->hw.ptr = 0;
|
|
Packit Service |
db8eaa |
*pcm->appl.ptr = 0;
|
|
Packit Service |
db8eaa |
if (plugin->init) {
|
|
Packit Service |
db8eaa |
err = plugin->init(pcm);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static int snd_pcm_plugin_reset(snd_pcm_t *pcm)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_t *plugin = pcm->private_data;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
err = snd_pcm_reset(plugin->gen.slave);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
*pcm->hw.ptr = 0;
|
|
Packit Service |
db8eaa |
*pcm->appl.ptr = 0;
|
|
Packit Service |
db8eaa |
if (plugin->init) {
|
|
Packit Service |
db8eaa |
err = plugin->init(pcm);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static snd_pcm_sframes_t snd_pcm_plugin_rewindable(snd_pcm_t *pcm)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
return snd_pcm_mmap_hw_rewindable(pcm);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_t *plugin = pcm->private_data;
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t n = snd_pcm_plugin_rewindable(pcm);
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t sframes;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
if ((snd_pcm_uframes_t)n < frames)
|
|
Packit Service |
db8eaa |
frames = n;
|
|
Packit Service |
db8eaa |
if (frames == 0)
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
sframes = frames;
|
|
Packit Service |
db8eaa |
sframes = snd_pcm_rewind(plugin->gen.slave, sframes);
|
|
Packit Service |
db8eaa |
if (sframes < 0)
|
|
Packit Service |
db8eaa |
return sframes;
|
|
Packit Service |
db8eaa |
snd_pcm_mmap_appl_backward(pcm, (snd_pcm_uframes_t) sframes);
|
|
Packit Service |
db8eaa |
return (snd_pcm_sframes_t) sframes;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static snd_pcm_sframes_t snd_pcm_plugin_forwardable(snd_pcm_t *pcm)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
return snd_pcm_mmap_avail(pcm);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_t *plugin = pcm->private_data;
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t n = snd_pcm_plugin_forwardable(pcm);
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t sframes;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
if ((snd_pcm_uframes_t)n < frames)
|
|
Packit Service |
db8eaa |
frames = n;
|
|
Packit Service |
db8eaa |
if (frames == 0)
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
sframes = frames;
|
|
Packit Service |
db8eaa |
sframes = INTERNAL(snd_pcm_forward)(plugin->gen.slave, sframes);
|
|
Packit Service |
db8eaa |
if (sframes < 0)
|
|
Packit Service |
db8eaa |
return sframes;
|
|
Packit Service |
db8eaa |
snd_pcm_mmap_appl_forward(pcm, (snd_pcm_uframes_t) frames);
|
|
Packit Service |
db8eaa |
return (snd_pcm_sframes_t) frames;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
const snd_pcm_channel_area_t *areas,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t offset,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t size)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_t *plugin = pcm->private_data;
|
|
Packit Service |
db8eaa |
snd_pcm_t *slave = plugin->gen.slave;
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t xfer = 0;
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t result;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
while (size > 0) {
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t frames = size;
|
|
Packit Service |
db8eaa |
const snd_pcm_channel_area_t *slave_areas;
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t slave_offset;
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t slave_frames = ULONG_MAX;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
|
|
Packit Service |
db8eaa |
if (result < 0) {
|
|
Packit Service |
db8eaa |
err = result;
|
|
Packit Service |
db8eaa |
goto error;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (slave_frames == 0)
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
frames = plugin->write(pcm, areas, offset, frames,
|
|
Packit Service |
db8eaa |
slave_areas, slave_offset, &slave_frames);
|
|
Packit Service |
db8eaa |
if (CHECK_SANITY(slave_frames > snd_pcm_mmap_playback_avail(slave))) {
|
|
Packit Service |
db8eaa |
SNDMSG("write overflow %ld > %ld", slave_frames,
|
|
Packit Service |
db8eaa |
snd_pcm_mmap_playback_avail(slave));
|
|
Packit Service |
db8eaa |
err = -EPIPE;
|
|
Packit Service |
db8eaa |
goto error;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
|
|
Packit Service |
db8eaa |
if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t res;
|
|
Packit Service |
db8eaa |
res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result);
|
|
Packit Service |
db8eaa |
if (res < 0) {
|
|
Packit Service |
db8eaa |
err = res;
|
|
Packit Service |
db8eaa |
goto error;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
frames -= res;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (result <= 0) {
|
|
Packit Service |
db8eaa |
err = result;
|
|
Packit Service |
db8eaa |
goto error;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
snd_pcm_mmap_appl_forward(pcm, frames);
|
|
Packit Service |
db8eaa |
offset += frames;
|
|
Packit Service |
db8eaa |
xfer += frames;
|
|
Packit Service |
db8eaa |
size -= frames;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return (snd_pcm_sframes_t)xfer;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
error:
|
|
Packit Service |
db8eaa |
return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
const snd_pcm_channel_area_t *areas,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t offset,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t size)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_t *plugin = pcm->private_data;
|
|
Packit Service |
db8eaa |
snd_pcm_t *slave = plugin->gen.slave;
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t xfer = 0;
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t result;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
while (size > 0) {
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t frames = size;
|
|
Packit Service |
db8eaa |
const snd_pcm_channel_area_t *slave_areas;
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t slave_offset;
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t slave_frames = ULONG_MAX;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
|
|
Packit Service |
db8eaa |
if (result < 0) {
|
|
Packit Service |
db8eaa |
err = result;
|
|
Packit Service |
db8eaa |
goto error;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (slave_frames == 0)
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
frames = (plugin->read)(pcm, areas, offset, frames,
|
|
Packit Service |
db8eaa |
slave_areas, slave_offset, &slave_frames);
|
|
Packit Service |
db8eaa |
if (CHECK_SANITY(slave_frames > snd_pcm_mmap_capture_avail(slave))) {
|
|
Packit Service |
db8eaa |
SNDMSG("read overflow %ld > %ld", slave_frames,
|
|
Packit Service |
db8eaa |
snd_pcm_mmap_playback_avail(slave));
|
|
Packit Service |
db8eaa |
err = -EPIPE;
|
|
Packit Service |
db8eaa |
goto error;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
|
|
Packit Service |
db8eaa |
if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t res;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
res = plugin->undo_read(slave, areas, offset, frames, slave_frames - result);
|
|
Packit Service |
db8eaa |
if (res < 0) {
|
|
Packit Service |
db8eaa |
err = res;
|
|
Packit Service |
db8eaa |
goto error;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
frames -= res;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (result <= 0) {
|
|
Packit Service |
db8eaa |
err = result;
|
|
Packit Service |
db8eaa |
goto error;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
snd_pcm_mmap_appl_forward(pcm, frames);
|
|
Packit Service |
db8eaa |
offset += frames;
|
|
Packit Service |
db8eaa |
xfer += frames;
|
|
Packit Service |
db8eaa |
size -= frames;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return (snd_pcm_sframes_t)xfer;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
error:
|
|
Packit Service |
db8eaa |
return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static snd_pcm_sframes_t
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_channel_area_t areas[pcm->channels];
|
|
Packit Service |
db8eaa |
snd_pcm_areas_from_buf(pcm, areas, (void*)buffer);
|
|
Packit Service |
db8eaa |
return snd_pcm_write_areas(pcm, areas, 0, size,
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_write_areas);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static snd_pcm_sframes_t
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_channel_area_t areas[pcm->channels];
|
|
Packit Service |
db8eaa |
snd_pcm_areas_from_bufs(pcm, areas, bufs);
|
|
Packit Service |
db8eaa |
return snd_pcm_write_areas(pcm, areas, 0, size,
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_write_areas);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static snd_pcm_sframes_t
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_channel_area_t areas[pcm->channels];
|
|
Packit Service |
db8eaa |
snd_pcm_areas_from_buf(pcm, areas, buffer);
|
|
Packit Service |
db8eaa |
return snd_pcm_read_areas(pcm, areas, 0, size,
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_read_areas);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static snd_pcm_sframes_t
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_channel_area_t areas[pcm->channels];
|
|
Packit Service |
db8eaa |
snd_pcm_areas_from_bufs(pcm, areas, bufs);
|
|
Packit Service |
db8eaa |
return snd_pcm_read_areas(pcm, areas, 0, size,
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_read_areas);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static snd_pcm_sframes_t
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t size)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_t *plugin = pcm->private_data;
|
|
Packit Service |
db8eaa |
snd_pcm_t *slave = plugin->gen.slave;
|
|
Packit Service |
db8eaa |
const snd_pcm_channel_area_t *areas;
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t appl_offset;
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t slave_size;
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t xfer;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
|
|
Packit Service |
db8eaa |
snd_pcm_mmap_appl_forward(pcm, size);
|
|
Packit Service |
db8eaa |
return size;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
slave_size = snd_pcm_avail_update(slave);
|
|
Packit Service |
db8eaa |
if (slave_size < 0)
|
|
Packit Service |
db8eaa |
return slave_size;
|
|
Packit Service |
db8eaa |
areas = snd_pcm_mmap_areas(pcm);
|
|
Packit Service |
db8eaa |
appl_offset = snd_pcm_mmap_offset(pcm);
|
|
Packit Service |
db8eaa |
xfer = 0;
|
|
Packit Service |
db8eaa |
while (size > 0 && slave_size > 0) {
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t frames = size;
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t cont = pcm->buffer_size - appl_offset;
|
|
Packit Service |
db8eaa |
const snd_pcm_channel_area_t *slave_areas;
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t slave_offset;
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t slave_frames = ULONG_MAX;
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t result;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
|
|
Packit Service |
db8eaa |
if (result < 0) {
|
|
Packit Service |
db8eaa |
err = result;
|
|
Packit Service |
db8eaa |
goto error;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (frames > cont)
|
|
Packit Service |
db8eaa |
frames = cont;
|
|
Packit Service |
db8eaa |
frames = plugin->write(pcm, areas, appl_offset, frames,
|
|
Packit Service |
db8eaa |
slave_areas, slave_offset, &slave_frames);
|
|
Packit Service |
db8eaa |
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
|
|
Packit Service |
db8eaa |
if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t res;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
res = plugin->undo_write(pcm, slave_areas, slave_offset + result, slave_frames, slave_frames - result);
|
|
Packit Service |
db8eaa |
if (res < 0) {
|
|
Packit Service |
db8eaa |
err = res;
|
|
Packit Service |
db8eaa |
goto error;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
frames -= res;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (result <= 0) {
|
|
Packit Service |
db8eaa |
err = result;
|
|
Packit Service |
db8eaa |
goto error;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
snd_pcm_mmap_appl_forward(pcm, frames);
|
|
Packit Service |
db8eaa |
if (frames == cont)
|
|
Packit Service |
db8eaa |
appl_offset = 0;
|
|
Packit Service |
db8eaa |
else
|
|
Packit Service |
db8eaa |
appl_offset += result;
|
|
Packit Service |
db8eaa |
size -= frames;
|
|
Packit Service |
db8eaa |
slave_size -= frames;
|
|
Packit Service |
db8eaa |
xfer += frames;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (CHECK_SANITY(size)) {
|
|
Packit Service |
db8eaa |
SNDMSG("short commit: %ld", size);
|
|
Packit Service |
db8eaa |
return -EPIPE;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return xfer;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
error:
|
|
Packit Service |
db8eaa |
return xfer > 0 ? xfer : err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
45dc4a |
static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_t *plugin = pcm->private_data;
|
|
Packit Service |
db8eaa |
snd_pcm_t *slave = plugin->gen.slave;
|
|
Packit Service |
45dc4a |
snd_pcm_sframes_t slave_size;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
45dc4a |
slave_size = snd_pcm_avail_update(slave);
|
|
Packit Service |
db8eaa |
if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
|
|
Packit Service |
db8eaa |
pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
|
|
Packit Service |
db8eaa |
pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED)
|
|
Packit Service |
45dc4a |
goto _capture;
|
|
Packit Service |
45dc4a |
*pcm->hw.ptr = *slave->hw.ptr;
|
|
Packit Service |
db8eaa |
return slave_size;
|
|
Packit Service |
45dc4a |
_capture:
|
|
Packit Service |
45dc4a |
{
|
|
Packit Service |
45dc4a |
const snd_pcm_channel_area_t *areas;
|
|
Packit Service |
45dc4a |
snd_pcm_uframes_t xfer, hw_offset, size;
|
|
Packit Service |
45dc4a |
|
|
Packit Service |
45dc4a |
xfer = snd_pcm_mmap_capture_avail(pcm);
|
|
Packit Service |
45dc4a |
size = pcm->buffer_size - xfer;
|
|
Packit Service |
45dc4a |
areas = snd_pcm_mmap_areas(pcm);
|
|
Packit Service |
45dc4a |
hw_offset = snd_pcm_mmap_hw_offset(pcm);
|
|
Packit Service |
45dc4a |
while (size > 0 && slave_size > 0) {
|
|
Packit Service |
45dc4a |
snd_pcm_uframes_t frames = size;
|
|
Packit Service |
45dc4a |
snd_pcm_uframes_t cont = pcm->buffer_size - hw_offset;
|
|
Packit Service |
45dc4a |
const snd_pcm_channel_area_t *slave_areas;
|
|
Packit Service |
45dc4a |
snd_pcm_uframes_t slave_offset;
|
|
Packit Service |
45dc4a |
snd_pcm_uframes_t slave_frames = ULONG_MAX;
|
|
Packit Service |
45dc4a |
snd_pcm_sframes_t result;
|
|
Packit Service |
45dc4a |
/* As mentioned in the ALSA API (see pcm/pcm.c:942):
|
|
Packit Service |
45dc4a |
* The function #snd_pcm_avail_update()
|
|
Packit Service |
45dc4a |
* have to be called before any mmap begin+commit operation.
|
|
Packit Service |
45dc4a |
* Otherwise the snd_pcm_areas_copy will not called a second time.
|
|
Packit Service |
45dc4a |
* But this is needed, if the ring buffer wrap is reached and
|
|
Packit Service |
45dc4a |
* there is more data available.
|
|
Packit Service |
45dc4a |
*/
|
|
Packit Service |
45dc4a |
slave_size = snd_pcm_avail_update(slave);
|
|
Packit Service |
45dc4a |
result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
|
|
Packit Service |
45dc4a |
if (result < 0) {
|
|
Packit Service |
45dc4a |
err = result;
|
|
Packit Service |
45dc4a |
goto error;
|
|
Packit Service |
45dc4a |
}
|
|
Packit Service |
45dc4a |
if (frames > cont)
|
|
Packit Service |
45dc4a |
frames = cont;
|
|
Packit Service |
45dc4a |
frames = (plugin->read)(pcm, areas, hw_offset, frames,
|
|
Packit Service |
45dc4a |
slave_areas, slave_offset, &slave_frames);
|
|
Packit Service |
45dc4a |
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
|
|
Packit Service |
45dc4a |
if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) {
|
|
Packit Service |
45dc4a |
snd_pcm_sframes_t res;
|
|
Packit Service |
45dc4a |
|
|
Packit Service |
45dc4a |
res = plugin->undo_read(slave, areas, hw_offset, frames, slave_frames - result);
|
|
Packit Service |
45dc4a |
if (res < 0) {
|
|
Packit Service |
45dc4a |
err = res;
|
|
Packit Service |
45dc4a |
goto error;
|
|
Packit Service |
45dc4a |
}
|
|
Packit Service |
45dc4a |
frames -= res;
|
|
Packit Service |
45dc4a |
}
|
|
Packit Service |
45dc4a |
if (result <= 0) {
|
|
Packit Service |
45dc4a |
err = result;
|
|
Packit Service |
45dc4a |
goto error;
|
|
Packit Service |
45dc4a |
}
|
|
Packit Service |
45dc4a |
snd_pcm_mmap_hw_forward(pcm, frames);
|
|
Packit Service |
45dc4a |
if (frames == cont)
|
|
Packit Service |
45dc4a |
hw_offset = 0;
|
|
Packit Service |
45dc4a |
else
|
|
Packit Service |
45dc4a |
hw_offset += frames;
|
|
Packit Service |
45dc4a |
size -= frames;
|
|
Packit Service |
45dc4a |
slave_size -= slave_frames;
|
|
Packit Service |
45dc4a |
xfer += frames;
|
|
Packit Service |
45dc4a |
}
|
|
Packit Service |
45dc4a |
return (snd_pcm_sframes_t)xfer;
|
|
Packit Service |
8875a0 |
|
|
Packit Service |
45dc4a |
error:
|
|
Packit Service |
45dc4a |
return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
|
|
Packit Service |
45dc4a |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_t *plugin = pcm->private_data;
|
|
Packit Service |
45dc4a |
snd_pcm_sframes_t err, avail;
|
|
Packit Service |
45dc4a |
|
|
Packit Service |
45dc4a |
/* sync with the latest hw and appl ptrs */
|
|
Packit Service |
45dc4a |
avail = snd_pcm_plugin_avail_update(pcm);
|
|
Packit Service |
45dc4a |
if (avail < 0)
|
|
Packit Service |
45dc4a |
return avail;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
err = snd_pcm_status(plugin->gen.slave, status);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
45dc4a |
status->appl_ptr = *pcm->appl.ptr;
|
|
Packit Service |
45dc4a |
status->hw_ptr = *pcm->hw.ptr;
|
|
Packit Service |
45dc4a |
status->avail = avail;
|
|
Packit Service |
45dc4a |
status->delay = snd_pcm_mmap_delay(pcm);
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_plugin_may_wait_for_avail_min(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t avail)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
|
|
Packit Service |
db8eaa |
pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
|
|
Packit Service |
db8eaa |
pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
|
|
Packit Service |
db8eaa |
/* mmap access on capture device already consumes data from
|
|
Packit Service |
db8eaa |
* slave in avail_update operation. Entering snd_pcm_wait after
|
|
Packit Service |
db8eaa |
* having already consumed some fragments leads to waiting for
|
|
Packit Service |
db8eaa |
* too long time, as slave will unnecessarily wait for avail_min
|
|
Packit Service |
db8eaa |
* condition reached again. To avoid unnecessary wait times we
|
|
Packit Service |
db8eaa |
* adapt the avail_min threshold on slave dynamically. Just
|
|
Packit Service |
db8eaa |
* modifying slave->avail_min as a shortcut and lightweight
|
|
Packit Service |
db8eaa |
* solution does not work for all slave plugin types and in
|
|
Packit Service |
db8eaa |
* addition it will not propagate the change through all
|
|
Packit Service |
db8eaa |
* downstream plugins, so we have to use the sw_params API.
|
|
Packit Service |
db8eaa |
* note: reading fragmental parts from slave will only happen
|
|
Packit Service |
db8eaa |
* in case
|
|
Packit Service |
db8eaa |
* a) the slave can provide contineous hw_ptr between periods
|
|
Packit Service |
db8eaa |
* b) avail_min does not match one slave_period
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
snd_pcm_plugin_t *plugin = pcm->private_data;
|
|
Packit Service |
db8eaa |
snd_pcm_t *slave = plugin->gen.slave;
|
|
Packit Service |
db8eaa |
snd_pcm_uframes_t needed_slave_avail_min;
|
|
Packit Service |
db8eaa |
snd_pcm_sframes_t available;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* update, as it might have changed. This will also call
|
|
Packit Service |
db8eaa |
* avail_update on slave and also can return error
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
available = snd_pcm_avail_update(pcm);
|
|
Packit Service |
db8eaa |
if (available < 0)
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
if ((snd_pcm_uframes_t)available >= pcm->avail_min)
|
|
Packit Service |
db8eaa |
/* don't wait at all. As we can't configure avail_min
|
|
Packit Service |
db8eaa |
* of slave to 0 return here
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
needed_slave_avail_min = pcm->avail_min - available;
|
|
Packit Service |
db8eaa |
if (slave->avail_min != needed_slave_avail_min) {
|
|
Packit Service |
db8eaa |
snd_pcm_sw_params_t *swparams;
|
|
Packit Service |
db8eaa |
snd_pcm_sw_params_alloca(&swparams);
|
|
Packit Service |
db8eaa |
/* pray that changing sw_params while running is
|
|
Packit Service |
db8eaa |
* properly implemented in all downstream plugins...
|
|
Packit Service |
db8eaa |
* it's legal but not commonly used.
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
snd_pcm_sw_params_current(slave, swparams);
|
|
Packit Service |
db8eaa |
/* snd_pcm_sw_params_set_avail_min() restricts setting
|
|
Packit Service |
db8eaa |
* to >= period size. This conflicts at least with our
|
|
Packit Service |
db8eaa |
* dshare patch which allows combining multiple periods
|
|
Packit Service |
db8eaa |
* or with slaves which return hw postions between
|
|
Packit Service |
db8eaa |
* periods -> set directly in sw_param structure
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
swparams->avail_min = needed_slave_avail_min;
|
|
Packit Service |
db8eaa |
snd_pcm_sw_params(slave, swparams);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
avail = available;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return snd_pcm_generic_may_wait_for_avail_min(pcm, avail);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
const snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
|
|
Packit Service |
db8eaa |
.status = snd_pcm_plugin_status,
|
|
Packit Service |
db8eaa |
.state = snd_pcm_generic_state,
|
|
Packit Service |
db8eaa |
.hwsync = snd_pcm_generic_hwsync,
|
|
Packit Service |
db8eaa |
.delay = snd_pcm_plugin_delay,
|
|
Packit Service |
db8eaa |
.prepare = snd_pcm_plugin_prepare,
|
|
Packit Service |
db8eaa |
.reset = snd_pcm_plugin_reset,
|
|
Packit Service |
db8eaa |
.start = snd_pcm_generic_start,
|
|
Packit Service |
db8eaa |
.drop = snd_pcm_generic_drop,
|
|
Packit Service |
db8eaa |
.drain = snd_pcm_generic_drain,
|
|
Packit Service |
db8eaa |
.pause = snd_pcm_generic_pause,
|
|
Packit Service |
db8eaa |
.rewindable = snd_pcm_plugin_rewindable,
|
|
Packit Service |
db8eaa |
.rewind = snd_pcm_plugin_rewind,
|
|
Packit Service |
db8eaa |
.forwardable = snd_pcm_plugin_forwardable,
|
|
Packit Service |
db8eaa |
.forward = snd_pcm_plugin_forward,
|
|
Packit Service |
db8eaa |
.resume = snd_pcm_generic_resume,
|
|
Packit Service |
db8eaa |
.link = snd_pcm_generic_link,
|
|
Packit Service |
db8eaa |
.link_slaves = snd_pcm_generic_link_slaves,
|
|
Packit Service |
db8eaa |
.unlink = snd_pcm_generic_unlink,
|
|
Packit Service |
db8eaa |
.writei = snd_pcm_plugin_writei,
|
|
Packit Service |
db8eaa |
.writen = snd_pcm_plugin_writen,
|
|
Packit Service |
db8eaa |
.readi = snd_pcm_plugin_readi,
|
|
Packit Service |
db8eaa |
.readn = snd_pcm_plugin_readn,
|
|
Packit Service |
db8eaa |
.avail_update = snd_pcm_plugin_avail_update,
|
|
Packit Service |
db8eaa |
.mmap_commit = snd_pcm_plugin_mmap_commit,
|
|
Packit Service |
db8eaa |
.htimestamp = snd_pcm_generic_htimestamp,
|
|
Packit Service |
db8eaa |
.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
|
|
Packit Service |
db8eaa |
.poll_descriptors = snd_pcm_generic_poll_descriptors,
|
|
Packit Service |
db8eaa |
.poll_revents = snd_pcm_generic_poll_revents,
|
|
Packit Service |
db8eaa |
.may_wait_for_avail_min = snd_pcm_plugin_may_wait_for_avail_min,
|
|
Packit Service |
db8eaa |
};
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#endif
|