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