Fix direct plugins running on 32bit emulation with 64bit arch

Fix the problems of dmix/dsnoop/dshare plugins running on 32bit mode with
64bit biarch.
This commit is contained in:
Takashi Iwai 2005-08-12 15:53:02 +00:00
parent 99005614ba
commit e80f80866f
5 changed files with 147 additions and 108 deletions

View 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, static int hw_param_interval_refine_one(snd_pcm_hw_params_t *params,
snd_pcm_hw_param_t var, snd_pcm_hw_param_t var,
snd_pcm_hw_params_t *src) snd_interval_t *src)
{ {
snd_interval_t *i; 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); SNDERR("dshare interval %i empty?", (int)var);
return -EINVAL; return -EINVAL;
} }
if (snd_interval_refine(i, hw_param_interval(src, var))) if (snd_interval_refine(i, src))
params->cmask |= 1<<var; params->cmask |= 1<<var;
return 0; 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) 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_direct_t *dshare = pcm->private_data;
snd_pcm_hw_params_t *hw_params = &dshare->shmptr->hw_params;
static snd_mask_t access = { .bits = { static snd_mask_t access = { .bits = {
(1<<SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) | (1<<SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) |
(1<<SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED) | (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; return -EINVAL;
} }
if (snd_mask_refine_set(hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT), 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; params->cmask |= 1<<SND_PCM_HW_PARAM_FORMAT;
} }
//snd_mask_none(hw_param_mask(params, SND_PCM_HW_PARAM_SUBFORMAT)); //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) if (err < 0)
return err; 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) if (err < 0)
return err; 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) if (err < 0)
return err; 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) if (err < 0)
return err; 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) if (err < 0)
return err; 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) if (err < 0)
return err; 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) if (err < 0)
return err; return err;
params->info = dshare->shmptr->s.info; 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; struct pollfd fd;
int loops = 10; int loops = 10;
hw_params = &dmix->shmptr->hw_params; snd_pcm_hw_params_alloca(&hw_params);
sw_params = &dmix->shmptr->sw_params; snd_pcm_sw_params_alloca(&sw_params);
__again: __again:
if (loops-- <= 0) { 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; 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); ret = snd_pcm_sw_params_current(spcm, sw_params);
if (ret < 0) { if (ret < 0) {
SNDERR("unable to get current sw_params"); 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.channels = spcm->channels;
dmix->shmptr->s.rate = spcm->rate; dmix->shmptr->s.rate = spcm->rate;
dmix->shmptr->s.format = spcm->format; 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.info = spcm->info & ~SND_PCM_INFO_PAUSE;
dmix->shmptr->s.msbits = spcm->msbits; 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; spcm->donot_close = 1;
return 0; return 0;
} }
@ -936,6 +961,54 @@ int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix)
return 0; 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) int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix)
{ {
snd_timer_params_t *params; snd_timer_params_t *params;

View file

@ -48,13 +48,20 @@ struct slave_params {
typedef struct { typedef struct {
char socket_name[256]; /* name of communication socket */ char socket_name[256]; /* name of communication socket */
snd_pcm_type_t type; /* PCM type (currently only hw) */ 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 { struct {
snd_pcm_uframes_t buffer_size; unsigned int format;
snd_pcm_uframes_t period_size; snd_interval_t rate;
snd_pcm_uframes_t boundary; snd_interval_t buffer_size;
snd_pcm_uframes_t channels; 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 sample_bits;
unsigned int rate; unsigned int rate;
snd_pcm_format_t format; snd_pcm_format_t format;
@ -85,6 +92,9 @@ struct snd_pcm_direct {
snd_pcm_uframes_t avail_max; snd_pcm_uframes_t avail_max;
snd_pcm_uframes_t slave_appl_ptr; snd_pcm_uframes_t slave_appl_ptr;
snd_pcm_uframes_t slave_hw_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); int (*sync_ptr)(snd_pcm_t *pcm);
snd_pcm_state_t state; snd_pcm_state_t state;
snd_htimestamp_t trigger_tstamp; 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); int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix);
void snd_pcm_direct_clear_timer_queue(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_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); int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm); struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);

View 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) static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
{ {
snd_pcm_direct_t *dmix = pcm->private_data; snd_pcm_direct_t *dmix = pcm->private_data;
snd_pcm_uframes_t appl_ptr, slave_appl_ptr, slave_bsize; snd_pcm_uframes_t slave_hw_ptr, slave_appl_ptr, slave_size;
snd_pcm_uframes_t size, slave_size, slave_hw_ptr; snd_pcm_uframes_t appl_ptr, size;
const snd_pcm_channel_area_t *src_areas, *dst_areas; const snd_pcm_channel_area_t *src_areas, *dst_areas;
/* calculate the size to transfer */ /* calculate the size to transfer */
@ -253,17 +253,16 @@ static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
size = pcm->boundary - size; size = pcm->boundary - size;
/* check the available size in the slave PCM buffer */ /* check the available size in the slave PCM buffer */
slave_bsize = dmix->shmptr->s.buffer_size;
slave_hw_ptr = dmix->slave_hw_ptr; slave_hw_ptr = dmix->slave_hw_ptr;
/* don't write on the last active period - this area may be cleared /* don't write on the last active period - this area may be cleared
* by the driver during mix operation... * by the driver during mix operation...
*/ */
slave_hw_ptr -= slave_hw_ptr % dmix->shmptr->s.period_size; slave_hw_ptr -= slave_hw_ptr % dmix->slave_period_size;
slave_hw_ptr += slave_bsize; slave_hw_ptr += dmix->slave_buffer_size;
if (slave_hw_ptr >= dmix->shmptr->s.boundary) if (slave_hw_ptr >= dmix->slave_boundary)
slave_hw_ptr -= dmix->shmptr->s.boundary; slave_hw_ptr -= dmix->slave_boundary;
if (slave_hw_ptr < dmix->slave_appl_ptr) 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 else
slave_size = slave_hw_ptr - dmix->slave_appl_ptr; slave_size = slave_hw_ptr - dmix->slave_appl_ptr;
if (slave_size < size) 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; appl_ptr = dmix->last_appl_ptr % pcm->buffer_size;
dmix->last_appl_ptr += size; dmix->last_appl_ptr += size;
dmix->last_appl_ptr %= pcm->boundary; 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 += size;
dmix->slave_appl_ptr %= dmix->shmptr->s.boundary; dmix->slave_appl_ptr %= dmix->slave_boundary;
dmix_down_sem(dmix); dmix_down_sem(dmix);
for (;;) { for (;;) {
snd_pcm_uframes_t transfer = size; snd_pcm_uframes_t transfer = size;
if (appl_ptr + transfer > pcm->buffer_size) if (appl_ptr + transfer > pcm->buffer_size)
transfer = pcm->buffer_size - appl_ptr; transfer = pcm->buffer_size - appl_ptr;
if (slave_appl_ptr + transfer > slave_bsize) if (slave_appl_ptr + transfer > dmix->slave_buffer_size)
transfer = slave_bsize - slave_appl_ptr; transfer = dmix->slave_buffer_size - slave_appl_ptr;
mix_areas(dmix, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer); mix_areas(dmix, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer);
size -= transfer; size -= transfer;
if (! size) if (! size)
break; break;
slave_appl_ptr += transfer; slave_appl_ptr += transfer;
slave_appl_ptr %= slave_bsize; slave_appl_ptr %= dmix->slave_buffer_size;
appl_ptr += transfer; appl_ptr += transfer;
appl_ptr %= pcm->buffer_size; 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 */ /* not really started yet - don't update hw_ptr */
return 0; return 0;
if (diff < 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; diff = slave_hw_ptr - old_slave_hw_ptr;
} }
dmix->hw_ptr += diff; 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_t *dmix = pcm->private_data;
snd_pcm_direct_check_interleave(dmix, pcm); snd_pcm_direct_check_interleave(dmix, pcm);
// assert(pcm->boundary == dmix->shmptr->s.boundary); /* for sure */
dmix->state = SND_PCM_STATE_PREPARED; dmix->state = SND_PCM_STATE_PREPARED;
dmix->appl_ptr = dmix->last_appl_ptr = 0; dmix->appl_ptr = dmix->last_appl_ptr = 0;
dmix->hw_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); snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
ret = snd_pcm_hw_open_fd(&spcm, "dmix_client", dmix->hw_fd, 0, 0); ret = snd_pcm_direct_open_secondary_client(&spcm, dmix, "dmix_client");
if (ret < 0) { if (ret < 0)
SNDERR("unable to open hardware");
goto _err; 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");
goto _err;
}
dmix->spcm = spcm; dmix->spcm = spcm;
} }

View 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) static void snd_pcm_dshare_sync_area(snd_pcm_t *pcm)
{ {
snd_pcm_direct_t *dshare = pcm->private_data; snd_pcm_direct_t *dshare = pcm->private_data;
snd_pcm_uframes_t appl_ptr, slave_appl_ptr, slave_bsize; snd_pcm_uframes_t slave_hw_ptr, slave_appl_ptr, slave_size;
snd_pcm_uframes_t size, slave_hw_ptr; snd_pcm_uframes_t appl_ptr, size;
const snd_pcm_channel_area_t *src_areas, *dst_areas; const snd_pcm_channel_area_t *src_areas, *dst_areas;
/* calculate the size to transfer */ /* calculate the size to transfer */
size = dshare->appl_ptr - dshare->last_appl_ptr; size = dshare->appl_ptr - dshare->last_appl_ptr;
if (! size) if (! size)
return; return;
slave_bsize = dshare->shmptr->s.buffer_size;
slave_hw_ptr = dshare->slave_hw_ptr; slave_hw_ptr = dshare->slave_hw_ptr;
/* don't write on the last active period - this area may be cleared /* don't write on the last active period - this area may be cleared
* by the driver during write operation... * by the driver during write operation...
*/ */
slave_hw_ptr -= slave_hw_ptr % dshare->shmptr->s.period_size; slave_hw_ptr -= slave_hw_ptr % dshare->slave_period_size;
slave_hw_ptr += slave_bsize; slave_hw_ptr += dshare->slave_buffer_size;
if (dshare->slave_hw_ptr > dshare->slave_appl_ptr) if (dshare->slave_hw_ptr > dshare->slave_boundary)
slave_hw_ptr -= dshare->shmptr->s.boundary; slave_hw_ptr -= dshare->slave_boundary;
if (dshare->slave_appl_ptr + size >= slave_hw_ptr) if (slave_hw_ptr < dshare->slave_appl_ptr)
size = 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) if (! size)
return; return;
/* add sample areas here */ /* add sample areas here */
src_areas = snd_pcm_mmap_areas(pcm); src_areas = snd_pcm_mmap_areas(pcm);
dst_areas = snd_pcm_mmap_areas(dshare->spcm); dst_areas = snd_pcm_mmap_areas(dshare->spcm);
appl_ptr = dshare->last_appl_ptr % pcm->buffer_size; appl_ptr = dshare->last_appl_ptr % pcm->buffer_size;
dshare->last_appl_ptr += size; dshare->last_appl_ptr += size;
dshare->last_appl_ptr %= pcm->boundary; 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 += size;
dshare->slave_appl_ptr %= dshare->shmptr->s.boundary; dshare->slave_appl_ptr %= dshare->slave_boundary;
for (;;) { for (;;) {
snd_pcm_uframes_t transfer = size; snd_pcm_uframes_t transfer = size;
if (appl_ptr + transfer > pcm->buffer_size) if (appl_ptr + transfer > pcm->buffer_size)
transfer = pcm->buffer_size - appl_ptr; transfer = pcm->buffer_size - appl_ptr;
if (slave_appl_ptr + transfer > slave_bsize) if (slave_appl_ptr + transfer > dshare->slave_buffer_size)
transfer = slave_bsize - slave_appl_ptr; transfer = dshare->slave_buffer_size - slave_appl_ptr;
share_areas(dshare, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer); share_areas(dshare, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer);
size -= transfer; size -= transfer;
if (! size) if (! size)
break; break;
slave_appl_ptr += transfer; slave_appl_ptr += transfer;
slave_appl_ptr %= slave_bsize; slave_appl_ptr %= dshare->slave_buffer_size;
appl_ptr += transfer; appl_ptr += transfer;
appl_ptr %= pcm->buffer_size; 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 */ /* not really started yet - don't update hw_ptr */
return 0; return 0;
if (diff < 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; diff = slave_hw_ptr - old_slave_hw_ptr;
} }
dshare->hw_ptr += diff; 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_t *dshare = pcm->private_data;
snd_pcm_direct_check_interleave(dshare, pcm); snd_pcm_direct_check_interleave(dshare, pcm);
// assert(pcm->boundary == dshare->shmptr->s.boundary); /* for sure */
dshare->state = SND_PCM_STATE_PREPARED; dshare->state = SND_PCM_STATE_PREPARED;
dshare->appl_ptr = dshare->last_appl_ptr = 0; dshare->appl_ptr = dshare->last_appl_ptr = 0;
dshare->hw_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); 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); ret = snd_pcm_hw_open_fd(&spcm, "dshare_client", dshare->hw_fd, 0, 0);
if (ret < 0) { if (ret < 0)
SNDERR("unable to open hardware");
goto _err; 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; dshare->spcm = spcm;
} }

View 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); dst_areas = snd_pcm_mmap_areas(pcm);
src_areas = snd_pcm_mmap_areas(dsnoop->spcm); src_areas = snd_pcm_mmap_areas(dsnoop->spcm);
hw_ptr %= pcm->buffer_size; hw_ptr %= pcm->buffer_size;
slave_hw_ptr %= dsnoop->shmptr->s.buffer_size; slave_hw_ptr %= dsnoop->slave_buffer_size;
while (size > 0) { while (size > 0) {
transfer = hw_ptr + size > pcm->buffer_size ? pcm->buffer_size - hw_ptr : size; 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; size -= transfer;
snoop_areas(dsnoop, src_areas, dst_areas, slave_hw_ptr, hw_ptr, transfer); snoop_areas(dsnoop, src_areas, dst_areas, slave_hw_ptr, hw_ptr, transfer);
slave_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 += transfer;
hw_ptr %= pcm->buffer_size; 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 */ if (diff == 0) /* fast path */
return 0; return 0;
if (diff < 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; diff = slave_hw_ptr - old_slave_hw_ptr;
} }
snd_pcm_dsnoop_sync_area(pcm, old_slave_hw_ptr, diff); 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_t *dsnoop = pcm->private_data;
snd_pcm_direct_check_interleave(dsnoop, pcm); snd_pcm_direct_check_interleave(dsnoop, pcm);
// assert(pcm->boundary == dsnoop->shmptr->s.boundary); /* for sure */
dsnoop->state = SND_PCM_STATE_PREPARED; dsnoop->state = SND_PCM_STATE_PREPARED;
dsnoop->appl_ptr = 0; dsnoop->appl_ptr = 0;
dsnoop->hw_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); 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) { ret = snd_pcm_direct_open_secondary_client(&spcm, dsnoop, "dsnoop_client");
SNDERR("unable to open hardware"); if (ret < 0)
goto _err; 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");
goto _err;
}
dsnoop->spcm = spcm; dsnoop->spcm = spcm;
} }