-SUBDIRS=doc include src test utils
+SUBDIRS=doc include src aserver test utils
EXTRA_DIST=ChangeLog INSTALL TODO configure cvscompile libtool version
INCLUDES=-I$(top_srcdir)/include
#if !defined(SND_PROTOCOL_VERSION) || !defined(SND_PROTOCOL_INCOMPATIBLE)
#error not found
#else
-#if !defined(SND_PCM_IOCTL_APPL_PTR)
+#if !defined(SND_PCM_IOCTL_REWIND)
#error wrong version
#endif
exit(0);
bin_PROGRAMS = aserver
aserver_SOURCES = aserver.c
# aserver_LDADD = -lasound
-aserver_LDADD = ../libasound.la
+aserver_LDADD = ../src/libasound.la
all: aserver
INCLUDES=-I$(top_srcdir)/include -I$(top_srcdir)/src/pcm
-../libasound.la:
- $(MAKE) -C .. libasound.la
+../src/libasound.la:
+ $(MAKE) -C ../src libasound.la
case SND_PCM_IOCTL_CHANNEL_SETUP:
ctrl->result = snd_pcm_channel_setup(pcm, &ctrl->u.channel_setup);
break;
- case SND_PCM_IOCTL_APPL_PTR:
- ctrl->result = snd_pcm_appl_ptr(pcm, ctrl->u.appl_ptr);
+ case SND_PCM_IOCTL_REWIND:
+ ctrl->result = snd_pcm_rewind(pcm, ctrl->u.rewind);
break;
case SND_PCM_IOCTL_LINK:
{
AC_OUTPUT(Makefile doc/Makefile include/Makefile src/Makefile \
src/control/Makefile src/mixer/Makefile src/pcm/Makefile \
- src/pcm/plugin/Makefile src/rawmidi/Makefile src/timer/Makefile \
+ src/rawmidi/Makefile src/timer/Makefile \
src/hwdep/Makefile src/seq/Makefile src/instr/Makefile \
- src/compat/Makefile src/conf/Makefile src/aserver/Makefile \
+ src/compat/Makefile src/conf/Makefile aserver/Makefile \
test/Makefile utils/Makefile \
utils/alsa-lib.spec)
#define SND_PCM_IOCTL_CLOSE _IO ('A', 0xf9)
typedef struct {
- int result;
+ long result;
int cmd;
union {
snd_pcm_info_t info;
snd_pcm_channel_info_t channel_info;
snd_pcm_channel_params_t channel_params;
snd_pcm_channel_setup_t channel_setup;
- off_t appl_ptr;
- int hw_ptr;
+ ssize_t rewind;
int link;
size_t mmap_forward;
} u;
int snd_pcm_pause(snd_pcm_t *handle, int enable);
int snd_pcm_state(snd_pcm_t *handle);
int snd_pcm_delay(snd_pcm_t *handle, ssize_t *delayp);
-size_t snd_pcm_hw_ptr(snd_pcm_t *handle);
-ssize_t snd_pcm_appl_ptr(snd_pcm_t *handle, off_t offset);
+ssize_t snd_pcm_rewind(snd_pcm_t *handle, size_t frames);
ssize_t snd_pcm_writei(snd_pcm_t *handle, const void *buffer, size_t size);
ssize_t snd_pcm_readi(snd_pcm_t *handle, void *buffer, size_t size);
ssize_t snd_pcm_writen(snd_pcm_t *handle, void **bufs, size_t size);
-SUBDIRS=control mixer pcm rawmidi timer hwdep seq instr compat conf aserver
+SUBDIRS=control mixer pcm rawmidi timer hwdep seq instr compat conf
COMPATNUM=@LIBTOOL_VERSION_INFO@
lib_LTLIBRARIES = libasound.la
}
-ssize_t snd_pcm_appl_ptr(snd_pcm_t *pcm, off_t offset)
+ssize_t snd_pcm_rewind(snd_pcm_t *pcm, size_t frames)
{
assert(pcm);
assert(pcm->valid_setup);
- if (pcm->mmap_control) {
- if (offset == 0)
- return pcm->mmap_control->appl_ptr;
- }
- return pcm->fast_ops->appl_ptr(pcm->fast_op_arg, offset);
+ assert(frames > 0);
+ return pcm->fast_ops->rewind(pcm->fast_op_arg, frames);
}
ssize_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, size_t size)
return pcm->fast_ops->mmap_forward(pcm->fast_op_arg, size);
}
-size_t snd_pcm_hw_ptr(snd_pcm_t *pcm)
-{
- return pcm->mmap_status->hw_ptr;
-}
-
int snd_pcm_area_silence(snd_pcm_channel_area_t *dst_area, size_t dst_offset,
size_t samples, int format)
{
return ctrl->result;
}
-static ssize_t snd_pcm_client_shm_appl_ptr(snd_pcm_t *pcm, off_t offset)
+static ssize_t snd_pcm_client_shm_rewind(snd_pcm_t *pcm, size_t frames)
{
snd_pcm_client_t *client = pcm->private;
snd_pcm_client_shm_t *ctrl = client->u.shm.ctrl;
int err;
- ctrl->cmd = SND_PCM_IOCTL_APPL_PTR;
- ctrl->u.appl_ptr = offset;
+ ctrl->cmd = SND_PCM_IOCTL_REWIND;
+ ctrl->u.rewind = frames;
err = snd_pcm_client_shm_action(pcm);
if (err < 0)
return err;
stop: snd_pcm_client_shm_stop,
flush: snd_pcm_client_shm_flush,
pause: snd_pcm_client_shm_pause,
- appl_ptr: snd_pcm_client_shm_appl_ptr,
+ rewind: snd_pcm_client_shm_rewind,
writei: snd_pcm_mmap_writei,
writen: snd_pcm_mmap_writen,
readi: snd_pcm_mmap_readi,
return snd_pcm_pause(file->slave, enable);
}
-static ssize_t snd_pcm_file_appl_ptr(snd_pcm_t *pcm, off_t offset)
+static ssize_t snd_pcm_file_rewind(snd_pcm_t *pcm, size_t frames)
{
snd_pcm_file_t *file = pcm->private;
- return snd_pcm_appl_ptr(file->slave, offset);
+ ssize_t f = snd_pcm_rewind(file->slave, frames);
+ off_t err;
+ if (f > 0) {
+ err = lseek(file->fd, -snd_pcm_frames_to_bytes(pcm, f), SEEK_CUR);
+ if (err < 0)
+ return err;
+ }
+ return f;
}
static void snd_pcm_file_write_areas(snd_pcm_t *pcm,
stop: snd_pcm_file_stop,
flush: snd_pcm_file_flush,
pause: snd_pcm_file_pause,
- appl_ptr: snd_pcm_file_appl_ptr,
+ rewind: snd_pcm_file_rewind,
writei: snd_pcm_file_writei,
writen: snd_pcm_file_writen,
readi: snd_pcm_file_readi,
return 0;
}
-static ssize_t snd_pcm_hw_appl_ptr(snd_pcm_t *pcm, off_t offset)
+static ssize_t snd_pcm_hw_rewind(snd_pcm_t *pcm, size_t frames)
{
- ssize_t result;
- snd_pcm_hw_t *hw = pcm->private;
- int fd = hw->fd;
- if (pcm->mmap_status && pcm->mmap_control)
- return snd_pcm_mmap_appl_ptr(pcm, offset);
- result = ioctl(fd, SND_PCM_IOCTL_APPL_PTR, offset);
- if (result < 0)
- return -errno;
- return result;
+ ssize_t used;
+ if (pcm->setup.xrun_mode == SND_PCM_XRUN_ASAP) {
+ ssize_t d;
+ int err = snd_pcm_hw_delay(pcm, &d);
+ if (err < 0)
+ return 0;
+ }
+ used = pcm->setup.buffer_size - snd_pcm_mmap_avail(pcm);
+ if (used <= 0)
+ return 0;
+ if (frames > (size_t)used)
+ frames = used;
+ snd_pcm_mmap_appl_backward(pcm, frames);
+ return frames;
}
static ssize_t snd_pcm_hw_writei(snd_pcm_t *pcm, const void *buffer, size_t size)
stop: snd_pcm_hw_stop,
flush: snd_pcm_hw_flush,
pause: snd_pcm_hw_pause,
- appl_ptr: snd_pcm_hw_appl_ptr,
+ rewind: snd_pcm_hw_rewind,
writei: snd_pcm_hw_writei,
writen: snd_pcm_hw_writen,
readi: snd_pcm_hw_readi,
int (*pause)(snd_pcm_t *pcm, int enable);
int (*state)(snd_pcm_t *pcm);
int (*delay)(snd_pcm_t *pcm, ssize_t *delayp);
- ssize_t (*appl_ptr)(snd_pcm_t *pcm, off_t offset);
+ ssize_t (*rewind)(snd_pcm_t *pcm, size_t frames);
ssize_t (*writei)(snd_pcm_t *pcm, const void *buffer, size_t size);
ssize_t (*writen)(snd_pcm_t *pcm, void **bufs, size_t size);
ssize_t (*readi)(snd_pcm_t *pcm, void *buffer, size_t size);
int snd_pcm_munmap_data(snd_pcm_t *pcm);
int snd_pcm_mmap_ready(snd_pcm_t *pcm);
ssize_t snd_pcm_mmap_appl_ptr(snd_pcm_t *pcm, off_t offset);
+void snd_pcm_mmap_appl_backward(snd_pcm_t *pcm, size_t frames);
void snd_pcm_mmap_appl_forward(snd_pcm_t *pcm, size_t frames);
void snd_pcm_mmap_hw_forward(snd_pcm_t *pcm, size_t frames);
size_t snd_pcm_mmap_hw_offset(snd_pcm_t *pcm);
return appl_ptr;
}
+void snd_pcm_mmap_appl_backward(snd_pcm_t *pcm, size_t frames)
+{
+ ssize_t appl_ptr = pcm->mmap_control->appl_ptr;
+ appl_ptr -= frames;
+ if (appl_ptr < 0)
+ appl_ptr += pcm->setup.boundary;
+ pcm->mmap_control->appl_ptr = appl_ptr;
+}
+
void snd_pcm_mmap_appl_forward(snd_pcm_t *pcm, size_t frames)
{
size_t appl_ptr = pcm->mmap_control->appl_ptr;
return err;
if (setup->format.rate != s.format.rate)
return -EINVAL;
- /* mmap is not feasible */
if (setup->buffer_size != s.buffer_size)
return -EINVAL;
if (setup->mmap_shape != SND_PCM_MMAP_NONINTERLEAVED ||
return 0;
}
-static ssize_t snd_pcm_multi_appl_ptr(snd_pcm_t *pcm, off_t offset)
+static ssize_t snd_pcm_multi_rewind(snd_pcm_t *pcm, size_t frames)
{
snd_pcm_multi_t *multi = pcm->private;
- ssize_t pos, newpos;
unsigned int i;
- snd_pcm_t *handle_0 = multi->slaves[0].handle;
-
- pos = snd_pcm_appl_ptr(handle_0, 0);
- newpos = snd_pcm_appl_ptr(handle_0, offset);
- if (newpos < 0)
- return newpos;
- offset = newpos - pos;
- if (offset < 0)
- offset += handle_0->setup.boundary;
-
- for (i = 1; i < multi->slaves_count; ++i) {
+ size_t pos[multi->slaves_count];
+ memset(pos, 0, sizeof(pos));
+ for (i = 0; i < multi->slaves_count; ++i) {
snd_pcm_t *handle_i = multi->slaves[i].handle;
- ssize_t newpos_i;
- newpos_i = snd_pcm_appl_ptr(handle_i, offset);
- if (newpos_i < 0)
- return newpos_i;
- if (newpos_i != newpos)
- return -EBADFD;
+ ssize_t f = snd_pcm_rewind(handle_i, frames);
+ if (f < 0)
+ return f;
+ pos[i] = f;
+ frames = f;
+ }
+ /* Realign the pointers */
+ for (i = 0; i < multi->slaves_count; ++i) {
+ snd_pcm_t *handle_i = multi->slaves[i].handle;
+ size_t f = pos[i] - frames;
+ if (f > 0)
+ snd_pcm_mmap_appl_forward(handle_i, f);
}
- return newpos;
+ return frames;
}
static int snd_pcm_multi_mmap_status(snd_pcm_t *pcm)
writen: snd_pcm_mmap_writen,
readi: snd_pcm_mmap_readi,
readn: snd_pcm_mmap_readn,
- appl_ptr: snd_pcm_multi_appl_ptr,
+ rewind: snd_pcm_multi_rewind,
poll_descriptor: snd_pcm_multi_poll_descriptor,
channels_mask: snd_pcm_multi_channels_mask,
avail_update: snd_pcm_multi_avail_update,
return snd_pcm_pause(plugin->slave, enable);
}
-ssize_t snd_pcm_plugin_appl_ptr(snd_pcm_t *pcm, off_t offset)
+ssize_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, size_t frames)
{
- /* FIXME */
- return -ENOSYS;
+ snd_pcm_plugin_t *plugin = pcm->private;
+ ssize_t n = pcm->setup.buffer_size - snd_pcm_mmap_avail(pcm);
+ if (n > 0) {
+ if ((size_t)n > frames)
+ n = frames;
+ snd_pcm_mmap_appl_backward(pcm, n);
+ frames -= n;
+ }
+ if (frames > 0) {
+ ssize_t err = snd_pcm_rewind(plugin->slave, frames);
+ if (err < 0) {
+ if (n > 0)
+ return n;
+ return err;
+ }
+ if (plugin->client_frames)
+ err = plugin->client_frames(pcm, err);
+ n += err;
+ }
+ return n;
}
ssize_t snd_pcm_plugin_writei(snd_pcm_t *pcm, const void *buffer, size_t size)
stop: snd_pcm_plugin_stop,
flush: snd_pcm_plugin_flush,
pause: snd_pcm_plugin_pause,
- appl_ptr: snd_pcm_plugin_appl_ptr,
+ rewind: snd_pcm_plugin_rewind,
writei: snd_pcm_plugin_writei,
writen: snd_pcm_plugin_writen,
readi: snd_pcm_plugin_readi,
int snd_pcm_plugin_stop(snd_pcm_t *pcm);
int snd_pcm_plugin_flush(snd_pcm_t *pcm);
int snd_pcm_plugin_pause(snd_pcm_t *pcm, int enable);
-ssize_t snd_pcm_plugin_appl_ptr(snd_pcm_t *pcm, off_t offset);
+ssize_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, size_t frames);
ssize_t snd_pcm_plugin_writei(snd_pcm_t *pcm, const void *buffer, size_t size);
ssize_t snd_pcm_plugin_writen(snd_pcm_t *pcm, void **bufs, size_t size);
ssize_t snd_pcm_plugin_readi(snd_pcm_t *pcm, void *buffer, size_t size);