4 * \brief PCM Null Plugin Interface
5 * \author Abramo Bagnara <abramo@alsa-project.org>
10 * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
13 * This library is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License as
15 * published by the Free Software Foundation; either version 2.1 of
16 * the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include "pcm_local.h"
33 #include "pcm_plugin.h"
36 /* entry for static linking */
37 const char *_snd_module_pcm_null = "";
42 snd_htimestamp_t trigger_tstamp;
43 snd_pcm_state_t state;
44 snd_pcm_uframes_t appl_ptr;
45 snd_pcm_uframes_t hw_ptr;
50 static int snd_pcm_null_close(snd_pcm_t *pcm)
52 snd_pcm_null_t *null = pcm->private_data;
58 static int snd_pcm_null_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED)
63 static int snd_pcm_null_async(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int sig ATTRIBUTE_UNUSED, pid_t pid ATTRIBUTE_UNUSED)
68 static int snd_pcm_null_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
70 memset(info, 0, sizeof(*info));
71 info->stream = pcm->stream;
74 strncpy(info->id, pcm->name, sizeof(info->id));
75 strncpy(info->name, pcm->name, sizeof(info->name));
76 strncpy(info->subname, pcm->name, sizeof(info->subname));
78 info->subdevices_count = 1;
82 static int snd_pcm_null_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info)
84 return snd_pcm_channel_info_shm(pcm, info, -1);
87 static int snd_pcm_null_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
89 snd_pcm_null_t *null = pcm->private_data;
91 memset(status, 0, sizeof(*status));
92 status->state = null->state;
93 status->trigger_tstamp = null->trigger_tstamp;
95 status->tstamp.tv_sec = tv.tv_sec;
96 status->tstamp.tv_nsec = tv.tv_usec * 1000L;
97 status->avail = pcm->buffer_size;
98 status->avail_max = status->avail;
102 static snd_pcm_state_t snd_pcm_null_state(snd_pcm_t *pcm)
104 snd_pcm_null_t *null = pcm->private_data;
108 static int snd_pcm_null_hwsync(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
113 static int snd_pcm_null_delay(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sframes_t *delayp)
119 static int snd_pcm_null_prepare(snd_pcm_t *pcm)
121 snd_pcm_null_t *null = pcm->private_data;
122 null->state = SND_PCM_STATE_PREPARED;
128 static int snd_pcm_null_reset(snd_pcm_t *pcm)
135 static int snd_pcm_null_start(snd_pcm_t *pcm)
137 snd_pcm_null_t *null = pcm->private_data;
138 assert(null->state == SND_PCM_STATE_PREPARED);
139 null->state = SND_PCM_STATE_RUNNING;
140 if (pcm->stream == SND_PCM_STREAM_CAPTURE)
141 *pcm->hw.ptr = *pcm->appl.ptr + pcm->buffer_size;
143 *pcm->hw.ptr = *pcm->appl.ptr;
147 static int snd_pcm_null_drop(snd_pcm_t *pcm)
149 snd_pcm_null_t *null = pcm->private_data;
150 assert(null->state != SND_PCM_STATE_OPEN);
151 null->state = SND_PCM_STATE_SETUP;
155 static int snd_pcm_null_drain(snd_pcm_t *pcm)
157 snd_pcm_null_t *null = pcm->private_data;
158 assert(null->state != SND_PCM_STATE_OPEN);
159 null->state = SND_PCM_STATE_SETUP;
163 static int snd_pcm_null_pause(snd_pcm_t *pcm, int enable)
165 snd_pcm_null_t *null = pcm->private_data;
167 if (null->state != SND_PCM_STATE_RUNNING)
169 null->state = SND_PCM_STATE_PAUSED;
171 if (null->state != SND_PCM_STATE_PAUSED)
173 null->state = SND_PCM_STATE_RUNNING;
178 static snd_pcm_sframes_t snd_pcm_null_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
180 snd_pcm_null_t *null = pcm->private_data;
181 switch (null->state) {
182 case SND_PCM_STATE_RUNNING:
183 snd_pcm_mmap_hw_backward(pcm, frames);
185 case SND_PCM_STATE_PREPARED:
186 snd_pcm_mmap_appl_backward(pcm, frames);
193 static snd_pcm_sframes_t snd_pcm_null_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
195 snd_pcm_null_t *null = pcm->private_data;
196 switch (null->state) {
197 case SND_PCM_STATE_RUNNING:
198 snd_pcm_mmap_hw_forward(pcm, frames);
200 case SND_PCM_STATE_PREPARED:
201 snd_pcm_mmap_appl_forward(pcm, frames);
208 static int snd_pcm_null_resume(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
213 static snd_pcm_sframes_t snd_pcm_null_fwd(snd_pcm_t *pcm, snd_pcm_uframes_t size)
215 snd_pcm_null_t *null = pcm->private_data;
216 switch (null->state) {
217 case SND_PCM_STATE_RUNNING:
218 snd_pcm_mmap_hw_forward(pcm, size);
220 case SND_PCM_STATE_PREPARED:
221 snd_pcm_mmap_appl_forward(pcm, size);
228 static snd_pcm_sframes_t snd_pcm_null_xfer_areas(snd_pcm_t *pcm,
229 const snd_pcm_channel_area_t *areas ATTRIBUTE_UNUSED,
230 snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
231 snd_pcm_uframes_t size)
233 snd_pcm_mmap_appl_forward(pcm, size);
234 snd_pcm_mmap_hw_forward(pcm, size);
238 static snd_pcm_sframes_t snd_pcm_null_writei(snd_pcm_t *pcm, const void *buffer ATTRIBUTE_UNUSED, snd_pcm_uframes_t size)
240 return snd_pcm_write_areas(pcm, NULL, 0, size, snd_pcm_null_xfer_areas);
243 static snd_pcm_sframes_t snd_pcm_null_writen(snd_pcm_t *pcm, void **bufs ATTRIBUTE_UNUSED, snd_pcm_uframes_t size)
245 return snd_pcm_write_areas(pcm, NULL, 0, size, snd_pcm_null_xfer_areas);
248 static snd_pcm_sframes_t snd_pcm_null_readi(snd_pcm_t *pcm, void *buffer ATTRIBUTE_UNUSED, snd_pcm_uframes_t size)
250 return snd_pcm_read_areas(pcm, NULL, 0, size, snd_pcm_null_xfer_areas);
253 static snd_pcm_sframes_t snd_pcm_null_readn(snd_pcm_t *pcm, void **bufs ATTRIBUTE_UNUSED, snd_pcm_uframes_t size)
255 return snd_pcm_read_areas(pcm, NULL, 0, size, snd_pcm_null_xfer_areas);
258 static snd_pcm_sframes_t snd_pcm_null_mmap_commit(snd_pcm_t *pcm,
259 snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
260 snd_pcm_uframes_t size)
262 snd_pcm_sframes_t res;
264 res = snd_pcm_null_fwd(pcm, size);
270 static snd_pcm_sframes_t snd_pcm_null_avail_update(snd_pcm_t *pcm)
272 return pcm->buffer_size;
275 static int snd_pcm_null_hw_refine(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
277 int err = snd_pcm_hw_refine_soft(pcm, params);
278 params->fifo_size = 0;
282 static int snd_pcm_null_hw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t * params ATTRIBUTE_UNUSED)
287 static int snd_pcm_null_hw_free(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
292 static int snd_pcm_null_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t * params ATTRIBUTE_UNUSED)
297 static int snd_pcm_null_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
302 static int snd_pcm_null_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
307 static void snd_pcm_null_dump(snd_pcm_t *pcm, snd_output_t *out)
309 snd_output_printf(out, "Null PCM\n");
311 snd_output_printf(out, "Its setup is:\n");
312 snd_pcm_dump_setup(pcm, out);
316 static snd_pcm_ops_t snd_pcm_null_ops = {
317 .close = snd_pcm_null_close,
318 .info = snd_pcm_null_info,
319 .hw_refine = snd_pcm_null_hw_refine,
320 .hw_params = snd_pcm_null_hw_params,
321 .hw_free = snd_pcm_null_hw_free,
322 .sw_params = snd_pcm_null_sw_params,
323 .channel_info = snd_pcm_null_channel_info,
324 .dump = snd_pcm_null_dump,
325 .nonblock = snd_pcm_null_nonblock,
326 .async = snd_pcm_null_async,
327 .mmap = snd_pcm_null_mmap,
328 .munmap = snd_pcm_null_munmap,
331 static snd_pcm_fast_ops_t snd_pcm_null_fast_ops = {
332 .status = snd_pcm_null_status,
333 .state = snd_pcm_null_state,
334 .hwsync = snd_pcm_null_hwsync,
335 .delay = snd_pcm_null_delay,
336 .prepare = snd_pcm_null_prepare,
337 .reset = snd_pcm_null_reset,
338 .start = snd_pcm_null_start,
339 .drop = snd_pcm_null_drop,
340 .drain = snd_pcm_null_drain,
341 .pause = snd_pcm_null_pause,
342 .rewind = snd_pcm_null_rewind,
343 .forward = snd_pcm_null_forward,
344 .resume = snd_pcm_null_resume,
345 .writei = snd_pcm_null_writei,
346 .writen = snd_pcm_null_writen,
347 .readi = snd_pcm_null_readi,
348 .readn = snd_pcm_null_readn,
349 .avail_update = snd_pcm_null_avail_update,
350 .mmap_commit = snd_pcm_null_mmap_commit,
354 * \brief Creates a new null PCM
355 * \param pcmp Returns created PCM handle
356 * \param name Name of PCM
357 * \param stream Stream type
358 * \param mode Stream mode
359 * \retval zero on success otherwise a negative error code
360 * \warning Using of this function might be dangerous in the sense
361 * of compatibility reasons. The prototype might be freely
364 int snd_pcm_null_open(snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t stream, int mode)
367 snd_pcm_null_t *null;
371 if (stream == SND_PCM_STREAM_PLAYBACK) {
372 fd = open("/dev/null", O_WRONLY);
374 SYSERR("Cannot open /dev/null");
378 fd = open("/dev/full", O_RDONLY);
380 SYSERR("Cannot open /dev/full");
384 null = calloc(1, sizeof(snd_pcm_null_t));
390 null->state = SND_PCM_STATE_OPEN;
392 err = snd_pcm_new(&pcm, SND_PCM_TYPE_NULL, name, stream, mode);
398 pcm->ops = &snd_pcm_null_ops;
399 pcm->fast_ops = &snd_pcm_null_fast_ops;
400 pcm->private_data = null;
402 pcm->poll_events = stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN;
403 snd_pcm_set_hw_ptr(pcm, &null->hw_ptr, -1, 0);
404 snd_pcm_set_appl_ptr(pcm, &null->appl_ptr, -1, 0);
410 /*! \page pcm_plugins
412 \section pcm_plugins_null Plugin: Null
414 This plugin discards contents of a PCM stream or creates a stream with zero
417 Note: This implementation uses devices /dev/null (playback, must be writable)
418 and /dev/full (capture, must be readable).
426 \subsection pcm_plugins_null_funcref Function reference
429 <LI>snd_pcm_null_open()
430 <LI>_snd_pcm_null_open()
436 * \brief Creates a new Null PCM
437 * \param pcmp Returns created PCM handle
438 * \param name Name of PCM
439 * \param root Root configuration node
440 * \param conf Configuration node with Null PCM description
441 * \param stream Stream type
442 * \param mode Stream mode
443 * \retval zero on success otherwise a negative error code
444 * \warning Using of this function might be dangerous in the sense
445 * of compatibility reasons. The prototype might be freely
448 int _snd_pcm_null_open(snd_pcm_t **pcmp, const char *name,
449 snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *conf,
450 snd_pcm_stream_t stream, int mode)
452 snd_config_iterator_t i, next;
453 snd_config_for_each(i, next, conf) {
454 snd_config_t *n = snd_config_iterator_entry(i);
456 if (snd_config_get_id(n, &id) < 0)
458 if (snd_pcm_conf_generic_id(id))
460 SNDERR("Unknown field %s", id);
463 return snd_pcm_null_open(pcmp, name, stream, mode);
466 SND_DLSYM_BUILD_VERSION(_snd_pcm_null_open, SND_PCM_DLSYM_VERSION);