1d5ac70f0Sopenharmony_ci/** 2d5ac70f0Sopenharmony_ci * \file pcm/pcm_null.c 3d5ac70f0Sopenharmony_ci * \ingroup PCM_Plugins 4d5ac70f0Sopenharmony_ci * \brief PCM Null Plugin Interface 5d5ac70f0Sopenharmony_ci * \author Abramo Bagnara <abramo@alsa-project.org> 6d5ac70f0Sopenharmony_ci * \date 2000-2001 7d5ac70f0Sopenharmony_ci */ 8d5ac70f0Sopenharmony_ci/* 9d5ac70f0Sopenharmony_ci * PCM - Null plugin 10d5ac70f0Sopenharmony_ci * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org> 11d5ac70f0Sopenharmony_ci * 12d5ac70f0Sopenharmony_ci * 13d5ac70f0Sopenharmony_ci * This library is free software; you can redistribute it and/or modify 14d5ac70f0Sopenharmony_ci * it under the terms of the GNU Lesser General Public License as 15d5ac70f0Sopenharmony_ci * published by the Free Software Foundation; either version 2.1 of 16d5ac70f0Sopenharmony_ci * the License, or (at your option) any later version. 17d5ac70f0Sopenharmony_ci * 18d5ac70f0Sopenharmony_ci * This program is distributed in the hope that it will be useful, 19d5ac70f0Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 20d5ac70f0Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21d5ac70f0Sopenharmony_ci * GNU Lesser General Public License for more details. 22d5ac70f0Sopenharmony_ci * 23d5ac70f0Sopenharmony_ci * You should have received a copy of the GNU Lesser General Public 24d5ac70f0Sopenharmony_ci * License along with this library; if not, write to the Free Software 25d5ac70f0Sopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 26d5ac70f0Sopenharmony_ci * 27d5ac70f0Sopenharmony_ci */ 28d5ac70f0Sopenharmony_ci 29d5ac70f0Sopenharmony_ci#include "pcm_local.h" 30d5ac70f0Sopenharmony_ci#include "pcm_plugin.h" 31d5ac70f0Sopenharmony_ci#include "bswap.h" 32d5ac70f0Sopenharmony_ci#include <limits.h> 33d5ac70f0Sopenharmony_ci 34d5ac70f0Sopenharmony_ci#ifndef PIC 35d5ac70f0Sopenharmony_ci/* entry for static linking */ 36d5ac70f0Sopenharmony_ciconst char *_snd_module_pcm_null = ""; 37d5ac70f0Sopenharmony_ci#endif 38d5ac70f0Sopenharmony_ci 39d5ac70f0Sopenharmony_ci#ifndef DOC_HIDDEN 40d5ac70f0Sopenharmony_citypedef struct { 41d5ac70f0Sopenharmony_ci snd_htimestamp_t trigger_tstamp; 42d5ac70f0Sopenharmony_ci snd_pcm_state_t state; 43d5ac70f0Sopenharmony_ci snd_pcm_uframes_t appl_ptr; 44d5ac70f0Sopenharmony_ci snd_pcm_uframes_t hw_ptr; 45d5ac70f0Sopenharmony_ci int poll_fd; 46d5ac70f0Sopenharmony_ci snd_pcm_chmap_query_t **chmap; 47d5ac70f0Sopenharmony_ci} snd_pcm_null_t; 48d5ac70f0Sopenharmony_ci#endif 49d5ac70f0Sopenharmony_ci 50d5ac70f0Sopenharmony_cistatic int snd_pcm_null_close(snd_pcm_t *pcm) 51d5ac70f0Sopenharmony_ci{ 52d5ac70f0Sopenharmony_ci snd_pcm_null_t *null = pcm->private_data; 53d5ac70f0Sopenharmony_ci close(null->poll_fd); 54d5ac70f0Sopenharmony_ci free(null); 55d5ac70f0Sopenharmony_ci return 0; 56d5ac70f0Sopenharmony_ci} 57d5ac70f0Sopenharmony_ci 58d5ac70f0Sopenharmony_cistatic int snd_pcm_null_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED) 59d5ac70f0Sopenharmony_ci{ 60d5ac70f0Sopenharmony_ci return 0; 61d5ac70f0Sopenharmony_ci} 62d5ac70f0Sopenharmony_ci 63d5ac70f0Sopenharmony_cistatic int snd_pcm_null_async(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int sig ATTRIBUTE_UNUSED, pid_t pid ATTRIBUTE_UNUSED) 64d5ac70f0Sopenharmony_ci{ 65d5ac70f0Sopenharmony_ci return -ENOSYS; 66d5ac70f0Sopenharmony_ci} 67d5ac70f0Sopenharmony_ci 68d5ac70f0Sopenharmony_cistatic int snd_pcm_null_info(snd_pcm_t *pcm, snd_pcm_info_t * info) 69d5ac70f0Sopenharmony_ci{ 70d5ac70f0Sopenharmony_ci memset(info, 0, sizeof(*info)); 71d5ac70f0Sopenharmony_ci info->stream = pcm->stream; 72d5ac70f0Sopenharmony_ci info->card = -1; 73d5ac70f0Sopenharmony_ci if (pcm->name) { 74d5ac70f0Sopenharmony_ci snd_strlcpy((char *)info->id, pcm->name, sizeof(info->id)); 75d5ac70f0Sopenharmony_ci snd_strlcpy((char *)info->name, pcm->name, sizeof(info->name)); 76d5ac70f0Sopenharmony_ci snd_strlcpy((char *)info->subname, pcm->name, sizeof(info->subname)); 77d5ac70f0Sopenharmony_ci } 78d5ac70f0Sopenharmony_ci info->subdevices_count = 1; 79d5ac70f0Sopenharmony_ci return 0; 80d5ac70f0Sopenharmony_ci} 81d5ac70f0Sopenharmony_ci 82d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_null_avail_update(snd_pcm_t *pcm) 83d5ac70f0Sopenharmony_ci{ 84d5ac70f0Sopenharmony_ci snd_pcm_null_t *null = pcm->private_data; 85d5ac70f0Sopenharmony_ci if (null->state == SND_PCM_STATE_PREPARED) { 86d5ac70f0Sopenharmony_ci /* it is required to return the correct avail count for */ 87d5ac70f0Sopenharmony_ci /* the prepared stream, otherwise the start is not called */ 88d5ac70f0Sopenharmony_ci return snd_pcm_mmap_avail(pcm); 89d5ac70f0Sopenharmony_ci } 90d5ac70f0Sopenharmony_ci return pcm->buffer_size; 91d5ac70f0Sopenharmony_ci} 92d5ac70f0Sopenharmony_ci 93d5ac70f0Sopenharmony_cistatic int snd_pcm_null_status(snd_pcm_t *pcm, snd_pcm_status_t * status) 94d5ac70f0Sopenharmony_ci{ 95d5ac70f0Sopenharmony_ci snd_pcm_null_t *null = pcm->private_data; 96d5ac70f0Sopenharmony_ci memset(status, 0, sizeof(*status)); 97d5ac70f0Sopenharmony_ci status->state = null->state; 98d5ac70f0Sopenharmony_ci status->trigger_tstamp = null->trigger_tstamp; 99d5ac70f0Sopenharmony_ci status->appl_ptr = *pcm->appl.ptr; 100d5ac70f0Sopenharmony_ci status->hw_ptr = *pcm->hw.ptr; 101d5ac70f0Sopenharmony_ci gettimestamp(&status->tstamp, pcm->tstamp_type); 102d5ac70f0Sopenharmony_ci status->avail = snd_pcm_null_avail_update(pcm); 103d5ac70f0Sopenharmony_ci status->avail_max = pcm->buffer_size; 104d5ac70f0Sopenharmony_ci return 0; 105d5ac70f0Sopenharmony_ci} 106d5ac70f0Sopenharmony_ci 107d5ac70f0Sopenharmony_cistatic snd_pcm_state_t snd_pcm_null_state(snd_pcm_t *pcm) 108d5ac70f0Sopenharmony_ci{ 109d5ac70f0Sopenharmony_ci snd_pcm_null_t *null = pcm->private_data; 110d5ac70f0Sopenharmony_ci return null->state; 111d5ac70f0Sopenharmony_ci} 112d5ac70f0Sopenharmony_ci 113d5ac70f0Sopenharmony_cistatic int snd_pcm_null_hwsync(snd_pcm_t *pcm ATTRIBUTE_UNUSED) 114d5ac70f0Sopenharmony_ci{ 115d5ac70f0Sopenharmony_ci return 0; 116d5ac70f0Sopenharmony_ci} 117d5ac70f0Sopenharmony_ci 118d5ac70f0Sopenharmony_cistatic int snd_pcm_null_delay(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sframes_t *delayp) 119d5ac70f0Sopenharmony_ci{ 120d5ac70f0Sopenharmony_ci *delayp = 0; 121d5ac70f0Sopenharmony_ci return 0; 122d5ac70f0Sopenharmony_ci} 123d5ac70f0Sopenharmony_ci 124d5ac70f0Sopenharmony_cistatic int snd_pcm_null_reset(snd_pcm_t *pcm) 125d5ac70f0Sopenharmony_ci{ 126d5ac70f0Sopenharmony_ci *pcm->appl.ptr = 0; 127d5ac70f0Sopenharmony_ci *pcm->hw.ptr = 0; 128d5ac70f0Sopenharmony_ci return 0; 129d5ac70f0Sopenharmony_ci} 130d5ac70f0Sopenharmony_ci 131d5ac70f0Sopenharmony_cistatic int snd_pcm_null_prepare(snd_pcm_t *pcm) 132d5ac70f0Sopenharmony_ci{ 133d5ac70f0Sopenharmony_ci snd_pcm_null_t *null = pcm->private_data; 134d5ac70f0Sopenharmony_ci null->state = SND_PCM_STATE_PREPARED; 135d5ac70f0Sopenharmony_ci return snd_pcm_null_reset(pcm); 136d5ac70f0Sopenharmony_ci} 137d5ac70f0Sopenharmony_ci 138d5ac70f0Sopenharmony_cistatic int snd_pcm_null_start(snd_pcm_t *pcm) 139d5ac70f0Sopenharmony_ci{ 140d5ac70f0Sopenharmony_ci snd_pcm_null_t *null = pcm->private_data; 141d5ac70f0Sopenharmony_ci assert(null->state == SND_PCM_STATE_PREPARED); 142d5ac70f0Sopenharmony_ci null->state = SND_PCM_STATE_RUNNING; 143d5ac70f0Sopenharmony_ci if (pcm->stream == SND_PCM_STREAM_CAPTURE) 144d5ac70f0Sopenharmony_ci *pcm->hw.ptr = *pcm->appl.ptr + pcm->buffer_size; 145d5ac70f0Sopenharmony_ci else 146d5ac70f0Sopenharmony_ci *pcm->hw.ptr = *pcm->appl.ptr; 147d5ac70f0Sopenharmony_ci return 0; 148d5ac70f0Sopenharmony_ci} 149d5ac70f0Sopenharmony_ci 150d5ac70f0Sopenharmony_cistatic int snd_pcm_null_drop(snd_pcm_t *pcm) 151d5ac70f0Sopenharmony_ci{ 152d5ac70f0Sopenharmony_ci snd_pcm_null_t *null = pcm->private_data; 153d5ac70f0Sopenharmony_ci assert(null->state != SND_PCM_STATE_OPEN); 154d5ac70f0Sopenharmony_ci null->state = SND_PCM_STATE_SETUP; 155d5ac70f0Sopenharmony_ci return 0; 156d5ac70f0Sopenharmony_ci} 157d5ac70f0Sopenharmony_ci 158d5ac70f0Sopenharmony_cistatic int snd_pcm_null_drain(snd_pcm_t *pcm) 159d5ac70f0Sopenharmony_ci{ 160d5ac70f0Sopenharmony_ci snd_pcm_null_t *null = pcm->private_data; 161d5ac70f0Sopenharmony_ci assert(null->state != SND_PCM_STATE_OPEN); 162d5ac70f0Sopenharmony_ci null->state = SND_PCM_STATE_SETUP; 163d5ac70f0Sopenharmony_ci return 0; 164d5ac70f0Sopenharmony_ci} 165d5ac70f0Sopenharmony_ci 166d5ac70f0Sopenharmony_cistatic int snd_pcm_null_pause(snd_pcm_t *pcm, int enable) 167d5ac70f0Sopenharmony_ci{ 168d5ac70f0Sopenharmony_ci snd_pcm_null_t *null = pcm->private_data; 169d5ac70f0Sopenharmony_ci if (enable) { 170d5ac70f0Sopenharmony_ci if (null->state != SND_PCM_STATE_RUNNING) 171d5ac70f0Sopenharmony_ci return -EBADFD; 172d5ac70f0Sopenharmony_ci null->state = SND_PCM_STATE_PAUSED; 173d5ac70f0Sopenharmony_ci } else { 174d5ac70f0Sopenharmony_ci if (null->state != SND_PCM_STATE_PAUSED) 175d5ac70f0Sopenharmony_ci return -EBADFD; 176d5ac70f0Sopenharmony_ci null->state = SND_PCM_STATE_RUNNING; 177d5ac70f0Sopenharmony_ci } 178d5ac70f0Sopenharmony_ci return 0; 179d5ac70f0Sopenharmony_ci} 180d5ac70f0Sopenharmony_ci 181d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_null_rewindable(snd_pcm_t *pcm) 182d5ac70f0Sopenharmony_ci{ 183d5ac70f0Sopenharmony_ci return pcm->buffer_size; 184d5ac70f0Sopenharmony_ci} 185d5ac70f0Sopenharmony_ci 186d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_null_forwardable(snd_pcm_t *pcm ATTRIBUTE_UNUSED) 187d5ac70f0Sopenharmony_ci{ 188d5ac70f0Sopenharmony_ci return 0; 189d5ac70f0Sopenharmony_ci} 190d5ac70f0Sopenharmony_ci 191d5ac70f0Sopenharmony_ci 192d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_null_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) 193d5ac70f0Sopenharmony_ci{ 194d5ac70f0Sopenharmony_ci snd_pcm_null_t *null = pcm->private_data; 195d5ac70f0Sopenharmony_ci switch (null->state) { 196d5ac70f0Sopenharmony_ci case SND_PCM_STATE_RUNNING: 197d5ac70f0Sopenharmony_ci snd_pcm_mmap_hw_backward(pcm, frames); 198d5ac70f0Sopenharmony_ci /* Fall through */ 199d5ac70f0Sopenharmony_ci case SND_PCM_STATE_PREPARED: 200d5ac70f0Sopenharmony_ci snd_pcm_mmap_appl_backward(pcm, frames); 201d5ac70f0Sopenharmony_ci return frames; 202d5ac70f0Sopenharmony_ci default: 203d5ac70f0Sopenharmony_ci return -EBADFD; 204d5ac70f0Sopenharmony_ci } 205d5ac70f0Sopenharmony_ci} 206d5ac70f0Sopenharmony_ci 207d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_null_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames) 208d5ac70f0Sopenharmony_ci{ 209d5ac70f0Sopenharmony_ci snd_pcm_null_t *null = pcm->private_data; 210d5ac70f0Sopenharmony_ci switch (null->state) { 211d5ac70f0Sopenharmony_ci case SND_PCM_STATE_RUNNING: 212d5ac70f0Sopenharmony_ci snd_pcm_mmap_hw_forward(pcm, frames); 213d5ac70f0Sopenharmony_ci /* Fall through */ 214d5ac70f0Sopenharmony_ci case SND_PCM_STATE_PREPARED: 215d5ac70f0Sopenharmony_ci snd_pcm_mmap_appl_forward(pcm, frames); 216d5ac70f0Sopenharmony_ci return frames; 217d5ac70f0Sopenharmony_ci default: 218d5ac70f0Sopenharmony_ci return -EBADFD; 219d5ac70f0Sopenharmony_ci } 220d5ac70f0Sopenharmony_ci} 221d5ac70f0Sopenharmony_ci 222d5ac70f0Sopenharmony_cistatic int snd_pcm_null_resume(snd_pcm_t *pcm ATTRIBUTE_UNUSED) 223d5ac70f0Sopenharmony_ci{ 224d5ac70f0Sopenharmony_ci return 0; 225d5ac70f0Sopenharmony_ci} 226d5ac70f0Sopenharmony_ci 227d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_null_xfer_areas(snd_pcm_t *pcm, 228d5ac70f0Sopenharmony_ci const snd_pcm_channel_area_t *areas ATTRIBUTE_UNUSED, 229d5ac70f0Sopenharmony_ci snd_pcm_uframes_t offset ATTRIBUTE_UNUSED, 230d5ac70f0Sopenharmony_ci snd_pcm_uframes_t size) 231d5ac70f0Sopenharmony_ci{ 232d5ac70f0Sopenharmony_ci snd_pcm_mmap_appl_forward(pcm, size); 233d5ac70f0Sopenharmony_ci snd_pcm_mmap_hw_forward(pcm, size); 234d5ac70f0Sopenharmony_ci return size; 235d5ac70f0Sopenharmony_ci} 236d5ac70f0Sopenharmony_ci 237d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_null_writei(snd_pcm_t *pcm, const void *buffer ATTRIBUTE_UNUSED, snd_pcm_uframes_t size) 238d5ac70f0Sopenharmony_ci{ 239d5ac70f0Sopenharmony_ci return snd_pcm_write_areas(pcm, NULL, 0, size, snd_pcm_null_xfer_areas); 240d5ac70f0Sopenharmony_ci} 241d5ac70f0Sopenharmony_ci 242d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_null_writen(snd_pcm_t *pcm, void **bufs ATTRIBUTE_UNUSED, snd_pcm_uframes_t size) 243d5ac70f0Sopenharmony_ci{ 244d5ac70f0Sopenharmony_ci return snd_pcm_write_areas(pcm, NULL, 0, size, snd_pcm_null_xfer_areas); 245d5ac70f0Sopenharmony_ci} 246d5ac70f0Sopenharmony_ci 247d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_null_readi(snd_pcm_t *pcm, void *buffer ATTRIBUTE_UNUSED, snd_pcm_uframes_t size) 248d5ac70f0Sopenharmony_ci{ 249d5ac70f0Sopenharmony_ci return snd_pcm_read_areas(pcm, NULL, 0, size, snd_pcm_null_xfer_areas); 250d5ac70f0Sopenharmony_ci} 251d5ac70f0Sopenharmony_ci 252d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_null_readn(snd_pcm_t *pcm, void **bufs ATTRIBUTE_UNUSED, snd_pcm_uframes_t size) 253d5ac70f0Sopenharmony_ci{ 254d5ac70f0Sopenharmony_ci return snd_pcm_read_areas(pcm, NULL, 0, size, snd_pcm_null_xfer_areas); 255d5ac70f0Sopenharmony_ci} 256d5ac70f0Sopenharmony_ci 257d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_null_mmap_commit(snd_pcm_t *pcm, 258d5ac70f0Sopenharmony_ci snd_pcm_uframes_t offset ATTRIBUTE_UNUSED, 259d5ac70f0Sopenharmony_ci snd_pcm_uframes_t size) 260d5ac70f0Sopenharmony_ci{ 261d5ac70f0Sopenharmony_ci return snd_pcm_null_forward(pcm, size); 262d5ac70f0Sopenharmony_ci} 263d5ac70f0Sopenharmony_ci 264d5ac70f0Sopenharmony_cistatic int snd_pcm_null_hw_refine(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params) 265d5ac70f0Sopenharmony_ci{ 266d5ac70f0Sopenharmony_ci int err; 267d5ac70f0Sopenharmony_ci 268d5ac70f0Sopenharmony_ci /* Do not return a period size of 0 because for example portaudio cannot 269d5ac70f0Sopenharmony_ci * handle it. 270d5ac70f0Sopenharmony_ci */ 271d5ac70f0Sopenharmony_ci err = _snd_pcm_hw_param_set_min(params, SND_PCM_HW_PARAM_PERIOD_SIZE, 1, 272d5ac70f0Sopenharmony_ci 0); 273d5ac70f0Sopenharmony_ci if (err < 0) 274d5ac70f0Sopenharmony_ci return err; 275d5ac70f0Sopenharmony_ci 276d5ac70f0Sopenharmony_ci err = snd_pcm_hw_refine_soft(pcm, params); 277d5ac70f0Sopenharmony_ci params->info = SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID | 278d5ac70f0Sopenharmony_ci SND_PCM_INFO_RESUME | SND_PCM_INFO_PAUSE; 279d5ac70f0Sopenharmony_ci params->fifo_size = 0; 280d5ac70f0Sopenharmony_ci return err; 281d5ac70f0Sopenharmony_ci} 282d5ac70f0Sopenharmony_ci 283d5ac70f0Sopenharmony_cistatic int snd_pcm_null_hw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t * params ATTRIBUTE_UNUSED) 284d5ac70f0Sopenharmony_ci{ 285d5ac70f0Sopenharmony_ci return 0; 286d5ac70f0Sopenharmony_ci} 287d5ac70f0Sopenharmony_ci 288d5ac70f0Sopenharmony_cistatic int snd_pcm_null_hw_free(snd_pcm_t *pcm ATTRIBUTE_UNUSED) 289d5ac70f0Sopenharmony_ci{ 290d5ac70f0Sopenharmony_ci return 0; 291d5ac70f0Sopenharmony_ci} 292d5ac70f0Sopenharmony_ci 293d5ac70f0Sopenharmony_cistatic int snd_pcm_null_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t * params ATTRIBUTE_UNUSED) 294d5ac70f0Sopenharmony_ci{ 295d5ac70f0Sopenharmony_ci return 0; 296d5ac70f0Sopenharmony_ci} 297d5ac70f0Sopenharmony_ci 298d5ac70f0Sopenharmony_cistatic snd_pcm_chmap_query_t **snd_pcm_null_query_chmaps(snd_pcm_t *pcm) 299d5ac70f0Sopenharmony_ci{ 300d5ac70f0Sopenharmony_ci snd_pcm_null_t *null = pcm->private_data; 301d5ac70f0Sopenharmony_ci 302d5ac70f0Sopenharmony_ci if (null->chmap) 303d5ac70f0Sopenharmony_ci return _snd_pcm_copy_chmap_query(null->chmap); 304d5ac70f0Sopenharmony_ci return NULL; 305d5ac70f0Sopenharmony_ci} 306d5ac70f0Sopenharmony_ci 307d5ac70f0Sopenharmony_cistatic snd_pcm_chmap_t *snd_pcm_null_get_chmap(snd_pcm_t *pcm) 308d5ac70f0Sopenharmony_ci{ 309d5ac70f0Sopenharmony_ci snd_pcm_null_t *null = pcm->private_data; 310d5ac70f0Sopenharmony_ci 311d5ac70f0Sopenharmony_ci if (null->chmap) 312d5ac70f0Sopenharmony_ci return _snd_pcm_choose_fixed_chmap(pcm, null->chmap); 313d5ac70f0Sopenharmony_ci return NULL; 314d5ac70f0Sopenharmony_ci} 315d5ac70f0Sopenharmony_ci 316d5ac70f0Sopenharmony_cistatic void snd_pcm_null_dump(snd_pcm_t *pcm, snd_output_t *out) 317d5ac70f0Sopenharmony_ci{ 318d5ac70f0Sopenharmony_ci snd_output_printf(out, "Null PCM\n"); 319d5ac70f0Sopenharmony_ci if (pcm->setup) { 320d5ac70f0Sopenharmony_ci snd_output_printf(out, "Its setup is:\n"); 321d5ac70f0Sopenharmony_ci snd_pcm_dump_setup(pcm, out); 322d5ac70f0Sopenharmony_ci } 323d5ac70f0Sopenharmony_ci} 324d5ac70f0Sopenharmony_ci 325d5ac70f0Sopenharmony_cistatic const snd_pcm_ops_t snd_pcm_null_ops = { 326d5ac70f0Sopenharmony_ci .close = snd_pcm_null_close, 327d5ac70f0Sopenharmony_ci .info = snd_pcm_null_info, 328d5ac70f0Sopenharmony_ci .hw_refine = snd_pcm_null_hw_refine, 329d5ac70f0Sopenharmony_ci .hw_params = snd_pcm_null_hw_params, 330d5ac70f0Sopenharmony_ci .hw_free = snd_pcm_null_hw_free, 331d5ac70f0Sopenharmony_ci .sw_params = snd_pcm_null_sw_params, 332d5ac70f0Sopenharmony_ci .channel_info = snd_pcm_generic_channel_info, 333d5ac70f0Sopenharmony_ci .dump = snd_pcm_null_dump, 334d5ac70f0Sopenharmony_ci .nonblock = snd_pcm_null_nonblock, 335d5ac70f0Sopenharmony_ci .async = snd_pcm_null_async, 336d5ac70f0Sopenharmony_ci .mmap = snd_pcm_generic_mmap, 337d5ac70f0Sopenharmony_ci .munmap = snd_pcm_generic_munmap, 338d5ac70f0Sopenharmony_ci .query_chmaps = snd_pcm_null_query_chmaps, 339d5ac70f0Sopenharmony_ci .get_chmap = snd_pcm_null_get_chmap, 340d5ac70f0Sopenharmony_ci .set_chmap = NULL, 341d5ac70f0Sopenharmony_ci}; 342d5ac70f0Sopenharmony_ci 343d5ac70f0Sopenharmony_cistatic const snd_pcm_fast_ops_t snd_pcm_null_fast_ops = { 344d5ac70f0Sopenharmony_ci .status = snd_pcm_null_status, 345d5ac70f0Sopenharmony_ci .state = snd_pcm_null_state, 346d5ac70f0Sopenharmony_ci .hwsync = snd_pcm_null_hwsync, 347d5ac70f0Sopenharmony_ci .delay = snd_pcm_null_delay, 348d5ac70f0Sopenharmony_ci .prepare = snd_pcm_null_prepare, 349d5ac70f0Sopenharmony_ci .reset = snd_pcm_null_reset, 350d5ac70f0Sopenharmony_ci .start = snd_pcm_null_start, 351d5ac70f0Sopenharmony_ci .drop = snd_pcm_null_drop, 352d5ac70f0Sopenharmony_ci .drain = snd_pcm_null_drain, 353d5ac70f0Sopenharmony_ci .pause = snd_pcm_null_pause, 354d5ac70f0Sopenharmony_ci .rewindable = snd_pcm_null_rewindable, 355d5ac70f0Sopenharmony_ci .rewind = snd_pcm_null_rewind, 356d5ac70f0Sopenharmony_ci .forwardable = snd_pcm_null_forwardable, 357d5ac70f0Sopenharmony_ci .forward = snd_pcm_null_forward, 358d5ac70f0Sopenharmony_ci .resume = snd_pcm_null_resume, 359d5ac70f0Sopenharmony_ci .writei = snd_pcm_null_writei, 360d5ac70f0Sopenharmony_ci .writen = snd_pcm_null_writen, 361d5ac70f0Sopenharmony_ci .readi = snd_pcm_null_readi, 362d5ac70f0Sopenharmony_ci .readn = snd_pcm_null_readn, 363d5ac70f0Sopenharmony_ci .avail_update = snd_pcm_null_avail_update, 364d5ac70f0Sopenharmony_ci .mmap_commit = snd_pcm_null_mmap_commit, 365d5ac70f0Sopenharmony_ci .htimestamp = snd_pcm_generic_real_htimestamp, 366d5ac70f0Sopenharmony_ci}; 367d5ac70f0Sopenharmony_ci 368d5ac70f0Sopenharmony_ci/** 369d5ac70f0Sopenharmony_ci * \brief Creates a new null PCM 370d5ac70f0Sopenharmony_ci * \param pcmp Returns created PCM handle 371d5ac70f0Sopenharmony_ci * \param name Name of PCM 372d5ac70f0Sopenharmony_ci * \param stream Stream type 373d5ac70f0Sopenharmony_ci * \param mode Stream mode 374d5ac70f0Sopenharmony_ci * \retval zero on success otherwise a negative error code 375d5ac70f0Sopenharmony_ci * \warning Using of this function might be dangerous in the sense 376d5ac70f0Sopenharmony_ci * of compatibility reasons. The prototype might be freely 377d5ac70f0Sopenharmony_ci * changed in future. 378d5ac70f0Sopenharmony_ci */ 379d5ac70f0Sopenharmony_ciint snd_pcm_null_open(snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t stream, int mode) 380d5ac70f0Sopenharmony_ci{ 381d5ac70f0Sopenharmony_ci snd_pcm_t *pcm; 382d5ac70f0Sopenharmony_ci snd_pcm_null_t *null; 383d5ac70f0Sopenharmony_ci int fd; 384d5ac70f0Sopenharmony_ci int err; 385d5ac70f0Sopenharmony_ci assert(pcmp); 386d5ac70f0Sopenharmony_ci if (stream == SND_PCM_STREAM_PLAYBACK) { 387d5ac70f0Sopenharmony_ci fd = open("/dev/null", O_WRONLY); 388d5ac70f0Sopenharmony_ci if (fd < 0) { 389d5ac70f0Sopenharmony_ci SYSERR("Cannot open /dev/null"); 390d5ac70f0Sopenharmony_ci return -errno; 391d5ac70f0Sopenharmony_ci } 392d5ac70f0Sopenharmony_ci } else { 393d5ac70f0Sopenharmony_ci fd = open("/dev/full", O_RDONLY); 394d5ac70f0Sopenharmony_ci if (fd < 0) { 395d5ac70f0Sopenharmony_ci SYSERR("Cannot open /dev/full"); 396d5ac70f0Sopenharmony_ci return -errno; 397d5ac70f0Sopenharmony_ci } 398d5ac70f0Sopenharmony_ci } 399d5ac70f0Sopenharmony_ci null = calloc(1, sizeof(snd_pcm_null_t)); 400d5ac70f0Sopenharmony_ci if (!null) { 401d5ac70f0Sopenharmony_ci close(fd); 402d5ac70f0Sopenharmony_ci return -ENOMEM; 403d5ac70f0Sopenharmony_ci } 404d5ac70f0Sopenharmony_ci null->poll_fd = fd; 405d5ac70f0Sopenharmony_ci null->state = SND_PCM_STATE_OPEN; 406d5ac70f0Sopenharmony_ci 407d5ac70f0Sopenharmony_ci err = snd_pcm_new(&pcm, SND_PCM_TYPE_NULL, name, stream, mode); 408d5ac70f0Sopenharmony_ci if (err < 0) { 409d5ac70f0Sopenharmony_ci close(fd); 410d5ac70f0Sopenharmony_ci free(null); 411d5ac70f0Sopenharmony_ci return err; 412d5ac70f0Sopenharmony_ci } 413d5ac70f0Sopenharmony_ci pcm->ops = &snd_pcm_null_ops; 414d5ac70f0Sopenharmony_ci pcm->fast_ops = &snd_pcm_null_fast_ops; 415d5ac70f0Sopenharmony_ci pcm->private_data = null; 416d5ac70f0Sopenharmony_ci pcm->poll_fd = fd; 417d5ac70f0Sopenharmony_ci pcm->poll_events = stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN; 418d5ac70f0Sopenharmony_ci snd_pcm_set_hw_ptr(pcm, &null->hw_ptr, -1, 0); 419d5ac70f0Sopenharmony_ci snd_pcm_set_appl_ptr(pcm, &null->appl_ptr, -1, 0); 420d5ac70f0Sopenharmony_ci *pcmp = pcm; 421d5ac70f0Sopenharmony_ci 422d5ac70f0Sopenharmony_ci return 0; 423d5ac70f0Sopenharmony_ci} 424d5ac70f0Sopenharmony_ci 425d5ac70f0Sopenharmony_ci/*! \page pcm_plugins 426d5ac70f0Sopenharmony_ci 427d5ac70f0Sopenharmony_ci\section pcm_plugins_null Plugin: Null 428d5ac70f0Sopenharmony_ci 429d5ac70f0Sopenharmony_ciThis plugin discards contents of a PCM stream or creates a stream with zero 430d5ac70f0Sopenharmony_cisamples. 431d5ac70f0Sopenharmony_ci 432d5ac70f0Sopenharmony_ciNote: This implementation uses devices /dev/null (playback, must be writable) 433d5ac70f0Sopenharmony_ciand /dev/full (capture, must be readable). 434d5ac70f0Sopenharmony_ci 435d5ac70f0Sopenharmony_ci\code 436d5ac70f0Sopenharmony_cipcm.name { 437d5ac70f0Sopenharmony_ci type null # Null PCM 438d5ac70f0Sopenharmony_ci [chmap MAP] # Provide channel maps; MAP is a string array 439d5ac70f0Sopenharmony_ci} 440d5ac70f0Sopenharmony_ci\endcode 441d5ac70f0Sopenharmony_ci 442d5ac70f0Sopenharmony_ci\subsection pcm_plugins_null_funcref Function reference 443d5ac70f0Sopenharmony_ci 444d5ac70f0Sopenharmony_ci<UL> 445d5ac70f0Sopenharmony_ci <LI>snd_pcm_null_open() 446d5ac70f0Sopenharmony_ci <LI>_snd_pcm_null_open() 447d5ac70f0Sopenharmony_ci</UL> 448d5ac70f0Sopenharmony_ci 449d5ac70f0Sopenharmony_ci*/ 450d5ac70f0Sopenharmony_ci 451d5ac70f0Sopenharmony_ci/** 452d5ac70f0Sopenharmony_ci * \brief Creates a new Null PCM 453d5ac70f0Sopenharmony_ci * \param pcmp Returns created PCM handle 454d5ac70f0Sopenharmony_ci * \param name Name of PCM 455d5ac70f0Sopenharmony_ci * \param root Root configuration node 456d5ac70f0Sopenharmony_ci * \param conf Configuration node with Null PCM description 457d5ac70f0Sopenharmony_ci * \param stream Stream type 458d5ac70f0Sopenharmony_ci * \param mode Stream mode 459d5ac70f0Sopenharmony_ci * \retval zero on success otherwise a negative error code 460d5ac70f0Sopenharmony_ci * \warning Using of this function might be dangerous in the sense 461d5ac70f0Sopenharmony_ci * of compatibility reasons. The prototype might be freely 462d5ac70f0Sopenharmony_ci * changed in future. 463d5ac70f0Sopenharmony_ci */ 464d5ac70f0Sopenharmony_ciint _snd_pcm_null_open(snd_pcm_t **pcmp, const char *name, 465d5ac70f0Sopenharmony_ci snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *conf, 466d5ac70f0Sopenharmony_ci snd_pcm_stream_t stream, int mode) 467d5ac70f0Sopenharmony_ci{ 468d5ac70f0Sopenharmony_ci snd_config_iterator_t i, next; 469d5ac70f0Sopenharmony_ci snd_pcm_null_t *null; 470d5ac70f0Sopenharmony_ci snd_pcm_chmap_query_t **chmap = NULL; 471d5ac70f0Sopenharmony_ci int err; 472d5ac70f0Sopenharmony_ci 473d5ac70f0Sopenharmony_ci snd_config_for_each(i, next, conf) { 474d5ac70f0Sopenharmony_ci snd_config_t *n = snd_config_iterator_entry(i); 475d5ac70f0Sopenharmony_ci const char *id; 476d5ac70f0Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 477d5ac70f0Sopenharmony_ci continue; 478d5ac70f0Sopenharmony_ci if (snd_pcm_conf_generic_id(id)) 479d5ac70f0Sopenharmony_ci continue; 480d5ac70f0Sopenharmony_ci if (strcmp(id, "chmap") == 0) { 481d5ac70f0Sopenharmony_ci snd_pcm_free_chmaps(chmap); 482d5ac70f0Sopenharmony_ci chmap = _snd_pcm_parse_config_chmaps(n); 483d5ac70f0Sopenharmony_ci if (!chmap) { 484d5ac70f0Sopenharmony_ci SNDERR("Invalid channel map for %s", id); 485d5ac70f0Sopenharmony_ci return -EINVAL; 486d5ac70f0Sopenharmony_ci } 487d5ac70f0Sopenharmony_ci continue; 488d5ac70f0Sopenharmony_ci } 489d5ac70f0Sopenharmony_ci SNDERR("Unknown field %s", id); 490d5ac70f0Sopenharmony_ci snd_pcm_free_chmaps(chmap); 491d5ac70f0Sopenharmony_ci return -EINVAL; 492d5ac70f0Sopenharmony_ci } 493d5ac70f0Sopenharmony_ci err = snd_pcm_null_open(pcmp, name, stream, mode); 494d5ac70f0Sopenharmony_ci if (err < 0) { 495d5ac70f0Sopenharmony_ci snd_pcm_free_chmaps(chmap); 496d5ac70f0Sopenharmony_ci return err; 497d5ac70f0Sopenharmony_ci } 498d5ac70f0Sopenharmony_ci 499d5ac70f0Sopenharmony_ci null = (*pcmp)->private_data; 500d5ac70f0Sopenharmony_ci null->chmap = chmap; 501d5ac70f0Sopenharmony_ci return 0; 502d5ac70f0Sopenharmony_ci} 503d5ac70f0Sopenharmony_ci#ifndef DOC_HIDDEN 504d5ac70f0Sopenharmony_ciSND_DLSYM_BUILD_VERSION(_snd_pcm_null_open, SND_PCM_DLSYM_VERSION); 505d5ac70f0Sopenharmony_ci#endif 506