OSDN Git Service

Fixed pointers use
authorAbramo Bagnara <abramo@alsa-project.org>
Sat, 14 Oct 2000 18:34:51 +0000 (18:34 +0000)
committerAbramo Bagnara <abramo@alsa-project.org>
Sat, 14 Oct 2000 18:34:51 +0000 (18:34 +0000)
aserver/aserver.c
include/aserver.h
src/pcm/pcm.c
src/pcm/pcm_mmap.c
src/pcm/pcm_route.c
src/pcm/pcm_share.c
src/pcm/pcm_shm.c

index a35570c..8cda2b3 100644 (file)
@@ -288,7 +288,7 @@ int pcm_shm_open(client_t *client, int *cookie)
        }
        client->transport.shm.ctrl_id = shmid;
        client->transport.shm.ctrl = shmat(shmid, 0, 0);
-       if (!client->transport.shm.ctrl) {
+       if (client->transport.shm.ctrl == (void*) -1) {
                result = -errno;
                shmctl(shmid, IPC_RMID, 0);
                SYSERR("shmat");
@@ -360,7 +360,7 @@ int shm_ack_fd(client_t *client, int fd)
 
 int pcm_shm_cmd(client_t *client)
 {
-       snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
        char buf[1];
        int err;
        int cmd;
@@ -376,34 +376,39 @@ int pcm_shm_cmd(client_t *client)
                ctrl->result = snd_pcm_async(pcm, ctrl->u.async.sig, ctrl->u.async.pid);
                break;
        case SND_PCM_IOCTL_INFO:
-               ctrl->result = snd_pcm_info(pcm, &ctrl->u.info);
+               ctrl->result = snd_pcm_info(pcm, (snd_pcm_info_t *) &ctrl->u.info);
                break;
        case SND_PCM_IOCTL_PARAMS:
-               ctrl->result = snd_pcm_params(pcm, &ctrl->u.params);
+               ctrl->result = snd_pcm_params(pcm, (snd_pcm_params_t *) &ctrl->u.params);
                break;
        case SND_PCM_IOCTL_PARAMS_INFO:
-               ctrl->result = snd_pcm_params_info(pcm, &ctrl->u.params_info);
+               ctrl->result = snd_pcm_params_info(pcm, (snd_pcm_params_info_t *) &ctrl->u.params_info);
                break;
        case SND_PCM_IOCTL_SETUP:
-               ctrl->result = snd_pcm_setup(pcm, &ctrl->u.setup);
+               ctrl->result = snd_pcm_setup(pcm, (snd_pcm_setup_t *) &ctrl->u.setup);
                break;
        case SND_PCM_IOCTL_STATUS:
-               ctrl->result = snd_pcm_status(pcm, &ctrl->u.status);
+               ctrl->result = snd_pcm_status(pcm, (snd_pcm_status_t *) &ctrl->u.status);
                break;
        case SND_PCM_IOCTL_STATE:
                ctrl->result = snd_pcm_state(pcm);
                break;
        case SND_PCM_IOCTL_DELAY:
-               ctrl->result = snd_pcm_delay(pcm, &ctrl->u.delay);
+               ctrl->result = snd_pcm_delay(pcm, (ssize_t *) &ctrl->u.delay.frames);
                break;
        case SND_PCM_IOCTL_AVAIL_UPDATE:
                ctrl->result = snd_pcm_avail_update(pcm);
+               ctrl->hw_ptr = *pcm->hw_ptr;
                break;
        case SND_PCM_IOCTL_PREPARE:
                ctrl->result = snd_pcm_prepare(pcm);
+               ctrl->appl_ptr = *pcm->appl_ptr;
+               ctrl->hw_ptr = *pcm->hw_ptr;
                break;
        case SND_PCM_IOCTL_START:
                ctrl->result = snd_pcm_start(pcm);
+               ctrl->appl_ptr = *pcm->appl_ptr;
+               ctrl->hw_ptr = *pcm->hw_ptr;
                break;
        case SND_PCM_IOCTL_DRAIN:
                ctrl->result = snd_pcm_drain(pcm);
@@ -412,19 +417,20 @@ int pcm_shm_cmd(client_t *client)
                ctrl->result = snd_pcm_drop(pcm);
                break;
        case SND_PCM_IOCTL_PAUSE:
-               ctrl->result = snd_pcm_pause(pcm, ctrl->u.pause);
+               ctrl->result = snd_pcm_pause(pcm, ctrl->u.pause.enable);
                break;
        case SND_PCM_IOCTL_CHANNEL_INFO:
-               ctrl->result = snd_pcm_channel_info(pcm, &ctrl->u.channel_info);
+               ctrl->result = snd_pcm_channel_info(pcm, (snd_pcm_channel_info_t *) &ctrl->u.channel_info);
                break;
        case SND_PCM_IOCTL_CHANNEL_PARAMS:
-               ctrl->result = snd_pcm_channel_params(pcm, &ctrl->u.channel_params);
+               ctrl->result = snd_pcm_channel_params(pcm, (snd_pcm_channel_params_t *) &ctrl->u.channel_params);
                break;
        case SND_PCM_IOCTL_CHANNEL_SETUP:
-               ctrl->result = snd_pcm_channel_setup(pcm, &ctrl->u.channel_setup);
+               ctrl->result = snd_pcm_channel_setup(pcm, (snd_pcm_channel_setup_t *) &ctrl->u.channel_setup);
                break;
        case SND_PCM_IOCTL_REWIND:
-               ctrl->result = snd_pcm_rewind(pcm, ctrl->u.rewind);
+               ctrl->result = snd_pcm_rewind(pcm, ctrl->u.rewind.frames);
+               ctrl->appl_ptr = *pcm->appl_ptr;
                break;
        case SND_PCM_IOCTL_LINK:
        {
@@ -454,11 +460,18 @@ int pcm_shm_cmd(client_t *client)
                }
                i = &pcm->mmap_info[index];
                if (i->type == SND_PCM_MMAP_USER) {
-                       i->u.user.shmid = shmget(IPC_PRIVATE, i->size, 0666);
-                       if (i->u.user.shmid < 0) {
+                       void *ptr;
+                       int shmid = shmget(IPC_PRIVATE, i->size, 0666);
+                       if (shmid < 0) {
                                SYSERR("shmget");
                                return -EINVAL;
                        }
+                       ptr = shmat(shmid, i->addr, 0);
+                       if (ptr != i->addr) {
+                               SYSERR("shmat");
+                               return -EINVAL;
+                       }
+                       i->u.user.shmid = shmid;
                }
                ctrl->u.mmap_info = *i;
                ctrl->u.mmap_info.index = index;
@@ -483,7 +496,8 @@ int pcm_shm_cmd(client_t *client)
                break;
        }
        case SND_PCM_IOCTL_MMAP_FORWARD:
-               ctrl->result = snd_pcm_mmap_forward(pcm, ctrl->u.mmap_forward);
+               ctrl->result = snd_pcm_mmap_forward(pcm, ctrl->u.mmap_forward.frames);
+               ctrl->appl_ptr = *pcm->appl_ptr;
                break;
        case SND_PCM_IOCTL_POLL_DESCRIPTOR:
                ctrl->result = 0;
@@ -895,7 +909,7 @@ int server(char *sockname, int port)
                struct pollfd pfds[OPEN_MAX];
                size_t pfds_count;
                do {
-                       err = poll(pollfds, pollfds_count, 1000);
+                       err = poll(pollfds, pollfds_count, -1);
                } while (err == 0);
                if (err < 0) {
                        SYSERR("poll");
index 9a68b0d..643c568 100644 (file)
@@ -34,6 +34,8 @@
 typedef struct {
        long result;
        int cmd;
+       size_t hw_ptr;
+       size_t appl_ptr;
        union {
                struct {
                        int sig;
@@ -45,14 +47,24 @@ typedef struct {
                snd_pcm_params_info_t params_info;
                snd_pcm_setup_t setup;
                snd_pcm_status_t status;
-               ssize_t delay;
-               int pause;
+               struct {
+                       ssize_t frames;
+               } delay;
+               struct {
+                       int enable;
+               } pause;
                snd_pcm_channel_info_t channel_info;
                snd_pcm_channel_params_t channel_params;
                snd_pcm_channel_setup_t channel_setup;
-               ssize_t rewind;
-               int link;
-               size_t mmap_forward;
+               struct {
+                       ssize_t frames;
+               } rewind;
+               struct {
+                       int fd;
+               } link;
+               struct {
+                       ssize_t frames;
+               } mmap_forward;
        } u;
        char data[0];
 } snd_pcm_shm_ctrl_t;
index 5c85320..e1a797e 100644 (file)
@@ -1039,6 +1039,7 @@ ssize_t snd_pcm_write_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *areas,
                        err = snd_pcm_start(pcm);
                        if (err < 0)
                                break;
+                       state = SND_PCM_STATE_RUNNING;
                }
        }
        if (xfer > 0)
index ffdb845..4eb51d4 100644 (file)
@@ -122,7 +122,6 @@ ssize_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm,
                                 size_t *slave_sizep)
 {
        size_t xfer;
-       ssize_t err = 0;
        if (slave_sizep && *slave_sizep < size)
                size = *slave_sizep;
        xfer = 0;
@@ -132,19 +131,13 @@ ssize_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm,
                                   snd_pcm_mmap_areas(pcm), snd_pcm_mmap_offset(pcm),
                                   pcm->setup.format.channels, 
                                   frames, pcm->setup.format.sfmt);
-               err = snd_pcm_mmap_forward(pcm, frames);
-               if (err < 0)
-                       break;
-               assert((size_t)err == frames);
-               offset += err;
-               xfer += err;
-       }
-       if (xfer > 0) {
-               if (slave_sizep)
-                       *slave_sizep = xfer;
-               return xfer;
+               snd_pcm_mmap_forward(pcm, frames);
+               offset += frames;
+               xfer += frames;
        }
-       return err;
+       if (slave_sizep)
+               *slave_sizep = xfer;
+       return xfer;
 }
 
 ssize_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm,
@@ -154,7 +147,6 @@ ssize_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm,
                                size_t *slave_sizep)
 {
        size_t xfer;
-       ssize_t err = 0;
        if (slave_sizep && *slave_sizep < size)
                size = *slave_sizep;
        xfer = 0;
@@ -164,19 +156,13 @@ ssize_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm,
                                   areas, offset, 
                                   pcm->setup.format.channels, 
                                   frames, pcm->setup.format.sfmt);
-               err = snd_pcm_mmap_forward(pcm, frames);
-               if (err < 0)
-                       break;
-               assert((size_t)err == frames);
-               offset += err;
-               xfer += err;
-       }
-       if (xfer > 0) {
-               if (slave_sizep)
-                       *slave_sizep = xfer;
-               return xfer;
+               snd_pcm_mmap_forward(pcm, frames);
+               offset += frames;
+               xfer += frames;
        }
-       return err;
+       if (slave_sizep)
+               *slave_sizep = xfer;
+       return xfer;
 }
 
 ssize_t snd_pcm_mmap_writei(snd_pcm_t *pcm, const void *buffer, size_t size)
index c51be60..7b6883c 100644 (file)
@@ -547,6 +547,30 @@ static int snd_pcm_route_setup(snd_pcm_t *pcm, snd_pcm_setup_t * setup)
        return 0;
 }
 
+static int snd_pcm_route_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t * setup)
+{
+#if 0
+       snd_pcm_plugin_t *plugin = pcm->private;
+       int err;
+       err = snd_pcm_channel_setup(plugin->slave, setup);
+       if (err < 0)
+               return err;
+#endif
+       if (!pcm->mmap_info)
+               return 0;
+       if (pcm->setup.mmap_shape == SND_PCM_MMAP_INTERLEAVED) {
+               setup->running_area.addr = pcm->mmap_info->addr;
+               setup->running_area.first = setup->channel * pcm->bits_per_sample;
+               setup->running_area.step = pcm->bits_per_frame;
+       } else {
+               setup->running_area.addr = pcm->mmap_info->addr + setup->channel * pcm->setup.buffer_size * pcm->bits_per_sample / 8;
+               setup->running_area.first = 0;
+               setup->running_area.step = pcm->bits_per_sample;
+       }
+       setup->stopped_area = setup->running_area;
+       return 0;
+}
+
 static ssize_t snd_pcm_route_write_areas(snd_pcm_t *pcm,
                                         snd_pcm_channel_area_t *areas,
                                         size_t offset,
@@ -581,30 +605,6 @@ static ssize_t snd_pcm_route_write_areas(snd_pcm_t *pcm,
        return err;
 }
 
-static int snd_pcm_route_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t * setup)
-{
-#if 0
-       snd_pcm_plugin_t *plugin = pcm->private;
-       int err;
-       err = snd_pcm_channel_setup(plugin->slave, setup);
-       if (err < 0)
-               return err;
-#endif
-       if (!pcm->mmap_info)
-               return 0;
-       if (pcm->setup.mmap_shape == SND_PCM_MMAP_INTERLEAVED) {
-               setup->running_area.addr = pcm->mmap_info->addr;
-               setup->running_area.first = setup->channel * pcm->bits_per_sample;
-               setup->running_area.step = pcm->bits_per_frame;
-       } else {
-               setup->running_area.addr = pcm->mmap_info->addr + setup->channel * pcm->setup.buffer_size * pcm->bits_per_sample / 8;
-               setup->running_area.first = 0;
-               setup->running_area.step = pcm->bits_per_sample;
-       }
-       setup->stopped_area = setup->running_area;
-       return 0;
-}
-
 static ssize_t snd_pcm_route_read_areas(snd_pcm_t *pcm,
                                         snd_pcm_channel_area_t *areas,
                                         size_t offset,
index 9876afa..98aa2c4 100644 (file)
@@ -152,18 +152,17 @@ static void snd_pcm_share_stop(snd_pcm_t *pcm, int state)
        gettimeofday(&share->trigger_time, 0);
        slave->prepared_count--;
        slave->running_count--;
-       if (slave->running_count == 0) {
-               int err = snd_pcm_drop(slave->pcm);
-               assert(err >= 0);
-       }
        if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
+               snd_pcm_avail_update(slave->pcm);
                snd_pcm_areas_copy(pcm->running_areas, 0,
                                   pcm->stopped_areas, 0,
                                   pcm->setup.format.channels, pcm->setup.buffer_size,
                                   pcm->setup.format.sfmt);
        }
-       share->hw_ptr = *slave->pcm->hw_ptr;
-       pcm->hw_ptr = &share->hw_ptr;
+       if (slave->running_count == 0) {
+               int err = snd_pcm_drop(slave->pcm);
+               assert(err >= 0);
+       }
 }
 
 /* Warning: take the mutex before to call this */
@@ -557,6 +556,8 @@ static ssize_t snd_pcm_share_avail_update(snd_pcm_t *pcm)
        ssize_t ret = 0;
        pthread_mutex_lock(&slave->mutex);
        ret = snd_pcm_avail_update(slave->pcm);
+       if (share->state == SND_PCM_STATE_RUNNING)
+               share->hw_ptr = *slave->pcm->hw_ptr;
        if (ret == -EPIPE) {
                struct list_head *i;
                for (i = slave->clients.next; i != &slave->clients; i = i->next) {
@@ -570,8 +571,12 @@ static ssize_t snd_pcm_share_avail_update(snd_pcm_t *pcm)
        pthread_mutex_unlock(&slave->mutex);
        if (ret >= 0) {
                ret = snd_pcm_mmap_avail(pcm);
-               if ((size_t)ret > pcm->setup.buffer_size)
+               if ((size_t)ret > pcm->setup.buffer_size) {
+                       if (share->state == SND_PCM_STATE_RUNNING &&
+                           pcm->setup.xrun_mode != SND_PCM_XRUN_NONE)
+                               snd_pcm_share_stop(pcm, SND_PCM_STATE_XRUN);
                        return -EPIPE;
+               }
        }
        return ret;
 }
@@ -659,8 +664,7 @@ static int snd_pcm_share_start(snd_pcm_t *pcm)
                                goto _end;
                }
                assert(share->hw_ptr == 0);
-               /* Share the same hw_ptr of slave */
-               pcm->hw_ptr = slave->pcm->hw_ptr;
+               share->hw_ptr = *slave->pcm->hw_ptr;
                share->appl_ptr = *slave->pcm->appl_ptr;
                snd_pcm_areas_copy(pcm->stopped_areas, 0,
                                   pcm->running_areas, snd_pcm_mmap_offset(pcm),
index 0541ffe..766e7ba 100644 (file)
@@ -40,9 +40,7 @@
 
 typedef struct {
        int socket;
-       void *ctrl;
-       size_t hw_ptr;
-       size_t appl_ptr;
+       volatile snd_pcm_shm_ctrl_t *ctrl;
        snd_pcm_mmap_info_t *slave_mmap_info;
 } snd_pcm_shm_t;
 
@@ -85,7 +83,7 @@ static int snd_pcm_shm_action(snd_pcm_t *pcm)
        snd_pcm_shm_t *shm = pcm->private;
        int err;
        char buf[1];
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        err = write(shm->socket, buf, 1);
        if (err != 1)
                return -EBADFD;
@@ -104,7 +102,7 @@ static int snd_pcm_shm_action_fd(snd_pcm_t *pcm, int *fd)
        snd_pcm_shm_t *shm = pcm->private;
        int err;
        char buf[1];
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        err = write(shm->socket, buf, 1);
        if (err != 1)
                return -EBADFD;
@@ -118,36 +116,6 @@ static int snd_pcm_shm_action_fd(snd_pcm_t *pcm, int *fd)
        return ctrl->result;
 }
 
-static int snd_pcm_shm_drain(snd_pcm_t *pcm)
-{
-       snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
-       int err;
-       ctrl->cmd = SND_PCM_IOCTL_DRAIN;
-       err = snd_pcm_shm_action(pcm);
-       if (err < 0)
-               return err;
-       if (!(pcm->mode & SND_PCM_NONBLOCK))
-               snd_pcm_wait(pcm, -1);
-       return err;
-}
-
-static int snd_pcm_shm_close(snd_pcm_t *pcm)
-{
-       snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
-       int result;
-       if (!(pcm->mode & SND_PCM_NONBLOCK))
-               snd_pcm_shm_drain(pcm);
-       ctrl->cmd = SND_PCM_IOCTL_CLOSE;
-       result = snd_pcm_shm_action(pcm);
-       shmdt((void *)ctrl);
-       close(shm->socket);
-       close(pcm->poll_fd);
-       free(shm);
-       return result;
-}
-
 static int snd_pcm_shm_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED)
 {
        return 0;
@@ -156,7 +124,7 @@ static int snd_pcm_shm_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock AT
 static int snd_pcm_shm_async(snd_pcm_t *pcm, int sig, pid_t pid)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        ctrl->cmd = SND_PCM_IOCTL_ASYNC;
        ctrl->u.async.sig = sig;
        if (pid == 0)
@@ -168,7 +136,7 @@ static int snd_pcm_shm_async(snd_pcm_t *pcm, int sig, pid_t pid)
 static int snd_pcm_shm_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        int err;
 //     ctrl->u.info = *info;
        ctrl->cmd = SND_PCM_IOCTL_INFO;
@@ -182,7 +150,7 @@ static int snd_pcm_shm_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
 static int snd_pcm_shm_params_info(snd_pcm_t *pcm, snd_pcm_params_info_t * info)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_PARAMS_INFO;
        ctrl->u.params_info = *info;
@@ -196,7 +164,7 @@ static int snd_pcm_shm_params_info(snd_pcm_t *pcm, snd_pcm_params_info_t * info)
 static int snd_pcm_shm_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_PARAMS;
        ctrl->u.params = *params;
@@ -210,7 +178,7 @@ static int snd_pcm_shm_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
 static int snd_pcm_shm_setup(snd_pcm_t *pcm, snd_pcm_setup_t * setup)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_SETUP;
        // ctrl->u.setup = *setup;
@@ -224,7 +192,7 @@ static int snd_pcm_shm_setup(snd_pcm_t *pcm, snd_pcm_setup_t * setup)
 static int snd_pcm_shm_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_CHANNEL_INFO;
        ctrl->u.channel_info = *info;
@@ -238,7 +206,7 @@ static int snd_pcm_shm_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * inf
 static int snd_pcm_shm_channel_params(snd_pcm_t *pcm, snd_pcm_channel_params_t * params)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_CHANNEL_PARAMS;
        ctrl->u.channel_params = *params;
@@ -270,7 +238,7 @@ static void *convert_addr(void *addr, size_t count, snd_pcm_mmap_info_t *old, sn
 static int snd_pcm_shm_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t * setup)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_CHANNEL_SETUP;
        ctrl->u.channel_setup = *setup;
@@ -288,7 +256,7 @@ static int snd_pcm_shm_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t * s
 static int snd_pcm_shm_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_STATUS;
        // ctrl->u.status = *status;
@@ -302,7 +270,7 @@ static int snd_pcm_shm_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 static int snd_pcm_shm_state(snd_pcm_t *pcm)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        ctrl->cmd = SND_PCM_IOCTL_STATE;
        return snd_pcm_shm_action(pcm);
 }
@@ -310,37 +278,32 @@ static int snd_pcm_shm_state(snd_pcm_t *pcm)
 static int snd_pcm_shm_delay(snd_pcm_t *pcm, ssize_t *delayp)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_DELAY;
        err = snd_pcm_shm_action(pcm);
        if (err < 0)
                return err;
-       *delayp = ctrl->u.delay;
+       *delayp = ctrl->u.delay.frames;
        return err;
 }
 
 static ssize_t snd_pcm_shm_avail_update(snd_pcm_t *pcm)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        int err;
        ctrl->cmd = SND_PCM_IOCTL_AVAIL_UPDATE;
        err = snd_pcm_shm_action(pcm);
        if (err < 0)
                return err;
-       shm->hw_ptr = shm->appl_ptr;
-       if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
-               snd_pcm_mmap_hw_backward(pcm, err);
-       else
-               snd_pcm_mmap_hw_forward(pcm, err);
        return err;
 }
 
 static int snd_pcm_shm_prepare(snd_pcm_t *pcm)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        ctrl->cmd = SND_PCM_IOCTL_PREPARE;
        return snd_pcm_shm_action(pcm);
 }
@@ -348,7 +311,7 @@ static int snd_pcm_shm_prepare(snd_pcm_t *pcm)
 static int snd_pcm_shm_start(snd_pcm_t *pcm)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        ctrl->cmd = SND_PCM_IOCTL_START;
        return snd_pcm_shm_action(pcm);
 }
@@ -356,37 +319,47 @@ static int snd_pcm_shm_start(snd_pcm_t *pcm)
 static int snd_pcm_shm_drop(snd_pcm_t *pcm)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        ctrl->cmd = SND_PCM_IOCTL_DROP;
        return snd_pcm_shm_action(pcm);
 }
 
+static int snd_pcm_shm_drain(snd_pcm_t *pcm)
+{
+       snd_pcm_shm_t *shm = pcm->private;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       int err;
+       ctrl->cmd = SND_PCM_IOCTL_DRAIN;
+       err = snd_pcm_shm_action(pcm);
+       if (err < 0)
+               return err;
+       if (!(pcm->mode & SND_PCM_NONBLOCK))
+               snd_pcm_wait(pcm, -1);
+       return err;
+}
+
 static int snd_pcm_shm_pause(snd_pcm_t *pcm, int enable)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        ctrl->cmd = SND_PCM_IOCTL_PAUSE;
-       ctrl->u.pause = enable;
+       ctrl->u.pause.enable = enable;
        return snd_pcm_shm_action(pcm);
 }
 
 static ssize_t snd_pcm_shm_rewind(snd_pcm_t *pcm, size_t frames)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
-       int err;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        ctrl->cmd = SND_PCM_IOCTL_REWIND;
-       ctrl->u.rewind = frames;
-       err = snd_pcm_shm_action(pcm);
-       if (err >= 0)
-               snd_pcm_mmap_appl_backward(pcm, err);
-       return err;
+       ctrl->u.rewind.frames = frames;
+       return snd_pcm_shm_action(pcm);
 }
 
 static int snd_pcm_shm_mmap(snd_pcm_t *pcm)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        int count, k, err, fd;
        ctrl->cmd = SND_PCM_IOCTL_MMAP;
        count = snd_pcm_shm_action(pcm);
@@ -432,7 +405,7 @@ static int snd_pcm_shm_mmap(snd_pcm_t *pcm)
 static int snd_pcm_shm_munmap(snd_pcm_t *pcm)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        int err;
        unsigned int k;
        ctrl->cmd = SND_PCM_IOCTL_MUNMAP;
@@ -464,20 +437,16 @@ static int snd_pcm_shm_munmap(snd_pcm_t *pcm)
 static ssize_t snd_pcm_shm_mmap_forward(snd_pcm_t *pcm, size_t size)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
-       int err;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        ctrl->cmd = SND_PCM_IOCTL_MMAP_FORWARD;
-       ctrl->u.mmap_forward = size;
-       err = snd_pcm_shm_action(pcm);
-       if (err >= 0)
-               snd_pcm_mmap_appl_forward(pcm, err);
-       return err;
+       ctrl->u.mmap_forward.frames = size;
+       return snd_pcm_shm_action(pcm);
 }
 
 static int snd_pcm_shm_poll_descriptor(snd_pcm_t *pcm)
 {
        snd_pcm_shm_t *shm = pcm->private;
-       snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
        int fd, err;
        ctrl->cmd = SND_PCM_IOCTL_POLL_DESCRIPTOR;
        err = snd_pcm_shm_action_fd(pcm, &fd);
@@ -492,6 +461,23 @@ static int snd_pcm_shm_channels_mask(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
        return 0;
 }
 
+static int snd_pcm_shm_close(snd_pcm_t *pcm)
+{
+       snd_pcm_shm_t *shm = pcm->private;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       int result;
+       if (!(pcm->mode & SND_PCM_NONBLOCK) &&
+           snd_pcm_shm_state(pcm) == SND_PCM_STATE_RUNNING)
+               snd_pcm_shm_drain(pcm);
+       ctrl->cmd = SND_PCM_IOCTL_CLOSE;
+       result = snd_pcm_shm_action(pcm);
+       shmdt((void *)ctrl);
+       close(shm->socket);
+       close(pcm->poll_fd);
+       free(shm);
+       return result;
+}
+
 static void snd_pcm_shm_dump(snd_pcm_t *pcm, FILE *fp)
 {
        fprintf(fp, "Shm PCM\n");
@@ -680,8 +666,8 @@ int snd_pcm_shm_open(snd_pcm_t **pcmp, char *name, char *socket, char *sname, in
                return err;
        }
        pcm->poll_fd = err;
-       pcm->hw_ptr = &shm->hw_ptr;
-       pcm->appl_ptr = &shm->appl_ptr;
+       pcm->hw_ptr = &ctrl->hw_ptr;
+       pcm->appl_ptr = &ctrl->appl_ptr;
        *pcmp = pcm;
        return 0;