case SND_PCM_IOCTL_HW_PARAMS:
ctrl->result = snd_pcm_hw_params(pcm, (snd_pcm_hw_params_t *) &ctrl->u.hw_params);
break;
+ case SND_PCM_IOCTL_HW_FREE:
+ ctrl->result = snd_pcm_hw_free(pcm);
+ break;
case SND_PCM_IOCTL_SW_PARAMS:
ctrl->result = snd_pcm_sw_params(pcm, (snd_pcm_sw_params_t *) &ctrl->u.sw_params);
break;
int snd_pcm_info(snd_pcm_t *pcm, snd_pcm_info_t *info);
int snd_pcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
+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 snd_pcm_status(snd_pcm_t *pcm, snd_pcm_status_t *status);
int snd_pcm_prepare(snd_pcm_t *pcm);
snd_pcm_drop(pcm);
else
snd_pcm_drain(pcm);
- }
- if (pcm->mmap_channels) {
- if ((err = snd_pcm_munmap(pcm)) < 0)
+ err = snd_pcm_hw_free(pcm);
+ if (err < 0)
ret = err;
}
if ((err = pcm->ops->close(pcm->op_arg)) < 0)
}
}
-static int snd_pcm_adpcm_close(snd_pcm_t *pcm)
-{
- snd_pcm_adpcm_t *adpcm = pcm->private;
- int err = 0;
- if (adpcm->plug.close_slave)
- err = snd_pcm_close(adpcm->plug.slave);
- if (adpcm->states)
- free(adpcm->states);
- free(adpcm);
- return 0;
-}
-
static int snd_pcm_adpcm_hw_refine_cprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
{
snd_pcm_adpcm_t *adpcm = pcm->private;
adpcm->func = adpcm_encode;
}
}
- if (adpcm->states)
- free(adpcm->states);
+ assert(!adpcm->states);
adpcm->states = malloc(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_CHANNELS, 0) * sizeof(*adpcm->states));
return 0;
}
+static int snd_pcm_adpcm_hw_free(snd_pcm_t *pcm)
+{
+ snd_pcm_adpcm_t *adpcm = pcm->private;
+ if (adpcm->states) {
+ free(adpcm->states);
+ adpcm->states = 0;
+ }
+ return snd_pcm_hw_free(adpcm->plug.slave);
+}
+
static int snd_pcm_adpcm_init(snd_pcm_t *pcm)
{
snd_pcm_adpcm_t *adpcm = pcm->private;
}
snd_pcm_ops_t snd_pcm_adpcm_ops = {
- close: snd_pcm_adpcm_close,
+ close: snd_pcm_plugin_close,
card: snd_pcm_plugin_card,
info: snd_pcm_plugin_info,
hw_refine: snd_pcm_adpcm_hw_refine,
hw_params: snd_pcm_adpcm_hw_params,
+ hw_free: snd_pcm_adpcm_hw_free,
sw_params: snd_pcm_plugin_sw_params,
channel_info: snd_pcm_plugin_channel_info,
dump: snd_pcm_adpcm_dump,
info: snd_pcm_plugin_info,
hw_refine: snd_pcm_alaw_hw_refine,
hw_params: snd_pcm_alaw_hw_params,
+ hw_free: snd_pcm_plugin_hw_free,
sw_params: snd_pcm_plugin_sw_params,
channel_info: snd_pcm_plugin_channel_info,
dump: snd_pcm_alaw_dump,
info: snd_pcm_plugin_info,
hw_refine: snd_pcm_copy_hw_refine,
hw_params: snd_pcm_copy_hw_params,
+ hw_free: snd_pcm_plugin_hw_free,
sw_params: snd_pcm_plugin_sw_params,
channel_info: snd_pcm_plugin_channel_info,
dump: snd_pcm_copy_dump,
free(file->fname);
close(file->fd);
}
- if (file->wbuf) {
- free(file->wbuf);
- free(file->wbuf_areas);
- file->wbuf = 0;
- file->wbuf_areas = 0;
- }
free(file);
return 0;
}
int err = snd_pcm_hw_params(slave, params);
if (err < 0)
return err;
- if (file->wbuf) {
- free(file->wbuf);
- free(file->wbuf_areas);
- }
file->buffer_bytes = snd_pcm_frames_to_bytes(slave, slave->buffer_size);
file->wbuf_size = slave->buffer_size * 2;
file->wbuf_size_bytes = snd_pcm_frames_to_bytes(slave, file->wbuf_size);
+ assert(!file->wbuf);
file->wbuf = malloc(file->wbuf_size_bytes);
file->wbuf_areas = malloc(sizeof(*file->wbuf_areas) * slave->channels);
file->appl_ptr = file->file_ptr_bytes = 0;
return 0;
}
+static int snd_pcm_file_hw_free(snd_pcm_t *pcm)
+{
+ snd_pcm_file_t *file = pcm->private;
+ if (file->wbuf) {
+ free(file->wbuf);
+ free(file->wbuf_areas);
+ file->wbuf = 0;
+ file->wbuf_areas = 0;
+ }
+ return snd_pcm_hw_free(file->slave);
+}
+
static int snd_pcm_file_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
{
snd_pcm_file_t *file = pcm->private;
info: snd_pcm_file_info,
hw_refine: snd_pcm_file_hw_refine,
hw_params: snd_pcm_file_hw_params,
+ hw_free: snd_pcm_file_hw_free,
sw_params: snd_pcm_file_sw_params,
channel_info: snd_pcm_file_channel_info,
dump: snd_pcm_file_dump,
return 0;
}
+static int snd_pcm_hw_hw_free(snd_pcm_t *pcm)
+{
+ snd_pcm_hw_t *hw = pcm->private;
+ int fd = hw->fd;
+ if (ioctl(fd, SND_PCM_IOCTL_HW_FREE) < 0) {
+ SYSERR("SND_PCM_IOCTL_HW_FREE failed");
+ return -errno;
+ }
+ return 0;
+}
+
static int snd_pcm_hw_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
{
snd_pcm_hw_t *hw = pcm->private;
info: snd_pcm_hw_info,
hw_refine: snd_pcm_hw_hw_refine,
hw_params: snd_pcm_hw_hw_params,
+ hw_free: snd_pcm_hw_hw_free,
sw_params: snd_pcm_hw_sw_params,
channel_info: snd_pcm_hw_channel_info,
dump: snd_pcm_hw_dump,
info: snd_pcm_plugin_info,
hw_refine: snd_pcm_linear_hw_refine,
hw_params: snd_pcm_linear_hw_params,
+ hw_free: snd_pcm_plugin_hw_free,
sw_params: snd_pcm_plugin_sw_params,
channel_info: snd_pcm_plugin_channel_info,
dump: snd_pcm_linear_dump,
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);
+ int (*hw_free)(snd_pcm_t *pcm);
int (*sw_params)(snd_pcm_t *pcm, snd_pcm_sw_params_t *params);
int (*channel_info)(snd_pcm_t *pcm, snd_pcm_channel_info_t *info);
void (*dump)(snd_pcm_t *pcm, snd_output_t *out);
info: snd_pcm_plugin_info,
hw_refine: snd_pcm_mulaw_hw_refine,
hw_params: snd_pcm_mulaw_hw_params,
+ hw_free: snd_pcm_plugin_hw_free,
sw_params: snd_pcm_plugin_sw_params,
channel_info: snd_pcm_plugin_channel_info,
dump: snd_pcm_mulaw_dump,
return 0;
}
+static int snd_pcm_multi_hw_free(snd_pcm_t *pcm)
+{
+ snd_pcm_multi_t *multi = pcm->private;
+ unsigned int i;
+ int err = 0;
+ for (i = 0; i < multi->slaves_count; ++i) {
+ snd_pcm_t *slave = multi->slaves[i].pcm;
+ int e = snd_pcm_hw_free(slave);
+ if (e < 0)
+ err = e;
+ }
+ return err;
+}
+
static int snd_pcm_multi_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
{
snd_pcm_multi_t *multi = pcm->private;
info: snd_pcm_multi_info,
hw_refine: snd_pcm_multi_hw_refine,
hw_params: snd_pcm_multi_hw_params,
+ hw_free: snd_pcm_multi_hw_free,
sw_params: snd_pcm_multi_sw_params,
channel_info: snd_pcm_multi_channel_info,
dump: snd_pcm_multi_dump,
return 0;
}
+static int snd_pcm_null_hw_free(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
static int snd_pcm_null_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t * params ATTRIBUTE_UNUSED)
{
return 0;
info: snd_pcm_null_info,
hw_refine: snd_pcm_null_hw_refine,
hw_params: snd_pcm_null_hw_params,
+ hw_free: snd_pcm_null_hw_free,
sw_params: snd_pcm_null_sw_params,
channel_info: snd_pcm_null_channel_info,
dump: snd_pcm_null_dump,
if (err < 0)
return err;
snd_pcm_hw_params_choose(pcm, params);
- if (pcm->mmap_channels) {
- err = snd_pcm_munmap(pcm);
+ if (pcm->setup) {
+ err = snd_pcm_hw_free(pcm);
if (err < 0)
- return err;
+ return 0;
}
err = pcm->ops->hw_params(pcm->op_arg, params);
if (err < 0)
- goto _mmap;
+ return err;
pcm->setup = 1;
pcm->access = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_ACCESS, 0);
err = snd_pcm_sw_params(pcm, &sw);
assert(err >= 0);
- _mmap:
- if (pcm->setup &&
- (pcm->mmap_rw ||
- (pcm->access == SND_PCM_ACCESS_MMAP_INTERLEAVED ||
- pcm->access == SND_PCM_ACCESS_MMAP_NONINTERLEAVED ||
- pcm->access == SND_PCM_ACCESS_MMAP_COMPLEX))) {
- int err;
+ if (pcm->mmap_rw ||
+ pcm->access == SND_PCM_ACCESS_MMAP_INTERLEAVED ||
+ pcm->access == SND_PCM_ACCESS_MMAP_NONINTERLEAVED ||
+ pcm->access == SND_PCM_ACCESS_MMAP_COMPLEX) {
err = snd_pcm_mmap(pcm);
- if (err < 0)
- return err;
}
if (err >= 0)
err = snd_pcm_prepare(pcm);
return err;
}
+int snd_pcm_hw_free(snd_pcm_t *pcm)
+{
+ int err;
+ assert(pcm->setup);
+ assert(snd_pcm_state(pcm) <= SND_PCM_STATE_PREPARED);
+ if (pcm->mmap_channels) {
+ err = snd_pcm_munmap(pcm);
+ if (err < 0)
+ return err;
+ }
+ err = pcm->ops->hw_free(pcm->op_arg);
+ pcm->setup = 0;
+ return err;
+}
+
int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
{
int err;
int err, result = 0;
if (plug->ttable)
free(plug->ttable);
- if (plug->slave != plug->req_slave) {
- err = snd_pcm_close(plug->slave);
- if (err < 0)
- result = err;
- }
+ assert(plug->slave == plug->req_slave);
if (plug->close_slave) {
err = snd_pcm_close(plug->req_slave);
if (err < 0)
return 0;
}
+static int snd_pcm_plug_hw_free(snd_pcm_t *pcm)
+{
+ snd_pcm_plug_t *plug = pcm->private;
+ snd_pcm_t *slave = plug->slave;
+ int err = snd_pcm_hw_free(slave);
+ snd_pcm_plug_clear(pcm);
+ return err;
+}
+
static int snd_pcm_plug_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
{
snd_pcm_plug_t *plug = pcm->private;
info: snd_pcm_plug_info,
hw_refine: snd_pcm_plug_hw_refine,
hw_params: snd_pcm_plug_hw_params,
+ hw_free: snd_pcm_plug_hw_free,
sw_params: snd_pcm_plug_sw_params,
channel_info: snd_pcm_plug_channel_info,
dump: snd_pcm_plug_dump,
return snd_pcm_info(plugin->slave, info);
}
+int snd_pcm_plugin_hw_free(snd_pcm_t *pcm)
+{
+ snd_pcm_plugin_t *plugin = pcm->private;
+ return snd_pcm_hw_free(plugin->slave);
+}
+
int snd_pcm_plugin_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
{
snd_pcm_plugin_t *plugin = pcm->private;
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_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);
int snd_pcm_plugin_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params);
int snd_pcm_plugin_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info);
return src_frames1;
}
-static int snd_pcm_rate_close(snd_pcm_t *pcm)
-{
- snd_pcm_rate_t *rate = pcm->private;
- int err = 0;
- if (rate->plug.close_slave)
- err = snd_pcm_close(rate->plug.slave);
- if (rate->states)
- free(rate->states);
- free(rate);
- return 0;
-}
-
static int snd_pcm_rate_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
{
int err;
/* pitch is get_increment */
}
rate->pitch = (((u_int64_t)dst_rate * DIV) + src_rate / 2) / src_rate;
- if (rate->states)
- free(rate->states);
+ assert(!rate->states);
rate->states = malloc(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_CHANNELS, 0) * sizeof(*rate->states));
return 0;
}
+static int snd_pcm_rate_hw_free(snd_pcm_t *pcm)
+{
+ snd_pcm_rate_t *rate = pcm->private;
+ if (rate->states) {
+ free(rate->states);
+ rate->states = 0;
+ }
+ return snd_pcm_hw_free(rate->plug.slave);
+}
+
static int snd_pcm_rate_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
{
snd_pcm_rate_t *rate = pcm->private;
}
snd_pcm_ops_t snd_pcm_rate_ops = {
- close: snd_pcm_rate_close,
+ close: snd_pcm_plugin_close,
card: snd_pcm_plugin_card,
info: snd_pcm_plugin_info,
hw_refine: snd_pcm_rate_hw_refine,
hw_params: snd_pcm_rate_hw_params,
+ hw_free: snd_pcm_rate_hw_free,
sw_params: snd_pcm_rate_sw_params,
channel_info: snd_pcm_plugin_channel_info,
dump: snd_pcm_rate_dump,
info: snd_pcm_plugin_info,
hw_refine: snd_pcm_route_hw_refine,
hw_params: snd_pcm_route_hw_params,
+ hw_free: snd_pcm_plugin_hw_free,
sw_params: snd_pcm_plugin_sw_params,
channel_info: snd_pcm_plugin_channel_info,
dump: snd_pcm_route_dump,
return err;
}
+static int snd_pcm_share_hw_free(snd_pcm_t *pcm)
+{
+ snd_pcm_share_t *share = pcm->private;
+ snd_pcm_share_slave_t *slave = share->slave;
+ int err = 0;
+ Pthread_mutex_lock(&slave->mutex);
+ slave->setup_count--;
+ if (slave->setup_count == 0)
+ err = snd_pcm_hw_free(slave->pcm);
+ share->state = SND_PCM_STATE_OPEN;
+ Pthread_mutex_unlock(&slave->mutex);
+ return err;
+}
+
static int snd_pcm_share_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params ATTRIBUTE_UNUSED)
{
return 0;
int err = 0;
Pthread_mutex_lock(&slaves_mutex);
Pthread_mutex_lock(&slave->mutex);
- if (pcm->setup)
- slave->setup_count--;
slave->open_count--;
if (slave->open_count == 0) {
err = snd_pcm_close(slave->pcm);
info: snd_pcm_share_info,
hw_refine: snd_pcm_share_hw_refine,
hw_params: snd_pcm_share_hw_params,
+ hw_free: snd_pcm_share_hw_free,
sw_params: snd_pcm_share_sw_params,
channel_info: snd_pcm_share_channel_info,
dump: snd_pcm_share_dump,
snd_pcm_shm_hw_params_slave);
}
+static int snd_pcm_shm_hw_free(snd_pcm_t *pcm)
+{
+ snd_pcm_shm_t *shm = pcm->private;
+ volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+ ctrl->cmd = SND_PCM_IOCTL_HW_FREE;
+ return snd_pcm_shm_action(pcm);
+}
+
static int snd_pcm_shm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
{
snd_pcm_shm_t *shm = pcm->private;
info: snd_pcm_shm_info,
hw_refine: snd_pcm_shm_hw_refine,
hw_params: snd_pcm_shm_hw_params,
+ hw_free: snd_pcm_shm_hw_free,
sw_params: snd_pcm_shm_sw_params,
channel_info: snd_pcm_shm_channel_info,
dump: snd_pcm_shm_dump,