]> git.alsa-project.org Git - alsa-lib.git/commitdiff
More changes for dmix plugin:
authorJaroslav Kysela <perex@perex.cz>
Tue, 11 Feb 2003 18:14:43 +0000 (18:14 +0000)
committerJaroslav Kysela <perex@perex.cz>
Tue, 11 Feb 2003 18:14:43 +0000 (18:14 +0000)
  - added poll_events to main pcm structure
  - added poll_revents callback to pcm->ops structure
  - fixed snd_pcm_wait() - call revents function and enhanced
    error code reporting
DMIX plugin:
  - more complete code (works at least for one instance)
  - still no "mix" code (it's silent)

24 files changed:
src/pcm/pcm.c
src/pcm/pcm_adpcm.c
src/pcm/pcm_alaw.c
src/pcm/pcm_copy.c
src/pcm/pcm_dmix.c
src/pcm/pcm_file.c
src/pcm/pcm_hooks.c
src/pcm/pcm_hw.c
src/pcm/pcm_ladspa.c
src/pcm/pcm_lfloat.c
src/pcm/pcm_linear.c
src/pcm/pcm_local.h
src/pcm/pcm_meter.c
src/pcm/pcm_mulaw.c
src/pcm/pcm_multi.c
src/pcm/pcm_null.c
src/pcm/pcm_params.c
src/pcm/pcm_plug.c
src/pcm/pcm_plugin.c
src/pcm/pcm_plugin.h
src/pcm/pcm_rate.c
src/pcm/pcm_route.c
src/pcm/pcm_share.c
src/pcm/pcm_shm.c

index 7894994ac8bb1d9d38b7247c6bac7cf3c95d02a7..525fd2f60b3ffa380206b458ce38ceb229afa056 100644 (file)
@@ -812,6 +812,7 @@ int snd_pcm_hw_free(snd_pcm_t *pcm)
 int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
 {
        int err;
+       assert(pcm->setup);             /* the hw_params must be set at first!!! */
        err = pcm->ops->sw_params(pcm->op_arg, params);
        if (err < 0)
                return err;
@@ -1169,9 +1170,10 @@ int snd_pcm_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int s
        assert(pcm && pfds);
        if (space >= 1 && pfds) {
                pfds->fd = pcm->poll_fd;
-               pfds->events = pcm->stream == SND_PCM_STREAM_PLAYBACK ? (POLLOUT|POLLERR|POLLNVAL) : (POLLIN|POLLERR|POLLNVAL);
-       } else
+               pfds->events = pcm->poll_events | POLLERR | POLLNVAL;
+       } else {
                return 0;
+       }
        return 1;
 }
 
@@ -1186,6 +1188,8 @@ int snd_pcm_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int s
 int snd_pcm_poll_descriptors_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
 {
        assert(pcm && pfds && revents);
+       if (pcm->ops->poll_revents)
+               return pcm->ops->poll_revents(pcm, pfds, nfds, revents);
        if (nfds == 1) {
                *revents = pfds->revents;
                return 0;
@@ -1903,12 +1907,18 @@ int snd_pcm_open_slave(snd_pcm_t **pcmp, snd_config_t *root,
 int snd_pcm_wait(snd_pcm_t *pcm, int timeout)
 {
        struct pollfd pfd;
+       unsigned short revents;
        int err;
        err = snd_pcm_poll_descriptors(pcm, &pfd, 1);
        assert(err == 1);
        err = poll(&pfd, 1, timeout);
        if (err < 0)
                return -errno;
+       err = snd_pcm_poll_descriptors_revents(pcm, &pfd, 1, &revents);
+       if (err < 0)
+               return err;
+       if (revents & (POLLERR | POLLNVAL))
+               return -EIO;
        return err > 0 ? 1 : 0;
 }
 
index 85fbfe5d2d517aa8a41989f4541b48d559ed1b3c..5b112ceffc15d56ffcbf3e6a3fb4b3ad4d0829cf 100644 (file)
@@ -527,6 +527,7 @@ static snd_pcm_ops_t snd_pcm_adpcm_ops = {
        dump: snd_pcm_adpcm_dump,
        nonblock: snd_pcm_plugin_nonblock,
        async: snd_pcm_plugin_async,
+       poll_revents: snd_pcm_plugin_poll_revents,
        mmap: snd_pcm_plugin_mmap,
        munmap: snd_pcm_plugin_munmap,
 };
@@ -573,6 +574,7 @@ int snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfor
        pcm->fast_ops = &snd_pcm_plugin_fast_ops;
        pcm->private_data = adpcm;
        pcm->poll_fd = slave->poll_fd;
+       pcm->poll_events = slave->poll_events;
        snd_pcm_set_hw_ptr(pcm, &adpcm->plug.hw_ptr, -1, 0);
        snd_pcm_set_appl_ptr(pcm, &adpcm->plug.appl_ptr, -1, 0);
        *pcmp = pcm;
index 4ade34249b2c6391d86535a898e2f8e94b9d69bc..1bb3f5d9da5cb8656c7f820e40acd17773888eaf 100644 (file)
@@ -400,6 +400,7 @@ static snd_pcm_ops_t snd_pcm_alaw_ops = {
        dump: snd_pcm_alaw_dump,
        nonblock: snd_pcm_plugin_nonblock,
        async: snd_pcm_plugin_async,
+       poll_revents: snd_pcm_plugin_poll_revents,
        mmap: snd_pcm_plugin_mmap,
        munmap: snd_pcm_plugin_munmap,
 };
@@ -447,6 +448,7 @@ int snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sform
        pcm->fast_ops = &snd_pcm_plugin_fast_ops;
        pcm->private_data = alaw;
        pcm->poll_fd = slave->poll_fd;
+       pcm->poll_events = slave->poll_events;
        snd_pcm_set_hw_ptr(pcm, &alaw->plug.hw_ptr, -1, 0);
        snd_pcm_set_appl_ptr(pcm, &alaw->plug.appl_ptr, -1, 0);
        *pcmp = pcm;
index e27cd9379a28d06fdab61447af6c1b3ae1a8486a..2bca627bd1845ebbb5941a1b57df3c82a9926dfa 100644 (file)
@@ -163,6 +163,7 @@ static snd_pcm_ops_t snd_pcm_copy_ops = {
        dump: snd_pcm_copy_dump,
        nonblock: snd_pcm_plugin_nonblock,
        async: snd_pcm_plugin_async,
+       poll_revents: snd_pcm_plugin_poll_revents,
        mmap: snd_pcm_plugin_mmap,
        munmap: snd_pcm_plugin_munmap,
 };
index 0b47dc2daf9c875541eb32a23ecaeb59da5c9456..40200ad042c94c85de4c78e298f8a6981ab59c80 100644 (file)
 const char *_snd_module_pcm_dmix = "";
 #endif
 
+/*
+ *
+ */
+/*
+ * FIXME:
+ *  add possibility to use futexes here
+ */
+#define DMIX_IPC_SEMS          1
+#define DMIX_IPC_SEM_CLIENT    0
+
 /*
  *
  */
@@ -80,12 +92,16 @@ typedef struct {
 typedef struct {
        key_t ipc_key;  /* IPC key for semaphore and memory */
        int semid;      /* IPC global semaphore identification */
-       int semlock;    /* locked with our process? */
        int shmid;      /* IPC global shared memory identification */
        snd_pcm_dmix_share_t *shmptr;   /* pointer to shared memory area */
        snd_pcm_t *spcm; /* slave PCM handle */
        snd_pcm_uframes_t appl_ptr;
        snd_pcm_uframes_t hw_ptr;
+       snd_pcm_uframes_t avail_max;
+       snd_pcm_uframes_t slave_appl_ptr;
+       snd_pcm_uframes_t slave_hw_ptr;
+       snd_pcm_state_t state;
+       snd_timestamp_t trigger_tstamp;
        int server, client;
        int comm_fd;    /* communication file descriptor (socket) */
        int hw_fd;      /* hardware file descriptor */
@@ -109,7 +125,7 @@ struct sembuf {
 
 static int semaphore_create_or_connect(snd_pcm_dmix_t *dmix)
 {
-       dmix->semid = semget(dmix->ipc_key, 1, IPC_CREAT | 0666);
+       dmix->semid = semget(dmix->ipc_key, DMIX_IPC_SEMS, IPC_CREAT | 0666);
        if (dmix->semid < 0)
                return -errno;
        return 0;
@@ -121,28 +137,28 @@ static int semaphore_discard(snd_pcm_dmix_t *dmix)
                return -EINVAL;
        if (semctl(dmix->semid, 0, IPC_RMID, NULL) < 0)
                return -errno;
-       dmix->semlock = 0;
        dmix->semid = -1;
        return 0;
 }
 
-static int semaphore_down(snd_pcm_dmix_t *dmix)
+static int semaphore_down(snd_pcm_dmix_t *dmix, int sem_num)
 {
-       static struct sembuf op[2] = { { 0, 0, SEM_UNDO }, { 0, 1, SEM_UNDO | IPC_NOWAIT } };
+       struct sembuf op[2] = { { 0, 0, SEM_UNDO }, { 0, 1, SEM_UNDO | IPC_NOWAIT } };
        assert(dmix->semid >= 0);
-       if (semop(dmix->semid, op, 1) < 0)
+       op[0].sem_num = sem_num;
+       op[1].sem_num = sem_num;
+       if (semop(dmix->semid, op, 2) < 0)
                return -errno;
-       dmix->semlock = 1;
        return 0;
 }
 
-static int semaphore_up(snd_pcm_dmix_t *dmix)
+static int semaphore_up(snd_pcm_dmix_t *dmix, int sem_num)
 {
-       static struct sembuf op = { 0, -1, SEM_UNDO | IPC_NOWAIT };
+       struct sembuf op = { 0, -1, SEM_UNDO | IPC_NOWAIT };
        assert(dmix->semid >= 0);
+       op.sem_num = sem_num;
        if (semop(dmix->semid, &op, 1) < 0)
                return -errno;
-       dmix->semlock = 0;
        return 0;
 }
 
@@ -279,6 +295,12 @@ static int send_fd(int sock, void *data, size_t len, int fd)
        return ret;
 }
 
+#if 0
+#define server_printf(fmt, args...) printf(fmt, ##args)
+#else
+#define server_printf(fmt, args...) /* nothing */
+#endif
+
 static void server_job(snd_pcm_dmix_t *dmix)
 {
        int ret, sck, i;
@@ -287,7 +309,7 @@ static void server_job(snd_pcm_dmix_t *dmix)
        
        /* close all files to free resources */
        i = sysconf(_SC_OPEN_MAX);
-       while (--i >= 0) {
+       while (--i >= 3) {
                if (i != dmix->server_fd && i != dmix->hw_fd)
                        close(i);
        }
@@ -298,22 +320,27 @@ static void server_job(snd_pcm_dmix_t *dmix)
        pfds[0].fd = dmix->server_fd;
        pfds[0].events = POLLIN | POLLERR | POLLHUP;
 
+       server_printf("DMIX SERVER STARTED\n");
        while (1) {
                ret = poll(pfds, current + 1, 500);
+               server_printf("DMIX SERVER: poll ret = %i, revents[0] = 0x%x\n", ret, pfds[0].revents);
                if (ret < 0)    /* some error */
                        break;
-               if (ret == 0) { /* timeout */
+               if (ret == 0 || pfds[0].revents & (POLLERR | POLLHUP)) {        /* timeout or error? */
                        struct shmid_ds buf;
+                       semaphore_down(dmix, DMIX_IPC_SEM_CLIENT);
                        if (shmctl(dmix->shmid, IPC_STAT, &buf) < 0) {
                                shm_discard(dmix);
                                continue;
                        }
-                       if (buf.shm_nattch == 0)        /* server is the last user, exit */
+                       server_printf("DMIX SERVER: nattch = %i\n", (int)buf.shm_nattch);
+                       if (buf.shm_nattch == 1)        /* server is the last user, exit */
                                break;
+                       semaphore_up(dmix, DMIX_IPC_SEM_CLIENT);
+                       continue;
                }
-               if (pfds[0].revents & (POLLERR | POLLHUP))
-                       break;
                if (pfds[0].revents & POLLIN) {
+                       ret--;
                        sck = accept(dmix->server_fd, 0, 0);
                        if (sck >= 0) {
                                if (current == max) {
@@ -327,20 +354,22 @@ static void server_job(snd_pcm_dmix_t *dmix)
                                }
                        }
                }
-               for (i = 0; i < max; i++) {
+               for (i = 0; i < max && ret > 0; i++) {
                        struct pollfd *pfd = &pfds[i+1];
                        unsigned char cmd;
                        if (pfd->revents & (POLLERR | POLLHUP)) {
+                               ret--;
                                close(pfd->fd);
                                pfd->fd = -1;
                                continue;
                        }
                        if (!(pfd->revents & POLLIN))
                                continue;
+                       ret--;
                        if (read(pfd->fd, &cmd, 1) == 1)
                                cmd = 0 /*process command */;
                }
-               for (i = 0; i < max; i++) {
+               for (i = 0; i < max && ret > 0; i++) {
                        if (pfds[i+1].fd < 0) {
                                if (i + 1 != max)
                                        memcpy(&pfds[i+1], &pfds[i+2], sizeof(struct pollfd) * (max - i - 1));
@@ -349,8 +378,10 @@ static void server_job(snd_pcm_dmix_t *dmix)
                }
        }
        close(dmix->server_fd);
-       close(dmix->poll_fd);
+       close(dmix->hw_fd);
        shm_discard(dmix);
+       semaphore_discard(dmix);
+       server_printf("DMIX SERVER EXIT\n");
        exit(EXIT_SUCCESS);
 }
 
@@ -390,8 +421,8 @@ static int server_create(snd_pcm_dmix_t *dmix)
 static int server_discard(snd_pcm_dmix_t *dmix)
 {
        if (dmix->server) {
-               kill(dmix->server_pid, SIGTERM);
-               waitpid(dmix->server_pid, NULL, 0);
+               //kill(dmix->server_pid, SIGTERM);
+               //waitpid(dmix->server_pid, NULL, 0);
                dmix->server_pid = (pid_t)-1;
        }
        if (dmix->server_fd > 0) {
@@ -445,7 +476,7 @@ static int client_discard(snd_pcm_dmix_t *dmix)
 /*
  *  synchronize shm ring buffer with hardware
  */
-static void snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm, snd_pcm_uframes_t size)
+static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm, snd_pcm_uframes_t size)
 {
        snd_pcm_dmix_t *dmix = pcm->private_data;
        snd_pcm_uframes_t appl_ptr;
@@ -454,13 +485,47 @@ static void snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm, snd_pcm_uframes_t size)
        appl_ptr = dmix->appl_ptr - size;
        if (appl_ptr > pcm->boundary)
                appl_ptr += pcm->boundary;
+       /* add sample areas here */
+}
+
+/*
+ *  synchronize hardware pointer (hw_ptr) with ours
+ */
+static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
+{
+       snd_pcm_dmix_t *dmix = pcm->private_data;
+       snd_pcm_uframes_t slave_hw_ptr, old_slave_hw_ptr, avail;
+       snd_pcm_sframes_t diff;
+       
+       old_slave_hw_ptr = dmix->slave_hw_ptr;
+       slave_hw_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
+       diff = slave_hw_ptr - old_slave_hw_ptr;
+       if (diff == 0)          /* fast path */
+               return 0;
+       if (diff < 0) {
+               slave_hw_ptr += dmix->spcm->boundary;
+               diff = slave_hw_ptr - old_slave_hw_ptr;
+       }
+       dmix->hw_ptr += diff;
+       dmix->hw_ptr %= pcm->boundary;
+       // printf("sync ptr diff = %li\n", diff);
+       if (pcm->stop_threshold >= pcm->boundary)       /* don't care */
+               return 0;
+       if ((avail = snd_pcm_mmap_playback_avail(pcm)) >= pcm->stop_threshold) {
+               dmix->state = SND_PCM_STATE_XRUN;
+               dmix->avail_max = avail;
+               return -EPIPE;
+       }
+       if (avail > dmix->avail_max)
+               dmix->avail_max = avail;
+       return 0;
 }
 
 /*
  *  plugin implementation
  */
 
-static int snd_pcm_dmix_nonblock(snd_pcm_t *pcm, int nonblock ATTRIBUTE_UNUSED)
+static int snd_pcm_dmix_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED)
 {
        /* value is cached for us in pcm->mode (SND_PCM_NONBLOCK flag) */
        return 0;
@@ -472,9 +537,28 @@ static int snd_pcm_dmix_async(snd_pcm_t *pcm, int sig, pid_t pid)
        return snd_timer_async(dmix->timer, sig, pid);
 }
 
-static int snd_pcm_dmix_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
+static int snd_pcm_dmix_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
 {
        snd_pcm_dmix_t *dmix = pcm->private_data;
+       unsigned short events;
+       static snd_timer_read_t rbuf[5];        /* can be overwriten by multiple plugins, we don't need the value */
+
+       assert(pfds && nfds == 1 && revents);
+       events = pfds[0].revents;
+       if (events & POLLIN) {
+               events |= POLLOUT;
+               events &= ~POLLIN;
+               /* empty the timer read queue */
+               while (snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)) == sizeof(rbuf)) ;
+       }
+       *revents = events;
+       return 0;
+}
+
+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;
@@ -584,21 +668,22 @@ static int snd_pcm_dmix_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
        return 0;
 }
 
-static int snd_pcm_dmix_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
+static int snd_pcm_dmix_hw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t * params ATTRIBUTE_UNUSED)
 {
-       // snd_pcm_dmix_t *dmix = pcm->private_data;
+       /* values are cached in the pcm structure */
+       
        return 0;
 }
 
-static int snd_pcm_dmix_hw_free(snd_pcm_t *pcm)
+static int snd_pcm_dmix_hw_free(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
 {
-       // snd_pcm_dmix_t *dmix = pcm->private_data;
+       /* values are cached in the pcm structure */
        return 0;
 }
 
-static int snd_pcm_dmix_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
+static int snd_pcm_dmix_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t * params ATTRIBUTE_UNUSED)
 {
-       // snd_pcm_dmix_t *dmix = pcm->private_data;
+       /* values are cached in the pcm structure */
        return 0;
 }
 
@@ -610,72 +695,143 @@ static int snd_pcm_dmix_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * in
 static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 {
        snd_pcm_dmix_t *dmix = pcm->private_data;
+
+       memset(status, 0, sizeof(*status));
+       status->state = dmix->state;
+       status->trigger_tstamp = dmix->trigger_tstamp;
+       gettimeofday(&status->tstamp, 0);
+       status->avail = snd_pcm_mmap_playback_avail(pcm);
+       status->avail_max = status->avail > dmix->avail_max ? status->avail : dmix->avail_max;
+       dmix->avail_max = 0;
        return 0;
 }
 
 static snd_pcm_state_t snd_pcm_dmix_state(snd_pcm_t *pcm)
 {
        snd_pcm_dmix_t *dmix = pcm->private_data;
-       return 0;
+       return dmix->state;
 }
 
 static int snd_pcm_dmix_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 {
        snd_pcm_dmix_t *dmix = pcm->private_data;
-       return 0;
+       int err;
+       
+       assert(pcm && delayp);
+       switch(dmix->state) {
+       case SNDRV_PCM_STATE_DRAINING:
+       case SNDRV_PCM_STATE_RUNNING:
+               err = snd_pcm_dmix_sync_ptr(pcm);
+               if (err < 0)
+                       return err;
+       case SNDRV_PCM_STATE_PREPARED:
+       case SNDRV_PCM_STATE_SUSPENDED:
+               *delayp = snd_pcm_mmap_playback_hw_avail(pcm);
+               return 0;
+       case SNDRV_PCM_STATE_XRUN:
+               return -EPIPE;
+       default:
+               return -EBADFD;
+       }
 }
 
 static int snd_pcm_dmix_hwsync(snd_pcm_t *pcm)
 {
        snd_pcm_dmix_t *dmix = pcm->private_data;
-       return 0;
+
+       switch(dmix->state) {
+       case SNDRV_PCM_STATE_DRAINING:
+       case SNDRV_PCM_STATE_RUNNING:
+               return snd_pcm_dmix_sync_ptr(pcm);
+       case SNDRV_PCM_STATE_PREPARED:
+       case SNDRV_PCM_STATE_SUSPENDED:
+               return 0;
+       case SNDRV_PCM_STATE_XRUN:
+               return -EPIPE;
+       default:
+               return -EBADFD;
+       }
 }
 
 static int snd_pcm_dmix_prepare(snd_pcm_t *pcm)
 {
        snd_pcm_dmix_t *dmix = pcm->private_data;
+
+       assert(pcm->boundary == dmix->spcm->boundary);  /* for sure */
+       dmix->state = SND_PCM_STATE_PREPARED;
+       dmix->appl_ptr = 0;
+       dmix->hw_ptr = 0;
        return 0;
 }
 
 static int snd_pcm_dmix_reset(snd_pcm_t *pcm)
 {
        snd_pcm_dmix_t *dmix = pcm->private_data;
+       dmix->hw_ptr %= pcm->period_size;
+       dmix->appl_ptr = dmix->hw_ptr;
        return 0;
 }
 
 static int snd_pcm_dmix_start(snd_pcm_t *pcm)
 {
        snd_pcm_dmix_t *dmix = pcm->private_data;
+       int err;
+       
+       if (dmix->state != SND_PCM_STATE_PREPARED)
+               return -EBADFD;
+       err = snd_timer_start(dmix->timer);
+       if (err < 0)
+               return err;
+       dmix->state = SND_PCM_STATE_RUNNING;
+       dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
+       snd_pcm_dmix_sync_area(pcm, dmix->appl_ptr < pcm->buffer_size ? dmix->appl_ptr : pcm->buffer_size);
        return 0;
 }
 
 static int snd_pcm_dmix_drop(snd_pcm_t *pcm)
 {
        snd_pcm_dmix_t *dmix = pcm->private_data;
+       if (dmix->state == SND_PCM_STATE_OPEN)
+               return -EBADFD;
+       dmix->state = SND_PCM_STATE_SETUP;
        return 0;
 }
 
 static int snd_pcm_dmix_drain(snd_pcm_t *pcm)
 {
        snd_pcm_dmix_t *dmix = pcm->private_data;
+       if (dmix->state == SND_PCM_STATE_OPEN)
+               return -EBADFD;
+       dmix->state = SND_PCM_STATE_SETUP;
        return 0;
 }
 
 static int snd_pcm_dmix_pause(snd_pcm_t *pcm, int enable)
 {
        snd_pcm_dmix_t *dmix = pcm->private_data;
+        if (enable) {
+               if (dmix->state != SND_PCM_STATE_RUNNING)
+                       return -EBADFD;
+               dmix->state = SND_PCM_STATE_PAUSED;
+       } else {
+               if (dmix->state != SND_PCM_STATE_PAUSED)
+                       return -EBADFD;
+                dmix->state = SND_PCM_STATE_RUNNING;
+       }
        return 0;
 }
 
 static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
-       snd_pcm_dmix_t *dmix = pcm->private_data;
+       /* FIXME: substract samples from the mix ring buffer, too? */
+       snd_pcm_mmap_appl_backward(pcm, frames);
        return frames;
 }
 
-static int snd_pcm_dmix_resume(snd_pcm_t *pcm)
+static int snd_pcm_dmix_resume(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
 {
-       snd_pcm_dmix_t *dmix = pcm->private_data;
+       // snd_pcm_dmix_t *dmix = pcm->private_data;
+       // FIXME
        return 0;
 }
 
@@ -705,7 +861,7 @@ static int snd_pcm_dmix_close(snd_pcm_t *pcm)
 
        if (dmix->timer)
                snd_timer_close(dmix->timer);
-       semaphore_down(dmix);
+       semaphore_down(dmix, DMIX_IPC_SEM_CLIENT);
        snd_pcm_close(dmix->spcm);
        if (dmix->server)
                server_discard(dmix);
@@ -713,9 +869,10 @@ static int snd_pcm_dmix_close(snd_pcm_t *pcm)
                client_discard(dmix);
        if (shm_discard(dmix) > 0) {
                if (semaphore_discard(dmix) < 0)
-                       semaphore_up(dmix);
-       }
-       semaphore_up(dmix);
+                       semaphore_up(dmix, DMIX_IPC_SEM_CLIENT);
+       } else {
+               semaphore_up(dmix, DMIX_IPC_SEM_CLIENT);
+       }
        pcm->private_data = NULL;
        free(dmix);
        return 0;
@@ -725,25 +882,38 @@ 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)
 {
+       int err;
+
        snd_pcm_mmap_appl_forward(pcm, size);
-       snd_pcm_dmix_sync_ptr(pcm, size);
+       err = snd_pcm_dmix_sync_ptr(pcm);
+       if (err < 0)
+               return err;
+       /* ok, we commit the changes after the validation of area */
+       /* it's intended, although the result might be crappy */
+       snd_pcm_dmix_sync_area(pcm, size);
        return size;
 }
 
 static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
 {
-       //snd_pcm_dmix_t *dmix = pcm->private_data;
-       return 0;
+       int err;
+       
+       err = snd_pcm_dmix_sync_ptr(pcm);
+       if (err < 0)
+               return err;
+       return snd_pcm_mmap_playback_avail(pcm);
 }
 
 static void snd_pcm_dmix_dump(snd_pcm_t *pcm, snd_output_t *out)
 {
-       // snd_pcm_dmix_t *dmix = pcm->private_data;
+       snd_pcm_dmix_t *dmix = pcm->private_data;
        snd_output_printf(out, "Direct Stream Mixing PCM\n");
        if (pcm->setup) {
                snd_output_printf(out, "\nIts setup is:\n");
                snd_pcm_dump_setup(pcm, out);
        }
+       if (dmix->spcm)
+               snd_pcm_dump(dmix->spcm, out);
 }
 
 static snd_pcm_ops_t snd_pcm_dmix_ops = {
@@ -757,6 +927,7 @@ static snd_pcm_ops_t snd_pcm_dmix_ops = {
        dump: snd_pcm_dmix_dump,
        nonblock: snd_pcm_dmix_nonblock,
        async: snd_pcm_dmix_async,
+       poll_revents: snd_pcm_dmix_poll_revents,
        mmap: snd_pcm_dmix_mmap,
        munmap: snd_pcm_dmix_munmap,
 };
@@ -792,7 +963,7 @@ static int snd_pcm_dmix_initialize_slave(snd_pcm_dmix_t *dmix, snd_pcm_t *spcm,
        snd_pcm_hw_params_t *hw_params;
        snd_pcm_sw_params_t *sw_params;
        int ret, buffer_is_not_initialized;
-       snd_pcm_uframes_t boundary, buffer_size;
+       snd_pcm_uframes_t boundary;
 
        hw_params = &dmix->shmptr->hw_params;
        sw_params = &dmix->shmptr->sw_params;
@@ -887,14 +1058,14 @@ static int snd_pcm_dmix_initialize_slave(snd_pcm_dmix_t *dmix, snd_pcm_t *spcm,
                SNDERR("unable to set stop threshold\n");
                return ret;
        }
-       ret = INTERNAL(snd_pcm_hw_params_get_buffer_size)(hw_params, &buffer_size);
+       ret = snd_pcm_sw_params_set_silence_threshold(spcm, sw_params, 0);
        if (ret < 0) {
-               SNDERR("unable to get buffer size\n");
+               SNDERR("unable to set silence threshold\n");
                return ret;
        }
-       ret = snd_pcm_sw_params_set_silence_threshold(spcm, sw_params, buffer_size);
+       ret = snd_pcm_sw_params_set_silence_size(spcm, sw_params, boundary);
        if (ret < 0) {
-               SNDERR("unable to set silence threshold\n");
+               SNDERR("unable to set silence threshold (please upgrade to 0.9.0rc8+ driver)\n");
                return ret;
        }
 
@@ -924,6 +1095,7 @@ static int snd_pcm_dmix_initialize_poll_fd(snd_pcm_dmix_t *dmix)
        snd_pcm_info_t *info;
        snd_timer_params_t *params;
        char name[128];
+       struct pollfd fd;
        
        snd_pcm_info_alloca(&info);
        snd_timer_params_alloca(&params);
@@ -949,6 +1121,12 @@ static int snd_pcm_dmix_initialize_poll_fd(snd_pcm_dmix_t *dmix)
                SNDERR("unable to set timer parameters\n", name);
                 return ret;
        }
+       if (snd_timer_poll_descriptors_count(dmix->timer) != 1) {
+               SNDERR("unable to use timer with fd more than one!!!\n", name);
+               return ret;
+       }
+       snd_timer_poll_descriptors(dmix->timer, &fd, 1);
+       dmix->poll_fd = fd.fd;
        return 0;
 }
 
@@ -1002,7 +1180,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
                goto _err;
        }
        
-       ret = semaphore_down(dmix);
+       ret = semaphore_down(dmix, DMIX_IPC_SEM_CLIENT);
        if (ret < 0) {
                semaphore_discard(dmix);
                goto _err;
@@ -1017,6 +1195,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
        pcm->ops = &snd_pcm_dmix_ops;
        pcm->fast_ops = &snd_pcm_dmix_fast_ops;
        pcm->private_data = dmix;
+       dmix->state = SND_PCM_STATE_OPEN;
 
        if (first_instance) {
                ret = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
@@ -1064,12 +1243,15 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
        }
                
        pcm->poll_fd = dmix->poll_fd;
+       pcm->poll_events = POLLIN;      /* it's different than other plugins */
                
        dmix->shmptr->type = spcm->type;
 
        snd_pcm_set_hw_ptr(pcm, &dmix->hw_ptr, -1, 0);
        snd_pcm_set_appl_ptr(pcm, &dmix->appl_ptr, -1, 0);
 
+       semaphore_up(dmix, DMIX_IPC_SEM_CLIENT);
+
        *pcmp = pcm;
        return 0;
        
@@ -1086,7 +1268,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
                if (shm_discard(dmix) > 0) {
                        if (dmix->semid >= 0) {
                                if (semaphore_discard(dmix) < 0)
-                                       semaphore_up(dmix);
+                                       semaphore_up(dmix, DMIX_IPC_SEM_CLIENT);
                        }
                }
        }
index 0eee4c323593383a03dde8434f88e903fc9840b1..e14217c88d2feef10113097750e3483fc16463d2 100644 (file)
@@ -492,6 +492,7 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
        pcm->fast_ops = &snd_pcm_file_fast_ops;
        pcm->private_data = file;
        pcm->poll_fd = slave->poll_fd;
+       pcm->poll_events = slave->poll_events;
        snd_pcm_link_hw_ptr(pcm, slave);
        snd_pcm_link_appl_ptr(pcm, slave);
        *pcmp = pcm;
index cd0b96184c5c3cf3df15106e63cbf489e832b8b6..6f9cf98c7782e5041a1ca21f5606930f7a9d413e 100644 (file)
@@ -351,6 +351,7 @@ int snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int
        pcm->fast_ops = &snd_pcm_hooks_fast_ops;
        pcm->private_data = h;
        pcm->poll_fd = slave->poll_fd;
+       pcm->poll_events = slave->poll_events;
        snd_pcm_link_hw_ptr(pcm, slave);
        snd_pcm_link_appl_ptr(pcm, slave);
        *pcmp = pcm;
index 85f9892c76812dba1b479620a083f0bfe24d6dfc..d4b58b8ef120b49b4012941b98aad6331b1f7f49 100644 (file)
@@ -898,6 +898,7 @@ int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name,
        pcm->fast_ops = &snd_pcm_hw_fast_ops;
        pcm->private_data = hw;
        pcm->poll_fd = fd;
+       pcm->poll_events = info.stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN;
 
        *pcmp = pcm;
 
index 696203b6af6ab808dca97d8c2145dc132ef31e01..7d24eddb7b7e093cd13f7d86e99ff9e3633331dc 100644 (file)
@@ -706,6 +706,7 @@ static snd_pcm_ops_t snd_pcm_ladspa_ops = {
        dump: snd_pcm_ladspa_dump,
        nonblock: snd_pcm_plugin_nonblock,
        async: snd_pcm_plugin_async,
+       poll_revents: snd_pcm_plugin_poll_revents,
        mmap: snd_pcm_plugin_mmap,
        munmap: snd_pcm_plugin_munmap,
 };
@@ -1173,6 +1174,7 @@ int snd_pcm_ladspa_open(snd_pcm_t **pcmp, const char *name,
        pcm->fast_ops = &snd_pcm_plugin_fast_ops;
        pcm->private_data = ladspa;
        pcm->poll_fd = slave->poll_fd;
+       pcm->poll_events = slave->poll_events;
        snd_pcm_set_hw_ptr(pcm, &ladspa->plug.hw_ptr, -1, 0);
        snd_pcm_set_appl_ptr(pcm, &ladspa->plug.appl_ptr, -1, 0);
        *pcmp = pcm;
index 1280db4279c6b56d59aee445a2eebd54d951b49a..b49b4ae65481c99c739e43076203ce419d4842ed 100644 (file)
@@ -360,6 +360,7 @@ static snd_pcm_ops_t snd_pcm_lfloat_ops = {
        dump: snd_pcm_lfloat_dump,
        nonblock: snd_pcm_plugin_nonblock,
        async: snd_pcm_plugin_async,
+       poll_revents: snd_pcm_plugin_poll_revents,
        mmap: snd_pcm_plugin_mmap,
        munmap: snd_pcm_plugin_munmap,
 };
@@ -407,6 +408,7 @@ int snd_pcm_lfloat_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo
        pcm->fast_ops = &snd_pcm_plugin_fast_ops;
        pcm->private_data = lfloat;
        pcm->poll_fd = slave->poll_fd;
+       pcm->poll_events = slave->poll_events;
        snd_pcm_set_hw_ptr(pcm, &lfloat->plug.hw_ptr, -1, 0);
        snd_pcm_set_appl_ptr(pcm, &lfloat->plug.appl_ptr, -1, 0);
        *pcmp = pcm;
index 4a4e42917e6505bd825133cd423b3e13e18fd986..437d01e387adc98c8b56c7ae58540e17ca556281 100644 (file)
@@ -416,6 +416,7 @@ static snd_pcm_ops_t snd_pcm_linear_ops = {
        dump: snd_pcm_linear_dump,
        nonblock: snd_pcm_plugin_nonblock,
        async: snd_pcm_plugin_async,
+       poll_revents: snd_pcm_plugin_poll_revents,
        mmap: snd_pcm_plugin_mmap,
        munmap: snd_pcm_plugin_munmap,
 };
@@ -463,6 +464,7 @@ int snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo
        pcm->fast_ops = &snd_pcm_plugin_fast_ops;
        pcm->private_data = linear;
        pcm->poll_fd = slave->poll_fd;
+       pcm->poll_events = slave->poll_events;
        snd_pcm_set_hw_ptr(pcm, &linear->plug.hw_ptr, -1, 0);
        snd_pcm_set_appl_ptr(pcm, &linear->plug.appl_ptr, -1, 0);
        *pcmp = pcm;
index a2be05ea919d1fecfc455dab075ce5341e7f563c..14de711ec0ae3e9c7a45a4fcfef54c4adef4825e 100644 (file)
@@ -125,6 +125,7 @@ typedef struct {
        int (*close)(snd_pcm_t *pcm);
        int (*nonblock)(snd_pcm_t *pcm, int nonblock);
        int (*async)(snd_pcm_t *pcm, int sig, pid_t pid);
+       int (*poll_revents)(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
        int (*info)(snd_pcm_t *pcm, snd_pcm_info_t *info);
        int (*hw_refine)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
        int (*hw_params)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
@@ -164,6 +165,7 @@ struct _snd_pcm {
        snd_pcm_stream_t stream;
        int mode;
        int poll_fd;
+       unsigned short poll_events;
        int setup;
        snd_pcm_access_t access;        /* access mode */
        snd_pcm_format_t format;        /* SND_PCM_FORMAT_* */
index 26e169b7864d6a762938950da9e9ec50bd259b89..0eb6a07ef3dc210bc1cd87c2cc51ce85f3be7c59 100644 (file)
@@ -655,6 +655,7 @@ int snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name, unsigned int frequenc
        pcm->fast_ops = &snd_pcm_meter_fast_ops;
        pcm->private_data = meter;
        pcm->poll_fd = slave->poll_fd;
+       pcm->poll_events = slave->poll_events;
        snd_pcm_link_hw_ptr(pcm, slave);
        snd_pcm_link_appl_ptr(pcm, slave);
        *pcmp = pcm;
index 6534f84e5926f951111eb3f73025bae39e4b7626..16a389d6c53b1c78725b03831b6d8b6bbf2f648f 100644 (file)
@@ -415,6 +415,7 @@ static snd_pcm_ops_t snd_pcm_mulaw_ops = {
        dump: snd_pcm_mulaw_dump,
        nonblock: snd_pcm_plugin_nonblock,
        async: snd_pcm_plugin_async,
+       poll_revents: snd_pcm_plugin_poll_revents,
        mmap: snd_pcm_plugin_mmap,
        munmap: snd_pcm_plugin_munmap,
 };
@@ -462,6 +463,7 @@ int snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfor
        pcm->fast_ops = &snd_pcm_plugin_fast_ops;
        pcm->private_data = mulaw;
        pcm->poll_fd = slave->poll_fd;
+       pcm->poll_events = slave->poll_events;
        snd_pcm_set_hw_ptr(pcm, &mulaw->plug.hw_ptr, -1, 0);
        snd_pcm_set_appl_ptr(pcm, &mulaw->plug.appl_ptr, -1, 0);
        *pcmp = pcm;
index c52f094e2a25f004ee7ba8e6bbd05c7b38774630..0be871650c103848b66516156ffc726cad85ba89 100644 (file)
@@ -698,6 +698,7 @@ int snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
        pcm->fast_ops = &snd_pcm_multi_fast_ops;
        pcm->private_data = multi;
        pcm->poll_fd = multi->slaves[master_slave].pcm->poll_fd;
+       pcm->poll_events = multi->slaves[master_slave].pcm->poll_events;
        snd_pcm_link_hw_ptr(pcm, multi->slaves[master_slave].pcm);
        snd_pcm_link_appl_ptr(pcm, multi->slaves[master_slave].pcm);
        *pcmp = pcm;
index c77038507bb5f16f79215dd627e6272b9525b4a8..a727f2b11f6b487c96681ddaff5010de3e4c75ad 100644 (file)
@@ -378,6 +378,7 @@ int snd_pcm_null_open(snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t strea
        pcm->fast_ops = &snd_pcm_null_fast_ops;
        pcm->private_data = null;
        pcm->poll_fd = fd;
+       pcm->poll_events = stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN;
        snd_pcm_set_hw_ptr(pcm, &null->hw_ptr, -1, 0);
        snd_pcm_set_appl_ptr(pcm, &null->appl_ptr, -1, 0);
        *pcmp = pcm;
index 0648faf02d0b3ef75f4636fef99222db1cdef972..8d4d255b03081fbfe0f9ad5a5f4958b8560ad000 100644 (file)
@@ -1020,6 +1020,9 @@ int snd_pcm_hw_param_never_eq(const snd_pcm_hw_params_t *params,
        return -EINVAL;
 }
 
+#if 0
+#define CHOOSE_DEBUG
+#endif
 
 /* Choose one configuration from configuration space defined by PARAMS
    The configuration chosen is that obtained fixing in this order:
@@ -1035,6 +1038,12 @@ int snd_pcm_hw_param_never_eq(const snd_pcm_hw_params_t *params,
 static int snd_pcm_hw_params_choose(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
 {
        int err;
+#ifdef CHOOSE_DEBUG
+       snd_output_t *log;
+       snd_output_stdio_attach(&log, stderr, 0);
+       snd_output_printf(log, "CHOOSE called:\n");
+       snd_pcm_hw_params_dump(params, log);
+#endif
 
        err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_ACCESS, NULL, 0);
        if (err < 0)
@@ -1063,6 +1072,11 @@ static int snd_pcm_hw_params_choose(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
        err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_TICK_TIME, NULL, 0);
        if (err < 0)
                return err;
+#ifdef CHOOSE_DEBUG
+       snd_output_printf(log, "choose done\n");
+       snd_pcm_hw_params_dump(params, log);
+       snd_output_close(log);
+#endif
        return 0;
 }
 
@@ -2204,6 +2218,7 @@ int snd_pcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
        res = pcm->ops->hw_refine(pcm->op_arg, params);
 #ifdef REFINE_DEBUG
        snd_output_printf(log, "refine done - result = %i\n", res);
+       snd_pcm_hw_params_dump(params, log);
        snd_output_close(log);
 #endif
        return res;
index e0c05faa3f49c8d31cb86fd010cc36e88ab597af..6328d1475e69b849c4cbf7a5c00bef4e74597156 100644 (file)
@@ -92,6 +92,12 @@ static int snd_pcm_plug_async(snd_pcm_t *pcm, int sig, pid_t pid)
        return snd_pcm_async(plug->slave, sig, pid);
 }
 
+static int snd_pcm_plug_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
+{
+       snd_pcm_plug_t *plug = pcm->private_data;
+       return snd_pcm_poll_descriptors_revents(plug->slave, pfds, nfds, revents);
+}
+
 static int snd_pcm_plug_info(snd_pcm_t *pcm, snd_pcm_info_t *info)
 {
        snd_pcm_plug_t *plug = pcm->private_data;
@@ -959,6 +965,7 @@ static snd_pcm_ops_t snd_pcm_plug_ops = {
        dump: snd_pcm_plug_dump,
        nonblock: snd_pcm_plug_nonblock,
        async: snd_pcm_plug_async,
+       poll_revents: snd_pcm_plug_poll_revents,
        mmap: snd_pcm_plug_mmap,
        munmap: snd_pcm_plug_munmap,
 };
@@ -1013,6 +1020,7 @@ int snd_pcm_plug_open(snd_pcm_t **pcmp,
        pcm->fast_op_arg = slave->fast_op_arg;
        pcm->private_data = plug;
        pcm->poll_fd = slave->poll_fd;
+       pcm->poll_events = slave->poll_events;
        snd_pcm_link_hw_ptr(pcm, slave);
        snd_pcm_link_appl_ptr(pcm, slave);
        *pcmp = pcm;
index 858fdd2637e4086034962e6ffe4e76b63ce7ba11..b01d30f8df186cab505483e9920eaec7bf745f57 100644 (file)
@@ -158,6 +158,12 @@ int snd_pcm_plugin_async(snd_pcm_t *pcm, int sig, pid_t pid)
        return snd_pcm_async(plugin->slave, sig, pid);
 }
 
+int snd_pcm_plugin_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
+{
+       snd_pcm_plugin_t *plugin = pcm->private_data;
+       return snd_pcm_poll_descriptors_revents(plugin->slave, pfds, nfds, revents);
+}
+
 int snd_pcm_plugin_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
 {
        snd_pcm_plugin_t *plugin = pcm->private_data;
index df8f9c4d88793e34c75d755b7fa477ef1255904a..a4353c51104f9a340b7912b28a9b32d72242f739 100644 (file)
@@ -56,6 +56,7 @@ int snd_pcm_plugin_close(snd_pcm_t *pcm);
 int snd_pcm_plugin_card(snd_pcm_t *pcm);
 int snd_pcm_plugin_nonblock(snd_pcm_t *pcm, int nonblock);
 int snd_pcm_plugin_async(snd_pcm_t *pcm, int sig, pid_t pid);
+int snd_pcm_plugin_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
 int snd_pcm_plugin_info(snd_pcm_t *pcm, snd_pcm_info_t * info);
 int snd_pcm_plugin_hw_free(snd_pcm_t *pcm);
 int snd_pcm_plugin_sw_refine(snd_pcm_t *pcm, snd_pcm_sw_params_t *params);
index f2270c8c6b273a595b03eddec51d193ec4f9d053..395f5b67a9930b55782fd27001cd218133cb495a 100644 (file)
@@ -438,11 +438,39 @@ static int snd_pcm_rate_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
        snd_pcm_rate_t *rate = pcm->private_data;
        snd_pcm_t *slave = rate->plug.slave;
        snd_pcm_sw_params_t sparams;
+       snd_pcm_uframes_t boundary1, boundary2;
+
        sparams = *params;
+       if ((rate->pitch >= DIV ? 1 : 0) ^ (pcm->stream == SND_PCM_STREAM_CAPTURE ? 1 : 0)) {
+               boundary1 = pcm->buffer_size;
+               boundary2 = slave->buffer_size;
+               while (boundary2 * 2 <= LONG_MAX - slave->buffer_size) {
+                       boundary1 *= 2;
+                       boundary2 *= 2;
+               }
+       } else {
+               boundary1 = pcm->buffer_size;
+               boundary2 = slave->buffer_size;
+               while (boundary1 * 2 <= LONG_MAX - pcm->buffer_size) {
+                       boundary1 *= 2;
+                       boundary2 *= 2;
+               }
+       }
+       params->boundary = boundary1;
+       sparams.boundary = boundary2;
+       if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
+               rate->pitch = (((u_int64_t)boundary2 * DIV) + boundary1 / 2) / boundary1;
+       } else {
+               rate->pitch = (((u_int64_t)boundary1 * DIV) + boundary2 / 2) / boundary2;
+       }
        recalc(pcm, &sparams.avail_min);
        recalc(pcm, &sparams.xfer_align);
        recalc(pcm, &sparams.start_threshold);
-       recalc(pcm, &sparams.stop_threshold);
+       if (sparams.stop_threshold >= sparams.boundary) {
+               sparams.stop_threshold = sparams.boundary;
+       } else {
+               recalc(pcm, &sparams.stop_threshold);
+       }
        recalc(pcm, &sparams.silence_threshold);
        recalc(pcm, &sparams.silence_size);
        return snd_pcm_sw_params(slave, &sparams);
@@ -548,6 +576,7 @@ static snd_pcm_ops_t snd_pcm_rate_ops = {
        dump: snd_pcm_rate_dump,
        nonblock: snd_pcm_plugin_nonblock,
        async: snd_pcm_plugin_async,
+       poll_revents: snd_pcm_plugin_poll_revents,
        mmap: snd_pcm_plugin_mmap,
        munmap: snd_pcm_plugin_munmap,
 };
@@ -599,6 +628,7 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sform
        pcm->fast_ops = &snd_pcm_plugin_fast_ops;
        pcm->private_data = rate;
        pcm->poll_fd = slave->poll_fd;
+       pcm->poll_events = slave->poll_events;
        snd_pcm_set_hw_ptr(pcm, &rate->plug.hw_ptr, -1, 0);
        snd_pcm_set_appl_ptr(pcm, &rate->plug.appl_ptr, -1, 0);
        *pcmp = pcm;
index 73530bc58f0a592c02d633386d1605d386cd83f3..72faae0701ae9947294ad5fc70960780c2788ca6 100644 (file)
@@ -732,6 +732,7 @@ static snd_pcm_ops_t snd_pcm_route_ops = {
        dump: snd_pcm_route_dump,
        nonblock: snd_pcm_plugin_nonblock,
        async: snd_pcm_plugin_async,
+       poll_revents: snd_pcm_plugin_poll_revents,
        mmap: snd_pcm_plugin_mmap,
        munmap: snd_pcm_plugin_munmap,
 };
@@ -864,6 +865,7 @@ int snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
        pcm->fast_ops = &snd_pcm_plugin_fast_ops;
        pcm->private_data = route;
        pcm->poll_fd = slave->poll_fd;
+       pcm->poll_events = slave->poll_events;
        snd_pcm_set_hw_ptr(pcm, &route->plug.hw_ptr, -1, 0);
        snd_pcm_set_appl_ptr(pcm, &route->plug.appl_ptr, -1, 0);
        err = route_load_ttable(&route->params, pcm->stream, tt_ssize, ttable, tt_cused, tt_sused);
index 04a9a681dea7ece488ab95380c1ea363780ac442..7b82296ccd0f4fec09a27070b19ae57b76df3123 100644 (file)
@@ -1431,6 +1431,7 @@ int snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, const char *sname,
        pcm->fast_ops = &snd_pcm_share_fast_ops;
        pcm->private_data = share;
        pcm->poll_fd = share->client_socket;
+       pcm->poll_events = stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN;
        snd_pcm_set_hw_ptr(pcm, &share->hw_ptr, -1, 0);
        snd_pcm_set_appl_ptr(pcm, &share->appl_ptr, -1, 0);
 
index a9558e360339f457bd21e492bb16baed2a1700b3..687863263636004821941f14ce15f4c644430430 100644 (file)
@@ -788,6 +788,7 @@ int snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name,
                return err;
        }
        pcm->poll_fd = err;
+       pcm->poll_events = stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN;
        snd_pcm_set_hw_ptr(pcm, &ctrl->hw.ptr, -1, 0);
        snd_pcm_set_appl_ptr(pcm, &ctrl->appl.ptr, -1, 0);
        *pcmp = pcm;