mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-12-16 08:56:42 -05:00
Removed mmap emulation. Updated TODO. Fixed an over rename
This commit is contained in:
parent
f9eacbfc9e
commit
2ff2c87cdb
5 changed files with 21 additions and 328 deletions
1
TODO
1
TODO
|
|
@ -1,5 +1,4 @@
|
||||||
M plug sync and pos problems
|
M plug sync and pos problems
|
||||||
M Loopback implementation?
|
M Loopback implementation?
|
||||||
L complete mmap emulation (after plug sync and pos thought)
|
|
||||||
L add hsearch_r code from glibc (for compatibility with older distributions)
|
L add hsearch_r code from glibc (for compatibility with older distributions)
|
||||||
L move OSS emulation to user space (LD_PRELOAD)
|
L move OSS emulation to user space (LD_PRELOAD)
|
||||||
|
|
|
||||||
|
|
@ -225,34 +225,24 @@ int snd_pcm_stream_status(snd_pcm_t *pcm, snd_pcm_stream_status_t *status)
|
||||||
|
|
||||||
int snd_pcm_stream_update(snd_pcm_t *pcm, int stream)
|
int snd_pcm_stream_update(snd_pcm_t *pcm, int stream)
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
if (!pcm)
|
if (!pcm)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (stream < 0 || stream > 1)
|
if (stream < 0 || stream > 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!pcm->stream[stream].open)
|
if (!pcm->stream[stream].open)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
err = pcm->ops->stream_update(pcm, stream);
|
return pcm->ops->stream_update(pcm, stream);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
snd_pcm_mmap_status_streamge(pcm, stream, -1);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_pcm_stream_prepare(snd_pcm_t *pcm, int stream)
|
int snd_pcm_stream_prepare(snd_pcm_t *pcm, int stream)
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
if (!pcm)
|
if (!pcm)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (stream < 0 || stream > 1)
|
if (stream < 0 || stream > 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!pcm->stream[stream].open)
|
if (!pcm->stream[stream].open)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
err = pcm->ops->stream_prepare(pcm, stream);
|
return pcm->ops->stream_prepare(pcm, stream);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
snd_pcm_mmap_status_streamge(pcm, stream, SND_PCM_STATUS_PREPARED);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_pcm_playback_prepare(snd_pcm_t *pcm)
|
int snd_pcm_playback_prepare(snd_pcm_t *pcm)
|
||||||
|
|
@ -265,24 +255,8 @@ int snd_pcm_capture_prepare(snd_pcm_t *pcm)
|
||||||
return snd_pcm_stream_prepare(pcm, SND_PCM_STREAM_CAPTURE);
|
return snd_pcm_stream_prepare(pcm, SND_PCM_STREAM_CAPTURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mmap_playback_go(snd_pcm_t *pcm, int stream)
|
|
||||||
{
|
|
||||||
struct snd_pcm_stream *str = &pcm->stream[stream];
|
|
||||||
if (str->mmap_control->status != SND_PCM_STATUS_PREPARED)
|
|
||||||
return -EBADFD;
|
|
||||||
if (str->mmap_control->byte_data == 0)
|
|
||||||
return -EIO;
|
|
||||||
str->mmap_control->status = SND_PCM_STATUS_RUNNING;
|
|
||||||
pthread_mutex_lock(&str->mutex);
|
|
||||||
pthread_cond_signal(&str->status_cond);
|
|
||||||
pthread_cond_wait(&str->ready_cond, &str->mutex);
|
|
||||||
pthread_mutex_unlock(&str->mutex);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int snd_pcm_stream_go(snd_pcm_t *pcm, int stream)
|
int snd_pcm_stream_go(snd_pcm_t *pcm, int stream)
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
struct snd_pcm_stream *str;
|
struct snd_pcm_stream *str;
|
||||||
if (!pcm)
|
if (!pcm)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
@ -291,18 +265,7 @@ int snd_pcm_stream_go(snd_pcm_t *pcm, int stream)
|
||||||
str = &pcm->stream[stream];
|
str = &pcm->stream[stream];
|
||||||
if (!str->open)
|
if (!str->open)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
if (stream == SND_PCM_STREAM_PLAYBACK &&
|
return pcm->ops->stream_go(pcm, stream);
|
||||||
str->mmap_data_emulation) {
|
|
||||||
err = mmap_playback_go(pcm, stream);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
err = pcm->ops->stream_go(pcm, stream);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
if (stream == SND_PCM_STREAM_CAPTURE)
|
|
||||||
snd_pcm_mmap_status_streamge(pcm, stream, SND_PCM_STATUS_RUNNING);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_pcm_playback_go(snd_pcm_t *pcm)
|
int snd_pcm_playback_go(snd_pcm_t *pcm)
|
||||||
|
|
@ -317,22 +280,16 @@ int snd_pcm_capture_go(snd_pcm_t *pcm)
|
||||||
|
|
||||||
int snd_pcm_sync_go(snd_pcm_t *pcm, snd_pcm_sync_t *sync)
|
int snd_pcm_sync_go(snd_pcm_t *pcm, snd_pcm_sync_t *sync)
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
if (!pcm || !sync)
|
if (!pcm || !sync)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (!pcm->stream[SND_PCM_STREAM_PLAYBACK].open &&
|
if (!pcm->stream[SND_PCM_STREAM_PLAYBACK].open &&
|
||||||
!pcm->stream[SND_PCM_STREAM_CAPTURE].open)
|
!pcm->stream[SND_PCM_STREAM_CAPTURE].open)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
err = pcm->ops->sync_go(pcm, sync);
|
return pcm->ops->sync_go(pcm, sync);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
/* NYI: mmap emulation */
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_pcm_stream_drain(snd_pcm_t *pcm, int stream)
|
int snd_pcm_stream_drain(snd_pcm_t *pcm, int stream)
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
if (!pcm)
|
if (!pcm)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (stream < 0 || stream > 1)
|
if (stream < 0 || stream > 1)
|
||||||
|
|
@ -341,11 +298,7 @@ int snd_pcm_stream_drain(snd_pcm_t *pcm, int stream)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
if (stream != SND_PCM_STREAM_PLAYBACK)
|
if (stream != SND_PCM_STREAM_PLAYBACK)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
err = pcm->ops->stream_drain(pcm, stream);
|
return pcm->ops->stream_drain(pcm, stream);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
snd_pcm_mmap_status_streamge(pcm, stream, SND_PCM_STATUS_READY);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_pcm_playback_drain(snd_pcm_t *pcm)
|
int snd_pcm_playback_drain(snd_pcm_t *pcm)
|
||||||
|
|
@ -362,11 +315,7 @@ int snd_pcm_stream_flush(snd_pcm_t *pcm, int stream)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!pcm->stream[stream].open)
|
if (!pcm->stream[stream].open)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
err = pcm->ops->stream_flush(pcm, stream);
|
return pcm->ops->stream_flush(pcm, stream);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
snd_pcm_mmap_status_streamge(pcm, stream, SND_PCM_STATUS_READY);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_pcm_playback_flush(snd_pcm_t *pcm)
|
int snd_pcm_playback_flush(snd_pcm_t *pcm)
|
||||||
|
|
@ -390,11 +339,7 @@ int snd_pcm_stream_pause(snd_pcm_t *pcm, int stream, int enable)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
if (stream != SND_PCM_STREAM_PLAYBACK)
|
if (stream != SND_PCM_STREAM_PLAYBACK)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
err = pcm->ops->stream_pause(pcm, stream, enable);
|
return pcm->ops->stream_pause(pcm, stream, enable);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
snd_pcm_mmap_status_streamge(pcm, stream, SND_PCM_STATUS_PAUSED);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_pcm_playback_pause(snd_pcm_t *pcm, int enable)
|
int snd_pcm_playback_pause(snd_pcm_t *pcm, int enable)
|
||||||
|
|
|
||||||
|
|
@ -566,7 +566,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
|
||||||
if (srcparams->format.channels == 1)
|
if (srcparams->format.channels == 1)
|
||||||
srcparams->format.interleave = dstparams.format.interleave;
|
srcparams->format.interleave = dstparams.format.interleave;
|
||||||
|
|
||||||
/* Format streamge (linearization) */
|
/* Format change (linearization) */
|
||||||
if ((srcparams->format.format != dstparams.format.format ||
|
if ((srcparams->format.format != dstparams.format.format ||
|
||||||
srcparams->format.rate != dstparams.format.rate ||
|
srcparams->format.rate != dstparams.format.rate ||
|
||||||
srcparams->format.channels != dstparams.format.channels) &&
|
srcparams->format.channels != dstparams.format.channels) &&
|
||||||
|
|
@ -603,7 +603,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
pdprintf("params format streamge: src=%i, dst=%i returns %i\n", srcparams->format.format, tmpparams.format.format, err);
|
pdprintf("params format change: src=%i, dst=%i returns %i\n", srcparams->format.format, tmpparams.format.format, err);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = snd_pcm_plugin_append(plugin);
|
err = snd_pcm_plugin_append(plugin);
|
||||||
|
|
@ -727,7 +727,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
|
||||||
srcparams->format = tmpparams.format;
|
srcparams->format = tmpparams.format;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* format streamge */
|
/* format change */
|
||||||
if (srcparams->format.format != dstparams.format.format) {
|
if (srcparams->format.format != dstparams.format.format) {
|
||||||
tmpparams.format.format = dstparams.format.format;
|
tmpparams.format.format = dstparams.format.format;
|
||||||
tmpparams.format.interleave = dstparams.format.interleave;
|
tmpparams.format.interleave = dstparams.format.interleave;
|
||||||
|
|
@ -764,7 +764,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
pdprintf("params format streamge: src=%i, dst=%i returns %i\n", srcparams->format.format, tmpparams.format.format, err);
|
pdprintf("params format change: src=%i, dst=%i returns %i\n", srcparams->format.format, tmpparams.format.format, err);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = snd_pcm_plugin_append(plugin);
|
err = snd_pcm_plugin_append(plugin);
|
||||||
|
|
@ -783,7 +783,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
|
||||||
&srcparams->format,
|
&srcparams->format,
|
||||||
&tmpparams.format,
|
&tmpparams.format,
|
||||||
&plugin);
|
&plugin);
|
||||||
pdprintf("interleave streamge: src=%i, dst=%i returns %i\n", srcparams->format.interleave, tmpparams.format.interleave, err);
|
pdprintf("interleave change: src=%i, dst=%i returns %i\n", srcparams->format.interleave, tmpparams.format.interleave, err);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = snd_pcm_plugin_append(plugin);
|
err = snd_pcm_plugin_append(plugin);
|
||||||
|
|
|
||||||
|
|
@ -89,15 +89,8 @@ struct snd_pcm_stream {
|
||||||
size_t frames_per_frag;
|
size_t frames_per_frag;
|
||||||
snd_pcm_mmap_control_t *mmap_control;
|
snd_pcm_mmap_control_t *mmap_control;
|
||||||
size_t mmap_control_size;
|
size_t mmap_control_size;
|
||||||
int mmap_control_emulation;
|
|
||||||
char *mmap_data;
|
char *mmap_data;
|
||||||
size_t mmap_data_size;
|
size_t mmap_data_size;
|
||||||
int mmap_data_emulation;
|
|
||||||
pthread_t mmap_thread;
|
|
||||||
int mmap_thread_stop;
|
|
||||||
pthread_mutex_t mutex;
|
|
||||||
pthread_cond_t status_cond;
|
|
||||||
pthread_cond_t ready_cond;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct snd_pcm {
|
struct snd_pcm {
|
||||||
|
|
@ -108,8 +101,6 @@ struct snd_pcm {
|
||||||
int private[0];
|
int private[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
void snd_pcm_mmap_status_streamge(snd_pcm_t *pcm, int stream, int newstatus);
|
|
||||||
|
|
||||||
int snd_pcm_abstract_open(snd_pcm_t **handle, int mode, snd_pcm_type_t type, size_t extra);
|
int snd_pcm_abstract_open(snd_pcm_t **handle, int mode, snd_pcm_type_t type, size_t extra);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,39 +26,6 @@
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include "pcm_local.h"
|
#include "pcm_local.h"
|
||||||
|
|
||||||
static void snd_pcm_mmap_clear(snd_pcm_t *pcm, int stream)
|
|
||||||
{
|
|
||||||
struct snd_pcm_stream *str = &pcm->stream[stream];
|
|
||||||
str->mmap_control->byte_io = 0;
|
|
||||||
str->mmap_control->byte_data = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void snd_pcm_mmap_status_streamge(snd_pcm_t *pcm, int stream, int newstatus)
|
|
||||||
{
|
|
||||||
struct snd_pcm_stream *str = &pcm->stream[stream];
|
|
||||||
|
|
||||||
if (!str->mmap_control_emulation)
|
|
||||||
return;
|
|
||||||
if (newstatus < 0) {
|
|
||||||
snd_pcm_stream_status_t status;
|
|
||||||
status.stream = stream;
|
|
||||||
if (snd_pcm_stream_status(pcm, &status) < 0)
|
|
||||||
newstatus = SND_PCM_STATUS_NOTREADY;
|
|
||||||
else
|
|
||||||
newstatus = status.status;
|
|
||||||
}
|
|
||||||
if (str->mmap_control->status != newstatus) {
|
|
||||||
if (newstatus == SND_PCM_STATUS_READY ||
|
|
||||||
(newstatus == SND_PCM_STATUS_PREPARED &&
|
|
||||||
str->mmap_control->status != SND_PCM_STATUS_READY))
|
|
||||||
snd_pcm_mmap_clear(pcm, stream);
|
|
||||||
str->mmap_control->status = newstatus;
|
|
||||||
pthread_mutex_lock(&str->mutex);
|
|
||||||
pthread_cond_signal(&str->status_cond);
|
|
||||||
pthread_mutex_unlock(&str->mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline ssize_t snd_pcm_mmap_playback_bytes_used(struct snd_pcm_stream *str)
|
static inline ssize_t snd_pcm_mmap_playback_bytes_used(struct snd_pcm_stream *str)
|
||||||
{
|
{
|
||||||
ssize_t bytes_used;
|
ssize_t bytes_used;
|
||||||
|
|
@ -686,168 +653,6 @@ static ssize_t mmap_capture_bytes_xfer(struct snd_pcm_stream *str)
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *playback_mmap(void *d)
|
|
||||||
{
|
|
||||||
snd_pcm_t *pcm = d;
|
|
||||||
struct snd_pcm_stream *str = &pcm->stream[SND_PCM_STREAM_PLAYBACK];
|
|
||||||
snd_pcm_mmap_control_t *control;
|
|
||||||
char *data;
|
|
||||||
size_t channel_size;
|
|
||||||
int channels;
|
|
||||||
control = str->mmap_control;
|
|
||||||
data = str->mmap_data;
|
|
||||||
channels = str->setup.format.channels;
|
|
||||||
channel_size = str->mmap_data_size / channels;
|
|
||||||
while (1) {
|
|
||||||
int err;
|
|
||||||
struct pollfd pfd;
|
|
||||||
size_t pos, p, bytes;
|
|
||||||
if (str->mmap_thread_stop)
|
|
||||||
break;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&str->mutex);
|
|
||||||
if (control->status != SND_PCM_STATUS_RUNNING) {
|
|
||||||
pthread_cond_wait(&str->status_cond, &str->mutex);
|
|
||||||
pthread_mutex_unlock(&str->mutex);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&str->mutex);
|
|
||||||
|
|
||||||
pfd.fd = snd_pcm_file_descriptor(pcm, SND_PCM_STREAM_PLAYBACK);
|
|
||||||
pfd.events = POLLOUT | POLLERR;
|
|
||||||
err = poll(&pfd, 1, -1);
|
|
||||||
if (err < 0) {
|
|
||||||
fprintf(stderr, "poll err=%d\n", err);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (pfd.revents & POLLERR) {
|
|
||||||
snd_pcm_mmap_status_streamge(pcm, SND_PCM_STREAM_PLAYBACK, -1);
|
|
||||||
fprintf(stderr, "pollerr %d\n", control->status);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = control->byte_io;
|
|
||||||
bytes = mmap_playback_bytes_xfer(str);
|
|
||||||
if (bytes <= 0) {
|
|
||||||
fprintf(stderr, "underrun\n");
|
|
||||||
usleep(10000);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
p = pos % str->setup.buffer_size;
|
|
||||||
if (str->setup.format.interleave) {
|
|
||||||
err = snd_pcm_write(pcm, data + pos, bytes);
|
|
||||||
} else {
|
|
||||||
struct iovec vector[channels];
|
|
||||||
struct iovec *v = vector;
|
|
||||||
int channel;
|
|
||||||
size_t size = bytes / channels;
|
|
||||||
size_t posv = p / channels;
|
|
||||||
for (channel = 0; channel < channels; ++channel) {
|
|
||||||
v->iov_base = data + channel_size * channel + posv;
|
|
||||||
v->iov_len = size;
|
|
||||||
v++;
|
|
||||||
}
|
|
||||||
err = snd_pcm_writev(pcm, vector, channels);
|
|
||||||
}
|
|
||||||
if (err <= 0) {
|
|
||||||
fprintf(stderr, "write err=%d\n", err);
|
|
||||||
snd_pcm_mmap_status_streamge(pcm, SND_PCM_STREAM_PLAYBACK, -1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pthread_mutex_lock(&str->mutex);
|
|
||||||
pthread_cond_signal(&str->ready_cond);
|
|
||||||
pthread_mutex_unlock(&str->mutex);
|
|
||||||
pos += bytes;
|
|
||||||
if (pos == str->setup.byte_boundary)
|
|
||||||
pos = 0;
|
|
||||||
control->byte_io = pos;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *capture_mmap(void *d)
|
|
||||||
{
|
|
||||||
snd_pcm_t *pcm = d;
|
|
||||||
struct snd_pcm_stream *str = &pcm->stream[SND_PCM_STREAM_CAPTURE];
|
|
||||||
snd_pcm_mmap_control_t *control;
|
|
||||||
char *data;
|
|
||||||
int frags;
|
|
||||||
int frag_size, channel_size, channel_frag_size;
|
|
||||||
int channels;
|
|
||||||
control = str->mmap_control;
|
|
||||||
data = str->mmap_data;
|
|
||||||
frags = str->setup.frags;
|
|
||||||
frag_size = str->setup.frag_size;
|
|
||||||
channels = str->setup.format.channels;
|
|
||||||
channel_size = str->mmap_data_size / channels;
|
|
||||||
channel_frag_size = channel_size / frags;
|
|
||||||
while (1) {
|
|
||||||
int err;
|
|
||||||
struct pollfd pfd;
|
|
||||||
size_t pos, p, bytes;
|
|
||||||
if (str->mmap_thread_stop)
|
|
||||||
break;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&str->mutex);
|
|
||||||
if (control->status != SND_PCM_STATUS_RUNNING) {
|
|
||||||
pthread_cond_wait(&str->status_cond, &str->mutex);
|
|
||||||
pthread_mutex_unlock(&str->mutex);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&str->mutex);
|
|
||||||
|
|
||||||
pfd.fd = snd_pcm_file_descriptor(pcm, SND_PCM_STREAM_CAPTURE);
|
|
||||||
pfd.events = POLLIN | POLLERR;
|
|
||||||
err = poll(&pfd, 1, -1);
|
|
||||||
if (err < 0) {
|
|
||||||
fprintf(stderr, "poll err=%d\n", err);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (pfd.revents & POLLERR) {
|
|
||||||
snd_pcm_mmap_status_streamge(pcm, SND_PCM_STREAM_CAPTURE, -1);
|
|
||||||
fprintf(stderr, "pollerr %d\n", control->status);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = control->byte_io;
|
|
||||||
bytes = mmap_capture_bytes_xfer(str);
|
|
||||||
if (bytes <= 0) {
|
|
||||||
fprintf(stderr, "overrun\n");
|
|
||||||
usleep(10000);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
p = pos % str->setup.buffer_size;
|
|
||||||
if (str->setup.format.interleave) {
|
|
||||||
err = snd_pcm_read(pcm, data + pos, bytes);
|
|
||||||
} else {
|
|
||||||
struct iovec vector[channels];
|
|
||||||
struct iovec *v = vector;
|
|
||||||
int channel;
|
|
||||||
size_t size = bytes / channels;
|
|
||||||
size_t posv = p / channels;
|
|
||||||
for (channel = 0; channel < channels; ++channel) {
|
|
||||||
v->iov_base = data + channel_size * channel + posv;
|
|
||||||
v->iov_len = size;
|
|
||||||
v++;
|
|
||||||
}
|
|
||||||
err = snd_pcm_readv(pcm, vector, channels);
|
|
||||||
}
|
|
||||||
if (err < 0) {
|
|
||||||
fprintf(stderr, "read err=%d\n", err);
|
|
||||||
snd_pcm_mmap_status_streamge(pcm, SND_PCM_STREAM_CAPTURE, -1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pthread_mutex_lock(&str->mutex);
|
|
||||||
pthread_cond_signal(&str->ready_cond);
|
|
||||||
pthread_mutex_unlock(&str->mutex);
|
|
||||||
pos += bytes;
|
|
||||||
if (pos == str->setup.byte_boundary)
|
|
||||||
pos = 0;
|
|
||||||
control->byte_io = pos;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int snd_pcm_mmap_control(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **control)
|
int snd_pcm_mmap_control(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **control)
|
||||||
{
|
{
|
||||||
struct snd_pcm_stream *str;
|
struct snd_pcm_stream *str;
|
||||||
|
|
@ -869,17 +674,8 @@ int snd_pcm_mmap_control(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **co
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
csize = sizeof(snd_pcm_mmap_control_t);
|
csize = sizeof(snd_pcm_mmap_control_t);
|
||||||
|
|
||||||
info.stream = stream;
|
if ((err = pcm->ops->mmap_control(pcm, stream, control, csize)) < 0)
|
||||||
err = snd_pcm_stream_info(pcm, &info);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
return err;
|
||||||
if (info.flags & SND_PCM_STREAM_INFO_MMAP) {
|
|
||||||
if ((err = pcm->ops->mmap_control(pcm, stream, control, csize)) < 0)
|
|
||||||
return err;
|
|
||||||
} else {
|
|
||||||
*control = calloc(1, csize);
|
|
||||||
str->mmap_control_emulation = 1;
|
|
||||||
}
|
|
||||||
str->mmap_control = *control;
|
str->mmap_control = *control;
|
||||||
str->mmap_control_size = csize;
|
str->mmap_control_size = csize;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -940,30 +736,10 @@ int snd_pcm_mmap_data(snd_pcm_t *pcm, int stream, void **data)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
bsize = info.mmap_size;
|
bsize = info.mmap_size;
|
||||||
if (info.flags & SND_PCM_STREAM_INFO_MMAP) {
|
if (!(info.flags & SND_PCM_STREAM_INFO_MMAP))
|
||||||
if ((err = pcm->ops->mmap_data(pcm, stream, data, bsize)) < 0)
|
return -ENXIO;
|
||||||
return err;
|
if ((err = pcm->ops->mmap_data(pcm, stream, data, bsize)) < 0)
|
||||||
} else {
|
return err;
|
||||||
*data = calloc(1, bsize);
|
|
||||||
|
|
||||||
pthread_mutex_init(&str->mutex, NULL);
|
|
||||||
pthread_cond_init(&str->status_cond, NULL);
|
|
||||||
pthread_cond_init(&str->ready_cond, NULL);
|
|
||||||
str->mmap_thread_stop = 0;
|
|
||||||
if (stream == SND_PCM_STREAM_PLAYBACK)
|
|
||||||
err = pthread_create(&str->mmap_thread, NULL, playback_mmap, pcm);
|
|
||||||
else
|
|
||||||
err = pthread_create(&str->mmap_thread, NULL, capture_mmap, pcm);
|
|
||||||
if (err < 0) {
|
|
||||||
pthread_cond_destroy(&str->status_cond);
|
|
||||||
pthread_cond_destroy(&str->ready_cond);
|
|
||||||
pthread_mutex_destroy(&str->mutex);
|
|
||||||
free(*data);
|
|
||||||
*data = 0;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
str->mmap_data_emulation = 1;
|
|
||||||
}
|
|
||||||
str->mmap_data = *data;
|
str->mmap_data = *data;
|
||||||
str->mmap_data_size = bsize;
|
str->mmap_data_size = bsize;
|
||||||
err = snd_pcm_mmap_get_areas(pcm, stream, NULL);
|
err = snd_pcm_mmap_get_areas(pcm, stream, NULL);
|
||||||
|
|
@ -999,13 +775,8 @@ int snd_pcm_munmap_control(snd_pcm_t *pcm, int stream)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
if (!str->mmap_control)
|
if (!str->mmap_control)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (str->mmap_control_emulation) {
|
if ((err = pcm->ops->munmap_control(pcm, stream, str->mmap_control, str->mmap_control_size)) < 0)
|
||||||
free(str->mmap_control);
|
return err;
|
||||||
str->mmap_control_emulation = 0;
|
|
||||||
} else {
|
|
||||||
if ((err = pcm->ops->munmap_control(pcm, stream, str->mmap_control, str->mmap_control_size)) < 0)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
str->mmap_control = 0;
|
str->mmap_control = 0;
|
||||||
str->mmap_control_size = 0;
|
str->mmap_control_size = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1024,21 +795,8 @@ int snd_pcm_munmap_data(snd_pcm_t *pcm, int stream)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
if (!str->mmap_data)
|
if (!str->mmap_data)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (str->mmap_data_emulation) {
|
if ((err = pcm->ops->munmap_data(pcm, stream, str->mmap_data, str->mmap_data_size)) < 0)
|
||||||
str->mmap_thread_stop = 1;
|
return err;
|
||||||
pthread_mutex_lock(&str->mutex);
|
|
||||||
pthread_cond_signal(&str->status_cond);
|
|
||||||
pthread_mutex_unlock(&str->mutex);
|
|
||||||
pthread_join(str->mmap_thread, NULL);
|
|
||||||
pthread_cond_destroy(&str->status_cond);
|
|
||||||
pthread_cond_destroy(&str->ready_cond);
|
|
||||||
pthread_mutex_destroy(&str->mutex);
|
|
||||||
free(str->mmap_data);
|
|
||||||
str->mmap_data_emulation = 0;
|
|
||||||
} else {
|
|
||||||
if ((err = pcm->ops->munmap_data(pcm, stream, str->mmap_data, str->mmap_data_size)) < 0)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
free(str->channels);
|
free(str->channels);
|
||||||
str->mmap_data = 0;
|
str->mmap_data = 0;
|
||||||
str->mmap_data_size = 0;
|
str->mmap_data_size = 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue