Changed direct plugins to handle DISCONNECT/SUSPEND states from slave.
SND_PCM_STATE_PAUSED,
/** Hardware is suspended */
SND_PCM_STATE_SUSPENDED,
- SND_PCM_STATE_LAST = SND_PCM_STATE_SUSPENDED
+ /** Hardware is disconnected */
+ SND_PCM_STATE_DISCONNECTED,
+ SND_PCM_STATE_LAST = SND_PCM_STATE_DISCONNECTED
} snd_pcm_state_t;
/** PCM start mode */
#snd_pcm_drop(), #snd_pcm_drain() can be used
to leave this state.
+\par SND_PCM_STATE_DISCONNECTED
+The device is physicaly disconnected. It does not accept any I/O calls in this state.
+
\section pcm_formats PCM formats
The full list of formats present the #snd_pcm_format_t type.
STATE(DRAINING),
STATE(PAUSED),
STATE(SUSPENDED),
+ STATE(DISCONNECTED),
};
static const char *snd_pcm_access_names[] = {
return -EPIPE;
case SND_PCM_STATE_SUSPENDED:
return -ESTRPIPE;
+ case SND_PCM_STATE_DISCONNECTED:
+ return -ENOTTY; /* linux VFS does this? */
default:
return -EIO;
}
return -EPIPE;
case SND_PCM_STATE_SUSPENDED:
return -ESTRPIPE;
+ case SND_PCM_STATE_DISCONNECTED:
+ return -ENOTTY;
default:
return -EBADFD;
}
return -EPIPE;
case SND_PCM_STATE_SUSPENDED:
return -ESTRPIPE;
+ case SND_PCM_STATE_DISCONNECTED:
+ return -ENOTTY;
default:
return -EBADFD;
}
snd_pcm_uframes_t slave_hw_ptr, old_slave_hw_ptr, avail;
snd_pcm_sframes_t diff;
+ switch (snd_pcm_state(dmix->spcm)) {
+ case SND_PCM_STATE_SUSPENDED:
+ return -ESTRPIPE;
+ case SND_PCM_STATE_DISCONNECTED:
+ dmix->state = -ENOTTY;
+ return -ENOTTY;
+ default:
+ break;
+ }
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;
static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
{
snd_pcm_direct_t *dmix = pcm->private_data;
+ snd_pcm_state_t state;
switch (dmix->state) {
case SNDRV_PCM_STATE_DRAINING:
break;
}
memset(status, 0, sizeof(*status));
- status->state = dmix->state;
+ state = snd_pcm_state(dmix->spcm);
+ status->state = state == SNDRV_PCM_STATE_RUNNING ? dmix->state : state;
status->trigger_tstamp = dmix->trigger_tstamp;
status->tstamp = snd_pcm_hw_fast_tstamp(dmix->spcm);
status->avail = snd_pcm_mmap_playback_avail(pcm);
static snd_pcm_state_t snd_pcm_dmix_state(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dmix = pcm->private_data;
+ switch (snd_pcm_state(dmix->spcm)) {
+ case SND_PCM_STATE_SUSPENDED:
+ return -ESTRPIPE;
+ case SND_PCM_STATE_DISCONNECTED:
+ dmix->state = -ENOTTY;
+ return -ENOTTY;
+ default:
+ break;
+ }
return dmix->state;
}
return 0;
case SNDRV_PCM_STATE_XRUN:
return -EPIPE;
+ case SNDRV_PCM_STATE_DISCONNECTED:
+ return -ENOTTY;
default:
return -EBADFD;
}
return 0;
case SNDRV_PCM_STATE_XRUN:
return -EPIPE;
+ case SNDRV_PCM_STATE_DISCONNECTED:
+ return -ENOTTY;
default:
return -EBADFD;
}
if (dmix->channels == UINT_MAX)
dmix->channels = dmix->shmptr->s.channels;
-
+
snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
*pcmp = pcm;
snd_pcm_uframes_t slave_hw_ptr, old_slave_hw_ptr, avail;
snd_pcm_sframes_t diff;
+ switch (snd_pcm_state(dshare->spcm)) {
+ case SND_PCM_STATE_SUSPENDED:
+ return -ESTRPIPE;
+ case SND_PCM_STATE_DISCONNECTED:
+ dshare->state = SNDRV_PCM_STATE_DISCONNECTED;
+ return -ENOTTY;
+ default:
+ break;
+ }
old_slave_hw_ptr = dshare->slave_hw_ptr;
slave_hw_ptr = dshare->slave_hw_ptr = *dshare->spcm->hw.ptr;
diff = slave_hw_ptr - old_slave_hw_ptr;
static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
{
snd_pcm_direct_t *dshare = pcm->private_data;
+ snd_pcm_state_t state;
switch (dshare->state) {
case SNDRV_PCM_STATE_DRAINING:
break;
}
memset(status, 0, sizeof(*status));
- status->state = dshare->state;
+ state = snd_pcm_state(dshare->spcm);
+ status->state = state == SND_PCM_STATE_RUNNING ? dshare->state : state;
status->trigger_tstamp = dshare->trigger_tstamp;
status->tstamp = snd_pcm_hw_fast_tstamp(dshare->spcm);
status->avail = snd_pcm_mmap_playback_avail(pcm);
static snd_pcm_state_t snd_pcm_dshare_state(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dshare = pcm->private_data;
+ switch (snd_pcm_state(dshare->spcm)) {
+ case SND_PCM_STATE_SUSPENDED:
+ return -ESTRPIPE;
+ case SND_PCM_STATE_DISCONNECTED:
+ dshare->state = SNDRV_PCM_STATE_DISCONNECTED;
+ return -ENOTTY;
+ default:
+ break;
+ }
return dshare->state;
}
return 0;
case SNDRV_PCM_STATE_XRUN:
return -EPIPE;
+ case SNDRV_PCM_STATE_DISCONNECTED:
+ return -ENOTTY;
default:
return -EBADFD;
}
return 0;
case SNDRV_PCM_STATE_XRUN:
return -EPIPE;
+ case SNDRV_PCM_STATE_DISCONNECTED:
+ return -ENOTTY;
default:
return -EBADFD;
}
snd_pcm_uframes_t slave_hw_ptr, old_slave_hw_ptr, avail;
snd_pcm_sframes_t diff;
+ switch (snd_pcm_state(dsnoop->spcm)) {
+ case SND_PCM_STATE_SUSPENDED:
+ return -ESTRPIPE;
+ case SND_PCM_STATE_DISCONNECTED:
+ dsnoop->state = SNDRV_PCM_STATE_DISCONNECTED;
+ return -ENOTTY;
+ default:
+ break;
+ }
old_slave_hw_ptr = dsnoop->slave_hw_ptr;
slave_hw_ptr = dsnoop->slave_hw_ptr = *dsnoop->spcm->hw.ptr;
diff = slave_hw_ptr - old_slave_hw_ptr;
static int snd_pcm_dsnoop_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
{
snd_pcm_direct_t *dsnoop = pcm->private_data;
+ snd_pcm_state_t state;
switch(dsnoop->state) {
case SNDRV_PCM_STATE_DRAINING:
break;
}
memset(status, 0, sizeof(*status));
- status->state = dsnoop->state;
+ state = snd_pcm_state(dsnoop->spcm);
+ status->state = state == SND_PCM_STATE_RUNNING ? dsnoop->state : state;
status->trigger_tstamp = dsnoop->trigger_tstamp;
status->tstamp = snd_pcm_hw_fast_tstamp(dsnoop->spcm);
status->avail = snd_pcm_mmap_capture_avail(pcm);
static snd_pcm_state_t snd_pcm_dsnoop_state(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dsnoop = pcm->private_data;
+ switch (snd_pcm_state(dsnoop->spcm)) {
+ case SND_PCM_STATE_SUSPENDED:
+ return -ESTRPIPE;
+ case SND_PCM_STATE_DISCONNECTED:
+ dsnoop->state = SNDRV_PCM_STATE_DISCONNECTED;
+ return -ENOTTY;
+ default:
+ break;
+ }
return dsnoop->state;
}
return 0;
case SNDRV_PCM_STATE_XRUN:
return -EPIPE;
+ case SNDRV_PCM_STATE_DISCONNECTED:
+ return -ENOTTY;
default:
return -EBADFD;
}
return 0;
case SNDRV_PCM_STATE_XRUN:
return -EPIPE;
+ case SNDRV_PCM_STATE_DISCONNECTED:
+ return -ENOTTY;
default:
return -EBADFD;
}