]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Fix direct plugins running on 32bit emulation with 64bit arch
authorTakashi Iwai <tiwai@suse.de>
Fri, 12 Aug 2005 15:53:02 +0000 (15:53 +0000)
committerTakashi Iwai <tiwai@suse.de>
Fri, 12 Aug 2005 15:53:02 +0000 (15:53 +0000)
Fix the problems of dmix/dsnoop/dshare plugins running on 32bit mode with
64bit biarch.

src/pcm/pcm_direct.c
src/pcm/pcm_direct.h
src/pcm/pcm_dmix.c
src/pcm/pcm_dshare.c
src/pcm/pcm_dsnoop.c

index f146ebf1c7214dbc4dfd7cbe5cdb82030ab59d2b..3d3f1d4a34e17c88d13f780bb45b89928d0ddcf9 100644 (file)
@@ -532,7 +532,7 @@ static inline snd_interval_t *hw_param_interval(snd_pcm_hw_params_t *params,
 
 static int hw_param_interval_refine_one(snd_pcm_hw_params_t *params,
                                        snd_pcm_hw_param_t var,
-                                       snd_pcm_hw_params_t *src)
+                                       snd_interval_t *src)
 {
        snd_interval_t *i;
 
@@ -543,7 +543,7 @@ static int hw_param_interval_refine_one(snd_pcm_hw_params_t *params,
                SNDERR("dshare interval %i empty?", (int)var);
                return -EINVAL;
        }
-       if (snd_interval_refine(i, hw_param_interval(src, var)))
+       if (snd_interval_refine(i, src))
                params->cmask |= 1<<var;
        return 0;
 }
@@ -553,7 +553,6 @@ static int hw_param_interval_refine_one(snd_pcm_hw_params_t *params,
 int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
 {
        snd_pcm_direct_t *dshare = pcm->private_data;
-       snd_pcm_hw_params_t *hw_params = &dshare->shmptr->hw_params;
        static snd_mask_t access = { .bits = { 
                                        (1<<SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) |
                                        (1<<SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED) |
@@ -582,7 +581,7 @@ int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
                        return -EINVAL;
                }
                if (snd_mask_refine_set(hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT),
-                                       snd_mask_value(hw_param_mask(hw_params, SND_PCM_HW_PARAM_FORMAT))))
+                                       dshare->shmptr->hw.format))
                        params->cmask |= 1<<SND_PCM_HW_PARAM_FORMAT;
        }
        //snd_mask_none(hw_param_mask(params, SND_PCM_HW_PARAM_SUBFORMAT));
@@ -595,22 +594,28 @@ int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
                if (err < 0)
                        return err;
        }
-       err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_RATE, hw_params);
+       err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_RATE,
+                                          &dshare->shmptr->hw.rate);
        if (err < 0)
                return err;
-       err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_SIZE, hw_params);
+       err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_SIZE,
+                                          &dshare->shmptr->hw.buffer_size);
        if (err < 0)
                return err;
-       err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_TIME, hw_params);
+       err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_TIME,
+                                          &dshare->shmptr->hw.buffer_time);
        if (err < 0)
                return err;
-       err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE, hw_params);
+       err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE,
+                                          &dshare->shmptr->hw.period_size);
        if (err < 0)
                return err;
-       err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME, hw_params);
+       err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME,
+                                          &dshare->shmptr->hw.period_time);
        if (err < 0)
                return err;
-       err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIODS, hw_params);
+       err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIODS,
+                                          &dshare->shmptr->hw.periods);
        if (err < 0)
                return err;
        params->info = dshare->shmptr->s.info;
@@ -675,8 +680,8 @@ int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, str
        struct pollfd fd;
        int loops = 10;
 
-       hw_params = &dmix->shmptr->hw_params;
-       sw_params = &dmix->shmptr->sw_params;
+       snd_pcm_hw_params_alloca(&hw_params);
+       snd_pcm_sw_params_alloca(&sw_params);
 
       __again:
        if (loops-- <= 0) {
@@ -800,6 +805,16 @@ int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, str
                return ret;
        }
 
+       /* store some hw_params values to shared info */
+       dmix->shmptr->hw.format = snd_mask_value(hw_param_mask(hw_params, SND_PCM_HW_PARAM_FORMAT));
+       dmix->shmptr->hw.rate = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_RATE);
+       dmix->shmptr->hw.buffer_size = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_BUFFER_SIZE);
+       dmix->shmptr->hw.buffer_time = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_BUFFER_TIME);
+       dmix->shmptr->hw.period_size = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_PERIOD_SIZE);
+       dmix->shmptr->hw.period_time = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_PERIOD_TIME);
+       dmix->shmptr->hw.periods = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_PERIODS);
+
+
        ret = snd_pcm_sw_params_current(spcm, sw_params);
        if (ret < 0) {
                SNDERR("unable to get current sw_params");
@@ -865,10 +880,20 @@ int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, str
        dmix->shmptr->s.channels = spcm->channels;
        dmix->shmptr->s.rate = spcm->rate;
        dmix->shmptr->s.format = spcm->format;
-       dmix->shmptr->s.boundary = spcm->boundary;
        dmix->shmptr->s.info = spcm->info & ~SND_PCM_INFO_PAUSE;
        dmix->shmptr->s.msbits = spcm->msbits;
 
+       /* Currently, we assume that each dmix client has the same
+        * hw_params setting.
+        * If the arbitrary hw_parmas is supported in future,
+        * boundary has to be taken from the slave config but
+        * recalculated for the native boundary size (for 32bit
+        * emulation on 64bit arch).
+        */
+       dmix->slave_buffer_size = spcm->buffer_size;
+       dmix->slave_period_size = spcm->period_size;
+       dmix->slave_boundary = spcm->boundary;
+
        spcm->donot_close = 1;
        return 0;
 }
@@ -936,6 +961,54 @@ int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix)
        return 0;
 }
 
+static snd_pcm_uframes_t recalc_boundary_size(unsigned long long bsize, snd_pcm_uframes_t buffer_size)
+{
+       if (bsize > LONG_MAX) {
+               bsize = buffer_size;
+               while (bsize * 2 <= LONG_MAX - buffer_size)
+                       bsize *= 2;
+       }
+       return (snd_pcm_uframes_t)bsize;
+}
+
+/*
+ * open a slave PCM as secondary client (dup'ed fd)
+ */
+int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name)
+{
+       int ret;
+       snd_pcm_t *spcm;
+
+       ret = snd_pcm_hw_open_fd(spcmp, client_name, dmix->hw_fd, 0, 0);
+       if (ret < 0) {
+               SNDERR("unable to open hardware");
+               return ret;
+       }
+               
+       spcm = *spcmp;
+       spcm->donot_close = 1;
+       spcm->setup = 1;
+       /* we copy the slave setting */
+       spcm->buffer_size = dmix->shmptr->s.buffer_size;
+       spcm->sample_bits = dmix->shmptr->s.sample_bits;
+       spcm->channels = dmix->shmptr->s.channels;
+       spcm->format = dmix->shmptr->s.format;
+       spcm->boundary = recalc_boundary_size(dmix->shmptr->s.boundary, spcm->buffer_size);
+       spcm->info = dmix->shmptr->s.info;
+
+       /* Use the slave setting as SPCM, so far */
+       dmix->slave_buffer_size = spcm->buffer_size;
+       dmix->slave_period_size = dmix->shmptr->s.period_size;
+       dmix->slave_boundary = spcm->boundary;
+
+       ret = snd_pcm_mmap(spcm);
+       if (ret < 0) {
+               SNDERR("unable to mmap channels");
+               return ret;
+       }
+       return 0;
+}
+
 int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix)
 {
        snd_timer_params_t *params;
index 5b6b938ba7cfb4bfe7adb08516ddf4768a8e0c3e..da300b783f6702590238be060f58fd1cc19ebf89 100644 (file)
@@ -48,13 +48,20 @@ struct slave_params {
 typedef struct {
        char socket_name[256];                  /* name of communication socket */
        snd_pcm_type_t type;                    /* PCM type (currently only hw) */
-       snd_pcm_hw_params_t hw_params;
-       snd_pcm_sw_params_t sw_params;
        struct {
-               snd_pcm_uframes_t buffer_size;
-               snd_pcm_uframes_t period_size;
-               snd_pcm_uframes_t boundary;
-               snd_pcm_uframes_t channels;
+               unsigned int format;
+               snd_interval_t rate;
+               snd_interval_t buffer_size;
+               snd_interval_t buffer_time;
+               snd_interval_t period_size;
+               snd_interval_t period_time;
+               snd_interval_t periods;
+       } hw;
+       struct {
+               unsigned int buffer_size;
+               unsigned int period_size;
+               unsigned long long boundary;
+               unsigned int channels;
                unsigned int sample_bits;
                unsigned int rate;
                snd_pcm_format_t format;
@@ -85,6 +92,9 @@ struct snd_pcm_direct {
        snd_pcm_uframes_t avail_max;
        snd_pcm_uframes_t slave_appl_ptr;
        snd_pcm_uframes_t slave_hw_ptr;
+       snd_pcm_uframes_t slave_period_size;
+       snd_pcm_uframes_t slave_buffer_size;
+       snd_pcm_uframes_t slave_boundary;
        int (*sync_ptr)(snd_pcm_t *pcm);
        snd_pcm_state_t state;
        snd_htimestamp_t trigger_tstamp;
@@ -146,6 +156,7 @@ int snd_pcm_direct_munmap(snd_pcm_t *pcm);
 int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix);
 void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix);
 int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix);
+int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name);
 
 int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
 struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);
index af4a67a9bcd79cfcd86cac7db7ef01ec54b3b4f4..36a7a5c99e1dcf0b512f057764446b176b5ed3d2 100644 (file)
@@ -238,8 +238,8 @@ static void mix_areas(snd_pcm_direct_t *dmix,
 static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
 {
        snd_pcm_direct_t *dmix = pcm->private_data;
-       snd_pcm_uframes_t appl_ptr, slave_appl_ptr, slave_bsize;
-       snd_pcm_uframes_t size, slave_size, slave_hw_ptr;
+       snd_pcm_uframes_t slave_hw_ptr, slave_appl_ptr, slave_size;
+       snd_pcm_uframes_t appl_ptr, size;
        const snd_pcm_channel_area_t *src_areas, *dst_areas;
        
        /* calculate the size to transfer */
@@ -253,17 +253,16 @@ static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
                size = pcm->boundary - size;
 
        /* check the available size in the slave PCM buffer */
-       slave_bsize = dmix->shmptr->s.buffer_size;
        slave_hw_ptr = dmix->slave_hw_ptr;
        /* don't write on the last active period - this area may be cleared
         * by the driver during mix operation...
         */
-       slave_hw_ptr -= slave_hw_ptr % dmix->shmptr->s.period_size;
-       slave_hw_ptr += slave_bsize;
-       if (slave_hw_ptr >= dmix->shmptr->s.boundary)
-               slave_hw_ptr -= dmix->shmptr->s.boundary;
+       slave_hw_ptr -= slave_hw_ptr % dmix->slave_period_size;
+       slave_hw_ptr += dmix->slave_buffer_size;
+       if (slave_hw_ptr >= dmix->slave_boundary)
+               slave_hw_ptr -= dmix->slave_boundary;
        if (slave_hw_ptr < dmix->slave_appl_ptr)
-               slave_size = slave_hw_ptr + (dmix->shmptr->s.boundary - dmix->slave_appl_ptr);
+               slave_size = slave_hw_ptr + (dmix->slave_boundary - dmix->slave_appl_ptr);
        else
                slave_size = slave_hw_ptr - dmix->slave_appl_ptr;
        if (slave_size < size)
@@ -277,22 +276,22 @@ static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
        appl_ptr = dmix->last_appl_ptr % pcm->buffer_size;
        dmix->last_appl_ptr += size;
        dmix->last_appl_ptr %= pcm->boundary;
-       slave_appl_ptr = dmix->slave_appl_ptr % slave_bsize;
+       slave_appl_ptr = dmix->slave_appl_ptr % dmix->slave_buffer_size;
        dmix->slave_appl_ptr += size;
-       dmix->slave_appl_ptr %= dmix->shmptr->s.boundary;
+       dmix->slave_appl_ptr %= dmix->slave_boundary;
        dmix_down_sem(dmix);
        for (;;) {
                snd_pcm_uframes_t transfer = size;
                if (appl_ptr + transfer > pcm->buffer_size)
                        transfer = pcm->buffer_size - appl_ptr;
-               if (slave_appl_ptr + transfer > slave_bsize)
-                       transfer = slave_bsize - slave_appl_ptr;
+               if (slave_appl_ptr + transfer > dmix->slave_buffer_size)
+                       transfer = dmix->slave_buffer_size - slave_appl_ptr;
                mix_areas(dmix, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer);
                size -= transfer;
                if (! size)
                        break;
                slave_appl_ptr += transfer;
-               slave_appl_ptr %= slave_bsize;
+               slave_appl_ptr %= dmix->slave_buffer_size;
                appl_ptr += transfer;
                appl_ptr %= pcm->buffer_size;
        }
@@ -327,7 +326,7 @@ static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
                /* not really started yet - don't update hw_ptr */
                return 0;
        if (diff < 0) {
-               slave_hw_ptr += dmix->shmptr->s.boundary;
+               slave_hw_ptr += dmix->slave_boundary;
                diff = slave_hw_ptr - old_slave_hw_ptr;
        }
        dmix->hw_ptr += diff;
@@ -451,7 +450,6 @@ static int snd_pcm_dmix_prepare(snd_pcm_t *pcm)
        snd_pcm_direct_t *dmix = pcm->private_data;
 
        snd_pcm_direct_check_interleave(dmix, pcm);
-       // assert(pcm->boundary == dmix->shmptr->s.boundary);   /* for sure */
        dmix->state = SND_PCM_STATE_PREPARED;
        dmix->appl_ptr = dmix->last_appl_ptr = 0;
        dmix->hw_ptr = 0;
@@ -861,25 +859,9 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
                }
                        
                snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
-               ret = snd_pcm_hw_open_fd(&spcm, "dmix_client", dmix->hw_fd, 0, 0);
-               if (ret < 0) {
-                       SNDERR("unable to open hardware");
-                       goto _err;
-               }
-               
-               spcm->donot_close = 1;
-               spcm->setup = 1;
-               spcm->buffer_size = dmix->shmptr->s.buffer_size;
-               spcm->sample_bits = dmix->shmptr->s.sample_bits;
-               spcm->channels = dmix->shmptr->s.channels;
-               spcm->format = dmix->shmptr->s.format;
-               spcm->boundary = dmix->shmptr->s.boundary;
-               spcm->info = dmix->shmptr->s.info;
-               ret = snd_pcm_mmap(spcm);
-               if (ret < 0) {
-                       SNDERR("unable to mmap channels");
+               ret = snd_pcm_direct_open_secondary_client(&spcm, dmix, "dmix_client");
+               if (ret < 0)
                        goto _err;
-               }
                dmix->spcm = spcm;
        }
 
index 434428f470dcff7779a1de1a4d93e65b704d943a..a90cd636ad528d6f9e8903bd8bb91298192813b2 100644 (file)
@@ -103,48 +103,52 @@ static void share_areas(snd_pcm_direct_t *dshare,
 static void snd_pcm_dshare_sync_area(snd_pcm_t *pcm)
 {
        snd_pcm_direct_t *dshare = pcm->private_data;
-       snd_pcm_uframes_t appl_ptr, slave_appl_ptr, slave_bsize;
-       snd_pcm_uframes_t size, slave_hw_ptr;
+       snd_pcm_uframes_t slave_hw_ptr, slave_appl_ptr, slave_size;
+       snd_pcm_uframes_t appl_ptr, size;
        const snd_pcm_channel_area_t *src_areas, *dst_areas;
        
        /* calculate the size to transfer */
        size = dshare->appl_ptr - dshare->last_appl_ptr;
        if (! size)
                return;
-       slave_bsize = dshare->shmptr->s.buffer_size;
        slave_hw_ptr = dshare->slave_hw_ptr;
        /* don't write on the last active period - this area may be cleared
         * by the driver during write operation...
         */
-       slave_hw_ptr -= slave_hw_ptr % dshare->shmptr->s.period_size;
-       slave_hw_ptr += slave_bsize;
-       if (dshare->slave_hw_ptr > dshare->slave_appl_ptr)
-               slave_hw_ptr -= dshare->shmptr->s.boundary;
-       if (dshare->slave_appl_ptr + size >= slave_hw_ptr)
-               size = slave_hw_ptr - dshare->slave_appl_ptr;
+       slave_hw_ptr -= slave_hw_ptr % dshare->slave_period_size;
+       slave_hw_ptr += dshare->slave_buffer_size;
+       if (dshare->slave_hw_ptr > dshare->slave_boundary)
+               slave_hw_ptr -= dshare->slave_boundary;
+       if (slave_hw_ptr < dshare->slave_appl_ptr)
+               slave_size = slave_hw_ptr + (dshare->slave_boundary - dshare->slave_appl_ptr);
+       else
+               slave_size = slave_hw_ptr - dshare->slave_appl_ptr;
+       if (slave_size < size)
+               size = slave_size;
        if (! size)
                return;
+
        /* add sample areas here */
        src_areas = snd_pcm_mmap_areas(pcm);
        dst_areas = snd_pcm_mmap_areas(dshare->spcm);
        appl_ptr = dshare->last_appl_ptr % pcm->buffer_size;
        dshare->last_appl_ptr += size;
        dshare->last_appl_ptr %= pcm->boundary;
-       slave_appl_ptr = dshare->slave_appl_ptr % slave_bsize;
+       slave_appl_ptr = dshare->slave_appl_ptr % dshare->slave_buffer_size;
        dshare->slave_appl_ptr += size;
-       dshare->slave_appl_ptr %= dshare->shmptr->s.boundary;
+       dshare->slave_appl_ptr %= dshare->slave_boundary;
        for (;;) {
                snd_pcm_uframes_t transfer = size;
                if (appl_ptr + transfer > pcm->buffer_size)
                        transfer = pcm->buffer_size - appl_ptr;
-               if (slave_appl_ptr + transfer > slave_bsize)
-                       transfer = slave_bsize - slave_appl_ptr;
+               if (slave_appl_ptr + transfer > dshare->slave_buffer_size)
+                       transfer = dshare->slave_buffer_size - slave_appl_ptr;
                share_areas(dshare, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer);
                size -= transfer;
                if (! size)
                        break;
                slave_appl_ptr += transfer;
-               slave_appl_ptr %= slave_bsize;
+               slave_appl_ptr %= dshare->slave_buffer_size;
                appl_ptr += transfer;
                appl_ptr %= pcm->buffer_size;
        }
@@ -178,7 +182,7 @@ static int snd_pcm_dshare_sync_ptr(snd_pcm_t *pcm)
                /* not really started yet - don't update hw_ptr */
                return 0;
        if (diff < 0) {
-               slave_hw_ptr += dshare->shmptr->s.boundary;
+               slave_hw_ptr += dshare->slave_boundary;
                diff = slave_hw_ptr - old_slave_hw_ptr;
        }
        dshare->hw_ptr += diff;
@@ -299,7 +303,6 @@ static int snd_pcm_dshare_prepare(snd_pcm_t *pcm)
        snd_pcm_direct_t *dshare = pcm->private_data;
 
        snd_pcm_direct_check_interleave(dshare, pcm);
-       // assert(pcm->boundary == dshare->shmptr->s.boundary); /* for sure */
        dshare->state = SND_PCM_STATE_PREPARED;
        dshare->appl_ptr = dshare->last_appl_ptr = 0;
        dshare->hw_ptr = 0;
@@ -706,25 +709,10 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
                }
                        
                snd_pcm_direct_semaphore_down(dshare, DIRECT_IPC_SEM_CLIENT);
+               ret = snd_pcm_direct_open_secondary_client(&spcm, dshare, "dshare_client");
                ret = snd_pcm_hw_open_fd(&spcm, "dshare_client", dshare->hw_fd, 0, 0);
-               if (ret < 0) {
-                       SNDERR("unable to open hardware");
+               if (ret < 0)
                        goto _err;
-               }
-               
-               spcm->donot_close = 1;
-               spcm->setup = 1;
-               spcm->buffer_size = dshare->shmptr->s.buffer_size;
-               spcm->sample_bits = dshare->shmptr->s.sample_bits;
-               spcm->channels = dshare->shmptr->s.channels;
-               spcm->format = dshare->shmptr->s.format;
-               spcm->boundary = dshare->shmptr->s.boundary;
-               spcm->info = dshare->shmptr->s.info;
-               ret = snd_pcm_mmap(spcm);
-               if (ret < 0) {
-                       SNDERR("unable to mmap channels");
-                       goto _err;
-               }
                dshare->spcm = spcm;
        }
 
index 82b55087d03a3913ebe6e8c1d55983e75fa03a77..d0f43576f3695551dc6c581ee85986a0daf58e02 100644 (file)
@@ -93,14 +93,15 @@ static void snd_pcm_dsnoop_sync_area(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_
        dst_areas = snd_pcm_mmap_areas(pcm);
        src_areas = snd_pcm_mmap_areas(dsnoop->spcm);
        hw_ptr %= pcm->buffer_size;
-       slave_hw_ptr %= dsnoop->shmptr->s.buffer_size;
+       slave_hw_ptr %= dsnoop->slave_buffer_size;
        while (size > 0) {
                transfer = hw_ptr + size > pcm->buffer_size ? pcm->buffer_size - hw_ptr : size;
-               transfer = slave_hw_ptr + transfer > dsnoop->shmptr->s.buffer_size ? dsnoop->shmptr->s.buffer_size - slave_hw_ptr : transfer;
+               transfer = slave_hw_ptr + transfer > dsnoop->slave_buffer_size ?
+                       dsnoop->slave_buffer_size - slave_hw_ptr : transfer;
                size -= transfer;
                snoop_areas(dsnoop, src_areas, dst_areas, slave_hw_ptr, hw_ptr, transfer);
                slave_hw_ptr += transfer;
-               slave_hw_ptr %= dsnoop->shmptr->s.buffer_size;
+               slave_hw_ptr %= dsnoop->slave_buffer_size;
                hw_ptr += transfer;
                hw_ptr %= pcm->buffer_size;
        }
@@ -130,7 +131,7 @@ static int snd_pcm_dsnoop_sync_ptr(snd_pcm_t *pcm)
        if (diff == 0)          /* fast path */
                return 0;
        if (diff < 0) {
-               slave_hw_ptr += dsnoop->shmptr->s.boundary;
+               slave_hw_ptr += dsnoop->slave_boundary;
                diff = slave_hw_ptr - old_slave_hw_ptr;
        }
        snd_pcm_dsnoop_sync_area(pcm, old_slave_hw_ptr, diff);
@@ -245,7 +246,6 @@ static int snd_pcm_dsnoop_prepare(snd_pcm_t *pcm)
        snd_pcm_direct_t *dsnoop = pcm->private_data;
 
        snd_pcm_direct_check_interleave(dsnoop, pcm);
-       // assert(pcm->boundary == dsnoop->shmptr->s.boundary); /* for sure */
        dsnoop->state = SND_PCM_STATE_PREPARED;
        dsnoop->appl_ptr = 0;
        dsnoop->hw_ptr = 0;
@@ -597,25 +597,10 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
                }
                        
                snd_pcm_direct_semaphore_down(dsnoop, DIRECT_IPC_SEM_CLIENT);
-               ret = snd_pcm_hw_open_fd(&spcm, "dsnoop_client", dsnoop->hw_fd, 0, 0);
-               if (ret < 0) {
-                       SNDERR("unable to open hardware");
-                       goto _err;
-               }
-               
-               spcm->donot_close = 1;
-               spcm->setup = 1;
-               spcm->buffer_size = dsnoop->shmptr->s.buffer_size;
-               spcm->sample_bits = dsnoop->shmptr->s.sample_bits;
-               spcm->channels = dsnoop->shmptr->s.channels;
-               spcm->format = dsnoop->shmptr->s.format;
-               spcm->boundary = dsnoop->shmptr->s.boundary;
-               spcm->info = dsnoop->shmptr->s.info;
-               ret = snd_pcm_mmap(spcm);
-               if (ret < 0) {
-                       SNDERR("unable to mmap channels");
+
+               ret = snd_pcm_direct_open_secondary_client(&spcm, dsnoop, "dsnoop_client");
+               if (ret < 0)
                        goto _err;
-               }
                dsnoop->spcm = spcm;
        }