1 /**
2  * \file pcm/pcm_dmix.c
3  * \ingroup PCM_Plugins
4  * \brief PCM Direct Stream Mixing (dmix) Plugin Interface
5  * \author Jaroslav Kysela <perex@perex.cz>
6  * \date 2003
7  */
8 /*
9  *  PCM - Direct Stream Mixing
10  *  Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
11  *
12  *
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.
17  *
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.
22  *
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
26  *
27  */
28 
29 #include "pcm_local.h"
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stddef.h>
33 #include <unistd.h>
34 #include <signal.h>
35 #include <string.h>
36 #include <fcntl.h>
37 #include <ctype.h>
38 #include <grp.h>
39 #include <sys/ioctl.h>
40 #include <sys/mman.h>
41 #include <sys/shm.h>
42 #include <sys/sem.h>
43 #include <sys/wait.h>
44 #include <sys/socket.h>
45 #include <sys/un.h>
46 #include <sys/mman.h>
47 #include "pcm_direct.h"
48 
49 #ifndef PIC
50 /* entry for static linking */
51 const char *_snd_module_pcm_dmix = "";
52 #endif
53 
54 #ifndef DOC_HIDDEN
55 /* start is pending - this state happens when rate plugin does a delayed commit */
56 #define STATE_RUN_PENDING	1024
57 #endif
58 
59 /*
60  *
61  */
62 
63 static int shm_sum_discard(snd_pcm_direct_t *dmix);
64 
65 /*
66  *  sum ring buffer shared memory area
67  */
shm_sum_create_or_connect(snd_pcm_direct_t *dmix)68 static int shm_sum_create_or_connect(snd_pcm_direct_t *dmix)
69 {
70 	struct shmid_ds buf;
71 	int tmpid, err;
72 	size_t size;
73 
74 	size = dmix->shmptr->s.channels *
75 	       dmix->shmptr->s.buffer_size *
76 	       sizeof(signed int);
77 retryshm:
78 	dmix->u.dmix.shmid_sum = shmget(dmix->ipc_key + 1, size,
79 					IPC_CREAT | dmix->ipc_perm);
80 	err = -errno;
81 	if (dmix->u.dmix.shmid_sum < 0) {
82 		if (errno == EINVAL)
83 		if ((tmpid = shmget(dmix->ipc_key + 1, 0, dmix->ipc_perm)) != -1)
84 		if (!shmctl(tmpid, IPC_STAT, &buf))
85 	    	if (!buf.shm_nattch)
86 		/* no users so destroy the segment */
87 		if (!shmctl(tmpid, IPC_RMID, NULL))
88 		    goto retryshm;
89 		return err;
90 	}
91 	if (shmctl(dmix->u.dmix.shmid_sum, IPC_STAT, &buf) < 0) {
92 		err = -errno;
93 		shm_sum_discard(dmix);
94 		return err;
95 	}
96 	if (dmix->ipc_gid >= 0) {
97 		buf.shm_perm.gid = dmix->ipc_gid;
98 		shmctl(dmix->u.dmix.shmid_sum, IPC_SET, &buf);
99 	}
100 	dmix->u.dmix.sum_buffer = shmat(dmix->u.dmix.shmid_sum, 0, 0);
101 	if (dmix->u.dmix.sum_buffer == (void *) -1) {
102 		err = -errno;
103 		shm_sum_discard(dmix);
104 		return err;
105 	}
106 	mlock(dmix->u.dmix.sum_buffer, size);
107 	return 0;
108 }
109 
shm_sum_discard(snd_pcm_direct_t *dmix)110 static int shm_sum_discard(snd_pcm_direct_t *dmix)
111 {
112 	struct shmid_ds buf;
113 	int ret = 0;
114 
115 	if (dmix->u.dmix.shmid_sum < 0)
116 		return -EINVAL;
117 	if (dmix->u.dmix.sum_buffer != (void *) -1 && shmdt(dmix->u.dmix.sum_buffer) < 0)
118 		return -errno;
119 	dmix->u.dmix.sum_buffer = (void *) -1;
120 	if (shmctl(dmix->u.dmix.shmid_sum, IPC_STAT, &buf) < 0)
121 		return -errno;
122 	if (buf.shm_nattch == 0) {	/* we're the last user, destroy the segment */
123 		if (shmctl(dmix->u.dmix.shmid_sum, IPC_RMID, NULL) < 0)
124 			return -errno;
125 		ret = 1;
126 	}
127 	dmix->u.dmix.shmid_sum = -1;
128 	return ret;
129 }
130 
dmix_server_free(snd_pcm_direct_t *dmix)131 static void dmix_server_free(snd_pcm_direct_t *dmix)
132 {
133 	/* remove the memory region */
134 	shm_sum_create_or_connect(dmix);
135 	shm_sum_discard(dmix);
136 }
137 
138 /*
139  *  the main function of this plugin: mixing
140  *  FIXME: optimize it for different architectures
141  */
142 
143 #include "pcm_dmix_generic.c"
144 #if defined(__i386__)
145 #include "pcm_dmix_i386.c"
146 #elif defined(__x86_64__)
147 #include "pcm_dmix_x86_64.c"
148 #else
149 #ifndef DOC_HIDDEN
150 #define mix_select_callbacks(x)	generic_mix_select_callbacks(x)
151 #define dmix_supported_format generic_dmix_supported_format
152 #endif
153 #endif
154 
mix_areas(snd_pcm_direct_t *dmix, const snd_pcm_channel_area_t *src_areas, const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t src_ofs, snd_pcm_uframes_t dst_ofs, snd_pcm_uframes_t size)155 static void mix_areas(snd_pcm_direct_t *dmix,
156 		      const snd_pcm_channel_area_t *src_areas,
157 		      const snd_pcm_channel_area_t *dst_areas,
158 		      snd_pcm_uframes_t src_ofs,
159 		      snd_pcm_uframes_t dst_ofs,
160 		      snd_pcm_uframes_t size)
161 {
162 	unsigned int src_step, dst_step;
163 	unsigned int chn, dchn, channels, sample_size;
164 	mix_areas_t *do_mix_areas;
165 
166 	channels = dmix->channels;
167 	switch (dmix->shmptr->s.format) {
168 	case SND_PCM_FORMAT_S16_LE:
169 	case SND_PCM_FORMAT_S16_BE:
170 		sample_size = 2;
171 		do_mix_areas = (mix_areas_t *)dmix->u.dmix.mix_areas_16;
172 		break;
173 	case SND_PCM_FORMAT_S32_LE:
174 	case SND_PCM_FORMAT_S32_BE:
175 		sample_size = 4;
176 		do_mix_areas = (mix_areas_t *)dmix->u.dmix.mix_areas_32;
177 		break;
178 	case SND_PCM_FORMAT_S24_LE:
179 		sample_size = 4;
180 		do_mix_areas = (mix_areas_t *)dmix->u.dmix.mix_areas_24;
181 		break;
182 	case SND_PCM_FORMAT_S24_3LE:
183 		sample_size = 3;
184 		do_mix_areas = (mix_areas_t *)dmix->u.dmix.mix_areas_24;
185 		break;
186 	case SND_PCM_FORMAT_U8:
187 		sample_size = 1;
188 		do_mix_areas = (mix_areas_t *)dmix->u.dmix.mix_areas_u8;
189 		break;
190 	default:
191 		return;
192 	}
193 	if (dmix->interleaved) {
194 		/*
195 		 * process all areas in one loop
196 		 * it optimizes the memory accesses for this case
197 		 */
198 		do_mix_areas(size * channels,
199 			     (unsigned char *)dst_areas[0].addr + sample_size * dst_ofs * channels,
200 			     (unsigned char *)src_areas[0].addr + sample_size * src_ofs * channels,
201 			     dmix->u.dmix.sum_buffer + dst_ofs * channels,
202 			     sample_size,
203 			     sample_size,
204 			     sizeof(signed int));
205 		return;
206 	}
207 	for (chn = 0; chn < channels; chn++) {
208 		dchn = dmix->bindings ? dmix->bindings[chn] : chn;
209 		if (dchn >= dmix->shmptr->s.channels)
210 			continue;
211 		src_step = src_areas[chn].step / 8;
212 		dst_step = dst_areas[dchn].step / 8;
213 		do_mix_areas(size,
214 			     ((unsigned char *)dst_areas[dchn].addr + dst_areas[dchn].first / 8) + dst_ofs * dst_step,
215 			     ((unsigned char *)src_areas[chn].addr + src_areas[chn].first / 8) + src_ofs * src_step,
216 			     dmix->u.dmix.sum_buffer + dmix->shmptr->s.channels * dst_ofs + dchn,
217 			     dst_step,
218 			     src_step,
219 			     dmix->shmptr->s.channels * sizeof(signed int));
220 	}
221 }
222 
remix_areas(snd_pcm_direct_t *dmix, const snd_pcm_channel_area_t *src_areas, const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t src_ofs, snd_pcm_uframes_t dst_ofs, snd_pcm_uframes_t size)223 static void remix_areas(snd_pcm_direct_t *dmix,
224 			const snd_pcm_channel_area_t *src_areas,
225 			const snd_pcm_channel_area_t *dst_areas,
226 			snd_pcm_uframes_t src_ofs,
227 			snd_pcm_uframes_t dst_ofs,
228 			snd_pcm_uframes_t size)
229 {
230 	unsigned int src_step, dst_step;
231 	unsigned int chn, dchn, channels, sample_size;
232 	mix_areas_t *do_remix_areas;
233 
234 	channels = dmix->channels;
235 	switch (dmix->shmptr->s.format) {
236 	case SND_PCM_FORMAT_S16_LE:
237 	case SND_PCM_FORMAT_S16_BE:
238 		sample_size = 2;
239 		do_remix_areas = (mix_areas_t *)dmix->u.dmix.remix_areas_16;
240 		break;
241 	case SND_PCM_FORMAT_S32_LE:
242 	case SND_PCM_FORMAT_S32_BE:
243 		sample_size = 4;
244 		do_remix_areas = (mix_areas_t *)dmix->u.dmix.remix_areas_32;
245 		break;
246 	case SND_PCM_FORMAT_S24_LE:
247 		sample_size = 4;
248 		do_remix_areas = (mix_areas_t *)dmix->u.dmix.remix_areas_24;
249 		break;
250 	case SND_PCM_FORMAT_S24_3LE:
251 		sample_size = 3;
252 		do_remix_areas = (mix_areas_t *)dmix->u.dmix.remix_areas_24;
253 		break;
254 	case SND_PCM_FORMAT_U8:
255 		sample_size = 1;
256 		do_remix_areas = (mix_areas_t *)dmix->u.dmix.remix_areas_u8;
257 		break;
258 	default:
259 		return;
260 	}
261 	if (dmix->interleaved) {
262 		/*
263 		 * process all areas in one loop
264 		 * it optimizes the memory accesses for this case
265 		 */
266 		do_remix_areas(size * channels,
267 			       (unsigned char *)dst_areas[0].addr + sample_size * dst_ofs * channels,
268 			       (unsigned char *)src_areas[0].addr + sample_size * src_ofs * channels,
269 			       dmix->u.dmix.sum_buffer + dst_ofs * channels,
270 			       sample_size,
271 			       sample_size,
272 			       sizeof(signed int));
273 		return;
274 	}
275 	for (chn = 0; chn < channels; chn++) {
276 		dchn = dmix->bindings ? dmix->bindings[chn] : chn;
277 		if (dchn >= dmix->shmptr->s.channels)
278 			continue;
279 		src_step = src_areas[chn].step / 8;
280 		dst_step = dst_areas[dchn].step / 8;
281 		do_remix_areas(size,
282 			       ((unsigned char *)dst_areas[dchn].addr + dst_areas[dchn].first / 8) + dst_ofs * dst_step,
283 			       ((unsigned char *)src_areas[chn].addr + src_areas[chn].first / 8) + src_ofs * src_step,
284 			       dmix->u.dmix.sum_buffer + dmix->shmptr->s.channels * dst_ofs + dchn,
285 			       dst_step,
286 			       src_step,
287 			       dmix->shmptr->s.channels * sizeof(signed int));
288 	}
289 }
290 
291 /*
292  * if no concurrent access is allowed in the mixing routines, we need to protect
293  * the area via semaphore
294  */
295 #ifndef DOC_HIDDEN
dmix_down_sem(snd_pcm_direct_t *dmix)296 static void dmix_down_sem(snd_pcm_direct_t *dmix)
297 {
298 	if (dmix->u.dmix.use_sem)
299 		snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
300 }
301 
dmix_up_sem(snd_pcm_direct_t *dmix)302 static void dmix_up_sem(snd_pcm_direct_t *dmix)
303 {
304 	if (dmix->u.dmix.use_sem)
305 		snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
306 }
307 #endif
308 
309 /*
310  *  synchronize shm ring buffer with hardware
311  */
snd_pcm_dmix_sync_area(snd_pcm_t *pcm)312 static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
313 {
314 	snd_pcm_direct_t *dmix = pcm->private_data;
315 	snd_pcm_uframes_t slave_hw_ptr, slave_appl_ptr, slave_size;
316 	snd_pcm_uframes_t appl_ptr, size, transfer;
317 	const snd_pcm_channel_area_t *src_areas, *dst_areas;
318 
319 	/* calculate the size to transfer */
320 	/* check the available size in the local buffer
321 	 * last_appl_ptr keeps the last updated position
322 	 */
323 	size = pcm_frame_diff2(dmix->appl_ptr, dmix->last_appl_ptr, pcm->boundary);
324 	if (! size)
325 		return;
326 
327 	/* the slave_app_ptr can be far behind the slave_hw_ptr */
328 	/* reduce mixing and errors here - just skip not catched writes */
329 	slave_size = pcm_frame_diff(dmix->slave_appl_ptr, dmix->slave_hw_ptr, dmix->slave_boundary);
330 	if (slave_size > dmix->slave_buffer_size) {
331 		transfer = dmix->slave_buffer_size - slave_size;
332 		if (transfer > size)
333 			transfer = size;
334 		dmix->last_appl_ptr += transfer;
335 		dmix->last_appl_ptr %= pcm->boundary;
336 		dmix->slave_appl_ptr += transfer;
337 		dmix->slave_appl_ptr %= dmix->slave_boundary;
338 		size = pcm_frame_diff2(dmix->appl_ptr, dmix->last_appl_ptr, pcm->boundary);
339 		if (! size)
340 			return;
341 	}
342 
343 	/* check the available size in the slave PCM buffer */
344 	slave_hw_ptr = dmix->slave_hw_ptr;
345 	/* don't write on the last active period - this area may be cleared
346 	 * by the driver during mix operation...
347 	 */
348 	slave_hw_ptr -= slave_hw_ptr % dmix->slave_period_size;
349 	slave_hw_ptr += dmix->slave_buffer_size;
350 	if (slave_hw_ptr >= dmix->slave_boundary)
351 		slave_hw_ptr -= dmix->slave_boundary;
352 	slave_size = pcm_frame_diff(slave_hw_ptr, dmix->slave_appl_ptr, dmix->slave_boundary);
353 	if (slave_size < size)
354 		size = slave_size;
355 	if (! size)
356 		return;
357 
358 	/* add sample areas here */
359 	src_areas = snd_pcm_mmap_areas(pcm);
360 	dst_areas = snd_pcm_mmap_areas(dmix->spcm);
361 	appl_ptr = dmix->last_appl_ptr % pcm->buffer_size;
362 	dmix->last_appl_ptr += size;
363 	dmix->last_appl_ptr %= pcm->boundary;
364 	slave_appl_ptr = dmix->slave_appl_ptr % dmix->slave_buffer_size;
365 	dmix->slave_appl_ptr += size;
366 	dmix->slave_appl_ptr %= dmix->slave_boundary;
367 	dmix_down_sem(dmix);
368 	for (;;) {
369 		transfer = size;
370 		if (appl_ptr + transfer > pcm->buffer_size)
371 			transfer = pcm->buffer_size - appl_ptr;
372 		if (slave_appl_ptr + transfer > dmix->slave_buffer_size)
373 			transfer = dmix->slave_buffer_size - slave_appl_ptr;
374 		mix_areas(dmix, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer);
375 		size -= transfer;
376 		if (! size)
377 			break;
378 		slave_appl_ptr += transfer;
379 		slave_appl_ptr %= dmix->slave_buffer_size;
380 		appl_ptr += transfer;
381 		appl_ptr %= pcm->buffer_size;
382 	}
383 	dmix_up_sem(dmix);
384 }
385 
386 /*
387  *  synchronize hardware pointer (hw_ptr) with ours
388  */
snd_pcm_dmix_sync_ptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_ptr)389 static int snd_pcm_dmix_sync_ptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_ptr)
390 {
391 	snd_pcm_direct_t *dmix = pcm->private_data;
392 	snd_pcm_uframes_t old_slave_hw_ptr, avail;
393 	snd_pcm_sframes_t diff;
394 
395 	old_slave_hw_ptr = dmix->slave_hw_ptr;
396 	dmix->slave_hw_ptr = slave_hw_ptr;
397 	diff = pcm_frame_diff(slave_hw_ptr, old_slave_hw_ptr, dmix->slave_boundary);
398 	if (diff == 0)		/* fast path */
399 		return 0;
400 	if (dmix->state != SND_PCM_STATE_RUNNING &&
401 	    dmix->state != SND_PCM_STATE_DRAINING)
402 		/* not really started yet - don't update hw_ptr */
403 		return 0;
404 	dmix->hw_ptr += diff;
405 	dmix->hw_ptr %= pcm->boundary;
406 	if (pcm->stop_threshold >= pcm->boundary)	/* don't care */
407 		return 0;
408 	avail = snd_pcm_mmap_playback_avail(pcm);
409 	if (avail > dmix->avail_max)
410 		dmix->avail_max = avail;
411 	if (avail >= pcm->stop_threshold) {
412 		snd_timer_stop(dmix->timer);
413 		gettimestamp(&dmix->trigger_tstamp, pcm->tstamp_type);
414 		if (dmix->state == SND_PCM_STATE_RUNNING) {
415 			dmix->state = SND_PCM_STATE_XRUN;
416 			return -EPIPE;
417 		}
418 		dmix->state = SND_PCM_STATE_SETUP;
419 		/* clear queue to remove pending poll events */
420 		snd_pcm_direct_clear_timer_queue(dmix);
421 	}
422 	return 0;
423 }
424 
snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)425 static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
426 {
427 	snd_pcm_direct_t *dmix = pcm->private_data;
428 	snd_pcm_uframes_t slave_hw_ptr;
429 	int err;
430 
431 	if (dmix->slowptr)
432 		snd_pcm_hwsync(dmix->spcm);
433 	slave_hw_ptr = *dmix->spcm->hw.ptr;
434 	err = snd_pcm_direct_check_xrun(dmix, pcm);
435 	if (err < 0)
436 		return err;
437 
438 	return snd_pcm_dmix_sync_ptr0(pcm, slave_hw_ptr);
439 }
440 
441 /*
442  *  plugin implementation
443  */
444 
snd_pcm_dmix_state(snd_pcm_t *pcm)445 static snd_pcm_state_t snd_pcm_dmix_state(snd_pcm_t *pcm)
446 {
447 	snd_pcm_direct_t *dmix = pcm->private_data;
448 
449 	snd_pcm_direct_check_xrun(dmix, pcm);
450 	if (dmix->state == STATE_RUN_PENDING)
451 		return SNDRV_PCM_STATE_RUNNING;
452 	return dmix->state;
453 }
454 
snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status)455 static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
456 {
457 	snd_pcm_direct_t *dmix = pcm->private_data;
458 
459 	memset(status, 0, sizeof(*status));
460 	snd_pcm_status(dmix->spcm, status);
461 
462 	switch (dmix->state) {
463 	case SNDRV_PCM_STATE_DRAINING:
464 	case SNDRV_PCM_STATE_RUNNING:
465 		snd_pcm_dmix_sync_ptr0(pcm, status->hw_ptr);
466 		status->delay = snd_pcm_mmap_playback_delay(pcm);
467 		break;
468 	default:
469 		break;
470 	}
471 
472 	status->state = snd_pcm_dmix_state(pcm);
473 	status->hw_ptr = *pcm->hw.ptr; /* boundary may be different */
474 	status->appl_ptr = *pcm->appl.ptr; /* slave PCM doesn't set appl_ptr */
475 	status->trigger_tstamp = dmix->trigger_tstamp;
476 	status->avail = snd_pcm_mmap_playback_avail(pcm);
477 	status->avail_max = status->avail > dmix->avail_max ? status->avail : dmix->avail_max;
478 	dmix->avail_max = 0;
479 	return 0;
480 }
481 
snd_pcm_dmix_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)482 static int snd_pcm_dmix_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
483 {
484 	snd_pcm_direct_t *dmix = pcm->private_data;
485 	int err;
486 
487 	switch(dmix->state) {
488 	case SNDRV_PCM_STATE_DRAINING:
489 	case SNDRV_PCM_STATE_RUNNING:
490 		err = snd_pcm_dmix_sync_ptr(pcm);
491 		if (err < 0)
492 			return err;
493 		/* fallthru */
494 	case SNDRV_PCM_STATE_PREPARED:
495 	case SNDRV_PCM_STATE_SUSPENDED:
496 	case STATE_RUN_PENDING:
497 		*delayp = snd_pcm_mmap_playback_delay(pcm);
498 		return 0;
499 	case SNDRV_PCM_STATE_XRUN:
500 		return -EPIPE;
501 	case SNDRV_PCM_STATE_DISCONNECTED:
502 		return -ENODEV;
503 	default:
504 		return -EBADFD;
505 	}
506 }
507 
snd_pcm_dmix_hwsync(snd_pcm_t *pcm)508 static int snd_pcm_dmix_hwsync(snd_pcm_t *pcm)
509 {
510 	snd_pcm_direct_t *dmix = pcm->private_data;
511 
512 	switch(dmix->state) {
513 	case SNDRV_PCM_STATE_DRAINING:
514 	case SNDRV_PCM_STATE_RUNNING:
515 		/* sync slave PCM */
516 		return snd_pcm_dmix_sync_ptr(pcm);
517 	case SNDRV_PCM_STATE_PREPARED:
518 	case SNDRV_PCM_STATE_SUSPENDED:
519 	case STATE_RUN_PENDING:
520 		return 0;
521 	case SNDRV_PCM_STATE_XRUN:
522 		return -EPIPE;
523 	case SNDRV_PCM_STATE_DISCONNECTED:
524 		return -ENODEV;
525 	default:
526 		return -EBADFD;
527 	}
528 }
529 
snd_pcm_dmix_reset(snd_pcm_t *pcm)530 static int snd_pcm_dmix_reset(snd_pcm_t *pcm)
531 {
532 	snd_pcm_direct_t *dmix = pcm->private_data;
533 	dmix->hw_ptr %= pcm->period_size;
534 	dmix->appl_ptr = dmix->last_appl_ptr = dmix->hw_ptr;
535 	snd_pcm_direct_reset_slave_ptr(pcm, dmix, *dmix->spcm->hw.ptr);
536 	return 0;
537 }
538 
snd_pcm_dmix_start_timer(snd_pcm_t *pcm, snd_pcm_direct_t *dmix)539 static int snd_pcm_dmix_start_timer(snd_pcm_t *pcm, snd_pcm_direct_t *dmix)
540 {
541 	int err;
542 
543 	snd_pcm_hwsync(dmix->spcm);
544 	snd_pcm_direct_reset_slave_ptr(pcm, dmix, *dmix->spcm->hw.ptr);
545 	err = snd_timer_start(dmix->timer);
546 	if (err < 0)
547 		return err;
548 	dmix->state = SND_PCM_STATE_RUNNING;
549 	return 0;
550 }
551 
snd_pcm_dmix_start(snd_pcm_t *pcm)552 static int snd_pcm_dmix_start(snd_pcm_t *pcm)
553 {
554 	snd_pcm_direct_t *dmix = pcm->private_data;
555 	snd_pcm_sframes_t avail;
556 	int err;
557 
558 	if (dmix->state != SND_PCM_STATE_PREPARED)
559 		return -EBADFD;
560 	avail = snd_pcm_mmap_playback_hw_avail(pcm);
561 	if (avail == 0)
562 		dmix->state = STATE_RUN_PENDING;
563 	else if (avail < 0)
564 		return 0;
565 	else {
566 		if ((err = snd_pcm_dmix_start_timer(pcm, dmix)) < 0)
567 			return err;
568 		snd_pcm_dmix_sync_area(pcm);
569 	}
570 	gettimestamp(&dmix->trigger_tstamp, pcm->tstamp_type);
571 	return 0;
572 }
573 
snd_pcm_dmix_drop(snd_pcm_t *pcm)574 static int snd_pcm_dmix_drop(snd_pcm_t *pcm)
575 {
576 	snd_pcm_direct_t *dmix = pcm->private_data;
577 	if (dmix->state == SND_PCM_STATE_OPEN)
578 		return -EBADFD;
579 	dmix->state = SND_PCM_STATE_SETUP;
580 	snd_pcm_direct_timer_stop(dmix);
581 	return 0;
582 }
583 
584 /* locked version */
__snd_pcm_dmix_drain(snd_pcm_t *pcm)585 static int __snd_pcm_dmix_drain(snd_pcm_t *pcm)
586 {
587 	snd_pcm_direct_t *dmix = pcm->private_data;
588 	snd_pcm_uframes_t stop_threshold;
589 	int err = 0;
590 
591 	switch (snd_pcm_state(dmix->spcm)) {
592 	case SND_PCM_STATE_SUSPENDED:
593 		return -ESTRPIPE;
594 	default:
595 		break;
596 	}
597 
598 	if (dmix->state == SND_PCM_STATE_OPEN)
599 		return -EBADFD;
600 	if (dmix->state == SND_PCM_STATE_PREPARED) {
601 		if (snd_pcm_mmap_playback_hw_avail(pcm) > 0)
602 			snd_pcm_dmix_start(pcm);
603 		else {
604 			snd_pcm_dmix_drop(pcm);
605 			return 0;
606 		}
607 	}
608 
609 	if (dmix->state == SND_PCM_STATE_XRUN) {
610 		snd_pcm_dmix_drop(pcm);
611 		return 0;
612 	}
613 
614 	stop_threshold = pcm->stop_threshold;
615 	if (pcm->stop_threshold > pcm->buffer_size)
616 		pcm->stop_threshold = pcm->buffer_size;
617 	dmix->state = SND_PCM_STATE_DRAINING;
618 	do {
619 		err = snd_pcm_dmix_sync_ptr(pcm);
620 		if (err < 0) {
621 			snd_pcm_dmix_drop(pcm);
622 			goto done;
623 		}
624 		if (dmix->state == SND_PCM_STATE_DRAINING) {
625 			snd_pcm_dmix_sync_area(pcm);
626 			if ((pcm->mode & SND_PCM_NONBLOCK) == 0) {
627 				snd_pcm_wait_nocheck(pcm, SND_PCM_WAIT_DRAIN);
628 				snd_pcm_direct_clear_timer_queue(dmix); /* force poll to wait */
629 			}
630 
631 			switch (snd_pcm_state(dmix->spcm)) {
632 			case SND_PCM_STATE_SUSPENDED:
633 				err = -ESTRPIPE;
634 				goto done;
635 			default:
636 				break;
637 			}
638 		}
639 		if (pcm->mode & SND_PCM_NONBLOCK) {
640 			if (dmix->state == SND_PCM_STATE_DRAINING) {
641 				err = -EAGAIN;
642 				goto done;
643 			}
644 		}
645 	} while (dmix->state == SND_PCM_STATE_DRAINING);
646 done:
647 	pcm->stop_threshold = stop_threshold;
648 	return err;
649 }
650 
snd_pcm_dmix_drain(snd_pcm_t *pcm)651 static int snd_pcm_dmix_drain(snd_pcm_t *pcm)
652 {
653 	int err;
654 
655 	snd_pcm_lock(pcm);
656 	err = __snd_pcm_dmix_drain(pcm);
657 	snd_pcm_unlock(pcm);
658 	return err;
659 }
660 
snd_pcm_dmix_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTRIBUTE_UNUSED)661 static int snd_pcm_dmix_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTRIBUTE_UNUSED)
662 {
663 	return -EIO;
664 }
665 
snd_pcm_dmix_rewindable(snd_pcm_t *pcm)666 static snd_pcm_sframes_t snd_pcm_dmix_rewindable(snd_pcm_t *pcm)
667 {
668 	return snd_pcm_mmap_playback_hw_rewindable(pcm);
669 }
670 
snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)671 static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
672 {
673 	snd_pcm_direct_t *dmix = pcm->private_data;
674 	snd_pcm_uframes_t slave_appl_ptr, slave_size;
675 	snd_pcm_uframes_t appl_ptr, size, transfer, result, frames_to_remix;
676 	int err;
677 	const snd_pcm_channel_area_t *src_areas, *dst_areas;
678 
679 	if (dmix->state == SND_PCM_STATE_RUNNING ||
680 	    dmix->state == SND_PCM_STATE_DRAINING) {
681 		err = snd_pcm_dmix_hwsync(pcm);
682 		if (err < 0)
683 			return err;
684 	}
685 
686 	/* (appl_ptr - last_appl_ptr) indicates the frames which are not
687 	 * already mixed
688 	 * (last_appl_ptr - hw_ptr)  indicates the frames which are already
689 	 * mixed but not played yet.
690 	 * So they can be remixed.
691 	 */
692 
693 	size = pcm_frame_diff(dmix->last_appl_ptr, dmix->appl_ptr, pcm->boundary);
694 	if (frames < size)
695 		size = frames;
696 	snd_pcm_mmap_appl_backward(pcm, size);
697 	frames -= size;
698 	if (!frames)
699 		return size;
700 	result = size;
701 
702 	/* Always at this point last_appl_ptr == appl_ptr
703 	 * So (appl_ptr - hw_ptr) indicates the frames which can be remixed
704 	 */
705 	size = pcm_frame_diff(dmix->appl_ptr, dmix->hw_ptr, pcm->boundary);
706 	if (size > frames)
707 		size = frames;
708 	slave_size = pcm_frame_diff(dmix->slave_appl_ptr, dmix->slave_hw_ptr, pcm->boundary);
709 	if (slave_size < size)
710 		size = slave_size;
711 
712 	/* frames which should be remixed will be saved
713 	 * to also backward the appl pointer on success
714 	 */
715 	frames_to_remix = size;
716 
717 	/* add sample areas here */
718 	src_areas = snd_pcm_mmap_areas(pcm);
719 	dst_areas = snd_pcm_mmap_areas(dmix->spcm);
720 	dmix->last_appl_ptr -= size;
721 	dmix->last_appl_ptr %= pcm->boundary;
722 	appl_ptr = dmix->last_appl_ptr % pcm->buffer_size;
723 	dmix->slave_appl_ptr -= size;
724 	dmix->slave_appl_ptr %= dmix->slave_boundary;
725 	slave_appl_ptr = dmix->slave_appl_ptr % dmix->slave_buffer_size;
726 	dmix_down_sem(dmix);
727 	for (;;) {
728 		transfer = size;
729 		if (appl_ptr + transfer > pcm->buffer_size)
730 			transfer = pcm->buffer_size - appl_ptr;
731 		if (slave_appl_ptr + transfer > dmix->slave_buffer_size)
732 			transfer = dmix->slave_buffer_size - slave_appl_ptr;
733 		remix_areas(dmix, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer);
734 		size -= transfer;
735 		if (! size)
736 			break;
737 		slave_appl_ptr += transfer;
738 		slave_appl_ptr %= dmix->slave_buffer_size;
739 		appl_ptr += transfer;
740 		appl_ptr %= pcm->buffer_size;
741 	}
742 	dmix_up_sem(dmix);
743 
744 	snd_pcm_mmap_appl_backward(pcm, frames_to_remix);
745 	result += frames_to_remix;
746 	/* At this point last_appl_ptr and appl_ptr has to indicate the
747 	 * position of the first not mixed frame
748 	 */
749 
750 	return result;
751 }
752 
snd_pcm_dmix_forwardable(snd_pcm_t *pcm)753 static snd_pcm_sframes_t snd_pcm_dmix_forwardable(snd_pcm_t *pcm)
754 {
755 	return snd_pcm_mmap_avail(pcm);
756 }
757 
snd_pcm_dmix_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)758 static snd_pcm_sframes_t snd_pcm_dmix_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
759 {
760 	snd_pcm_sframes_t avail;
761 
762 	avail = snd_pcm_dmix_forwardable(pcm);
763 	if (frames > (snd_pcm_uframes_t)avail)
764 		frames = avail;
765 	snd_pcm_mmap_appl_forward(pcm, frames);
766 	return frames;
767 }
768 
snd_pcm_dmix_readi(snd_pcm_t *pcm ATTRIBUTE_UNUSED, void *buffer ATTRIBUTE_UNUSED, snd_pcm_uframes_t size ATTRIBUTE_UNUSED)769 static snd_pcm_sframes_t snd_pcm_dmix_readi(snd_pcm_t *pcm ATTRIBUTE_UNUSED, void *buffer ATTRIBUTE_UNUSED, snd_pcm_uframes_t size ATTRIBUTE_UNUSED)
770 {
771 	return -ENODEV;
772 }
773 
snd_pcm_dmix_readn(snd_pcm_t *pcm ATTRIBUTE_UNUSED, void **bufs ATTRIBUTE_UNUSED, snd_pcm_uframes_t size ATTRIBUTE_UNUSED)774 static snd_pcm_sframes_t snd_pcm_dmix_readn(snd_pcm_t *pcm ATTRIBUTE_UNUSED, void **bufs ATTRIBUTE_UNUSED, snd_pcm_uframes_t size ATTRIBUTE_UNUSED)
775 {
776 	return -ENODEV;
777 }
778 
snd_pcm_dmix_close(snd_pcm_t *pcm)779 static int snd_pcm_dmix_close(snd_pcm_t *pcm)
780 {
781 	snd_pcm_direct_t *dmix = pcm->private_data;
782 
783 	if (dmix->timer)
784 		snd_timer_close(dmix->timer);
785 	snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
786 	snd_pcm_close(dmix->spcm);
787  	if (dmix->server)
788  		snd_pcm_direct_server_discard(dmix);
789  	if (dmix->client)
790  		snd_pcm_direct_client_discard(dmix);
791  	shm_sum_discard(dmix);
792 	if (snd_pcm_direct_shm_discard(dmix)) {
793 		if (snd_pcm_direct_semaphore_discard(dmix))
794 			snd_pcm_direct_semaphore_final(dmix, DIRECT_IPC_SEM_CLIENT);
795 	} else
796 		snd_pcm_direct_semaphore_final(dmix, DIRECT_IPC_SEM_CLIENT);
797 	free(dmix->bindings);
798 	pcm->private_data = NULL;
799 	free(dmix);
800 	return 0;
801 }
802 
snd_pcm_dmix_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset ATTRIBUTE_UNUSED, snd_pcm_uframes_t size)803 static snd_pcm_sframes_t snd_pcm_dmix_mmap_commit(snd_pcm_t *pcm,
804 						  snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
805 						  snd_pcm_uframes_t size)
806 {
807 	snd_pcm_direct_t *dmix = pcm->private_data;
808 	int err;
809 
810 	err = snd_pcm_direct_check_xrun(dmix, pcm);
811 	if (err < 0)
812 		return err;
813 	if (! size)
814 		return 0;
815 	snd_pcm_mmap_appl_forward(pcm, size);
816 	if (dmix->state == STATE_RUN_PENDING) {
817 		if ((err = snd_pcm_dmix_start_timer(pcm, dmix)) < 0)
818 			return err;
819 	} else if (dmix->state == SND_PCM_STATE_RUNNING ||
820 		   dmix->state == SND_PCM_STATE_DRAINING) {
821 		if ((err = snd_pcm_dmix_sync_ptr(pcm)) < 0)
822 			return err;
823 	}
824 	if (dmix->state == SND_PCM_STATE_RUNNING ||
825 	    dmix->state == SND_PCM_STATE_DRAINING) {
826 		/* ok, we commit the changes after the validation of area */
827 		/* it's intended, although the result might be crappy */
828 		snd_pcm_dmix_sync_area(pcm);
829 		/* clear timer queue to avoid a bogus return from poll */
830 		if (snd_pcm_mmap_playback_avail(pcm) < pcm->avail_min)
831 			snd_pcm_direct_clear_timer_queue(dmix);
832 	}
833 	return size;
834 }
835 
snd_pcm_dmix_avail_update(snd_pcm_t *pcm)836 static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm)
837 {
838 	snd_pcm_direct_t *dmix = pcm->private_data;
839 	int err;
840 
841 	if (dmix->state == SND_PCM_STATE_RUNNING ||
842 	    dmix->state == SND_PCM_STATE_DRAINING) {
843 		if ((err = snd_pcm_dmix_sync_ptr(pcm)) < 0)
844 			return err;
845 	}
846 	if (dmix->state == SND_PCM_STATE_XRUN)
847 		return -EPIPE;
848 
849 	return snd_pcm_mmap_playback_avail(pcm);
850 }
851 
snd_pcm_dmix_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail, snd_htimestamp_t *tstamp)852 static int snd_pcm_dmix_htimestamp(snd_pcm_t *pcm,
853 				   snd_pcm_uframes_t *avail,
854 				   snd_htimestamp_t *tstamp)
855 {
856 	snd_pcm_direct_t *dmix = pcm->private_data;
857 	snd_pcm_uframes_t avail1;
858 	int ok = 0;
859 
860 	while (1) {
861 		if (dmix->state == SND_PCM_STATE_RUNNING ||
862 		    dmix->state == SND_PCM_STATE_DRAINING)
863 			snd_pcm_dmix_sync_ptr(pcm);
864 		avail1 = snd_pcm_mmap_playback_avail(pcm);
865 		if (ok && *avail == avail1)
866 			break;
867 		*avail = avail1;
868 		*tstamp = snd_pcm_hw_fast_tstamp(dmix->spcm);
869 		ok = 1;
870 	}
871 	return 0;
872 }
873 
snd_pcm_dmix_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)874 static int snd_pcm_dmix_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
875 {
876 	snd_pcm_direct_t *dmix = pcm->private_data;
877 	if (dmix->state == SND_PCM_STATE_RUNNING)
878 		snd_pcm_dmix_sync_area(pcm);
879 	return snd_pcm_direct_poll_revents(pcm, pfds, nfds, revents);
880 }
881 
882 
snd_pcm_dmix_dump(snd_pcm_t *pcm, snd_output_t *out)883 static void snd_pcm_dmix_dump(snd_pcm_t *pcm, snd_output_t *out)
884 {
885 	snd_pcm_direct_t *dmix = pcm->private_data;
886 
887 	snd_output_printf(out, "Direct Stream Mixing PCM\n");
888 	if (pcm->setup) {
889 		snd_output_printf(out, "Its setup is:\n");
890 		snd_pcm_dump_setup(pcm, out);
891 	}
892 	if (dmix->spcm)
893 		snd_pcm_dump(dmix->spcm, out);
894 }
895 
896 static const snd_pcm_ops_t snd_pcm_dmix_ops = {
897 	.close = snd_pcm_dmix_close,
898 	.info = snd_pcm_direct_info,
899 	.hw_refine = snd_pcm_direct_hw_refine,
900 	.hw_params = snd_pcm_direct_hw_params,
901 	.hw_free = snd_pcm_direct_hw_free,
902 	.sw_params = snd_pcm_direct_sw_params,
903 	.channel_info = snd_pcm_direct_channel_info,
904 	.dump = snd_pcm_dmix_dump,
905 	.nonblock = snd_pcm_direct_nonblock,
906 	.async = snd_pcm_direct_async,
907 	.mmap = snd_pcm_direct_mmap,
908 	.munmap = snd_pcm_direct_munmap,
909 	.query_chmaps = snd_pcm_direct_query_chmaps,
910 	.get_chmap = snd_pcm_direct_get_chmap,
911 	.set_chmap = snd_pcm_direct_set_chmap,
912 };
913 
914 static const snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
915 	.status = snd_pcm_dmix_status,
916 	.state = snd_pcm_dmix_state,
917 	.hwsync = snd_pcm_dmix_hwsync,
918 	.delay = snd_pcm_dmix_delay,
919 	.prepare = snd_pcm_direct_prepare,
920 	.reset = snd_pcm_dmix_reset,
921 	.start = snd_pcm_dmix_start,
922 	.drop = snd_pcm_dmix_drop,
923 	.drain = snd_pcm_dmix_drain,
924 	.pause = snd_pcm_dmix_pause,
925 	.rewindable = snd_pcm_dmix_rewindable,
926 	.rewind = snd_pcm_dmix_rewind,
927 	.forwardable = snd_pcm_dmix_forwardable,
928 	.forward = snd_pcm_dmix_forward,
929 	.resume = snd_pcm_direct_resume,
930 	.link = NULL,
931 	.link_slaves = NULL,
932 	.unlink = NULL,
933 	.writei = snd_pcm_mmap_writei,
934 	.writen = snd_pcm_mmap_writen,
935 	.readi = snd_pcm_dmix_readi,
936 	.readn = snd_pcm_dmix_readn,
937 	.avail_update = snd_pcm_dmix_avail_update,
938 	.mmap_commit = snd_pcm_dmix_mmap_commit,
939 	.htimestamp = snd_pcm_dmix_htimestamp,
940 	.poll_descriptors = snd_pcm_direct_poll_descriptors,
941 	.poll_descriptors_count = NULL,
942 	.poll_revents = snd_pcm_dmix_poll_revents,
943 };
944 
945 /**
946  * \brief Creates a new dmix PCM
947  * \param pcmp Returns created PCM handle
948  * \param name Name of PCM
949  * \param opts Direct PCM configurations
950  * \param params Parameters for slave
951  * \param root Configuration root
952  * \param sconf Slave configuration
953  * \param stream PCM Direction (stream)
954  * \param mode PCM Mode
955  * \retval zero on success otherwise a negative error code
956  * \warning Using of this function might be dangerous in the sense
957  *          of compatibility reasons. The prototype might be freely
958  *          changed in future.
959  */
snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, struct snd_pcm_direct_open_conf *opts, struct slave_params *params, snd_config_t *root, snd_config_t *sconf, snd_pcm_stream_t stream, int mode)960 int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
961 		      struct snd_pcm_direct_open_conf *opts,
962 		      struct slave_params *params,
963 		      snd_config_t *root, snd_config_t *sconf,
964 		      snd_pcm_stream_t stream, int mode)
965 {
966 	snd_pcm_t *pcm, *spcm = NULL;
967 	snd_pcm_direct_t *dmix;
968 	int ret, first_instance;
969 
970 	assert(pcmp);
971 
972 	if (stream != SND_PCM_STREAM_PLAYBACK) {
973 		SNDERR("The dmix plugin supports only playback stream");
974 		return -EINVAL;
975 	}
976 
977 	ret = _snd_pcm_direct_new(&pcm, &dmix, SND_PCM_TYPE_DMIX, name, opts, params, stream, mode);
978 	if (ret < 0)
979 		return ret;
980 	first_instance = ret;
981 
982 	pcm->ops = &snd_pcm_dmix_ops;
983 	pcm->fast_ops = &snd_pcm_dmix_fast_ops;
984 	pcm->private_data = dmix;
985 	dmix->state = SND_PCM_STATE_OPEN;
986 	dmix->slowptr = opts->slowptr;
987 	dmix->max_periods = opts->max_periods;
988 	dmix->var_periodsize = opts->var_periodsize;
989 	dmix->hw_ptr_alignment = opts->hw_ptr_alignment;
990 	dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
991 	dmix->direct_memory_access = opts->direct_memory_access;
992 
993  retry:
994 	if (first_instance) {
995 		/* recursion is already checked in
996 		   snd_pcm_direct_get_slave_ipc_offset() */
997 		ret = snd_pcm_open_slave(&spcm, root, sconf, stream,
998 					 mode | SND_PCM_NONBLOCK, NULL);
999 		if (ret < 0) {
1000 			SNDERR("unable to open slave");
1001 			goto _err;
1002 		}
1003 
1004 		if (snd_pcm_type(spcm) != SND_PCM_TYPE_HW) {
1005 			SNDERR("dmix plugin can be only connected to hw plugin");
1006 			ret = -EINVAL;
1007 			goto _err;
1008 		}
1009 
1010 		ret = snd_pcm_direct_initialize_slave(dmix, spcm, params);
1011 		if (ret < 0) {
1012 			SNDERR("unable to initialize slave");
1013 			goto _err;
1014 		}
1015 
1016 		dmix->spcm = spcm;
1017 
1018 		if (dmix->shmptr->use_server) {
1019 			dmix->server_free = dmix_server_free;
1020 
1021 			ret = snd_pcm_direct_server_create(dmix);
1022 			if (ret < 0) {
1023 				SNDERR("unable to create server");
1024 				goto _err;
1025 			}
1026 		}
1027 
1028 		dmix->shmptr->type = spcm->type;
1029 	} else {
1030 		if (dmix->shmptr->use_server) {
1031 			/* up semaphore to avoid deadlock */
1032 			snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
1033 			ret = snd_pcm_direct_client_connect(dmix);
1034 			if (ret < 0) {
1035 				SNDERR("unable to connect client");
1036 				goto _err_nosem;
1037 			}
1038 
1039 			snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
1040 			ret = snd_pcm_direct_open_secondary_client(&spcm, dmix, "dmix_client");
1041 			if (ret < 0)
1042 				goto _err;
1043 		} else {
1044 
1045 			ret = snd_pcm_open_slave(&spcm, root, sconf, stream,
1046 						 mode | SND_PCM_NONBLOCK |
1047 						 SND_PCM_APPEND,
1048 						 NULL);
1049 			if (ret < 0) {
1050 				/* all other streams have been closed;
1051 				 * retry as the first instance
1052 				 */
1053 				if (ret == -EBADFD) {
1054 					first_instance = 1;
1055 					goto retry;
1056 				}
1057 				SNDERR("unable to open slave");
1058 				goto _err;
1059 			}
1060 			if (snd_pcm_type(spcm) != SND_PCM_TYPE_HW) {
1061 				SNDERR("dmix plugin can be only connected to hw plugin");
1062 				ret = -EINVAL;
1063 				goto _err;
1064 			}
1065 
1066 			ret = snd_pcm_direct_initialize_secondary_slave(dmix, spcm, params);
1067 			if (ret < 0) {
1068 				SNDERR("unable to initialize slave");
1069 				goto _err;
1070 			}
1071 		}
1072 
1073 		dmix->spcm = spcm;
1074 	}
1075 
1076 	ret = shm_sum_create_or_connect(dmix);
1077 	if (ret < 0) {
1078 		SNDERR("unable to initialize sum ring buffer");
1079 		goto _err;
1080 	}
1081 
1082 	ret = snd_pcm_direct_initialize_poll_fd(dmix);
1083 	if (ret < 0) {
1084 		SNDERR("unable to initialize poll_fd");
1085 		goto _err;
1086 	}
1087 
1088 	mix_select_callbacks(dmix);
1089 
1090 	pcm->poll_fd = dmix->poll_fd;
1091 	pcm->poll_events = POLLIN;	/* it's different than other plugins */
1092 	pcm->tstamp_type = spcm->tstamp_type;
1093 	pcm->mmap_rw = 1;
1094 	snd_pcm_set_hw_ptr(pcm, &dmix->hw_ptr, -1, 0);
1095 	snd_pcm_set_appl_ptr(pcm, &dmix->appl_ptr, -1, 0);
1096 
1097 	if (dmix->channels == UINT_MAX)
1098 		dmix->channels = dmix->shmptr->s.channels;
1099 
1100 	snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
1101 
1102 	*pcmp = pcm;
1103 	return 0;
1104 
1105  _err:
1106 	if (dmix->timer)
1107 		snd_timer_close(dmix->timer);
1108 	if (dmix->server)
1109 		snd_pcm_direct_server_discard(dmix);
1110 	if (dmix->client)
1111 		snd_pcm_direct_client_discard(dmix);
1112 	if (spcm)
1113 		snd_pcm_close(spcm);
1114 	if (dmix->u.dmix.shmid_sum >= 0)
1115 		shm_sum_discard(dmix);
1116 	if ((dmix->shmid >= 0) && (snd_pcm_direct_shm_discard(dmix))) {
1117 		if (snd_pcm_direct_semaphore_discard(dmix))
1118 			snd_pcm_direct_semaphore_final(dmix, DIRECT_IPC_SEM_CLIENT);
1119 	} else
1120 		snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
1121  _err_nosem:
1122 	free(dmix->bindings);
1123 	free(dmix);
1124 	snd_pcm_free(pcm);
1125 	return ret;
1126 }
1127 
1128 /*! \page pcm_plugins
1129 
1130 \section pcm_plugins_dmix Plugin: dmix
1131 
1132 This plugin provides direct mixing of multiple streams. The resolution
1133 for 32-bit mixing is only 24-bit. The low significant byte is filled with
1134 zeros. The extra 8 bits are used for the saturation.
1135 
1136 \code
1137 pcm.name {
1138 	type dmix		# Direct mix
1139 	ipc_key INT		# unique IPC key
1140 	ipc_key_add_uid BOOL	# add current uid to unique IPC key
1141 	ipc_perm INT		# IPC permissions (octal, default 0600)
1142 	hw_ptr_alignment STR	# Slave application and hw pointer alignment type
1143 				# STR can be one of the below strings :
1144 				# no (or off)
1145 				# roundup
1146 				# rounddown
1147 				# auto (default)
1148 	tstamp_type STR		# timestamp type
1149 				# STR can be one of the below strings :
1150 				# default, gettimeofday, monotonic, monotonic_raw
1151 	slave STR
1152 	# or
1153 	slave {			# Slave definition
1154 		pcm STR		# slave PCM name
1155 		# or
1156 		pcm { }		# slave PCM definition
1157 		format STR	# format definition
1158 		rate INT	# rate definition
1159 		channels INT
1160 		period_time INT	# in usec
1161 		# or
1162 		period_size INT	# in frames
1163 		buffer_time INT	# in usec
1164 		# or
1165 		buffer_size INT # in frames
1166 		periods INT	# when buffer_size or buffer_time is not specified
1167 	}
1168 	bindings {		# note: this is client independent!!!
1169 		N INT		# maps slave channel to client channel N
1170 	}
1171 	slowptr BOOL		# slow but more precise pointer updates
1172 }
1173 \endcode
1174 
1175 <code>ipc_key</code> specfies the unique IPC key in integer.
1176 This number must be unique for each different dmix definition,
1177 since the shared memory is created with this key number.
1178 When <code>ipc_key_add_uid</code> is set true, the uid value is
1179 added to the value set in <code>ipc_key</code>.  This will
1180 avoid the confliction of the same IPC key with different users
1181 concurrently.
1182 
1183 <code>hw_ptr_alignment</code> specifies slave application and hw
1184 pointer alignment type. By default hw_ptr_alignment is auto. Below are
1185 the possible configurations:
1186 - no: minimal latency with minimal frames dropped at startup. But
1187   wakeup of application (return from snd_pcm_wait() or poll()) can
1188   take up to 2 * period.
1189 - roundup: It is guaranteed that all frames will be played at
1190   startup. But the latency will increase upto period-1 frames.
1191 - rounddown: It is guaranteed that a wakeup will happen for each
1192   period and frames can be written from application. But on startup
1193   upto period-1 frames will be dropped.
1194 - auto: Selects the best approach depending on the used period and
1195   buffer size.
1196   If the application buffer size is < 2 * application period,
1197   "roundup" will be selected to avoid under runs. If the slave_period
1198   is < 10ms we could expect that there are low latency
1199   requirements. Therefore "rounddown" will be chosen to avoid long
1200   wakeup times. Such wakeup delay could otherwise end up with Xruns in
1201   case of a dependency to another sound device (e.g. forwarding of
1202   microphone to speaker). Else "no" will be chosen.
1203 
1204 Note that the dmix plugin itself supports only a single configuration.
1205 That is, it supports only the fixed rate (default 48000), format
1206 (\c S16), channels (2), and period_time (125000).
1207 For using other configuration, you have to set the value explicitly
1208 in the slave PCM definition.  The rate, format and channels can be
1209 covered by an additional \ref pcm_plugins_dmix "plug plugin",
1210 but there is only one base configuration, anyway.
1211 
1212 An example configuration for setting 44100 Hz, \c S32_LE format
1213 as the slave PCM of "hw:0" is like below:
1214 \code
1215 pcm.dmix_44 {
1216 	type dmix
1217 	ipc_key 321456	# any unique value
1218 	ipc_key_add_uid true
1219 	slave {
1220 		pcm "hw:0"
1221 		format S32_LE
1222 		rate 44100
1223 	}
1224 }
1225 \endcode
1226 You can hear 48000 Hz samples still using this dmix pcm via plug plugin
1227 like:
1228 \code
1229 % aplay -Dplug:dmix_44 foo_48k.wav
1230 \endcode
1231 
1232 For using the dmix plugin for OSS emulation device, you have to set
1233 the period and the buffer sizes in power of two.  For example,
1234 \code
1235 pcm.dmixoss {
1236 	type dmix
1237 	ipc_key 321456	# any unique value
1238 	ipc_key_add_uid true
1239 	slave {
1240 		pcm "hw:0"
1241 		period_time 0
1242 		period_size 1024  # must be power of 2
1243 		buffer_size 8192  # ditto
1244 	}
1245 }
1246 \endcode
1247 <code>period_time 0</code> must be set, too, for resetting the
1248 default value.  In the case of soundcards with multi-channel IO,
1249 adding the bindings would help
1250 \code
1251 pcm.dmixoss {
1252 	...
1253 	bindings {
1254 		0 0   # map from 0 to 0
1255 		1 1   # map from 1 to 1
1256 	}
1257 }
1258 \endcode
1259 so that only the first two channels are used by dmix.
1260 Also, note that ICE1712 have the limited buffer size, 5513 frames
1261 (corresponding to 640 kB).  In this case, reduce the buffer_size
1262 to 4096.
1263 
1264 \subsection pcm_plugins_dmix_funcref Function reference
1265 
1266 <UL>
1267   <LI>snd_pcm_dmix_open()
1268   <LI>_snd_pcm_dmix_open()
1269 </UL>
1270 
1271 */
1272 
1273 /**
1274  * \brief Creates a new dmix PCM
1275  * \param pcmp Returns created PCM handle
1276  * \param name Name of PCM
1277  * \param root Root configuration node
1278  * \param conf Configuration node with dmix PCM description
1279  * \param stream PCM Stream
1280  * \param mode PCM Mode
1281  * \warning Using of this function might be dangerous in the sense
1282  *          of compatibility reasons. The prototype might be freely
1283  *          changed in future.
1284  */
_snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, snd_config_t *root, snd_config_t *conf, snd_pcm_stream_t stream, int mode)1285 int _snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
1286 		       snd_config_t *root, snd_config_t *conf,
1287 		       snd_pcm_stream_t stream, int mode)
1288 {
1289 	snd_config_t *sconf;
1290 	struct slave_params params;
1291 	struct snd_pcm_direct_open_conf dopen;
1292 	int bsize, psize;
1293 	int err;
1294 
1295 	err = snd_pcm_direct_parse_open_conf(root, conf, stream, &dopen);
1296 	if (err < 0)
1297 		return err;
1298 
1299 	/* the default settings, it might be invalid for some hardware */
1300 	params.format = SND_PCM_FORMAT_S16;
1301 	params.rate = 48000;
1302 	params.channels = 2;
1303 	params.period_time = -1;
1304 	params.buffer_time = -1;
1305 	bsize = psize = -1;
1306 	params.periods = 3;
1307 
1308 	err = snd_pcm_slave_conf(root, dopen.slave, &sconf, 8,
1309 				 SND_PCM_HW_PARAM_FORMAT, SCONF_UNCHANGED, &params.format,
1310 				 SND_PCM_HW_PARAM_RATE, 0, &params.rate,
1311 				 SND_PCM_HW_PARAM_CHANNELS, 0, &params.channels,
1312 				 SND_PCM_HW_PARAM_PERIOD_TIME, 0, &params.period_time,
1313 				 SND_PCM_HW_PARAM_BUFFER_TIME, 0, &params.buffer_time,
1314 				 SND_PCM_HW_PARAM_PERIOD_SIZE, 0, &psize,
1315 				 SND_PCM_HW_PARAM_BUFFER_SIZE, 0, &bsize,
1316 				 SND_PCM_HW_PARAM_PERIODS, 0, &params.periods);
1317 	if (err < 0)
1318 		return err;
1319 
1320 	/* set a reasonable default */
1321 	if (psize == -1 && params.period_time == -1)
1322 		params.period_time = 125000;    /* 0.125 seconds */
1323 
1324 	if (params.format == -2)
1325 		params.format = SND_PCM_FORMAT_UNKNOWN;
1326 	else if (!(dmix_supported_format & (1ULL << params.format))) {
1327 		/* sorry, limited features */
1328 		SNDERR("Unsupported format");
1329 		snd_config_delete(sconf);
1330 		return -EINVAL;
1331 	}
1332 
1333 	params.period_size = psize;
1334 	params.buffer_size = bsize;
1335 
1336 	err = snd_pcm_dmix_open(pcmp, name, &dopen, &params,
1337 				root, sconf, stream, mode);
1338 	snd_config_delete(sconf);
1339 	return err;
1340 }
1341 #ifndef DOC_HIDDEN
1342 SND_DLSYM_BUILD_VERSION(_snd_pcm_dmix_open, SND_PCM_DLSYM_VERSION);
1343 #endif
1344