const char *_snd_module_pcm_dmix = "";
#endif
+/*
+ *
+ */
+
+int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
+
/*
*
*/
return 0;
}
+/*
+ * ring buffer operation
+ */
+
+/*
+ * synchronize shm ring buffer with hardware
+ */
+static void snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm, snd_pcm_uframes_t size)
+{
+ snd_pcm_dmix_t *dmix = pcm->private_data;
+ snd_pcm_uframes_t appl_ptr;
+
+ /* get the start of update area */
+ appl_ptr = dmix->appl_ptr - size;
+ if (appl_ptr > pcm->boundary)
+ appl_ptr += pcm->boundary;
+}
+
/*
* plugin implementation
*/
-static int snd_pcm_dmix_nonblock(snd_pcm_t *pcm, int nonblock)
+static int snd_pcm_dmix_nonblock(snd_pcm_t *pcm, int nonblock ATTRIBUTE_UNUSED)
{
+ /* value is cached for us in pcm->mode (SND_PCM_NONBLOCK flag) */
return 0;
}
static int snd_pcm_dmix_async(snd_pcm_t *pcm, int sig, pid_t pid)
{
snd_pcm_dmix_t *dmix = pcm->private_data;
- return 0;
+ return snd_timer_async(dmix->timer, sig, pid);
}
static int snd_pcm_dmix_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
{
snd_pcm_dmix_t *dmix = pcm->private_data;
+ memset(info, 0, sizeof(*info));
+ info->stream = pcm->stream;
+ info->card = -1;
+ /* FIXME: fill this with something more useful: we know the hardware name */
+ strncpy(info->id, pcm->name, sizeof(info->id));
+ strncpy(info->name, pcm->name, sizeof(info->name));
+ strncpy(info->subname, pcm->name, sizeof(info->subname));
+ info->subdevices_count = 1;
return 0;
}
static int snd_pcm_dmix_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
{
- snd_pcm_dmix_t *dmix = pcm->private_data;
+ // snd_pcm_dmix_t *dmix = pcm->private_data;
return 0;
}
static int snd_pcm_dmix_hw_free(snd_pcm_t *pcm)
{
- snd_pcm_dmix_t *dmix = pcm->private_data;
+ // snd_pcm_dmix_t *dmix = pcm->private_data;
return 0;
}
static int snd_pcm_dmix_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
{
- snd_pcm_dmix_t *dmix = pcm->private_data;
+ // snd_pcm_dmix_t *dmix = pcm->private_data;
return 0;
}
static int snd_pcm_dmix_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info)
{
- snd_pcm_dmix_t *dmix = pcm->private_data;
- return 0;
+ return snd_pcm_channel_info_shm(pcm, info, -1);
}
static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
static snd_pcm_sframes_t snd_pcm_dmix_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
{
- return -ENODEV;
+ int res = snd_pcm_mmap_writei(pcm, buffer, size);
+ snd_pcm_dmix_sync_ptr(pcm, size);
+ return res;
}
static snd_pcm_sframes_t snd_pcm_dmix_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
{
- return -ENODEV;
+ int res = snd_pcm_mmap_writen(pcm, bufs, size);
+ snd_pcm_dmix_sync_ptr(pcm, size);
+ return res;
}
-static snd_pcm_sframes_t snd_pcm_dmix_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
+static snd_pcm_sframes_t snd_pcm_dmix_readi(snd_pcm_t *pcm ATTRIBUTE_UNUSED, void *buffer ATTRIBUTE_UNUSED, snd_pcm_uframes_t size ATTRIBUTE_UNUSED)
{
return -ENODEV;
}
-static snd_pcm_sframes_t snd_pcm_dmix_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
+static snd_pcm_sframes_t snd_pcm_dmix_readn(snd_pcm_t *pcm ATTRIBUTE_UNUSED, void **bufs ATTRIBUTE_UNUSED, snd_pcm_uframes_t size ATTRIBUTE_UNUSED)
{
return -ENODEV;
}
-static int snd_pcm_dmix_mmap(snd_pcm_t *pcm)
+static int snd_pcm_dmix_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
{
- snd_pcm_dmix_t *dmix = pcm->private_data;
return 0;
}
-static int snd_pcm_dmix_munmap(snd_pcm_t *pcm)
+static int snd_pcm_dmix_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
{
- snd_pcm_dmix_t *dmix = pcm->private_data;
return 0;
}
}
static snd_pcm_sframes_t snd_pcm_dmix_mmap_commit(snd_pcm_t *pcm,
- snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
- snd_pcm_uframes_t size)
+ snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
+ snd_pcm_uframes_t size)
{
- snd_pcm_dmix_t *hw = pcm->private_data;
- return 0;
+ snd_pcm_mmap_appl_forward(pcm, size);
+ snd_pcm_dmix_sync_ptr(pcm, size);
+ return size;
}
-static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm)
+static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
{
- snd_pcm_dmix_t *hw = pcm->private_data;
+ //snd_pcm_dmix_t *dmix = pcm->private_data;
return 0;
}
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#define __USE_GNU
#include <fcntl.h>
#include <sys/ioctl.h>
#include "timer_local.h"
return 0;
}
+static int snd_timer_hw_async(snd_timer_t *timer, int sig, pid_t pid)
+{
+ long flags;
+ int fd;
+
+ assert(timer);
+ fd = timer->poll_fd;
+ if ((flags = fcntl(fd, F_GETFL)) < 0) {
+ SYSERR("F_GETFL failed");
+ return -errno;
+ }
+ if (sig >= 0)
+ flags |= O_ASYNC;
+ else
+ flags &= ~O_ASYNC;
+ if (fcntl(fd, F_SETFL, flags) < 0) {
+ SYSERR("F_SETFL for O_ASYNC failed");
+ return -errno;
+ }
+ if (sig < 0)
+ return 0;
+ if (fcntl(fd, F_SETSIG, (long)sig) < 0) {
+ SYSERR("F_SETSIG failed");
+ return -errno;
+ }
+ if (fcntl(fd, F_SETOWN, (long)pid) < 0) {
+ SYSERR("F_SETOWN failed");
+ return -errno;
+ }
+ return 0;
+}
+
static int snd_timer_hw_info(snd_timer_t *handle, snd_timer_info_t * info)
{
snd_timer_t *tmr;
}
static snd_timer_ops_t snd_timer_hw_ops = {
- close: snd_timer_hw_close,
- nonblock: snd_timer_hw_nonblock,
- info: snd_timer_hw_info,
- params: snd_timer_hw_params,
- status: snd_timer_hw_status,
- rt_start: snd_timer_hw_start,
- rt_stop: snd_timer_hw_stop,
- rt_continue: snd_timer_hw_continue,
- read: snd_timer_hw_read,
+ .close = snd_timer_hw_close,
+ .nonblock = snd_timer_hw_nonblock,
+ .async = snd_timer_hw_async,
+ .info = snd_timer_hw_info,
+ .params = snd_timer_hw_params,
+ .status = snd_timer_hw_status,
+ .rt_start = snd_timer_hw_start,
+ .rt_stop = snd_timer_hw_stop,
+ .rt_continue = snd_timer_hw_continue,
+ .read = snd_timer_hw_read,
};
int snd_timer_hw_open(snd_timer_t **handle, const char *name, int dev_class, int dev_sclass, int card, int device, int subdevice, int mode)